Menu Close

RISC-V CSR读写控制(1)exu_csr模块

1.输入/输出

 

相关参考文章:

RISC-V教学教案

 

本文使用的代码是基于FII RISC-V V2.01(没有JTAG和总线)。有关CSR六条指令的复习见文章RISC-V CSR寄存器(1)CSR简介和CSR指令,本文将从exu_csr模块开始介绍RISC-V CPU中如何控制CSR的读写。

%title插图%num

%title插图%num

下面是比较重要的输入输出信号,相应的解释标在了代码段中。



    input  sys_clk,              //系统时钟
    input  i_SYSTEM,             //CSR指令的opcode
    
    input  [ 31: 0 ] i_rs1_val,  //rs1的值
    input  [ 4: 0 ]  i_rd_idx,   //rd的索引
    input  [ 5: 0 ]  i_csr_instr,//csr的指令(6条之一)

    input  [ 11: 0 ] i_csr_addr, //索引CSR寄存器的12位地址
    input  [ 31: 0 ] i_csr_imm,  //零扩展后的立即数

    input  i_ext_irq,            //外部中断请求
    input  i_sft_irq,            //软件中断请求
    input  i_tmr_irq,            //计时器中断请求
    
    input  i_irq_src,            //中断源
    input  i_exp_src,            //异常源
    input  [ 31: 0 ] i_exe_pc,   //执行的程序计数器
    input  [ 31: 0 ] i_ir,       //指令寄存器

    output [ 31: 0 ]   o_irq_pc, //中断入口地址
    output [ 31: 0 ]   o_mepc,   //中断返回后需要执行的PC
    
    input  i_mret_ena,           //中断返回使能
    
//------------------------------省略与调试相关的信号-----------------------------------

    input  i_EXE_vld,            //执行有效


    output [ 31: 0 ] o_wr_csr_nxt,//写入CSR寄存器的值


    output o_rd_wen,             //CSR寄存器读使能,用于回写
    output [ 4: 0 ] o_wb_rd_idx, //回写索引
    output [ 31: 0 ] o_wb_data,  //回写数据

    output o_meie,               //外部中断使能
    output o_msie,               //软件中断使能
    output o_mtie,               //计时器中断使能
    output o_glb_irq,            //全局中断使能

    input  rst_n                 //复位

可以看出,以上主要可以分为中断相关信号和CSR指令执行相关信号。和exu_alu模块类似,csr指令的执行也需要寄存器相关的索引和值。中断相关的信号主要有高层模块输入的中断/异常请求信号,和底部模块输出的中断使能,PC信号。

 

2.执行

代码主体部分是CSR的6条指令,代码的解释如下:

 



//--------------------省略部分信号的声明和赋值-------------------------
// CSR指令按照如下排列
// i_csr_instr = {rv32i_csrrci, rv32i_csrrsi, rv32i_csrrwi,
//                rv32i_csrrc,  rv32i_csrrs,  rv32i_csrrw};

// 写入寄存器的值
always @ ( * )
begin
    reg_csr_val <= 32'b0;//初始化
    
    if ( i_SYSTEM & csr_wen )
    begin
       
        case ( i_csr_instr )
            6'h01:            //rv32i_csrrw
            begin
                reg_csr_val <= i_rs1_val;              
            end
            6'h02:            //rv32i_csrrs
            begin
                reg_csr_val <= i_rs1_val | w_csr_val;  
            end
            6'h04:            //rv32i_csrrc
            begin
                reg_csr_val <= ( ~i_rs1_val ) & w_csr_val; 
            end
            6'h08:            //rv32i_csrrwi
            begin
                reg_csr_val <= i_csr_imm; 
            end
            6'h10:            //rv32i_csrrsi
            begin
                reg_csr_val <= i_csr_imm | w_csr_val;  
            end
            6'h20:            //rv32i_csrrci
            begin
                reg_csr_val <= ( ~i_csr_imm ) & w_csr_val; 
            end
            default: ;
        endcase
    end

end


