Menu Close

RISC-V 总线和流水线(4)RISC-V CPU流水线介绍

1. 流水线CPU设计

 

相关参考文章:

RISC-V教学教案

 

本文在之前介绍流水线(详细的流水线CPU设计点击这里)的基础上,讨论如何解决流水线产生的冲突,以及结合具体实例说明CPU的流水线设计。FII RISC-V是3级流水线CPU。 这三个阶段为:

  • FCH

取指, 从ITCM中拿到和当前PC匹配的指令

  • EXE

执行,执行当前的指令(包括指令译码,指令执行)

  • WB

仅当需要修改31个register(硬连接为0的寄存器x0不计算在内)或者读写外围设备的时候,需要执行这个操作。如果不需要,可以跳过,这样就节省一个时钟周期。如果外围设备需要很长时间才能得到数据,需要将流水线暂停(地址不变,发送`INST_NOP指令)

根据回写阶段的反馈,可以看出它是非线性流水线。

 

1.1.解决流水线数据冲突

如上所述,处理流水线数据冲突,特别是在“写之后读”的情况下。 如图1所示,当前一个回写寄存器(Rd)与下一个指令提取的寄存器(R1, R2)相同时,该值将被直接bypass。

%title插图%num

图1 解决数据冲突的FPGA代码

 

1.2.PC跳转

在stage 1中,根据具体条件判断将下一条指令地址分配给instr_fch_pc。 通常,PC + 4是下一条指令地址。 当存在与跳转相关的指令或长周期加载和存储时,将为PC分配一个不同的值以获取正确的下一条指令地址,如图2所示。在stage 2中,将instr_fch_pc赋值到i_PC

%title插图%num

图2  instr_fch_pc

 

图3列出了跳转情况的代码,并根据跳转类型为jump_addr分配不同的地址。 表1列出了相关跳转的标志及解释。

%title插图%num

图3  jump_addr和 jump_flag

 

标志 描述 标志 描述
I_dbg_entry_set Jtag调试模式 dret 退出调试模式
Long_ir_cs 长周期指令 Irq_exp_flag 进入中断
mret 退出中断 default 跳转指令

表1 跳转标志

 

图4显示了将跳转标志赋值给waiting_r。 只要有任何跳转发生,waiting_r就会拉高。 在图5中,如果waiting_r为高,则将`INST_NOP(no operation,无操作)赋值给curr_instr。 当发生跳转指令时,已经进入流水线之后的指令将被替换为nop。 INST_NOP(0x0000_0001)被解码为nop,它不会对内存或地址上产生任何操作。

waiting

图4 waiting_r

 

%title插图%num

图5 将curr_instr赋值为nop

1.3.数码管显示实例及仿真

图6显示了一个反汇编示例,该示例在数码管中显示字符“ F”。 显然,在标签<START>之前,流水线按顺序提取,执行和回写每条指令。 但是,在8000_003c地址中存在分支条件指令。 如果条件被满足,PC将跳至8000_0038,而不是8000_0040。 当流水线已经提取了8000_0040地址的指令时,应特别注意其执行结果。

%title插图%num

图6 跳转示例

 

仿真结果如图7所示。可以看出,当curr_instr为0x0000_0001时,即为curr_instr被赋值为了nop时,i_PC会从0x8000_0040变为0x8000_0038,并且会带有延迟。 如前所述,跳转标志将使curr_instr从任何指令更改为ʻINST_NOP(0x0000_0001)。

%title插图%num

图7 仿真结果

 

1.4.UART串口输出实例及仿真

图8显示了另一个UART示例。 它从UART输出“This is a call function program(这是一个调用函数程序)”。图9显示了存储在rodata段中的打印输出信息。当流水线执行0x8000_0044指令时,0x8000_0048地址中的指令已经被提取了。但是,根据0x8000_0044指令,PC应指向0x8000_0078以加载打印数据。这时,PC将放弃0x8000_0048地址的指令,并保留地址直到加载0x8000_0078 rodata,PC才会返回指向0x8000_0048的地址。图10显示了UART示例的仿真结果。可以看出,在放弃0x8000_0048地址的指令后,已将curr_instr赋值为INST_NOP(0x0000_0001)。

%title插图%num

图8 UART示例

 

%title插图%num

图9 输出打印信息

 

%title插图%num

图10 仿真结果

 

1.5.长周期访存指令处理

在将实际地址分配给PC之前,将instr_fch_PC(PC + 4)赋值给next_addr,因为在执行加载/存储之后,正常的PC + 4地址将是下一个执行的PC,如图11所示。 图12与图2相同,但此处高亮显示了rib_delay_op。 这是一个决策判断,如果当前指令是长周期加载和存储,则将next_addr赋值给instr_fch_PC,在执行长周期加载和存储的时候,将next_addr分配给i_PC

%title插图%num

图11 将instr_fch_PC赋值给next_addr

 

%title插图%num

图12 长周期加载&存储

 

Posted in FPGA, RISC-V, RISC-V, RISC-V 教案, 应用开发, 开发板, 文章

发表评论

相关链接