E203 CSR rtl实现分析
本帖最后由 皋陶 于 2021-3-6 15:58 编辑CSR状态控制寄存器,每个hart都有自己的CSR。对于每个hart,可以配置的状态寄存器是4k。CSR寄存器的功能见:E203 CSR寄存器 CSR实现的rtl代码是e203_exu_csr.v,下面我们分析一下代码实现: 输出输入信号如下:module e203_exu_csr(
input csr_ena, //csr readwrite enable signal from alu,csr读写使能信号,
input csr_wr_en, //csr write enable,csr写使能信号
input csr_rd_en, //csr read enable,csr读使能信号
input csr_idx,//csr address index,csr地址索引
output tm_stop, //time stop, counterstop,输出time counter是否停止
output core_cgstop,//not is used by isa, 0xbfe, self-defined, core clock gating,核心clock gating设置
output tcm_cgstop,//not is used by isa, 0xbfe, Stop TCMclock gating, tight coupled memory,tcm 访问clock gating
output itcm_nohold, //not is used by isa,itcm是否hold上一次的读数据
output mdv_nob2b, //not is used by isa,是否是两个临接的乘除指令
output [`E203_XLEN-1:0] read_csr_dat,//read return data from csr,从csr读取的数据
input[`E203_XLEN-1:0] wbck_csr_dat,//data write back to csr,写数据到csr
input[`E203_HART_ID_W-1:0] core_mhartid, //point mhartid, if read mhartid register, return this value,e203只有一个核,所以为0
//mip register
inputext_irq_r,//external interrupt,是否是外部中断请求
inputsft_irq_r,//software interrupt 是否是软件中断请求
inputtmr_irq_r,//time interrupt, 是否是计时器中断请求
output status_mie_r,//输出状态寄存器的mie值,表示是否使能全局中断
//interrupt enble value for mie
output mtie_r, //机器模式定时器中断是否屏蔽, mie.mtie位
output msie_r, //机器方式软件中断是否屏蔽,
output meie_r, //机器模式外部中断是否屏蔽, mie.meie位//0x7b0 Debug Control and Status //0x7b1 Debug PC //0x7b2 Debug Scratch Register //0x7a0 Trigger selection register
output wr_dcsr_ena , //debug 模式下,写csr 使能
output wr_dpc_ena , //debug模式下,pc写使能
output wr_dscratch_ena, //debug模式下,scratch写使能
input [`E203_XLEN-1:0] dcsr_r , //输入dcsr值
input [`E203_PC_SIZE-1:0] dpc_r , //输入dpc值
input [`E203_XLEN-1:0] dscratch_r,//输入dscratch值
output [`E203_XLEN-1:0] wr_csr_nxt , //=wbck_csr_dat;
inputdbg_mode,//debug模式
inputdbg_stopcycle, //如果在debug模式,且置位这个信号,则停止perf counter计数
output u_mode,//输出当前的模式,如果为那个模式,则这个信号置1
output s_mode,
output h_mode,
output m_mode,
input [`E203_ADDR_SIZE-1:0] cmt_badaddr, //输入异常指令或者异常访存地址到mtval/mbadaddr
input cmt_badaddr_ena,//badaddr 使能信号
input [`E203_PC_SIZE-1:0] cmt_epc, //异常返回地址
input cmt_epc_ena, //epc使能信号
input [`E203_XLEN-1:0] cmt_cause, //异常原因输入
input cmt_cause_ena, //cause使能
input cmt_status_ena, //status使能
input cmt_instret_ena, //instret使能
input cmt_mret_ena, //mret使能
output[`E203_PC_SIZE-1:0]csr_epc_r, //输出epc值,异常地址
output[`E203_PC_SIZE-1:0]csr_dpc_r,//输出dpc,debug模式的pc值
output[`E203_XLEN-1:0] csr_mtvec_r,//输出异常模式基地址
inputclk_aon, //常开时钟信号,不会受clock gating影响
inputclk, //时钟信号
inputrst_n//复位信号
);E203仅支持机器模式,所以priv_mode=2’b11。接着实现mstatus的rtl代码wire wbck_csr_wen = csr_wr_en & csr_ena ;
wire read_csr_ena = csr_rd_en & csr_ena ;
wire priv_mode = u_mode ? 2'b00 :
s_mode ? 2'b01 :
h_mode ? 2'b10 :
m_mode ? 2'b11 :
2'b11;
//0x000 URW ustatus User status register.
// * Since we support the user-level interrupt, hence we need to support UIE
//0x300 MRW mstatus Machine status register.
wire sel_ustatus = (csr_idx == 12'h000);
wire sel_mstatus = (csr_idx == 12'h300);
wire rd_ustatus = sel_ustatus & csr_rd_en;
wire rd_mstatus = sel_mstatus & csr_rd_en;
wire wr_ustatus = sel_ustatus & csr_wr_en;
wire wr_mstatus = sel_mstatus & csr_wr_en;
/////////////////////////////////////////////////////////////////////
// Note: the below implementation only apply to Machine-mode config,
// if other mode is also supported, these logics need to be updated
//////////////////////////
// Implement MPIE field
//
wire status_mpie_r;
// The MPIE Feilds will be updates when: //在中断发生或者中断完成,返回时候,或者直接写该寄存器时候,使能该寄存器
wire status_mpie_ena=
// The CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) |
// The MRET instruction commited
cmt_mret_ena |
// The Trap is taken
cmt_status_ena;
wire status_mpie_nxt =
// See Priv SPEC:
// When a trap is taken from privilege mode y into privilege
// mode x, xPIE is set to the value of xIE;
// So, When the Trap is taken, the MPIE is updated with the current MIE value
cmt_status_ena ? status_mie_r : //进入中断的时候,保存mie的值。
// See Priv SPEC:
// When executing an xRET instruction, supposing xPP holds the value y, xIE
// is set to xPIE; the privilege mode is changed to y;
// xPIE is set to 1;
// So, When the MRET instruction commited, the MPIE is updated with 1
cmt_mret_ena? 1'b1 : //从中断返回时候更新为0
// When the CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) ? wbck_csr_dat : // MPIE is in field 7 of mstatus
status_mpie_r; // Unchanged
sirv_gnrl_dfflr #(1) status_mpie_dfflr (status_mpie_ena, status_mpie_nxt, status_mpie_r, clk, rst_n);
//////////////////////////
// Implement MIE field
//
// The MIE Feilds will be updates same as MPIE
wire status_mie_ena= status_mpie_ena;
wire status_mie_nxt =
// See Priv SPEC:
// When a trap is taken from privilege mode y into privilege
// mode x, xPIE is set to the value of xIE,
// xIE is set to 0;
// So, When the Trap is taken, the MIE is updated with 0
cmt_status_ena ? 1'b0 : //进入中断时候,关闭中断
// See Priv SPEC:
// When executing an xRET instruction, supposing xPP holds the value y, xIE
// is set to xPIE; the privilege mode is changed to y, xPIE is set to 1;
// So, When the MRET instruction commited, the MIE is updated with MPIE
cmt_mret_ena ? status_mpie_r : //从中断返回时候,恢复保存在mpie中的值。
// When the CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) ? wbck_csr_dat : // MIE is in field 3 of mstatus
status_mie_r; // Unchanged
sirv_gnrl_dfflr #(1) status_mie_dfflr (status_mie_ena, status_mie_nxt, status_mie_r, clk, rst_n);
//////////////////////////
// Implement SD field
//
//See Priv SPEC:
// The SD bit is read-only
// And is set when either the FS or XS bits encode a Dirty
// state (i.e., SD=((FS==11) OR (XS==11))).//因为没有浮点单元和协处理器,fs,xs域都为0
wire status_fs_r;
wire status_xs_r;
wire status_sd_r = (status_fs_r == 2'b11) | (status_xs_r == 2'b11);
//////////////////////////
// Implement XS field
//
//See Priv SPEC:
// XS field is read-only
// The XS field represents a summary of all extensions' status
// But in E200 we implement XS exactly same as FS to make it usable by software to
// disable extended accelerators
// If no EAI coprocessor interface configured, the XS is just hardwired to 0
assign status_xs_r = 2'b0;
//////////////////////////
// Implement FS field
//
`ifndef E203_HAS_FPU
// If no FPU configured, the FS is just hardwired to 0
assign status_fs_r = 2'b0;
`endif
//////////////////////////
// Pack to the full mstatus register
//
wire [`E203_XLEN-1:0] status_r;
assign status_r = status_sd_r; //SD
assign status_r = 8'b0; // Reserved
assign status_r = 6'b0; // TSR--MPRV
assign status_r = status_xs_r; // XS
assign status_r = status_fs_r; // FS
assign status_r = 2'b11; // MPP
assign status_r= 2'b0; // Reserved
assign status_r = 1'b0; // SPP
assign status_r = status_mpie_r; // MPIE
assign status_r = 1'b0; // Reserved
assign status_r = 1'b0; // SPIE
assign status_r = 1'b0; // UPIE
assign status_r = status_mie_r; // MIE
assign status_r = 1'b0; // Reserved
assign status_r = 1'b0; // SIE
assign status_r = 1'b0; // UIE
wire [`E203_XLEN-1:0] csr_mstatus = status_r;mie/mip rtl实现//0x004 URW uie User interrupt-enable register.
// * Since we dont delegate interrupt to user mode, hence it is as all 0s
//0x304 MRW mie Machine interrupt-enable register.
wire sel_mie = (csr_idx == 12'h304);
wire rd_mie = sel_mie & csr_rd_en;
wire wr_mie = sel_mie & csr_wr_en;
wire mie_ena = wr_mie & wbck_csr_wen;
wire [`E203_XLEN-1:0] mie_r;
wire [`E203_XLEN-1:0] mie_nxt;
assign mie_nxt = 20'b0;
assign mie_nxt = wbck_csr_dat;//MEIE
assign mie_nxt = 3'b0;
assign mie_nxt[ 7] = wbck_csr_dat[ 7];//MTIE
assign mie_nxt = 3'b0;
assign mie_nxt[ 3] = wbck_csr_dat[ 3];//MSIE
assign mie_nxt = 3'b0;
sirv_gnrl_dfflr #(`E203_XLEN) mie_dfflr (mie_ena, mie_nxt, mie_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mie = mie_r;
assign meie_r = csr_mie;
assign mtie_r = csr_mie[ 7];
assign msie_r = csr_mie[ 3];
//0x044 URW uip User interrupt pending.
//We dont support delegation scheme, so no need to support the uip
//0x344 MRW mip Machine interrupt pending
wire sel_mip = (csr_idx == 12'h344);
wire rd_mip = sel_mip & csr_rd_en;
//wire wr_mip = sel_mip & csr_wr_en;
// The MxIP is read-only
wire meip_r;
wire msip_r;
wire mtip_r;
sirv_gnrl_dffr #(1) meip_dffr (ext_irq_r, meip_r, clk, rst_n);
sirv_gnrl_dffr #(1) msip_dffr (sft_irq_r, msip_r, clk, rst_n);
sirv_gnrl_dffr #(1) mtip_dffr (tmr_irq_r, mtip_r, clk, rst_n);
wire [`E203_XLEN-1:0] ip_r;
assign ip_r = 20'b0;
assign ip_r = meip_r;
assign ip_r = 3'b0;
assign ip_r[ 7] = mtip_r;
assign ip_r = 3'b0;
assign ip_r[ 3] = msip_r;
assign ip_r = 3'b0;
wire [`E203_XLEN-1:0] csr_mip = ip_r;mtvec和mscratch rtl实现//0x005 URW utvec User trap handler base address.
//We dont support user trap, so no utvec needed
//0x305 MRW mtvec Machine trap-handler base address.
wire sel_mtvec = (csr_idx == 12'h305);
wire rd_mtvec = csr_rd_en & sel_mtvec;
`ifdef E203_SUPPORT_MTVEC //{
wire wr_mtvec = sel_mtvec & csr_wr_en;
wire mtvec_ena = (wr_mtvec & wbck_csr_wen);
wire [`E203_XLEN-1:0] mtvec_r;
wire [`E203_XLEN-1:0] mtvec_nxt = wbck_csr_dat;
sirv_gnrl_dfflr #(`E203_XLEN) mtvec_dfflr (mtvec_ena, mtvec_nxt, mtvec_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mtvec = mtvec_r;
`else//}{
// THe vector table base is a configurable parameter, so we dont support writeable to it
wire [`E203_XLEN-1:0] csr_mtvec = `E203_MTVEC_TRAP_BASE;
`endif//}
assign csr_mtvec_r = csr_mtvec;
//0x340 MRW mscratch
wire sel_mscratch = (csr_idx == 12'h340);
wire rd_mscratch = sel_mscratch & csr_rd_en;
`ifdef E203_SUPPORT_MSCRATCH //{
wire wr_mscratch = sel_mscratch & csr_wr_en;
wire mscratch_ena = (wr_mscratch & wbck_csr_wen);
wire [`E203_XLEN-1:0] mscratch_r;
wire [`E203_XLEN-1:0] mscratch_nxt = wbck_csr_dat;
sirv_gnrl_dfflr #(`E203_XLEN) mscratch_dfflr (mscratch_ena, mscratch_nxt, mscratch_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mscratch = mscratch_r;
`else//}{
wire [`E203_XLEN-1:0] csr_mscratch = `E203_XLEN'b0;
`endif//}mcycle/mcycleh/minstret/minstreth/counterstop/cgstop/itcmnohold/mdvnob2b等的rtl实现。// 0xB00 MRW mcycle
// 0xB02 MRW minstret
// 0xB80 MRW mcycleh
// 0xB82 MRW minstreth
wire sel_mcycle = (csr_idx == 12'hB00);
wire sel_mcycleh = (csr_idx == 12'hB80);
wire sel_minstret= (csr_idx == 12'hB02);
wire sel_minstreth = (csr_idx == 12'hB82);
// 0xBFF MRW counterstop
// This register is our self-defined register to stop
// the cycle/time/instret counters to save dynamic powers
wire sel_counterstop = (csr_idx == 12'hBFF);// This address is not used by ISA
// 0xBFE MRW mcgstop
// This register is our self-defined register to disable the
// automaticall clock gating for CPU logics for debugging purpose
wire sel_mcgstop = (csr_idx == 12'hBFE);// This address is not used by ISA
// 0xBFD MRW itcmnohold
// This register is our self-defined register to disble the
// ITCM SRAM output holdup feature, if set, then we assume
// ITCM SRAM output cannot holdup last read value
wire sel_itcmnohold = (csr_idx == 12'hBFD);// This address is not used by ISA
// 0xBF0 MRW mdvnob2b
// This register is our self-defined register to disble the
// Mul/div back2back feature
wire sel_mdvnob2b = (csr_idx == 12'hBF0);// This address is not used by ISA
wire rd_mcycle = csr_rd_en & sel_mcycle ;
wire rd_mcycleh = csr_rd_en & sel_mcycleh;
wire rd_minstret = csr_rd_en & sel_minstret ;
wire rd_minstreth= csr_rd_en & sel_minstreth;
wire rd_itcmnohold = csr_rd_en & sel_itcmnohold;
wire rd_mdvnob2b = csr_rd_en & sel_mdvnob2b;
wire rd_counterstop= csr_rd_en & sel_counterstop;
wire rd_mcgstop = csr_rd_en & sel_mcgstop;
`ifdef E203_SUPPORT_MCYCLE_MINSTRET //{
wire wr_mcycle = csr_wr_en & sel_mcycle ;
wire wr_mcycleh = csr_wr_en & sel_mcycleh;
wire wr_minstret = csr_wr_en & sel_minstret ;
wire wr_minstreth= csr_wr_en & sel_minstreth;
wire wr_itcmnohold = csr_wr_en & sel_itcmnohold ;
wire wr_mdvnob2b = csr_wr_en & sel_mdvnob2b ;
wire wr_counterstop= csr_wr_en & sel_counterstop;
wire wr_mcgstop = csr_wr_en & sel_mcgstop ;
wire mcycle_wr_ena = (wr_mcycle & wbck_csr_wen);
wire mcycleh_wr_ena = (wr_mcycleh & wbck_csr_wen);
wire minstret_wr_ena= (wr_minstret& wbck_csr_wen);
wire minstreth_wr_ena = (wr_minstreth & wbck_csr_wen);
wire itcmnohold_wr_ena= (wr_itcmnohold& wbck_csr_wen);
wire mdvnob2b_wr_ena= (wr_mdvnob2b& wbck_csr_wen);
wire counterstop_wr_ena = (wr_counterstop & wbck_csr_wen);
wire mcgstop_wr_ena = (wr_mcgstop & wbck_csr_wen);
wire [`E203_XLEN-1:0] mcycle_r ;
wire [`E203_XLEN-1:0] mcycleh_r;
wire [`E203_XLEN-1:0] minstret_r ;
wire [`E203_XLEN-1:0] minstreth_r;
wire cy_stop;
wire ir_stop;
wire stop_cycle_in_dbg = dbg_stopcycle & dbg_mode;
wire mcycle_ena = mcycle_wr_ena |
((~cy_stop) & (~stop_cycle_in_dbg) & (1'b1));
wire mcycleh_ena = mcycleh_wr_ena |
((~cy_stop) & (~stop_cycle_in_dbg) & ((mcycle_r == (~(`E203_XLEN'b0)))));
wire minstret_ena= minstret_wr_ena|
((~ir_stop) & (~stop_cycle_in_dbg) & (cmt_instret_ena));
wire minstreth_ena = minstreth_wr_ena |
((~ir_stop) & (~stop_cycle_in_dbg) & ((cmt_instret_ena & (minstret_r == (~(`E203_XLEN'b0))))));
//auto increment
wire [`E203_XLEN-1:0] mcycle_nxt = mcycle_wr_ena ? wbck_csr_dat : (mcycle_r + 1'b1);
wire [`E203_XLEN-1:0] mcycleh_nxt = mcycleh_wr_ena ? wbck_csr_dat : (mcycleh_r + 1'b1);
wire [`E203_XLEN-1:0] minstret_nxt= minstret_wr_ena? wbck_csr_dat : (minstret_r+ 1'b1);
wire [`E203_XLEN-1:0] minstreth_nxt = minstreth_wr_ena ? wbck_csr_dat : (minstreth_r + 1'b1);
//We need to use the always-on clock for this counter
sirv_gnrl_dfflr #(`E203_XLEN) mcycle_dfflr (mcycle_ena, mcycle_nxt, mcycle_r , clk_aon, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) mcycleh_dfflr (mcycleh_ena, mcycleh_nxt, mcycleh_r, clk_aon, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) minstret_dfflr (minstret_ena, minstret_nxt, minstret_r , clk, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) minstreth_dfflr (minstreth_ena, minstreth_nxt, minstreth_r, clk, rst_n);
wire [`E203_XLEN-1:0] counterstop_r;
wire counterstop_ena = counterstop_wr_ena;
wire [`E203_XLEN-1:0] counterstop_nxt = {29'b0,wbck_csr_dat};// Only LSB 3bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) counterstop_dfflr (counterstop_ena, counterstop_nxt, counterstop_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcycle = mcycle_r;
wire [`E203_XLEN-1:0] csr_mcycleh = mcycleh_r;
wire [`E203_XLEN-1:0] csr_minstret= minstret_r;
wire [`E203_XLEN-1:0] csr_minstreth = minstreth_r;
wire [`E203_XLEN-1:0] csr_counterstop = counterstop_r;
`else//}{
wire [`E203_XLEN-1:0] csr_mcycle = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_mcycleh = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_minstret= `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_minstreth = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_counterstop = `E203_XLEN'b0;
`endif//}
wire [`E203_XLEN-1:0] itcmnohold_r;
wire itcmnohold_ena = itcmnohold_wr_ena;
wire [`E203_XLEN-1:0] itcmnohold_nxt = {31'b0,wbck_csr_dat};// Only LSB 1bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) itcmnohold_dfflr (itcmnohold_ena, itcmnohold_nxt, itcmnohold_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_itcmnohold= itcmnohold_r;
wire [`E203_XLEN-1:0] mdvnob2b_r;
wire mdvnob2b_ena = mdvnob2b_wr_ena;
wire [`E203_XLEN-1:0] mdvnob2b_nxt = {31'b0,wbck_csr_dat};// Only LSB 1bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) mdvnob2b_dfflr (mdvnob2b_ena, mdvnob2b_nxt, mdvnob2b_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mdvnob2b= mdvnob2b_r;
assign cy_stop = counterstop_r;// Stop CYCLE counter
assign tm_stop = counterstop_r;// Stop TIME counter
assign ir_stop = counterstop_r;// Stop INSTRET counter,instruction number counter
assign itcm_nohold = itcmnohold_r;// ITCM no-hold up feature
assign mdv_nob2b = mdvnob2b_r;// Mul/Div no back2back feature
wire [`E203_XLEN-1:0] mcgstop_r;
wire mcgstop_ena = mcgstop_wr_ena;
wire [`E203_XLEN-1:0] mcgstop_nxt = {30'b0,wbck_csr_dat};// Only LSB 2bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) mcgstop_dfflr (mcgstop_ena, mcgstop_nxt, mcgstop_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcgstop = mcgstop_r;
assign core_cgstop = mcgstop_r;// Stop Core clock gating
assign tcm_cgstop = mcgstop_r;// Stop TCMclock gatingmepc/mcause/mbadaddr/misa等的rtl实现。//0x041 URW uepc User exception program counter.
//We dont support user trap, so no uepc needed
//0x341 MRW mepc Machine exception program counter.
wire sel_mepc = (csr_idx == 12'h341);
wire rd_mepc = sel_mepc & csr_rd_en;
wire wr_mepc = sel_mepc & csr_wr_en;
wire epc_ena = (wr_mepc & wbck_csr_wen) | cmt_epc_ena;
wire [`E203_PC_SIZE-1:0] epc_r;
wire [`E203_PC_SIZE-1:0] epc_nxt;
assign epc_nxt[`E203_PC_SIZE-1:1] = cmt_epc_ena ? cmt_epc[`E203_PC_SIZE-1:1] : wbck_csr_dat[`E203_PC_SIZE-1:1];
assign epc_nxt = 1'b0;// Must not hold PC which will generate the misalign exception according to ISA
sirv_gnrl_dfflr #(`E203_PC_SIZE) epc_dfflr (epc_ena, epc_nxt, epc_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mepc;
wire dummy_0;
assign {dummy_0,csr_mepc} = {{`E203_XLEN+1-`E203_PC_SIZE{1'b0}},epc_r};
assign csr_epc_r = csr_mepc;
//0x042 URW ucause User trap cause.
//We dont support user trap, so no ucause needed
//0x342 MRW mcause Machine trap cause.
wire sel_mcause = (csr_idx == 12'h342);
wire rd_mcause = sel_mcause & csr_rd_en;
wire wr_mcause = sel_mcause & csr_wr_en;
wire cause_ena = (wr_mcause & wbck_csr_wen) | cmt_cause_ena;
wire [`E203_XLEN-1:0] cause_r;
wire [`E203_XLEN-1:0] cause_nxt;
assign cause_nxt= cmt_cause_ena ? cmt_cause : wbck_csr_dat;
assign cause_nxt = 27'b0;
assign cause_nxt = cmt_cause_ena ? cmt_cause : wbck_csr_dat;
sirv_gnrl_dfflr #(`E203_XLEN) cause_dfflr (cause_ena, cause_nxt, cause_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcause = cause_r;
//0x043 URW ubadaddr User bad address.
//We dont support user trap, so no ubadaddr needed
//0x343 MRW mbadaddr Machine bad address.
wire sel_mbadaddr = (csr_idx == 12'h343);
wire rd_mbadaddr = sel_mbadaddr & csr_rd_en;
wire wr_mbadaddr = sel_mbadaddr & csr_wr_en;
wire cmt_trap_badaddr_ena = cmt_badaddr_ena;
wire badaddr_ena = (wr_mbadaddr & wbck_csr_wen) | cmt_trap_badaddr_ena;
wire [`E203_ADDR_SIZE-1:0] badaddr_r;
wire [`E203_ADDR_SIZE-1:0] badaddr_nxt;
assign badaddr_nxt = cmt_trap_badaddr_ena ? cmt_badaddr : wbck_csr_dat[`E203_ADDR_SIZE-1:0];
sirv_gnrl_dfflr #(`E203_ADDR_SIZE) badaddr_dfflr (badaddr_ena, badaddr_nxt, badaddr_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mbadaddr;
wire dummy_1;
assign {dummy_1,csr_mbadaddr} = {{`E203_XLEN+1-`E203_ADDR_SIZE{1'b0}},badaddr_r};
// We dont support the delegation scheme, so no need to implement
// delegete registers
//0x301 MRW misa ISA and extensions
wire sel_misa = (csr_idx == 12'h301);
wire rd_misa = sel_misa & csr_rd_en;
// Only implemented the M mode, IMC or EMC
wire [`E203_XLEN-1:0] csr_misa = {
2'b1
,4'b0 //WIRI
,1'b0 // 25 Z Reserved
,1'b0 // 24 Y Reserved
,1'b0 // 23 X Non-standard extensions present
,1'b0 // 22 W Reserved
,1'b0 // 21 V Tentatively reserved for Vector extension 20 U User mode implemented
,1'b0 // 20 U User mode implemented
,1'b0 // 19 T Tentatively reserved for Transactional Memory extension
,1'b0 // 18 S Supervisor mode implemented
,1'b0 // 17 R Reserved
,1'b0 // 16 Q Quad-precision floating-point extension
,1'b0 // 15 P Tentatively reserved for Packed-SIMD extension
,1'b0 // 14 O Reserved
,1'b0 // 13 N User-level interrupts supported
,1'b1 // 12 M Integer Multiply/Divide extension
,1'b0 // 11 L Tentatively reserved for Decimal Floating-Point extension
,1'b0 // 10 K Reserved
,1'b0 // 9 J Reserved
`ifdef E203_RFREG_NUM_IS_32
,1'b1 // 8 I RV32I/64I/128I base ISA
`else
,1'b0
`endif
,1'b0 // 7 H Hypervisor mode implemented
,1'b0 // 6 G Additional standard extensions present
`ifndef E203_HAS_FPU//{
,1'b0 // 5 F Single-precision floating-point extension
`endif//
`ifdef E203_RFREG_NUM_IS_32
,1'b0 // 4 E RV32E base ISA
`else
,1'b1 //
`endif
`ifndef E203_HAS_FPU//{
,1'b0 // 3 D Double-precision floating-point extension
`endif//
,1'b1 // 2 C Compressed extension
,1'b0 // 1 B Tentatively reserved for Bit operations extension
`ifdef E203_SUPPORT_AMO//{
,1'b1 // 0 A Atomic extension
`endif//E203_SUPPORT_AMO}
`ifndef E203_SUPPORT_AMO//{
,1'b0 // 0 A Atomic extension
`endif//}
};
//Machine Information Registers
//0xF11 MRO mvendorid Vendor ID.
//0xF12 MRO marchid Architecture ID.
//0xF13 MRO mimpid Implementation ID.
//0xF14 MRO mhartid Hardware thread ID.
wire [`E203_XLEN-1:0] csr_mvendorid = `E203_XLEN'h`E203_MVENDORID;
wire [`E203_XLEN-1:0] csr_marchid = `E203_XLEN'h`E203_MARCHID;
wire [`E203_XLEN-1:0] csr_mimpid = `E203_XLEN'h`E203_MIMPID ;
wire [`E203_XLEN-1:0] csr_mhartid = {{`E203_XLEN-`E203_HART_ID_W{1'b0}},core_mhartid};
wire rd_mvendorid = csr_rd_en & (csr_idx == 12'hF11);
wire rd_marchid = csr_rd_en & (csr_idx == 12'hF12);
wire rd_mimpid = csr_rd_en & (csr_idx == 12'hF13);
wire rd_mhartid = csr_rd_en & (csr_idx == 12'hF14);
//0x7b0 Debug Control and Status
//0x7b1 Debug PC
//0x7b2 Debug Scratch Register
//0x7a0 Trigger selection register
wire sel_dcsr = (csr_idx == 12'h7b0);
wire sel_dpc = (csr_idx == 12'h7b1);
wire sel_dscratch = (csr_idx == 12'h7b2);
wire rd_dcsr = dbg_mode & csr_rd_en & sel_dcsr ;
wire rd_dpc = dbg_mode & csr_rd_en & sel_dpc ;
wire rd_dscratch = dbg_mode & csr_rd_en & sel_dscratch;
assign wr_dcsr_ena = dbg_mode & csr_wr_en & sel_dcsr ;
assign wr_dpc_ena = dbg_mode & csr_wr_en & sel_dpc ;
assign wr_dscratch_ena = dbg_mode & csr_wr_en & sel_dscratch;
assign wr_csr_nxt = wbck_csr_dat;
wire [`E203_XLEN-1:0] csr_dcsr = dcsr_r ;
`ifdef E203_PC_SIZE_IS_16
wire [`E203_XLEN-1:0] csr_dpc = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
`endif
`ifdef E203_PC_SIZE_IS_24
wire [`E203_XLEN-1:0] csr_dpc = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
`endif
`ifdef E203_PC_SIZE_IS_32
wire [`E203_XLEN-1:0] csr_dpc = dpc_r ;
`endif
wire [`E203_XLEN-1:0] csr_dscratch = dscratch_r;
assign csr_dpc_r = dpc_r;下面是我的写的一个testbench,`include "e203_defines.v"
module e203_exu_csr_tb;
reg csr_ena; //csr readwrite enable signal from alu
reg csr_wr_en; //csr write enable
reg csr_rd_en; //csr read enable
reg csr_idx;//csr address index
wire tm_stop;
wire core_cgstop;
wire tcm_cgstop;
wire itcm_nohold;
wire mdv_nob2b;
wire [`E203_XLEN-1:0] read_csr_dat;
reg[`E203_XLEN-1:0] wbck_csr_dat;
reg[`E203_HART_ID_W-1:0] core_mhartid;
regext_irq_r;
regsft_irq_r;
regtmr_irq_r;
wire status_mie_r;
wire mtie_r;
wire msie_r;
wire meie_r;
wire wr_dcsr_ena ;
wire wr_dpc_ena ;
wire wr_dscratch_ena;
reg [`E203_XLEN-1:0] dcsr_r ;
reg [`E203_PC_SIZE-1:0] dpc_r ;
reg [`E203_XLEN-1:0] dscratch_r;
wire [`E203_XLEN-1:0] wr_csr_nxt ;
regdbg_mode;
regdbg_stopcycle;
wire u_mode;
wire s_mode;
wire h_mode;
wire m_mode;
reg [`E203_ADDR_SIZE-1:0] cmt_badaddr;
reg cmt_badaddr_ena;
reg [`E203_PC_SIZE-1:0] cmt_epc;
reg cmt_epc_ena;
reg [`E203_XLEN-1:0] cmt_cause;
reg cmt_cause_ena;
reg cmt_status_ena;
reg cmt_instret_ena;
reg cmt_mret_ena;
wire[`E203_PC_SIZE-1:0]csr_epc_r;
wire[`E203_PC_SIZE-1:0]csr_dpc_r;
wire[`E203_XLEN-1:0] csr_mtvec_r;
regclk=0;
regrst_n;
e203_exu_csrmycsr(
.csr_ena(csr_ena),
.csr_wr_en(csr_wr_en),
.csr_rd_en(csr_rd_en),
.csr_idx(csr_idx),
.tm_stop(tm_stop),
.core_cgstop(core_cgstop),
.tcm_cgstop(tcm_cgstop),
.itcm_nohold(itcm_nohold),
.mdv_nob2b(mdv_nob2b),
.read_csr_dat(read_csr_dat),
.wbck_csr_dat(wbck_csr_dat),
.core_mhartid(core_mhartid),
.ext_irq_r(ext_irq_r),
.sft_irq_r(sft_irq_r),
.tmr_irq_r(tmr_irq_r),
.status_mie_r(status_mie_r),
.mtie_r(mtie_r),
.msie_r(msie_r),
.meie_r(meie_r),
.wr_dcsr_ena(wr_dcsr_ena),
.wr_dpc_ena(wr_dpc_ena),
.wr_dscratch_ena(wr_dscratch_ena),
.dcsr_r(dcsr_r),
.dpc_r(dpc_r),
.dscratch_r(dscratch_r),
.wr_csr_nxt(wr_csr_nxt),
.dbg_mode(dbg_mode),
.dbg_stopcycle(dbg_stopcycle),
.u_mode(u_mode),
.s_mode(s_mode),
.h_mode(h_mode),
.m_mode(m_mode),
.cmt_badaddr(cmt_badaddr),
.cmt_badaddr_ena(cmt_badaddr_ena),
.cmt_epc(cmt_epc),
.cmt_epc_ena(cmt_epc_ena),
.cmt_cause(cmt_cause),
.cmt_cause_ena(cmt_cause_ena),
.cmt_status_ena(cmt_status_ena),
.cmt_instret_ena(cmt_instret_ena),
.cmt_mret_ena(cmt_mret_ena),
.csr_epc_r(csr_epc_r),
.csr_dpc_r(csr_dpc_r),
.csr_mtvec_r(csr_mtvec_r),
.clk_aon(clk),
.clk(clk),
.rst_n(rst_n)
);
always #10 clk=~clk;
initial
begin
rst_n = 1'b1;
#20
rst_n= 1'b0;
#20
rst_n=1'b1;
csr_ena = 1'b1;
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
csr_idx = 11'h300; //mstatus
wbck_csr_dat = 32'h0001f888;
core_mhartid = `E203_HART_ID_W'h0;
ext_irq_r = 1'b0;
sft_irq_r = 1'b0;
tmr_irq_r = 1'b0;
dcsr_r = `E203_XLEN'h5;
dpc_r =`E203_PC_SIZE'h5;
dscratch_r =`E203_XLEN'h5;
dbg_mode = 1'b0;
dbg_stopcycle= 1'b0;
cmt_badaddr=`E203_ADDR_SIZE'h4;
cmt_badaddr_ena = 1'b0;
cmt_epc=`E203_PC_SIZE'h4;
cmt_epc_ena = 1'b0;
cmt_cause=`E203_XLEN'h4;
cmt_cause_ena = 1'b0;
cmt_status_ena = 1'b0;
cmt_instret_ena = 1'b0;
cmt_mret_ena = 1'b0;
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h80;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h888;
csr_idx = 12'h304; //mie
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h800;
csr_idx = 12'h344; //mip
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'hff;
csr_idx = 12'h305; //mtvec
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'hff00;
csr_idx = 12'h340; //mscratch
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h7;
csr_idx = 12'hbff; //counterstop
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h3;
csr_idx = 12'hbfe; //mcgstop
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h1;
csr_idx = 12'hbfd; //itcmnohold
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h1;
csr_idx = 12'hbf0; //mdvnob2b
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h1;
csr_idx = 12'h341; //mepc
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'haa;
csr_idx = 12'h342; //mcasue
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'hffff;
csr_idx = 12'h343; //mbadaddr/mtval
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'h301; //misa
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf11; //mvendorid
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf12; //marchid
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf13; //mimpid
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf14; //mhartid
#100
$finish;
end
//initial
// $monitor($time,,,"clk=%b,i_instr=0x%h,i_pc=%h",clk,i_instr,i_pc);
initial
begin
//$dumpfile("dump.vcd");
//$dumpvars;
$fsdbDumpfile("dump.fsdb");
$fsdbDumpvars("+all");
end
endmoduleMakefile# VCS flags, if want to use dump fsdb in verilog file, need to add args -fsdb, otherwise will be compiled fail
VCS_FLAGS = -sverilog -full64 -fsdb -debug_all +v2k -timescale=1ns/1ns +define+DISABLE_SV_ASSERTION
# Source files
SRC_FILES = e203_exu_csr.v \
sirv_gnrl_dffs.v \
sirv_gnrl_xchecker.v \
e203_exu_csr_tb.v \
# Source directories
INCDIR = +incdir+./
all:
vcs $(VCS_FLAGS) $(INCDIR) $(SRC_FILES)
clean:
rm -rf ./csrc *.daidir ./csrc *.log *.vpd *.vdb simv* *.key *race.out* *vcd *fsdb
debug:
verdi -sv -ssf dump.fsdb -f verdi.f &完
页:
[1]