在RISC-V RV32I CPU 核中,需要32个通用的寄存器。这些寄存器是解析riscv 汇编指令的关键部分。
相关参考文章:
RISC-V 教学教案
RISC-V cpu 架构:

每一个RV32I 的risc-v 的cpu 中,都有32个通用的寄存器。 其中X0寄存器 在读取时,永远为‘0’。 写x0 寄存器时,cpu 硬件可以进行忽略(不做任何处理)。对于RV32E cpu 来说, 可以省略掉x16-x31 这16个通用寄存器,只是保留x0-x15 这16个寄存器,这样的设计可以减少cpu 的尺寸,但并不是非常通用。因为即使是rv32I 的cpu 尺寸也不是很大。

XLEN 是根据riscv 的 设计可以有所不同,对于RV64 来说, XLEN = 64; 对于RV32 来说,XLEN = 32。 我们当前设计的riscv cpu 为RV32I, 所以XLEN = 32。
module regfile_I(
input sys_clk, // 系统时钟
input i_EXE_vld, // 执行enable 信号
input [ 4: 0 ] i_rs1_idx, // 汇编指令中的rs1
input [ 4: 0 ] i_rs2_idx, // 汇编指令中的rs2
output [ 31: 0 ] o_rs1_val, // 汇编指令中的rs1,所对应的32个通用寄存器当中选中的寄存器的值
output [ 31: 0 ] o_rs2_val, // 汇编指令中的rs2,所对应的32个通用寄存器当中选中的寄存器的值
output o_wb_rdy, // 回写准备好,一直 等于 1
input i_wb_wen, // 写通用寄存器 信号
input [ 4: 0 ] i_wb_rd_idx, // 汇编指令中的rd,
input [ 31: 0 ] i_wb_val // 汇编指令中的rd,所对应的32个通用寄存器当中选中的寄存器的值
);
wire [ 31: 0 ] rf_r [ 31: 1 ];
wire [ 31: 1 ] rf_wen;
genvar i;
generate
for ( i = 1; i < 32; i = i + 1 )
begin : REG
assign rf_wen[ i ] = i_EXE_vld & i_wb_wen & ( i_wb_rd_idx == i ) ;
fii_dffl #( 32 ) rf_dffl ( rf_wen[ i ], i_wb_val, rf_r[ i ], sys_clk );
end
endgenerate
`ifdef sim
assign o_rs1_val = ( i_rs1_idx == 0 ) ? 32’b0 :
( rf_r[ i_rs1_idx ] == 32’hxxxxxxxx ) ? 32’b0 : rf_r[ i_rs1_idx ];
assign o_rs2_val = ( i_rs2_idx == 0 ) ? 32’b0 :
( rf_r[ i_rs2_idx ] == 32’hxxxxxxxx ) ? 32’b0 : rf_r[ i_rs2_idx ];
`else
assign o_rs1_val = ( i_rs1_idx == 0 ) ? 32’b0 : rf_r[ i_rs1_idx ];
assign o_rs2_val = ( i_rs2_idx == 0 ) ? 32’b0 : rf_r[ i_rs2_idx ];
`endif
assign o_wb_rdy = 1’b1;
endmodule
input [ 4: 0 ] i_rs1_idx, // 汇编指令中的rs1
input [ 4: 0 ] i_rs2_idx, // 汇编指令中的rs2
output [ 31: 0 ] o_rs1_val, // 汇编指令中的rs1,所对应的32个通用寄存器当中选中的寄存器的值
output [ 31: 0 ] o_rs2_val, // 汇编指令中的rs2,所对应的32个通用寄存器当中选中的寄存器的值
output o_wb_rdy, // 回写准备好,一直 等于 1
input i_wb_wen, // 写通用寄存器 信号
input [ 4: 0 ] i_wb_rd_idx,// 汇编指令中的rd,
input [ 31: 0 ] i_wb_val // 汇编指令中的rd,所对应的32个通用寄存器当中选中的寄存器的值
在代码段中:写操作
genvar i;
generate
for ( i = 1; i < 32; i = i + 1 )
begin : REG
assign rf_wen[ i ] = i_EXE_vld & i_wb_wen & ( i_wb_rd_idx == i ) ;
fii_dffl #( 32 ) rf_dffl ( rf_wen[ i ], i_wb_val, rf_r[ i ], sys_clk );
end
endgenerate
fii_dffl 文件代码:
module fii_dffl # (
parameter DW = 32
) (
input ld,
input [DW-1:0] din,
output reg [DW-1:0] q = 0,
input clk
);
always @(posedge clk )
if (ld)
q <= #1 din;
endmodule
在代码段中:读操作
assign o_rs1_val = ( i_rs1_idx == 0 ) ? 32’b0 : rf_r[ i_rs1_idx ];
assign o_rs2_val = ( i_rs2_idx == 0 ) ? 32’b0 : rf_r[ i_rs2_idx ];
在读取x0时(不论是rs1,还是rs2 读取x0), 直接返回0; 其他情况(1-31) 根据寄存器当中的值进行返回。

如果rs1和rs2为同一个寄存器呢?会不会冲突,是不是需要特殊处理一下
不会发生冲突,输出的RS1,RS2实际上是读出寄存器中的值。读操作都是立即执行的。RISC-V指令中是允许RS1,RS2指向同一个寄存器。