查看: 2620|回复: 0
收起左侧

E203 CSR rtl实现分析

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2021-3-6 15:59:07 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2021-3-6 15:58 编辑

    CSR状态控制寄存器,每个hart都有自己的CSR。对于每个hart,可以配置的状态寄存器是4k。CSR寄存器的功能见:E203 CSR寄存器
          CSR实现的rtl代码是e203_exu_csr.v,下面我们分析一下代码实现:
          输出输入信号如下:
    1. module e203_exu_csr(

    2.   input csr_ena, //csr readwrite enable signal from alu,csr读写使能信号,
    3.   input csr_wr_en, //csr write enable,csr写使能信号
    4.   input csr_rd_en, //csr read enable,csr读使能信号
    5.   input [11:0] csr_idx,//csr address index,csr地址索引

    6.   output tm_stop, //time stop, counterstop[1],输出time counter是否停止
    7.   output core_cgstop,//not is used by isa, 0xbfe, self-defined, core clock gating,核心clock gating设置
    8.   output tcm_cgstop,//not is used by isa, 0xbfe, Stop TCM  clock gating, tight coupled memory,tcm 访问clock gating
    9.   output itcm_nohold, //not is used by isa,itcm是否hold上一次的读数据
    10.   output mdv_nob2b, //not is used by isa,是否是两个临接的乘除指令


    11.   output [`E203_XLEN-1:0] read_csr_dat,//read return data from csr,从csr读取的数据
    12.   input  [`E203_XLEN-1:0] wbck_csr_dat,//data write back to csr,写数据到csr

    13.   input  [`E203_HART_ID_W-1:0] core_mhartid, //point mhartid, if read mhartid register, return this value,e203只有一个核,所以为0
    14.   //mip register
    15.   input  ext_irq_r,//external interrupt,是否是外部中断请求
    16.   input  sft_irq_r,//software interrupt 是否是软件中断请求
    17.   input  tmr_irq_r,//time interrupt, 是否是计时器中断请求

    18.   output status_mie_r,//输出状态寄存器的mie值,表示是否使能全局中断
    19.   //interrupt enble value for mie
    20.   output mtie_r, //机器模式定时器中断是否屏蔽, mie.mtie位
    21.   output msie_r, //机器方式软件中断是否屏蔽,
    22.   output meie_r,   //机器模式外部中断是否屏蔽, mie.meie位//0x7b0 Debug Control and Status //0x7b1 Debug PC //0x7b2 Debug Scratch Register //0x7a0 Trigger selection register
    23.   output wr_dcsr_ena    , //debug 模式下,写csr 使能
    24.   output wr_dpc_ena     , //debug模式下,pc写使能
    25.   output wr_dscratch_ena, //debug模式下,scratch写使能


    26.   input [`E203_XLEN-1:0] dcsr_r    , //输入dcsr值
    27.   input [`E203_PC_SIZE-1:0] dpc_r     , //输入dpc值
    28.   input [`E203_XLEN-1:0] dscratch_r,  //输入dscratch值

    29.   output [`E203_XLEN-1:0] wr_csr_nxt    , //=wbck_csr_dat;

    30.   input  dbg_mode,  //debug模式
    31.   input  dbg_stopcycle, //如果在debug模式,且置位这个信号,则停止perf counter计数

    32.   output u_mode,  //输出当前的模式,如果为那个模式,则这个信号置1
    33.   output s_mode,
    34.   output h_mode,
    35.   output m_mode,

    36.   input [`E203_ADDR_SIZE-1:0] cmt_badaddr, //输入异常指令或者异常访存地址到mtval/mbadaddr
    37.   input cmt_badaddr_ena,  //badaddr 使能信号
    38.   input [`E203_PC_SIZE-1:0] cmt_epc, //异常返回地址
    39.   input cmt_epc_ena,      //epc使能信号
    40.   input [`E203_XLEN-1:0] cmt_cause, //异常原因输入
    41.   input cmt_cause_ena,    //cause使能
    42.   input cmt_status_ena,    //status使能
    43.   input cmt_instret_ena,    //instret使能

    44.   input                      cmt_mret_ena, //mret使能
    45.   output[`E203_PC_SIZE-1:0]  csr_epc_r, //输出epc值,异常地址
    46.   output[`E203_PC_SIZE-1:0]  csr_dpc_r,  //输出dpc,debug模式的pc值
    47.   output[`E203_XLEN-1:0]     csr_mtvec_r,  //输出异常模式基地址


    48.   input  clk_aon, //常开时钟信号,不会受clock gating影响
    49.   input  clk,   //时钟信号
    50.   input  rst_n  //复位信号

    51.   );
    复制代码
    E203仅支持机器模式,所以priv_mode=2’b11。接着实现mstatus的rtl代码
    1. wire wbck_csr_wen = csr_wr_en & csr_ena ;
    2. wire read_csr_ena = csr_rd_en & csr_ena ;

    3. wire [1:0] priv_mode = u_mode ? 2'b00 :
    4.                        s_mode ? 2'b01 :
    5.                        h_mode ? 2'b10 :
    6.                        m_mode ? 2'b11 :
    7.                                 2'b11;

    8. //0x000 URW ustatus User status register.
    9. //    * Since we support the user-level interrupt, hence we need to support UIE
    10. //0x300 MRW mstatus Machine status register.
    11. wire sel_ustatus = (csr_idx == 12'h000);
    12. wire sel_mstatus = (csr_idx == 12'h300);

    13. wire rd_ustatus = sel_ustatus & csr_rd_en;
    14. wire rd_mstatus = sel_mstatus & csr_rd_en;
    15. wire wr_ustatus = sel_ustatus & csr_wr_en;
    16. wire wr_mstatus = sel_mstatus & csr_wr_en;


    17. /////////////////////////////////////////////////////////////////////
    18. // Note: the below implementation only apply to Machine-mode config,
    19. //       if other mode is also supported, these logics need to be updated

    20. //////////////////////////
    21. // Implement MPIE field
    22. //
    23. wire status_mpie_r;
    24.     // The MPIE Feilds will be updates when:     //在中断发生或者中断完成,返回时候,或者直接写该寄存器时候,使能该寄存器
    25. wire status_mpie_ena  =
    26.         // The CSR is written by CSR instructions
    27.         (wr_mstatus & wbck_csr_wen) |
    28.         // The MRET instruction commited
    29.         cmt_mret_ena |
    30.         // The Trap is taken
    31.         cmt_status_ena;

    32. wire status_mpie_nxt    =
    33.     //   See Priv SPEC:
    34.     //       When a trap is taken from privilege mode y into privilege
    35.     //       mode x, xPIE is set to the value of xIE;
    36.     // So, When the Trap is taken, the MPIE is updated with the current MIE value
    37.     cmt_status_ena ? status_mie_r : //进入中断的时候,保存mie的值。
    38.     //   See Priv SPEC:
    39.     //       When executing an xRET instruction, supposing xPP holds the value y, xIE
    40.     //       is set to xPIE; the privilege mode is changed to y;
    41.     //       xPIE is set to 1;
    42.     // So, When the MRET instruction commited, the MPIE is updated with 1
    43.     cmt_mret_ena  ? 1'b1 : //从中断返回时候更新为0
    44.     // When the CSR is written by CSR instructions
    45.     (wr_mstatus & wbck_csr_wen) ? wbck_csr_dat[7] : // MPIE is in field 7 of mstatus
    46.                   status_mpie_r; // Unchanged

    47. sirv_gnrl_dfflr #(1) status_mpie_dfflr (status_mpie_ena, status_mpie_nxt, status_mpie_r, clk, rst_n);

    48. //////////////////////////
    49. // Implement MIE field
    50. //
    51.     // The MIE Feilds will be updates same as MPIE
    52. wire status_mie_ena  = status_mpie_ena;
    53. wire status_mie_nxt    =
    54.     //   See Priv SPEC:
    55.     //       When a trap is taken from privilege mode y into privilege
    56.     //       mode x, xPIE is set to the value of xIE,
    57.     //       xIE is set to 0;
    58.     // So, When the Trap is taken, the MIE is updated with 0
    59.      cmt_status_ena ? 1'b0 : //进入中断时候,关闭中断
    60.     //   See Priv SPEC:
    61.     //       When executing an xRET instruction, supposing xPP holds the value y, xIE
    62.     //       is set to xPIE; the privilege mode is changed to y, xPIE is set to 1;
    63.     // So, When the MRET instruction commited, the MIE is updated with MPIE
    64.     cmt_mret_ena ? status_mpie_r : //从中断返回时候,恢复保存在mpie中的值。
    65.     // When the CSR is written by CSR instructions
    66.     (wr_mstatus & wbck_csr_wen) ? wbck_csr_dat[3] : // MIE is in field 3 of mstatus
    67.                   status_mie_r; // Unchanged

    68. sirv_gnrl_dfflr #(1) status_mie_dfflr (status_mie_ena, status_mie_nxt, status_mie_r, clk, rst_n);

    69. //////////////////////////
    70. // Implement SD field
    71. //
    72. //  See Priv SPEC:
    73. //    The SD bit is read-only
    74. //    And is set when either the FS or XS bits encode a Dirty
    75. //      state (i.e., SD=((FS==11) OR (XS==11))).//因为没有浮点单元和协处理器,fs,xs域都为0
    76. wire [1:0] status_fs_r;
    77. wire [1:0] status_xs_r;
    78. wire status_sd_r = (status_fs_r == 2'b11) | (status_xs_r == 2'b11);

    79. //////////////////////////
    80. // Implement XS field
    81. //
    82. //  See Priv SPEC:
    83. //    XS field is read-only
    84. //    The XS field represents a summary of all extensions' status
    85. // But in E200 we implement XS exactly same as FS to make it usable by software to
    86. //   disable extended accelerators
    87. // If no EAI coprocessor interface configured, the XS is just hardwired to 0
    88. assign status_xs_r = 2'b0;

    89. //////////////////////////
    90. // Implement FS field
    91. //

    92. `ifndef E203_HAS_FPU
    93.    // If no FPU configured, the FS is just hardwired to 0
    94. assign status_fs_r = 2'b0;
    95. `endif

    96. //////////////////////////
    97. // Pack to the full mstatus register
    98. //
    99. wire [`E203_XLEN-1:0] status_r;
    100. assign status_r[31]    = status_sd_r;                        //SD
    101. assign status_r[30:23] = 8'b0; // Reserved
    102. assign status_r[22:17] = 6'b0;               // TSR--MPRV
    103. assign status_r[16:15] = status_xs_r;                        // XS
    104. assign status_r[14:13] = status_fs_r;                        // FS
    105. assign status_r[12:11] = 2'b11;              // MPP
    106. assign status_r[10:9]  = 2'b0; // Reserved
    107. assign status_r[8]     = 1'b0;               // SPP
    108. assign status_r[7]     = status_mpie_r;                      // MPIE
    109. assign status_r[6]     = 1'b0; // Reserved
    110. assign status_r[5]     = 1'b0;               // SPIE
    111. assign status_r[4]     = 1'b0;               // UPIE
    112. assign status_r[3]     = status_mie_r;                       // MIE
    113. assign status_r[2]     = 1'b0; // Reserved
    114. assign status_r[1]     = 1'b0;               // SIE
    115. assign status_r[0]     = 1'b0;               // UIE

    116. wire [`E203_XLEN-1:0] csr_mstatus = status_r;
    复制代码
    mie/mip rtl实现
    1. //0x004 URW uie User interrupt-enable register.
    2. //    * Since we dont delegate interrupt to user mode, hence it is as all 0s
    3. //0x304 MRW mie Machine interrupt-enable register.
    4. wire sel_mie = (csr_idx == 12'h304);
    5. wire rd_mie = sel_mie & csr_rd_en;
    6. wire wr_mie = sel_mie & csr_wr_en;
    7. wire mie_ena = wr_mie & wbck_csr_wen;
    8. wire [`E203_XLEN-1:0] mie_r;
    9. wire [`E203_XLEN-1:0] mie_nxt;
    10. assign mie_nxt[31:12] = 20'b0;
    11. assign mie_nxt[11] = wbck_csr_dat[11];//MEIE
    12. assign mie_nxt[10:8] = 3'b0;
    13. assign mie_nxt[ 7] = wbck_csr_dat[ 7];//MTIE
    14. assign mie_nxt[6:4] = 3'b0;
    15. assign mie_nxt[ 3] = wbck_csr_dat[ 3];//MSIE
    16. assign mie_nxt[2:0] = 3'b0;
    17. sirv_gnrl_dfflr #(`E203_XLEN) mie_dfflr (mie_ena, mie_nxt, mie_r, clk, rst_n);
    18. wire [`E203_XLEN-1:0] csr_mie = mie_r;

    19. assign meie_r = csr_mie[11];
    20. assign mtie_r = csr_mie[ 7];
    21. assign msie_r = csr_mie[ 3];

    22. //0x044 URW uip User interrupt pending.
    23. //  We dont support delegation scheme, so no need to support the uip
    24. //0x344 MRW mip Machine interrupt pending
    25. wire sel_mip = (csr_idx == 12'h344);
    26. wire rd_mip = sel_mip & csr_rd_en;
    27. //wire wr_mip = sel_mip & csr_wr_en;
    28. // The MxIP is read-only
    29. wire meip_r;
    30. wire msip_r;
    31. wire mtip_r;
    32. sirv_gnrl_dffr #(1) meip_dffr (ext_irq_r, meip_r, clk, rst_n);
    33. sirv_gnrl_dffr #(1) msip_dffr (sft_irq_r, msip_r, clk, rst_n);
    34. sirv_gnrl_dffr #(1) mtip_dffr (tmr_irq_r, mtip_r, clk, rst_n);

    35. wire [`E203_XLEN-1:0] ip_r;
    36. assign ip_r[31:12] = 20'b0;
    37. assign ip_r[11] = meip_r;
    38. assign ip_r[10:8] = 3'b0;
    39. assign ip_r[ 7] = mtip_r;
    40. assign ip_r[6:4] = 3'b0;
    41. assign ip_r[ 3] = msip_r;
    42. assign ip_r[2:0] = 3'b0;
    43. wire [`E203_XLEN-1:0] csr_mip = ip_r;
    复制代码
    mtvec和mscratch rtl实现
    1. //0x005 URW utvec User trap handler base address.
    2. //  We dont support user trap, so no utvec needed
    3. //0x305 MRW mtvec Machine trap-handler base address.
    4. wire sel_mtvec = (csr_idx == 12'h305);
    5. wire rd_mtvec = csr_rd_en & sel_mtvec;
    6. `ifdef E203_SUPPORT_MTVEC //{
    7. wire wr_mtvec = sel_mtvec & csr_wr_en;
    8. wire mtvec_ena = (wr_mtvec & wbck_csr_wen);
    9. wire [`E203_XLEN-1:0] mtvec_r;
    10. wire [`E203_XLEN-1:0] mtvec_nxt = wbck_csr_dat;
    11. sirv_gnrl_dfflr #(`E203_XLEN) mtvec_dfflr (mtvec_ena, mtvec_nxt, mtvec_r, clk, rst_n);
    12. wire [`E203_XLEN-1:0] csr_mtvec = mtvec_r;
    13. `else//}{
    14.   // THe vector table base is a configurable parameter, so we dont support writeable to it
    15. wire [`E203_XLEN-1:0] csr_mtvec = `E203_MTVEC_TRAP_BASE;
    16. `endif//}
    17. assign csr_mtvec_r = csr_mtvec;

    18. //0x340 MRW mscratch
    19. wire sel_mscratch = (csr_idx == 12'h340);
    20. wire rd_mscratch = sel_mscratch & csr_rd_en;
    21. `ifdef E203_SUPPORT_MSCRATCH //{
    22. wire wr_mscratch = sel_mscratch & csr_wr_en;
    23. wire mscratch_ena = (wr_mscratch & wbck_csr_wen);
    24. wire [`E203_XLEN-1:0] mscratch_r;
    25. wire [`E203_XLEN-1:0] mscratch_nxt = wbck_csr_dat;
    26. sirv_gnrl_dfflr #(`E203_XLEN) mscratch_dfflr (mscratch_ena, mscratch_nxt, mscratch_r, clk, rst_n);
    27. wire [`E203_XLEN-1:0] csr_mscratch = mscratch_r;
    28. `else//}{
    29. wire [`E203_XLEN-1:0] csr_mscratch = `E203_XLEN'b0;
    30. `endif//}
    复制代码
    mcycle/mcycleh/minstret/minstreth/counterstop/cgstop/itcmnohold/mdvnob2b等的rtl实现。
    1. // 0xB00 MRW mcycle
    2. // 0xB02 MRW minstret
    3. // 0xB80 MRW mcycleh
    4. // 0xB82 MRW minstreth
    5. wire sel_mcycle    = (csr_idx == 12'hB00);
    6. wire sel_mcycleh   = (csr_idx == 12'hB80);
    7. wire sel_minstret  = (csr_idx == 12'hB02);
    8. wire sel_minstreth = (csr_idx == 12'hB82);

    9. // 0xBFF MRW counterstop
    10.       // This register is our self-defined register to stop
    11.       // the cycle/time/instret counters to save dynamic powers
    12. wire sel_counterstop = (csr_idx == 12'hBFF);// This address is not used by ISA
    13. // 0xBFE MRW mcgstop
    14.       // This register is our self-defined register to disable the
    15.       // automaticall clock gating for CPU logics for debugging purpose
    16. wire sel_mcgstop = (csr_idx == 12'hBFE);// This address is not used by ISA
    17. // 0xBFD MRW itcmnohold
    18.       // This register is our self-defined register to disble the
    19.       // ITCM SRAM output holdup feature, if set, then we assume
    20.       // ITCM SRAM output cannot holdup last read value
    21. wire sel_itcmnohold = (csr_idx == 12'hBFD);// This address is not used by ISA
    22. // 0xBF0 MRW mdvnob2b
    23.       // This register is our self-defined register to disble the
    24.       // Mul/div back2back feature
    25. wire sel_mdvnob2b = (csr_idx == 12'hBF0);// This address is not used by ISA


    26. wire rd_mcycle     = csr_rd_en & sel_mcycle   ;
    27. wire rd_mcycleh    = csr_rd_en & sel_mcycleh  ;
    28. wire rd_minstret   = csr_rd_en & sel_minstret ;
    29. wire rd_minstreth  = csr_rd_en & sel_minstreth;

    30. wire rd_itcmnohold   = csr_rd_en & sel_itcmnohold;
    31. wire rd_mdvnob2b   = csr_rd_en & sel_mdvnob2b;
    32. wire rd_counterstop  = csr_rd_en & sel_counterstop;
    33. wire rd_mcgstop       = csr_rd_en & sel_mcgstop;

    34. `ifdef E203_SUPPORT_MCYCLE_MINSTRET //{
    35. wire wr_mcycle     = csr_wr_en & sel_mcycle   ;
    36. wire wr_mcycleh    = csr_wr_en & sel_mcycleh  ;
    37. wire wr_minstret   = csr_wr_en & sel_minstret ;
    38. wire wr_minstreth  = csr_wr_en & sel_minstreth;

    39. wire wr_itcmnohold   = csr_wr_en & sel_itcmnohold ;
    40. wire wr_mdvnob2b   = csr_wr_en & sel_mdvnob2b ;
    41. wire wr_counterstop  = csr_wr_en & sel_counterstop;
    42. wire wr_mcgstop       = csr_wr_en & sel_mcgstop     ;

    43. wire mcycle_wr_ena    = (wr_mcycle    & wbck_csr_wen);
    44. wire mcycleh_wr_ena   = (wr_mcycleh   & wbck_csr_wen);
    45. wire minstret_wr_ena  = (wr_minstret  & wbck_csr_wen);
    46. wire minstreth_wr_ena = (wr_minstreth & wbck_csr_wen);

    47. wire itcmnohold_wr_ena  = (wr_itcmnohold  & wbck_csr_wen);
    48. wire mdvnob2b_wr_ena  = (wr_mdvnob2b  & wbck_csr_wen);
    49. wire counterstop_wr_ena = (wr_counterstop & wbck_csr_wen);
    50. wire mcgstop_wr_ena      = (wr_mcgstop      & wbck_csr_wen);

    51. wire [`E203_XLEN-1:0] mcycle_r   ;
    52. wire [`E203_XLEN-1:0] mcycleh_r  ;
    53. wire [`E203_XLEN-1:0] minstret_r ;
    54. wire [`E203_XLEN-1:0] minstreth_r;

    55. wire cy_stop;
    56. wire ir_stop;

    57. wire stop_cycle_in_dbg = dbg_stopcycle & dbg_mode;
    58. wire mcycle_ena    = mcycle_wr_ena    |
    59.                      ((~cy_stop) & (~stop_cycle_in_dbg) & (1'b1));
    60. wire mcycleh_ena   = mcycleh_wr_ena   |
    61.                      ((~cy_stop) & (~stop_cycle_in_dbg) & ((mcycle_r == (~(`E203_XLEN'b0)))));
    62. wire minstret_ena  = minstret_wr_ena  |
    63.                      ((~ir_stop) & (~stop_cycle_in_dbg) & (cmt_instret_ena));
    64. wire minstreth_ena = minstreth_wr_ena |
    65.                      ((~ir_stop) & (~stop_cycle_in_dbg) & ((cmt_instret_ena & (minstret_r == (~(`E203_XLEN'b0))))));
    66. //auto increment
    67. wire [`E203_XLEN-1:0] mcycle_nxt    = mcycle_wr_ena    ? wbck_csr_dat : (mcycle_r    + 1'b1);
    68. wire [`E203_XLEN-1:0] mcycleh_nxt   = mcycleh_wr_ena   ? wbck_csr_dat : (mcycleh_r   + 1'b1);
    69. wire [`E203_XLEN-1:0] minstret_nxt  = minstret_wr_ena  ? wbck_csr_dat : (minstret_r  + 1'b1);
    70. wire [`E203_XLEN-1:0] minstreth_nxt = minstreth_wr_ena ? wbck_csr_dat : (minstreth_r + 1'b1);

    71. //We need to use the always-on clock for this counter
    72. sirv_gnrl_dfflr #(`E203_XLEN) mcycle_dfflr (mcycle_ena, mcycle_nxt, mcycle_r   , clk_aon, rst_n);
    73. sirv_gnrl_dfflr #(`E203_XLEN) mcycleh_dfflr (mcycleh_ena, mcycleh_nxt, mcycleh_r  , clk_aon, rst_n);
    74. sirv_gnrl_dfflr #(`E203_XLEN) minstret_dfflr (minstret_ena, minstret_nxt, minstret_r , clk, rst_n);
    75. sirv_gnrl_dfflr #(`E203_XLEN) minstreth_dfflr (minstreth_ena, minstreth_nxt, minstreth_r, clk, rst_n);

    76. wire [`E203_XLEN-1:0] counterstop_r;
    77. wire counterstop_ena = counterstop_wr_ena;
    78. wire [`E203_XLEN-1:0] counterstop_nxt = {29'b0,wbck_csr_dat[2:0]};// Only LSB 3bits are useful
    79. sirv_gnrl_dfflr #(`E203_XLEN) counterstop_dfflr (counterstop_ena, counterstop_nxt, counterstop_r, clk, rst_n);

    80. wire [`E203_XLEN-1:0] csr_mcycle    = mcycle_r;
    81. wire [`E203_XLEN-1:0] csr_mcycleh   = mcycleh_r;
    82. wire [`E203_XLEN-1:0] csr_minstret  = minstret_r;
    83. wire [`E203_XLEN-1:0] csr_minstreth = minstreth_r;
    84. wire [`E203_XLEN-1:0] csr_counterstop = counterstop_r;
    85. `else//}{
    86. wire [`E203_XLEN-1:0] csr_mcycle    = `E203_XLEN'b0;
    87. wire [`E203_XLEN-1:0] csr_mcycleh   = `E203_XLEN'b0;
    88. wire [`E203_XLEN-1:0] csr_minstret  = `E203_XLEN'b0;
    89. wire [`E203_XLEN-1:0] csr_minstreth = `E203_XLEN'b0;
    90. wire [`E203_XLEN-1:0] csr_counterstop = `E203_XLEN'b0;
    91. `endif//}

    92. wire [`E203_XLEN-1:0] itcmnohold_r;
    93. wire itcmnohold_ena = itcmnohold_wr_ena;
    94. wire [`E203_XLEN-1:0] itcmnohold_nxt = {31'b0,wbck_csr_dat[0]};// Only LSB 1bits are useful
    95. sirv_gnrl_dfflr #(`E203_XLEN) itcmnohold_dfflr (itcmnohold_ena, itcmnohold_nxt, itcmnohold_r, clk, rst_n);

    96. wire [`E203_XLEN-1:0] csr_itcmnohold  = itcmnohold_r;

    97. wire [`E203_XLEN-1:0] mdvnob2b_r;
    98. wire mdvnob2b_ena = mdvnob2b_wr_ena;
    99. wire [`E203_XLEN-1:0] mdvnob2b_nxt = {31'b0,wbck_csr_dat[0]};// Only LSB 1bits are useful
    100. sirv_gnrl_dfflr #(`E203_XLEN) mdvnob2b_dfflr (mdvnob2b_ena, mdvnob2b_nxt, mdvnob2b_r, clk, rst_n);

    101. wire [`E203_XLEN-1:0] csr_mdvnob2b  = mdvnob2b_r;

    102. assign cy_stop = counterstop_r[0];// Stop CYCLE   counter
    103. assign tm_stop = counterstop_r[1];// Stop TIME    counter
    104. assign ir_stop = counterstop_r[2];// Stop INSTRET counter,instruction number counter

    105. assign itcm_nohold = itcmnohold_r[0];// ITCM no-hold up feature
    106. assign mdv_nob2b = mdvnob2b_r[0];// Mul/Div no back2back feature



    107. wire [`E203_XLEN-1:0] mcgstop_r;
    108. wire mcgstop_ena = mcgstop_wr_ena;
    109. wire [`E203_XLEN-1:0] mcgstop_nxt = {30'b0,wbck_csr_dat[1:0]};// Only LSB 2bits are useful
    110. sirv_gnrl_dfflr #(`E203_XLEN) mcgstop_dfflr (mcgstop_ena, mcgstop_nxt, mcgstop_r, clk, rst_n);
    111. wire [`E203_XLEN-1:0] csr_mcgstop = mcgstop_r;
    112. assign core_cgstop = mcgstop_r[0];// Stop Core clock gating
    113. assign tcm_cgstop = mcgstop_r[1];// Stop TCM  clock gating
    复制代码
    mepc/mcause/mbadaddr/misa等的rtl实现。
    1. //0x041 URW uepc User exception program counter.
    2. //  We dont support user trap, so no uepc needed
    3. //0x341 MRW mepc Machine exception program counter.
    4. wire sel_mepc = (csr_idx == 12'h341);
    5. wire rd_mepc = sel_mepc & csr_rd_en;
    6. wire wr_mepc = sel_mepc & csr_wr_en;
    7. wire epc_ena = (wr_mepc & wbck_csr_wen) | cmt_epc_ena;
    8. wire [`E203_PC_SIZE-1:0] epc_r;
    9. wire [`E203_PC_SIZE-1:0] epc_nxt;
    10. 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];
    11. assign epc_nxt[0] = 1'b0;// Must not hold PC which will generate the misalign exception according to ISA
    12. sirv_gnrl_dfflr #(`E203_PC_SIZE) epc_dfflr (epc_ena, epc_nxt, epc_r, clk, rst_n);
    13. wire [`E203_XLEN-1:0] csr_mepc;
    14. wire dummy_0;
    15. assign {dummy_0,csr_mepc} = {{`E203_XLEN+1-`E203_PC_SIZE{1'b0}},epc_r};
    16. assign csr_epc_r = csr_mepc;

    17. //0x042 URW ucause User trap cause.
    18. //  We dont support user trap, so no ucause needed
    19. //0x342 MRW mcause Machine trap cause.
    20. wire sel_mcause = (csr_idx == 12'h342);
    21. wire rd_mcause = sel_mcause & csr_rd_en;
    22. wire wr_mcause = sel_mcause & csr_wr_en;
    23. wire cause_ena = (wr_mcause & wbck_csr_wen) | cmt_cause_ena;
    24. wire [`E203_XLEN-1:0] cause_r;
    25. wire [`E203_XLEN-1:0] cause_nxt;
    26. assign cause_nxt[31]  = cmt_cause_ena ? cmt_cause[31] : wbck_csr_dat[31];
    27. assign cause_nxt[30:4] = 27'b0;
    28. assign cause_nxt[3:0] = cmt_cause_ena ? cmt_cause[3:0] : wbck_csr_dat[3:0];
    29. sirv_gnrl_dfflr #(`E203_XLEN) cause_dfflr (cause_ena, cause_nxt, cause_r, clk, rst_n);
    30. wire [`E203_XLEN-1:0] csr_mcause = cause_r;


    31. //0x043 URW ubadaddr User bad address.
    32. //  We dont support user trap, so no ubadaddr needed
    33. //0x343 MRW mbadaddr Machine bad address.
    34. wire sel_mbadaddr = (csr_idx == 12'h343);
    35. wire rd_mbadaddr = sel_mbadaddr & csr_rd_en;
    36. wire wr_mbadaddr = sel_mbadaddr & csr_wr_en;
    37. wire cmt_trap_badaddr_ena = cmt_badaddr_ena;
    38. wire badaddr_ena = (wr_mbadaddr & wbck_csr_wen) | cmt_trap_badaddr_ena;
    39. wire [`E203_ADDR_SIZE-1:0] badaddr_r;
    40. wire [`E203_ADDR_SIZE-1:0] badaddr_nxt;
    41. assign badaddr_nxt = cmt_trap_badaddr_ena ? cmt_badaddr : wbck_csr_dat[`E203_ADDR_SIZE-1:0];
    42. sirv_gnrl_dfflr #(`E203_ADDR_SIZE) badaddr_dfflr (badaddr_ena, badaddr_nxt, badaddr_r, clk, rst_n);
    43. wire [`E203_XLEN-1:0] csr_mbadaddr;
    44. wire dummy_1;
    45. assign {dummy_1,csr_mbadaddr} = {{`E203_XLEN+1-`E203_ADDR_SIZE{1'b0}},badaddr_r};

    46. // We dont support the delegation scheme, so no need to implement
    47. //   delegete registers


    48. //0x301 MRW misa ISA and extensions
    49. wire sel_misa = (csr_idx == 12'h301);
    50. wire rd_misa = sel_misa & csr_rd_en;
    51. // Only implemented the M mode, IMC or EMC
    52. wire [`E203_XLEN-1:0] csr_misa = {
    53.     2'b1
    54.    ,4'b0 //WIRI
    55.    ,1'b0 //              25 Z Reserved
    56.    ,1'b0 //              24 Y Reserved
    57.    ,1'b0 //              23 X Non-standard extensions present
    58.    ,1'b0 //              22 W Reserved
    59.    ,1'b0 //              21 V Tentatively reserved for Vector extension 20 U User mode implemented
    60.    ,1'b0 //              20 U User mode implemented
    61.    ,1'b0 //              19 T Tentatively reserved for Transactional Memory extension
    62.    ,1'b0 //              18 S Supervisor mode implemented
    63.    ,1'b0 //              17 R Reserved
    64.    ,1'b0 //              16 Q Quad-precision floating-point extension
    65.    ,1'b0 //              15 P Tentatively reserved for Packed-SIMD extension
    66.    ,1'b0 //              14 O Reserved
    67.    ,1'b0 //              13 N User-level interrupts supported
    68.    ,1'b1 // 12 M Integer Multiply/Divide extension
    69.    ,1'b0 //              11 L Tentatively reserved for Decimal Floating-Point extension
    70.    ,1'b0 //              10 K Reserved
    71.    ,1'b0 //              9 J Reserved
    72.    `ifdef E203_RFREG_NUM_IS_32
    73.    ,1'b1 // 8 I RV32I/64I/128I base ISA
    74.    `else
    75.    ,1'b0
    76.    `endif
    77.    ,1'b0 //              7 H Hypervisor mode implemented
    78.    ,1'b0 //              6 G Additional standard extensions present
    79.   `ifndef E203_HAS_FPU//{
    80.    ,1'b0 //              5 F Single-precision floating-point extension
    81.   `endif//
    82.    `ifdef E203_RFREG_NUM_IS_32
    83.    ,1'b0 //              4 E RV32E base ISA
    84.    `else
    85.    ,1'b1 //              
    86.    `endif
    87.   `ifndef E203_HAS_FPU//{
    88.    ,1'b0 //              3 D Double-precision floating-point extension
    89.   `endif//
    90.    ,1'b1 // 2 C Compressed extension
    91.    ,1'b0 //              1 B Tentatively reserved for Bit operations extension
    92.   `ifdef E203_SUPPORT_AMO//{
    93.    ,1'b1 //              0 A Atomic extension
    94.   `endif//E203_SUPPORT_AMO}
    95.   `ifndef E203_SUPPORT_AMO//{
    96.    ,1'b0 //              0 A Atomic extension
    97.   `endif//}
    98.                            };

    99. //Machine Information Registers
    100. //0xF11 MRO mvendorid Vendor ID.
    101. //0xF12 MRO marchid Architecture ID.
    102. //0xF13 MRO mimpid Implementation ID.
    103. //0xF14 MRO mhartid Hardware thread ID.
    104. wire [`E203_XLEN-1:0] csr_mvendorid = `E203_XLEN'h`E203_MVENDORID;
    105. wire [`E203_XLEN-1:0] csr_marchid   = `E203_XLEN'h`E203_MARCHID  ;
    106. wire [`E203_XLEN-1:0] csr_mimpid    = `E203_XLEN'h`E203_MIMPID   ;
    107. wire [`E203_XLEN-1:0] csr_mhartid   = {{`E203_XLEN-`E203_HART_ID_W{1'b0}},core_mhartid};
    108. wire rd_mvendorid = csr_rd_en & (csr_idx == 12'hF11);
    109. wire rd_marchid   = csr_rd_en & (csr_idx == 12'hF12);
    110. wire rd_mimpid    = csr_rd_en & (csr_idx == 12'hF13);
    111. wire rd_mhartid   = csr_rd_en & (csr_idx == 12'hF14);

    112. //0x7b0 Debug Control and Status
    113. //0x7b1 Debug PC
    114. //0x7b2 Debug Scratch Register
    115. //0x7a0 Trigger selection register
    116. wire sel_dcsr     = (csr_idx == 12'h7b0);
    117. wire sel_dpc      = (csr_idx == 12'h7b1);
    118. wire sel_dscratch = (csr_idx == 12'h7b2);

    119. wire rd_dcsr     = dbg_mode & csr_rd_en & sel_dcsr    ;
    120. wire rd_dpc      = dbg_mode & csr_rd_en & sel_dpc     ;
    121. wire rd_dscratch = dbg_mode & csr_rd_en & sel_dscratch;


    122. assign wr_dcsr_ena     = dbg_mode & csr_wr_en & sel_dcsr    ;
    123. assign wr_dpc_ena      = dbg_mode & csr_wr_en & sel_dpc     ;
    124. assign wr_dscratch_ena = dbg_mode & csr_wr_en & sel_dscratch;


    125. assign wr_csr_nxt     = wbck_csr_dat;


    126. wire [`E203_XLEN-1:0] csr_dcsr     = dcsr_r    ;
    127. `ifdef E203_PC_SIZE_IS_16
    128. wire [`E203_XLEN-1:0] csr_dpc      = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
    129. `endif
    130. `ifdef E203_PC_SIZE_IS_24
    131. wire [`E203_XLEN-1:0] csr_dpc      = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
    132. `endif
    133. `ifdef E203_PC_SIZE_IS_32
    134. wire [`E203_XLEN-1:0] csr_dpc      = dpc_r     ;
    135. `endif
    136. wire [`E203_XLEN-1:0] csr_dscratch = dscratch_r;

    137. assign csr_dpc_r = dpc_r;
    复制代码
    下面是我的写的一个testbench,
    1. `include "e203_defines.v"
    2. module e203_exu_csr_tb;

    3.   reg csr_ena; //csr readwrite enable signal from alu
    4.   reg csr_wr_en; //csr write enable
    5.   reg csr_rd_en; //csr read enable
    6.   reg [11:0] csr_idx;//csr address index

    7.   wire tm_stop;
    8.   wire core_cgstop;
    9.   wire tcm_cgstop;
    10.   wire itcm_nohold;
    11.   wire mdv_nob2b;


    12.   wire [`E203_XLEN-1:0] read_csr_dat;
    13.   reg  [`E203_XLEN-1:0] wbck_csr_dat;

    14.   reg  [`E203_HART_ID_W-1:0] core_mhartid;
    15.   reg  ext_irq_r;
    16.   reg  sft_irq_r;
    17.   reg  tmr_irq_r;

    18.   wire status_mie_r;
    19.   wire mtie_r;
    20.   wire msie_r;
    21.   wire meie_r;

    22.   wire wr_dcsr_ena    ;
    23.   wire wr_dpc_ena     ;
    24.   wire wr_dscratch_ena;


    25.   reg [`E203_XLEN-1:0] dcsr_r    ;
    26.   reg [`E203_PC_SIZE-1:0] dpc_r     ;
    27.   reg [`E203_XLEN-1:0] dscratch_r;

    28.   wire [`E203_XLEN-1:0] wr_csr_nxt    ;

    29.   reg  dbg_mode;
    30.   reg  dbg_stopcycle;

    31.   wire u_mode;
    32.   wire s_mode;
    33.   wire h_mode;
    34.   wire m_mode;

    35.   reg [`E203_ADDR_SIZE-1:0] cmt_badaddr;
    36.   reg cmt_badaddr_ena;
    37.   reg [`E203_PC_SIZE-1:0] cmt_epc;
    38.   reg cmt_epc_ena;
    39.   reg [`E203_XLEN-1:0] cmt_cause;
    40.   reg cmt_cause_ena;
    41.   reg cmt_status_ena;
    42.   reg cmt_instret_ena;

    43.   reg                      cmt_mret_ena;
    44.   wire[`E203_PC_SIZE-1:0]  csr_epc_r;
    45.   wire[`E203_PC_SIZE-1:0]  csr_dpc_r;
    46.   wire[`E203_XLEN-1:0]     csr_mtvec_r;


    47.   reg  clk=0;
    48.   reg  rst_n;

    49. e203_exu_csr  mycsr(
    50. .csr_ena(csr_ena),
    51. .csr_wr_en(csr_wr_en),
    52. .csr_rd_en(csr_rd_en),
    53. .csr_idx(csr_idx),
    54. .tm_stop(tm_stop),
    55. .core_cgstop(core_cgstop),
    56. .tcm_cgstop(tcm_cgstop),
    57. .itcm_nohold(itcm_nohold),
    58. .mdv_nob2b(mdv_nob2b),
    59. .read_csr_dat(read_csr_dat),
    60. .wbck_csr_dat(wbck_csr_dat),
    61. .core_mhartid(core_mhartid),
    62. .ext_irq_r(ext_irq_r),
    63. .sft_irq_r(sft_irq_r),
    64. .tmr_irq_r(tmr_irq_r),
    65. .status_mie_r(status_mie_r),
    66. .mtie_r(mtie_r),
    67. .msie_r(msie_r),
    68. .meie_r(meie_r),
    69. .wr_dcsr_ena(wr_dcsr_ena),
    70. .wr_dpc_ena(wr_dpc_ena),
    71. .wr_dscratch_ena(wr_dscratch_ena),
    72. .dcsr_r(dcsr_r),
    73. .dpc_r(dpc_r),
    74. .dscratch_r(dscratch_r),
    75. .wr_csr_nxt(wr_csr_nxt),
    76. .dbg_mode(dbg_mode),
    77. .dbg_stopcycle(dbg_stopcycle),
    78. .u_mode(u_mode),
    79. .s_mode(s_mode),
    80. .h_mode(h_mode),
    81. .m_mode(m_mode),
    82. .cmt_badaddr(cmt_badaddr),
    83. .cmt_badaddr_ena(cmt_badaddr_ena),
    84. .cmt_epc(cmt_epc),
    85. .cmt_epc_ena(cmt_epc_ena),
    86. .cmt_cause(cmt_cause),
    87. .cmt_cause_ena(cmt_cause_ena),
    88. .cmt_status_ena(cmt_status_ena),
    89. .cmt_instret_ena(cmt_instret_ena),
    90. .cmt_mret_ena(cmt_mret_ena),
    91. .csr_epc_r(csr_epc_r),
    92. .csr_dpc_r(csr_dpc_r),
    93. .csr_mtvec_r(csr_mtvec_r),
    94. .clk_aon(clk),
    95. .clk(clk),
    96. .rst_n(rst_n)
    97. );



    98.    always #10 clk=~clk;

    99.    initial
    100.    begin
    101.            rst_n = 1'b1;
    102.            #20
    103.            rst_n= 1'b0;
    104.            #20
    105.            rst_n=1'b1;
    106.            csr_ena = 1'b1;
    107.            csr_wr_en = 1'b1;
    108.            csr_rd_en = 1'b0;
    109.            csr_idx = 11'h300; //mstatus
    110.            wbck_csr_dat = 32'h0001f888;
    111.            core_mhartid = `E203_HART_ID_W'h0;
    112.            ext_irq_r = 1'b0;
    113.            sft_irq_r = 1'b0;
    114.            tmr_irq_r = 1'b0;
    115.            dcsr_r = `E203_XLEN'h5;
    116.            dpc_r =  `E203_PC_SIZE'h5;
    117.            dscratch_r =  `E203_XLEN'h5;
    118.            dbg_mode = 1'b0;
    119.            dbg_stopcycle= 1'b0;
    120.            cmt_badaddr=`E203_ADDR_SIZE'h4;
    121.            cmt_badaddr_ena = 1'b0;
    122.            cmt_epc=`E203_PC_SIZE'h4;
    123.            cmt_epc_ena = 1'b0;
    124.            cmt_cause=`E203_XLEN'h4;
    125.            cmt_cause_ena = 1'b0;
    126.            cmt_status_ena = 1'b0;
    127.            cmt_instret_ena = 1'b0;
    128.            cmt_mret_ena = 1'b0;

    129.            #20
    130.            csr_wr_en = 1'b0;
    131.            csr_rd_en = 1'b1;
    132.            #20

    133.            csr_wr_en = 1'b1;
    134.            csr_rd_en = 1'b0;
    135.            wbck_csr_dat = 32'h80;
    136.            #20
    137.            csr_wr_en = 1'b1;
    138.            csr_rd_en = 1'b0;
    139.            wbck_csr_dat = 32'h888;
    140.            csr_idx = 12'h304; //mie
    141.            #20
    142.            csr_wr_en = 1'b0;
    143.            csr_rd_en = 1'b1;
    144.            #20
    145.            csr_wr_en = 1'b1;
    146.            csr_rd_en = 1'b0;
    147.            wbck_csr_dat = 32'h800;
    148.            csr_idx = 12'h344; //mip
    149.            #20
    150.            csr_wr_en = 1'b0;
    151.            csr_rd_en = 1'b1;
    152.            #20
    153.            csr_wr_en = 1'b1;
    154.            csr_rd_en = 1'b0;
    155.            wbck_csr_dat = 32'hff;
    156.            csr_idx = 12'h305; //mtvec
    157.            #20
    158.            csr_wr_en = 1'b0;
    159.            csr_rd_en = 1'b1;
    160.            #20
    161.            csr_wr_en = 1'b1;
    162.            csr_rd_en = 1'b0;
    163.            wbck_csr_dat = 32'hff00;
    164.            csr_idx = 12'h340; //mscratch
    165.            #20
    166.            csr_wr_en = 1'b0;
    167.            csr_rd_en = 1'b1;
    168.            #20
    169.            csr_wr_en = 1'b1;
    170.            csr_rd_en = 1'b0;
    171.            wbck_csr_dat = 32'h7;
    172.            csr_idx = 12'hbff; //counterstop
    173.            #20
    174.            csr_wr_en = 1'b0;
    175.            csr_rd_en = 1'b1;
    176.            #20
    177.            csr_wr_en = 1'b1;
    178.            csr_rd_en = 1'b0;
    179.            wbck_csr_dat = 32'h3;
    180.            csr_idx = 12'hbfe; //mcgstop
    181.            #20
    182.            csr_wr_en = 1'b0;
    183.            csr_rd_en = 1'b1;
    184.            #20
    185.            csr_wr_en = 1'b1;
    186.            csr_rd_en = 1'b0;
    187.            wbck_csr_dat = 32'h1;
    188.            csr_idx = 12'hbfd; //itcmnohold
    189.            #20
    190.            csr_wr_en = 1'b0;
    191.            csr_rd_en = 1'b1;
    192.            #20
    193.            csr_wr_en = 1'b1;
    194.            csr_rd_en = 1'b0;
    195.            wbck_csr_dat = 32'h1;
    196.            csr_idx = 12'hbf0; //mdvnob2b
    197.            #20
    198.            csr_wr_en = 1'b0;
    199.            csr_rd_en = 1'b1;
    200.            #20
    201.            csr_wr_en = 1'b1;
    202.            csr_rd_en = 1'b0;
    203.            wbck_csr_dat = 32'h1;
    204.            csr_idx = 12'h341; //mepc
    205.            #20
    206.            csr_wr_en = 1'b0;
    207.            csr_rd_en = 1'b1;
    208.            #20
    209.            csr_wr_en = 1'b1;
    210.            csr_rd_en = 1'b0;
    211.            wbck_csr_dat = 32'haa;
    212.            csr_idx = 12'h342; //mcasue
    213.            #20
    214.            csr_wr_en = 1'b0;
    215.            csr_rd_en = 1'b1;
    216.            #20
    217.            csr_wr_en = 1'b1;
    218.            csr_rd_en = 1'b0;
    219.            wbck_csr_dat = 32'hffff;
    220.            csr_idx = 12'h343; //mbadaddr/mtval
    221.            #20
    222.            csr_wr_en = 1'b0;
    223.            csr_rd_en = 1'b1;
    224.            #20
    225.            csr_wr_en = 1'b0;
    226.            csr_rd_en = 1'b1;
    227.            csr_idx = 12'h301; //misa
    228.            #20
    229.            csr_wr_en = 1'b0;
    230.            csr_rd_en = 1'b1;
    231.            csr_idx = 12'hf11; //mvendorid
    232.            #20
    233.            csr_wr_en = 1'b0;
    234.            csr_rd_en = 1'b1;
    235.            csr_idx = 12'hf12; //marchid
    236.            #20
    237.            csr_wr_en = 1'b0;
    238.            csr_rd_en = 1'b1;
    239.            csr_idx = 12'hf13; //mimpid
    240.            #20
    241.            csr_wr_en = 1'b0;
    242.            csr_rd_en = 1'b1;
    243.            csr_idx = 12'hf14; //mhartid
    244.            #100


    245.            $finish;
    246.    end

    247.    //initial
    248.           // $monitor($time,,,"clk=%b,i_instr=0x%h,i_pc=%h",clk,i_instr,i_pc);
    249.    initial
    250.    begin
    251.            //$dumpfile("dump.vcd");
    252.            //$dumpvars;
    253.            $fsdbDumpfile("dump.fsdb");
    254.            $fsdbDumpvars("+all");
    255.    end

    256.    endmodule
    复制代码
    Makefile
    1. # VCS flags, if want to use dump fsdb in verilog file, need to add args -fsdb, otherwise will be compiled fail
    2. VCS_FLAGS = -sverilog -full64 -fsdb -debug_all +v2k -timescale=1ns/1ns +define+DISABLE_SV_ASSERTION

    3. # Source files
    4. SRC_FILES = e203_exu_csr.v \
    5.             sirv_gnrl_dffs.v \
    6.             sirv_gnrl_xchecker.v \
    7.             e203_exu_csr_tb.v \

    8. # Source directories
    9. INCDIR = +incdir+./

    10. all:
    11.         vcs $(VCS_FLAGS) $(INCDIR) $(SRC_FILES)
    12. clean:
    13.         rm -rf ./csrc *.daidir ./csrc *.log *.vpd *.vdb simv* *.key *race.out* *vcd *fsdb
    14. debug:
    15.         verdi -sv -ssf dump.fsdb -f verdi.f &
    复制代码





    上一篇:E203 CSR寄存器
    下一篇:E203数据冲突处理OITF
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-25 13:12 , Processed in 0.723758 second(s), 45 queries .

    快速回复 返回顶部 返回列表