//CSR[11:10]/机器码的bit 30-31如果不为2‘b11,即为可读可写的属性
wire csr_wen  = i_EXE_vld & i_SYSTEM & (i_csr_addr[11:10] != 2'b11);
wire csr_rden = i_EXE_vld & i_SYSTEM;

 

以上的代码用case选择,将CSR的指令进行区分以及写寄存器的实现。用以下代码举例

6’h02:

begin

reg_csr_val <= i_rs1_val | w_csr_val; //rv32i_csrrs

end

i_csr_instr的bit 2对应的CSR指令是CSRRS rd,csr,rs1。t = CSRs[csr]; CSRs[csr] = t | x[rs1]; x[rd] = t

该指令是把CSR寄存器中的值读出并赋值到rd寄存器中,且将CSR寄存器中的值和寄存器rs1中的值按位或(bitwise OR)的结果写入CSR寄存器。

%title插图%num

其指令的机器码如图1所示。这里的实现CSR置位的功能是reg_csr_val <= i_rs1_val | w_csr_val; 

另外一部分CSR读寄存器的功能会在csr_reg模块里实现,之后讲到该模块时再进行解释。

CSRRS

图1 CSRRS机器码格式 [1]

RISC-V CSR寄存器(1)CSR简介和CSR指令提到过,

所有的CSR指令都是每次只能对一个CSR寄存器操作,其机器码如图1所示。可以看到CSR指令类似于I-type指令。虽然也有12位的立即数域,但是实际上机器码的bit 20-31是用来 索引相应CSR寄存器的地址。所以理论上,一共可以实现2^12 = 4096位CSR寄存器。

按照惯例,CSR地址的高位(CSR[11:8]/机器码的bit 28-31)用于根据权限级别对CSR的读写可访问性进行编码。

//CSR寄存器bit 10-11如果不为2‘b11即为可读可写的属性 
wire csr_wen = i_EXE_vld & i_SYSTEM & (i_csr_addr[11:10] != 2'b11); 
wire csr_rden = i_EXE_vld & i_SYSTEM;
  • 前两位(CSR[11:10]/机器码的bit 30-31)指示该CSR寄存器是可读可写(00,01或10)还是只读(11)。
  • 接下来两位(CSR[9:8]/机器码的bit 28-29)编码表明可以访问该CSR寄存器的最低特权级别 [2]。

这里,通过wire csr_wen和wire csr_rden 信号的实现,对相应的CSR寄存器进行可读可写属性的区分。

 

3.csr_reg实例

exu_csr模块下由csr_reg模块的例化,很多exu_csr的输出信号由csr_reg模块传递上来,同样,一些exu_csr的输入信号,也继续往下传递到了csr_reg模块。详细代码见下图:



csr_reg csr_reg_U
(
    .sys_clk        ( sys_clk ),//系统时钟

    .i_mret_ena     ( i_mret_ena ),//中断返回使能

    .i_EXE_vld      ( i_EXE_vld ),//执行有效
//中断请求和中断源
    .i_ext_irq      ( i_ext_irq ),
    .i_sft_irq      ( i_sft_irq ),
    .i_tmr_irq      ( i_tmr_irq ),
    .i_irq_src      ( i_irq_src & o_glb_irq),
 
//异常源,异常PC和异常指令  
    .i_exp_src      ( i_exp_src ),
    .i_exe_pc       ( i_exe_pc ),
    .i_ir           ( i_ir ),
//中断PC和中断入口地址
    .o_irq_pc       ( o_irq_pc ),
    .o_mepc         ( o_mepc ),
    
//------------------------------省略与调试相关的信号-----------------------------------

//CSR指令相关信号    
    .i_csr_rden     ( csr_rden ),
    .i_csr_addr     ( i_csr_addr ),
    .i_csr_val      ( reg_csr_val ),
    .i_csr_wen      ( csr_wen ),
    .o_csr_val      ( w_csr_val ),

//由mie,mstatus寄存器输出的中断使能信号
    .o_meie         ( o_meie ),
    .o_msie         ( o_msie ),
    .o_mtie         ( o_mtie ),
    .o_glb_irq      ( o_glb_irq ),

    .rst_n          ( rst_n )//复位
);


 

4.文章参考

[1] D. Patterson and A. Waterman, The RISC-V reader. Berkeley: Strawberry Canyon LLC, 2018.

[2] Riscv.org, 2021. [Online]. Available: https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf. [Accessed: 22- Feb- 2021].

Posted in RISC-V, RISC-V 教案, 应用开发, 教材与教案, 文章

发表评论

相关链接