1. Input/Output
Related reference articles:
RISC-V teaching plan
The code used in this article is based on FII RISC-V V2.01 (without JTAG and bus). For a review of the six CSR instructions, see the article RISC-V CSR register (1) CSR introduction and CSR instructions . This article will start with the exu_csr module to introduce how to control the reading and writing of CSR in the RISC-V CPU.
The following are the more important input and output signals, and the corresponding explanations are marked in the code segment.
input sys_clk, //system clock input i_SYSTEM, //opcode of CSR instruction input [ 31: 0 ] i_rs1_val, // the value of rs1 input [ 4: 0 ] i_rd_idx, //index of rd input [ 5: 0 ] i_csr_instr, // csr instruction (one of 6) input [ 11: 0 ] i_csr_addr, // 12-bit address of index CSR register input [ 31: 0 ] i_csr_imm, //immediate number after zero extension 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_irq_pc, //Interrupt entry address output [ 31: 0 ] o_mepc, //PC that needs to be executed after the interrupt returns input i_mret_ena, //Interrupt return enable //-----------------------------Omit debug-related signals------------ ----------------------- input i_EXE_vld, //execute valid output [ 31: 0 ] o_wr_csr_nxt, //The value written to the CSR register output o_rd_wen, //CSR register read enable for write back output [ 4: 0 ] o_wb_rd_idx, // write back index output [ 31: 0 ] o_wb_data, //write back data 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
It can be seen that the above can be mainly divided into interrupt-related signals and CSR instruction execution-related signals. Similar to the exu_alu module, the execution of the CSR instruction also requires register-related indices and values. Interrupt-related signals mainly include the interrupt/abnormal request signal input by the high-level module, and the interrupt enable and PC signal output by the bottom module.
2. Execute
The main part of the code is the 6 instructions of CSR. The explanation of the code is as follows:
// CSR instructions are arranged as follows // i_csr_instr = {rv32i_csrrci, rv32i_csrrsi, rv32i_csrrwi, // rv32i_csrrc, rv32i_csrrs, rv32i_csrrw}; // write the value to the register always @ ( * ) begin reg_csr_val <= 32'b0;//initialization 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]/ If bit 30-31 of machine code is not 2'b11, it is a readable and writable attribute wire csr_wen = i_EXE_vld & i_SYSTEM & (i_csr_addr[11:10] != 2'b11); wire csr_rden = i_EXE_vld & i_SYSTEM;
The above code uses case selection to distinguish the CSR instructions and the realization of the write register. Example with the following code
6’h02:
begin
reg_csr_val <= i_rs1_val | w_csr_val; //rv32i_csrrs
end
The CSR instruction corresponding to bit 2 of i_csr_instr is CSRRS rd, csr, rs1. t = CSRs[csr]; CSRs[csr] = t | x[rs1]; x[rd] = t
This instruction reads and assigns the value in the CSR register to the rd register, and writes the result of bitwise OR (bitwise OR) between the value in the CSR register and the value in the register rs1 into the CSR register.
The machine code of its instructions is shown in Figure 1. The function to implement CSR setting here is reg_csr_val <= i_rs1_val | w_csr_val;
Another part of the CSR read register function will be implemented in the csr_reg module, which will be explained later when this module is mentioned.
Figure 1 CSRRS machine code format [1]
In the RISC-V CSR register (1) CSR introduction and CSR instructions mentioned,
All CSR instructions can only operate on one CSR register at a time, and its machine code is shown in Figure 1. It can be seen that the CSR instruction is similar to the I-type instruction. Although there is also a 12-bit immediate field, bits 20-31 of the machine code are actually used to index the address of the corresponding CSR register. So in theory, a total of 2^12 = 4096-bit CSR registers can be implemented.
By convention, the upper bits of the CSR address (CSR[11:8]/bits 28-31 of machine code) are used to encode the read and write accessibility of the CSR according to the privilege level.
//CSR register bit 10-11 is readable and writable if it is not 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;
- The first two bits (CSR[11:10]/bits 30-31 of machine code) indicate whether this CSR register is readable and writable (00, 01 or 10) or read-only (11).
- The next two bits (CSR[9:8]/bits 28-29 of machine code) are encoded to indicate the lowest privilege level [2] that can access this CSR register.
Here, through the realization of the wire csr_wen and wire csr_rden signals, the readable and writable attributes of the corresponding CSR registers are distinguished.
3. csr_reg instance
The exu_csr module is instantiated by the csr_reg module. Many output signals of exu_csr are passed up by the csr_reg module. Similarly, some input signals of exu_csr are also passed down to the csr_reg module. The detailed code is shown in the following figure:
csr_reg csr_reg_U ( .sys_clk ( sys_clk ), //system clock .i_mret_ena ( i_mret_ena ),//interrupt return enable .i_EXE_vld ( i_EXE_vld ),//The execution is valid //Interrupt request and interrupt source .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), //Exception source, exception PC and exception instruction .i_exp_src ( i_exp_src ), .i_exe_pc ( i_exe_pc ), .i_ir ( i_ir ), //Interrupt PC and interrupt entry address .o_irq_pc ( o_irq_pc ), .o_mepc ( o_mepc ), //CSR instruction related signals .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 ), //Interrupt enable signal output by mie, mstatus registers .o_meie ( o_meie ), .o_msie ( o_msie ), .o_mtie ( o_mtie ), .o_glb_irq ( o_glb_irq ), .rst_n ( rst_n )//reset );
4. Article references
[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] .