Menu Close

RISC-V CSR Read and Write Control Module(2)csr_reg Module

The code used in this article is based on FII RISC-V V2.01 (without JTAG and bus). For the upper-level module of csr_reg, see RISC-V CSR read-write control (1) exu_csr module , here will mainly introduce the csr_reg module, and continue the study of CSR read-write control.

Related reference articles:

RISC-V teaching plan

1. Input and output

    input sys_clk,              //system clock
//--------------- Debug related signals are also omitted here---------------
    input i_EXE_vld,            //execute valid

    input i_ext_irq,            //External interrupt request
    input i_sft_irq,            //software interrupt request
    input i_tmr_irq,            //Timer interrupt request

    input i_irq_src,            //interrupt source
    input i_exp_src,            //exception source
    input [ 31: 0 ] i_exe_pc,   //executed program counter
    input [ 31: 0 ] i_ir,       //instruction register

    output [ 31: 0 ] o_mepc,    //PC that needs to be executed after the interrupt returns
    output [ 31: 0 ] o_irq_pc,  //Interrupt entry address

    input i_csr_rden,           //CSR register can be read
    input [ 11: 0 ] i_csr_addr, //csr instruction (one of 6)
    input [ 31: 0 ] i_csr_val,  //The value written by the CSR instruction to the CSR register
    input i_csr_wen,            //CSR register can be written
    output [ 31: 0 ] o_csr_val, //The value read from the CSR register

    output o_meie,              //external interrupt enable
    output o_msie,              //software interrupt enable
    output o_mtie,              //timer interrupt enable
    output o_glb_irq,           //Global interrupt enable

    input rst_n                 //reset


As can be seen from the above code, the signal of the csr_reg module is basically similar to the signal in exu_csr, except that the readable/writable signal that defines the CSR register attribute in the exu_csr module is passed in, and the CSR instruction is directly written to the CSR register The value of is passed in, and the operation of the CSR instruction is not performed.


2. Execute

In addition to the declaration and transmission of some signals, the main body of the code also reads the CSR register. The code is as follows:

assign o_csr_val = csr_reh_sel; //The value read by the CSR register

always@( * ) //CSR read
case ( i_csr_addr & { 12{ i_csr_rden } } )
    12'h300: csr_reh_sel = w_mstatus;
    12'h301: csr_reh_sel = w_misa;
    12'h304: csr_reh_sel = w_mie;
    12'h305: csr_reh_sel = w_mtvec;
    12'h306: csr_reh_sel = w_mcounteren;
    12'hf11: csr_reh_sel = w_mvendorid;
    12'hf12: csr_reh_sel = w_marchid;
    12'hf13: csr_reh_sel = w_mimpid;
    12'hf14: csr_reh_sel = w_mhartid;
    12'h340: csr_reh_sel = w_mscratch;
    12'h341: csr_reh_sel = o_mepc;
    12'h342: csr_reh_sel = w_mcause;
    12'h343: csr_reh_sel = w_mtval;
    12'h344: csr_reh_sel = w_mip;
    12'hb00: csr_reh_sel = w_mcycle_l;
    12'hb80: csr_reh_sel = w_mcycle_h;
    12'hb02: csr_reh_sel = w_minstret_l;
    12'hb82: csr_reh_sel = w_minstret_h;
    12'h7b0: csr_reh_sel = i_dcsr;
    12'h7b1: csr_reh_sel = i_dpc;
    12'h7b2: csr_reh_sel = i_dscratch;
    default: csr_reh_sel = 32'b0;


It can be seen that by judging the index of the CSR address and the readable attribute of the CSR, the values ​​of different CSR registers are read out in different cases.

Note: The case selection here, although 21 are listed, in each CSR instruction read, only one exact CSR register is read, that is, a CSR instruction will only be based on the required address. Only one case is executed at a time.

case ( i_csr_addr & { 12{ i_csr_rden } } )

In this way of writing, i_csr_rden of { 12{ i_csr_rden } } is originally a 1-bit signal, and it is expanded to 12 bits here to facilitate the operation with the CSR address. E.g:

  • If the CSR register is readable, i_csr_rden is 1, { 12{ i_csr_rden } } is 12’b1111_1111_1111, and the value obtained by adding i_csr_addr is i_csr_addr itself , starting case selection;
  • If the CSR register is not readable, i_csr_rden is 0, { 12{ i_csr_rden } } is 12’b00000_0000_0000, and the value obtained by adding i_csr_addr is 0, any case is not satisfied, jump to the default statement, that is, set the CSR register The read value is assigned 0.


assign o_glb_irq = w_mstatus[3]; //Global interrupt enable

wire [ 31: 0 ] vect_pc = {w_mtvec[ 31: 2 ], 2'b00} + {w_mcause[ 3: 0 ], 2'b00}; // Mode1, vector address = base + 4 X cause

assign o_irq_pc = ( w_mtvec[ 1: 0 ] == 0 ) ? {w_mtvec[ 31: 2 ], 2'b00}://select interrupt entry address
                  ( w_mtvec[ 1 : 0 ] == 1 ) ? vect_pc : o_irq_pc;

wire status_ena = w_mstatus[3] & ( o_meie | o_mtie | o_msie ) & i_irq_src;//Interrupt


The above code is about outputting the global interrupt enable o_glb_irq and passing the ststus_ena interrupt generation signal to the mstatus register for the judgment of MPIE and MIE bits.

o_irq_pc is the entry address of the interrupt, and the output Mode is determined by bits 0-1 of w_mtvec

  • When Mode is 1, the interrupt entry address is the vector address, which is composed of base base address + 4 X cause (determined by mcause register)
  • When Mode is 0, the interrupt entry is directly assigned to the base base address
  • If Mode is equal to 2 or 3, the value is reserved, currently undefined

Note: There is only a 30-bit base address in bits 2-31 of the mtvec register, because the default interrupt jump addresses are all 4-byte aligned [1]. So the real interrupt entry address needs to be shifted left by 2 bits, which is {w_mtvec[ 31: 2 ], 2’b00 } in the above code .


3. CSR register example


The instance under the csr_reg module consists of all implemented CSR registers, with the following register modules:

  • csr_mtvec
  • csr_mstatus
  • csr_mtval
  • csr_mepc
  • csr_mcause
  • csr_mie
  • csr_mip
  • csr_misa
  • csr_mcounteren
  • csr_mid: includes mvendorid, marchid, mimpid and mhartid
  • csr_scratch: mscratch register
  • csr_mcycle: 32-bit registers including low-order and high-order bits, forming a total of 64 bits
  • csr_minstret: 32-bit registers including low-order and high-order bits, forming a total of 64 bits
  • dug_csr: includes some debugging-related signals

The specific implementation will be introduced later.


4. Article references

[1] , 2021. [Online]. Available: [Accessed: 22- Feb- 2021] .

Posted in FPGA, RISC-V, RISC-V Textbook, Textbook and Training Project

Related Articles

Leave a Reply

Your email address will not be published.

Leave the field below empty!