前提
RISC-V实践部分我们使用的是三级流水,包含了取指、译码和执行三个步骤。
tinyriscv的流水线结构图:
1.译码
tinyriscv整体框架图:
对比tinyriscv的流水线结构图和tinyriscv整体框架图,译码实际涉及到id.v(译码)模块、id_ex(流水线寄存器)模块,clint.v(中断)模块和csr_reg.v(CSR寄存器)模块控制这两个模块是用于例外中断的和特权架构的、ctrl.v(控制单元)模块是实行产生暂停流水线、跳转等控制信号。
C源代码到可运行程序的过程:
注释:译码就是将汇编转换成机器语言,懂吧我想去阿根廷去找梅西所以带了个翻译员来帮助我能听懂梅西在讲什么(我是梅西球迷)。涉及到RISC-V的汇编知识,请大家移步去看我的其他文章对RISC-V的汇编知识有了解再回来。
1. id.v(纯组合逻辑电路)
1.1功能
1.根据指令,翻译出是哪一条指令。
2.根据指令,确定涉及到寄存器。读寄存器是一个还是两个,是否需要写寄存器以及写哪一个寄存器。
3.访问通用寄存器,得到要读的寄存器的值(访存,但其实tinyriscv是不涉及访存的)。
1.2输入输出信号
序号 信号名 输入/输出 位宽(bits) 1 rst 输入 1 复位信号 2 inst_i 输入 32 指令内容,来源于if_id.v的inst_o 3 inst_addr_i 输入 32 指令地址,来源于if_id.v的inst_addr_o 4 reg1_rdata_i 输入 32 寄存器1输入数据,来源于regs.v的rdata1_o 5 reg2_rdata_i 输入 32 寄存器2输入数据,来源于regs.v的rdata2_o 6 csr_rdata_i 输入 32 CSR寄存器输入数据,来源于csr_reg.v的data_o
7 ex_jump_flag_i 输入 1 跳转信号,来源于ex.v的jump_flag_o 8 reg1_raddr_o 输出 5 读寄存器1地址,输出到regs.v 9 reg2_raddr_o 输出 5 读寄存器2地址,输出到regs.v 10 csr_raddr_o 输出 32 读CSR寄存器地址,输出到csr_reg.v 11 inst_o 输出 32 指令内容,输出到id_ex.v的 12 inst_addr_o 输出 32 指令地址,输出到id_ex.v的inst_addr_i 13 reg1_rdata_o 输出 32 通用寄存器1数据,输出到id_ex.v的reg1_rdata_i 14 reg2_rdata_o 输出 32 通用寄存器2数据,输出到id_ex.v的reg2_rdata_i 15 reg_we_o 输出 1 通用寄存器写使能,输出到id_ex.v的reg_we_i
16 reg_waddr_o 输出 5 通用寄存器写地址,输出到id_ex.v的reg_waddr_i 17 csr_we_o 输出 1 CSR寄存器写使能,输出到id_ex.v的csr_we_i 18 csr_rdata_o 输出 32 CSR寄存器读数据,输出到id_ex.v的csr_rdata_i 19 csr_waddr_o 输出 32 CSR寄存器写地址,输出到id_ex.v的csr_waddr_i
1.3代码注释
来自项目作者的解释:
注释:根据RISC-V的6种基本指令集格式我们就可以精确定位到我们需要的指令类型,再根据操作码就可以精确定位到我们需要的指令。
2.id_ex.v(时序逻辑电路)
2.1功能
进行了译码后的信号向执行模块传递
2.2输入输出信号
序号 信号名 输入/输出 位宽(bits) 说明 1 clk
输入 1 时钟输入信号 2 rst
输入 1 复位输入信号 3 inst_i
输入 32 指令内容,来源于id.v的inst_o
4 inst_addr_i 输入 32 指令地址,来源于id.v的inst_addr_o 5 reg_we_i 输入 1 写通用寄存器标志,来源于id.v的reg_we_o
6 reg_waddr_i 输入 5 写通用寄存器地址,来源于id.v的reg_waddr_o
7 reg1_rdata_i 输入 32 通用寄存器1读数据,来源于id.v的reg1_rdata_o
8 reg2_rdata_i 输入 32 通用寄存器2读数据,来源于id.v的reg2_rdata_o
9 csr_we_i 输入 1 写CSR寄存器标志,来源于id.v的id_csr_we_o
10 csr_waddr_i 输入 32 写CSR寄存器地址,来源于id.v的csr_waddr_o
11 csr_rdata_i 输入 32 CSR寄存器读数据,来源于id.v的id_csr_rdata_o
12 hold_flag_i 输入 3 流水线暂停标志,来源于ctrl.v的hold_flag_o
13 inst_o 输出 32 指令内容,输出到ex.v的inst_i
14 inst_addr_o 输出 32 指令地址,输出到ex.v的inst_addr_i
15 reg_we_o 输出 1 写通用寄存器标志,输出到ex.v的reg_we_i
16 reg_waddr_o 输出 5 写通用寄存器地址,输出到ex.v的reg_waddr_i
17 reg1_rdata_o 输出 32 通用寄存器1读数据,输出到ex.v的reg1_rdata_i
18 reg2_rdata_o 输出 32 通用寄存器2读数据,输出到ex.v的reg2_rdata_i
19 csr_we_o 输出 1 写CSR寄存器标志,输出到ex.v的csr_we_i
20 csr_waddr_o 输出 32 写CSR寄存器地址,输出到ex.v的csr_waddr_i
21 csr_rdata_o 输出 32 CSR寄存器读数据,输出到ex.v的csr_rdata_i
2.3代码注释
gen_pipe_dff #(32) inst_ff(clk, rst, hold_en, `INST_NOP, inst_i, inst);
注释:D触发器的例化啊,实现将输入的信号打一拍后再输出到执行模块(ex.v)的功能。