| module ibex_cs_registers ( |
| clk_i, |
| rst_ni, |
| hart_id_i, |
| priv_mode_id_o, |
| priv_mode_if_o, |
| priv_mode_lsu_o, |
| csr_mstatus_tw_o, |
| csr_mtvec_o, |
| csr_mtvec_init_i, |
| boot_addr_i, |
| csr_access_i, |
| csr_addr_i, |
| csr_wdata_i, |
| csr_op_i, |
| csr_op_en_i, |
| csr_rdata_o, |
| irq_software_i, |
| irq_timer_i, |
| irq_external_i, |
| irq_fast_i, |
| nmi_mode_i, |
| irq_pending_o, |
| irqs_o, |
| csr_mstatus_mie_o, |
| csr_mepc_o, |
| csr_pmp_cfg_o, |
| csr_pmp_addr_o, |
| csr_pmp_mseccfg_o, |
| debug_mode_i, |
| debug_cause_i, |
| debug_csr_save_i, |
| csr_depc_o, |
| debug_single_step_o, |
| debug_ebreakm_o, |
| debug_ebreaku_o, |
| trigger_match_o, |
| pc_if_i, |
| pc_id_i, |
| pc_wb_i, |
| data_ind_timing_o, |
| dummy_instr_en_o, |
| dummy_instr_mask_o, |
| dummy_instr_seed_en_o, |
| dummy_instr_seed_o, |
| icache_enable_o, |
| csr_shadow_err_o, |
| csr_save_if_i, |
| csr_save_id_i, |
| csr_save_wb_i, |
| csr_restore_mret_i, |
| csr_restore_dret_i, |
| csr_save_cause_i, |
| csr_mcause_i, |
| csr_mtval_i, |
| illegal_csr_insn_o, |
| instr_ret_i, |
| instr_ret_compressed_i, |
| instr_ret_spec_i, |
| instr_ret_compressed_spec_i, |
| iside_wait_i, |
| jump_i, |
| branch_i, |
| branch_taken_i, |
| mem_load_i, |
| mem_store_i, |
| dside_wait_i, |
| mul_wait_i, |
| div_wait_i |
| ); |
| parameter [0:0] DbgTriggerEn = 0; |
| parameter [31:0] DbgHwBreakNum = 1; |
| parameter [0:0] DataIndTiming = 1'b0; |
| parameter [0:0] DummyInstructions = 1'b0; |
| parameter [0:0] ShadowCSR = 1'b0; |
| parameter [0:0] ICache = 1'b0; |
| parameter [31:0] MHPMCounterNum = 10; |
| parameter [31:0] MHPMCounterWidth = 40; |
| parameter [0:0] PMPEnable = 0; |
| parameter [31:0] PMPGranularity = 0; |
| parameter [31:0] PMPNumRegions = 4; |
| parameter [0:0] RV32E = 0; |
| parameter integer RV32M = 32'sd2; |
| parameter integer RV32B = 32'sd0; |
| parameter integer RV32Zk = 32'sd0; |
| input wire clk_i; |
| input wire rst_ni; |
| input wire [31:0] hart_id_i; |
| output wire [1:0] priv_mode_id_o; |
| output wire [1:0] priv_mode_if_o; |
| output wire [1:0] priv_mode_lsu_o; |
| output wire csr_mstatus_tw_o; |
| output wire [31:0] csr_mtvec_o; |
| input wire csr_mtvec_init_i; |
| input wire [31:0] boot_addr_i; |
| input wire csr_access_i; |
| input wire [11:0] csr_addr_i; |
| input wire [31:0] csr_wdata_i; |
| input wire [1:0] csr_op_i; |
| input csr_op_en_i; |
| output wire [31:0] csr_rdata_o; |
| input wire irq_software_i; |
| input wire irq_timer_i; |
| input wire irq_external_i; |
| input wire [14:0] irq_fast_i; |
| input wire nmi_mode_i; |
| output wire irq_pending_o; |
| output wire [17:0] irqs_o; |
| output wire csr_mstatus_mie_o; |
| output wire [31:0] csr_mepc_o; |
| output wire [(PMPNumRegions * 6) - 1:0] csr_pmp_cfg_o; |
| output wire [(PMPNumRegions * 34) - 1:0] csr_pmp_addr_o; |
| output wire [2:0] csr_pmp_mseccfg_o; |
| input wire debug_mode_i; |
| input wire [2:0] debug_cause_i; |
| input wire debug_csr_save_i; |
| output wire [31:0] csr_depc_o; |
| output wire debug_single_step_o; |
| output wire debug_ebreakm_o; |
| output wire debug_ebreaku_o; |
| output wire trigger_match_o; |
| input wire [31:0] pc_if_i; |
| input wire [31:0] pc_id_i; |
| input wire [31:0] pc_wb_i; |
| output wire data_ind_timing_o; |
| output wire dummy_instr_en_o; |
| output wire [2:0] dummy_instr_mask_o; |
| output wire dummy_instr_seed_en_o; |
| output wire [31:0] dummy_instr_seed_o; |
| output wire icache_enable_o; |
| output wire csr_shadow_err_o; |
| input wire csr_save_if_i; |
| input wire csr_save_id_i; |
| input wire csr_save_wb_i; |
| input wire csr_restore_mret_i; |
| input wire csr_restore_dret_i; |
| input wire csr_save_cause_i; |
| input wire [5:0] csr_mcause_i; |
| input wire [31:0] csr_mtval_i; |
| output wire illegal_csr_insn_o; |
| input wire instr_ret_i; |
| input wire instr_ret_compressed_i; |
| input wire instr_ret_spec_i; |
| input wire instr_ret_compressed_spec_i; |
| input wire iside_wait_i; |
| input wire jump_i; |
| input wire branch_i; |
| input wire branch_taken_i; |
| input wire mem_load_i; |
| input wire mem_store_i; |
| input wire dside_wait_i; |
| input wire mul_wait_i; |
| input wire div_wait_i; |
| localparam [31:0] RV32BEnabled = (RV32B == 32'sd0 ? 0 : 1); |
| localparam [31:0] RV32MEnabled = (RV32M == 32'sd0 ? 0 : 1); |
| localparam [31:0] PMPAddrWidth = (PMPGranularity > 0 ? 33 - PMPGranularity : 32); |
| localparam [1:0] ibex_pkg_CSR_MISA_MXL = 2'd1; |
| function automatic [31:0] sv2v_cast_32; |
| input reg [31:0] inp; |
| sv2v_cast_32 = inp; |
| endfunction |
| localparam [31:0] MISA_VALUE = (((((((((((0 | (RV32BEnabled << 1)) | 4) | 0) | (sv2v_cast_32(RV32E) << 4)) | 0) | (sv2v_cast_32(!RV32E) << 8)) | (RV32MEnabled << 12)) | 0) | 0) | 1048576) | 0) | (sv2v_cast_32(ibex_pkg_CSR_MISA_MXL) << 30); |
| reg [31:0] exception_pc; |
| reg [1:0] priv_lvl_q; |
| reg [1:0] priv_lvl_d; |
| wire [5:0] mstatus_q; |
| reg [5:0] mstatus_d; |
| wire mstatus_err; |
| reg mstatus_en; |
| wire [17:0] mie_q; |
| wire [17:0] mie_d; |
| reg mie_en; |
| wire [31:0] mscratch_q; |
| reg mscratch_en; |
| wire [31:0] mepc_q; |
| reg [31:0] mepc_d; |
| reg mepc_en; |
| wire [5:0] mcause_q; |
| reg [5:0] mcause_d; |
| reg mcause_en; |
| wire [31:0] mtval_q; |
| reg [31:0] mtval_d; |
| reg mtval_en; |
| wire [31:0] mtvec_q; |
| reg [31:0] mtvec_d; |
| wire mtvec_err; |
| reg mtvec_en; |
| wire [17:0] mip; |
| wire [31:0] dcsr_q; |
| reg [31:0] dcsr_d; |
| reg dcsr_en; |
| wire [31:0] depc_q; |
| reg [31:0] depc_d; |
| reg depc_en; |
| wire [31:0] dscratch0_q; |
| wire [31:0] dscratch1_q; |
| reg dscratch0_en; |
| reg dscratch1_en; |
| wire [2:0] mstack_q; |
| reg [2:0] mstack_d; |
| reg mstack_en; |
| wire [31:0] mstack_epc_q; |
| reg [31:0] mstack_epc_d; |
| wire [5:0] mstack_cause_q; |
| reg [5:0] mstack_cause_d; |
| localparam [31:0] ibex_pkg_PMP_MAX_REGIONS = 16; |
| reg [31:0] pmp_addr_rdata [0:15]; |
| localparam [31:0] ibex_pkg_PMP_CFG_W = 8; |
| wire [7:0] pmp_cfg_rdata [0:15]; |
| wire pmp_csr_err; |
| wire [2:0] pmp_mseccfg; |
| wire [31:0] mcountinhibit; |
| reg [MHPMCounterNum + 2:0] mcountinhibit_d; |
| reg [MHPMCounterNum + 2:0] mcountinhibit_q; |
| reg mcountinhibit_we; |
| wire [63:0] mhpmcounter [0:31]; |
| reg [31:0] mhpmcounter_we; |
| reg [31:0] mhpmcounterh_we; |
| reg [31:0] mhpmcounter_incr; |
| reg [31:0] mhpmevent [0:31]; |
| wire [4:0] mhpmcounter_idx; |
| wire unused_mhpmcounter_we_1; |
| wire unused_mhpmcounterh_we_1; |
| wire unused_mhpmcounter_incr_1; |
| wire [63:0] minstret_next; |
| wire [63:0] minstret_raw; |
| wire [31:0] tselect_rdata; |
| wire [31:0] tmatch_control_rdata; |
| wire [31:0] tmatch_value_rdata; |
| wire [5:0] cpuctrl_q; |
| wire [5:0] cpuctrl_d; |
| wire [5:0] cpuctrl_wdata; |
| reg cpuctrl_we; |
| wire cpuctrl_err; |
| reg [31:0] csr_wdata_int; |
| reg [31:0] csr_rdata_int; |
| wire csr_we_int; |
| wire csr_wr; |
| reg illegal_csr; |
| wire illegal_csr_priv; |
| wire illegal_csr_write; |
| wire [7:0] unused_boot_addr; |
| wire [2:0] unused_csr_addr; |
| assign unused_boot_addr = boot_addr_i[7:0]; |
| wire [11:0] csr_addr; |
| assign csr_addr = {csr_addr_i}; |
| assign unused_csr_addr = csr_addr[7:5]; |
| assign mhpmcounter_idx = csr_addr[4:0]; |
| assign illegal_csr_priv = csr_addr[9:8] > {priv_lvl_q}; |
| assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_wr; |
| assign illegal_csr_insn_o = csr_access_i & ((illegal_csr | illegal_csr_write) | illegal_csr_priv); |
| assign mip[17] = irq_software_i; |
| assign mip[16] = irq_timer_i; |
| assign mip[15] = irq_external_i; |
| assign mip[14-:15] = irq_fast_i; |
| localparam [31:0] ibex_pkg_CSR_MARCHID_VALUE = 32'b00000000000000000000000000010110; |
| localparam [31:0] ibex_pkg_CSR_MEIX_BIT = 11; |
| localparam [31:0] ibex_pkg_CSR_MFIX_BIT_HIGH = 30; |
| localparam [31:0] ibex_pkg_CSR_MFIX_BIT_LOW = 16; |
| localparam [31:0] ibex_pkg_CSR_MIMPID_VALUE = 32'b00000000000000000000000000000000; |
| localparam [31:0] ibex_pkg_CSR_MSECCFG_MML_BIT = 0; |
| localparam [31:0] ibex_pkg_CSR_MSECCFG_MMWP_BIT = 1; |
| localparam [31:0] ibex_pkg_CSR_MSECCFG_RLB_BIT = 2; |
| localparam [31:0] ibex_pkg_CSR_MSIX_BIT = 3; |
| localparam [31:0] ibex_pkg_CSR_MSTATUS_MIE_BIT = 3; |
| localparam [31:0] ibex_pkg_CSR_MSTATUS_MPIE_BIT = 7; |
| localparam [31:0] ibex_pkg_CSR_MSTATUS_MPP_BIT_HIGH = 12; |
| localparam [31:0] ibex_pkg_CSR_MSTATUS_MPP_BIT_LOW = 11; |
| localparam [31:0] ibex_pkg_CSR_MSTATUS_MPRV_BIT = 17; |
| localparam [31:0] ibex_pkg_CSR_MSTATUS_TW_BIT = 21; |
| localparam [31:0] ibex_pkg_CSR_MTIX_BIT = 7; |
| localparam [31:0] ibex_pkg_CSR_MVENDORID_VALUE = 32'b00000000000000000000000000000000; |
| always @(*) begin |
| csr_rdata_int = 1'sb0; |
| illegal_csr = 1'b0; |
| case (csr_addr_i) |
| 12'hf11: csr_rdata_int = ibex_pkg_CSR_MVENDORID_VALUE; |
| 12'hf12: csr_rdata_int = ibex_pkg_CSR_MARCHID_VALUE; |
| 12'hf13: csr_rdata_int = ibex_pkg_CSR_MIMPID_VALUE; |
| 12'hf14: csr_rdata_int = hart_id_i; |
| 12'h015: |
| if (RV32Zk == 32'sd2) begin |
| if (csr_op_i == 2'd1) |
| csr_rdata_int = 32'hffffdead; |
| else |
| illegal_csr = 1'b1; |
| end |
| else |
| illegal_csr = 1'b1; |
| 12'h300: begin |
| csr_rdata_int = 1'sb0; |
| csr_rdata_int[ibex_pkg_CSR_MSTATUS_MIE_BIT] = mstatus_q[5]; |
| csr_rdata_int[ibex_pkg_CSR_MSTATUS_MPIE_BIT] = mstatus_q[4]; |
| csr_rdata_int[ibex_pkg_CSR_MSTATUS_MPP_BIT_HIGH:ibex_pkg_CSR_MSTATUS_MPP_BIT_LOW] = mstatus_q[3-:2]; |
| csr_rdata_int[ibex_pkg_CSR_MSTATUS_MPRV_BIT] = mstatus_q[1]; |
| csr_rdata_int[ibex_pkg_CSR_MSTATUS_TW_BIT] = mstatus_q[0]; |
| end |
| 12'h301: csr_rdata_int = MISA_VALUE; |
| 12'h304: begin |
| csr_rdata_int = 1'sb0; |
| csr_rdata_int[ibex_pkg_CSR_MSIX_BIT] = mie_q[17]; |
| csr_rdata_int[ibex_pkg_CSR_MTIX_BIT] = mie_q[16]; |
| csr_rdata_int[ibex_pkg_CSR_MEIX_BIT] = mie_q[15]; |
| csr_rdata_int[ibex_pkg_CSR_MFIX_BIT_HIGH:ibex_pkg_CSR_MFIX_BIT_LOW] = mie_q[14-:15]; |
| end |
| 12'h306: csr_rdata_int = 1'sb0; |
| 12'h340: csr_rdata_int = mscratch_q; |
| 12'h305: csr_rdata_int = mtvec_q; |
| 12'h341: csr_rdata_int = mepc_q; |
| 12'h342: csr_rdata_int = {mcause_q[5], 26'b00000000000000000000000000, mcause_q[4:0]}; |
| 12'h343: csr_rdata_int = mtval_q; |
| 12'h344: begin |
| csr_rdata_int = 1'sb0; |
| csr_rdata_int[ibex_pkg_CSR_MSIX_BIT] = mip[17]; |
| csr_rdata_int[ibex_pkg_CSR_MTIX_BIT] = mip[16]; |
| csr_rdata_int[ibex_pkg_CSR_MEIX_BIT] = mip[15]; |
| csr_rdata_int[ibex_pkg_CSR_MFIX_BIT_HIGH:ibex_pkg_CSR_MFIX_BIT_LOW] = mip[14-:15]; |
| end |
| 12'h747: |
| if (PMPEnable) begin |
| csr_rdata_int = 1'sb0; |
| csr_rdata_int[ibex_pkg_CSR_MSECCFG_MML_BIT] = pmp_mseccfg[0]; |
| csr_rdata_int[ibex_pkg_CSR_MSECCFG_MMWP_BIT] = pmp_mseccfg[1]; |
| csr_rdata_int[ibex_pkg_CSR_MSECCFG_RLB_BIT] = pmp_mseccfg[2]; |
| end |
| else |
| illegal_csr = 1'b1; |
| 12'h757: |
| if (PMPEnable) |
| csr_rdata_int = 1'sb0; |
| else |
| illegal_csr = 1'b1; |
| 12'h3a0: csr_rdata_int = {pmp_cfg_rdata[3], pmp_cfg_rdata[2], pmp_cfg_rdata[1], pmp_cfg_rdata[0]}; |
| 12'h3a1: csr_rdata_int = {pmp_cfg_rdata[7], pmp_cfg_rdata[6], pmp_cfg_rdata[5], pmp_cfg_rdata[4]}; |
| 12'h3a2: csr_rdata_int = {pmp_cfg_rdata[11], pmp_cfg_rdata[10], pmp_cfg_rdata[9], pmp_cfg_rdata[8]}; |
| 12'h3a3: csr_rdata_int = {pmp_cfg_rdata[15], pmp_cfg_rdata[14], pmp_cfg_rdata[13], pmp_cfg_rdata[12]}; |
| 12'h3b0: csr_rdata_int = pmp_addr_rdata[0]; |
| 12'h3b1: csr_rdata_int = pmp_addr_rdata[1]; |
| 12'h3b2: csr_rdata_int = pmp_addr_rdata[2]; |
| 12'h3b3: csr_rdata_int = pmp_addr_rdata[3]; |
| 12'h3b4: csr_rdata_int = pmp_addr_rdata[4]; |
| 12'h3b5: csr_rdata_int = pmp_addr_rdata[5]; |
| 12'h3b6: csr_rdata_int = pmp_addr_rdata[6]; |
| 12'h3b7: csr_rdata_int = pmp_addr_rdata[7]; |
| 12'h3b8: csr_rdata_int = pmp_addr_rdata[8]; |
| 12'h3b9: csr_rdata_int = pmp_addr_rdata[9]; |
| 12'h3ba: csr_rdata_int = pmp_addr_rdata[10]; |
| 12'h3bb: csr_rdata_int = pmp_addr_rdata[11]; |
| 12'h3bc: csr_rdata_int = pmp_addr_rdata[12]; |
| 12'h3bd: csr_rdata_int = pmp_addr_rdata[13]; |
| 12'h3be: csr_rdata_int = pmp_addr_rdata[14]; |
| 12'h3bf: csr_rdata_int = pmp_addr_rdata[15]; |
| 12'h7b0: begin |
| csr_rdata_int = dcsr_q; |
| illegal_csr = ~debug_mode_i; |
| end |
| 12'h7b1: begin |
| csr_rdata_int = depc_q; |
| illegal_csr = ~debug_mode_i; |
| end |
| 12'h7b2: begin |
| csr_rdata_int = dscratch0_q; |
| illegal_csr = ~debug_mode_i; |
| end |
| 12'h7b3: begin |
| csr_rdata_int = dscratch1_q; |
| illegal_csr = ~debug_mode_i; |
| end |
| 12'h320: csr_rdata_int = mcountinhibit; |
| 12'h323, 12'h324, 12'h325, 12'h326, 12'h327, 12'h328, 12'h329, 12'h32a, 12'h32b, 12'h32c, 12'h32d, 12'h32e, 12'h32f, 12'h330, 12'h331, 12'h332, 12'h333, 12'h334, 12'h335, 12'h336, 12'h337, 12'h338, 12'h339, 12'h33a, 12'h33b, 12'h33c, 12'h33d, 12'h33e, 12'h33f: csr_rdata_int = mhpmevent[mhpmcounter_idx]; |
| 12'hb00, 12'hb02, 12'hb03, 12'hb04, 12'hb05, 12'hb06, 12'hb07, 12'hb08, 12'hb09, 12'hb0a, 12'hb0b, 12'hb0c, 12'hb0d, 12'hb0e, 12'hb0f, 12'hb10, 12'hb11, 12'hb12, 12'hb13, 12'hb14, 12'hb15, 12'hb16, 12'hb17, 12'hb18, 12'hb19, 12'hb1a, 12'hb1b, 12'hb1c, 12'hb1d, 12'hb1e, 12'hb1f: csr_rdata_int = mhpmcounter[mhpmcounter_idx][31:0]; |
| 12'hb80, 12'hb82, 12'hb83, 12'hb84, 12'hb85, 12'hb86, 12'hb87, 12'hb88, 12'hb89, 12'hb8a, 12'hb8b, 12'hb8c, 12'hb8d, 12'hb8e, 12'hb8f, 12'hb90, 12'hb91, 12'hb92, 12'hb93, 12'hb94, 12'hb95, 12'hb96, 12'hb97, 12'hb98, 12'hb99, 12'hb9a, 12'hb9b, 12'hb9c, 12'hb9d, 12'hb9e, 12'hb9f: csr_rdata_int = mhpmcounter[mhpmcounter_idx][63:32]; |
| 12'h7a0: begin |
| csr_rdata_int = tselect_rdata; |
| illegal_csr = ~DbgTriggerEn; |
| end |
| 12'h7a1: begin |
| csr_rdata_int = tmatch_control_rdata; |
| illegal_csr = ~DbgTriggerEn; |
| end |
| 12'h7a2: begin |
| csr_rdata_int = tmatch_value_rdata; |
| illegal_csr = ~DbgTriggerEn; |
| end |
| 12'h7a3: begin |
| csr_rdata_int = 1'sb0; |
| illegal_csr = ~DbgTriggerEn; |
| end |
| 12'h7a8: begin |
| csr_rdata_int = 1'sb0; |
| illegal_csr = ~DbgTriggerEn; |
| end |
| 12'h7aa: begin |
| csr_rdata_int = 1'sb0; |
| illegal_csr = ~DbgTriggerEn; |
| end |
| 12'h7c0: csr_rdata_int = {{26 {1'b0}}, cpuctrl_q}; |
| 12'h7c1: csr_rdata_int = 1'sb0; |
| default: illegal_csr = 1'b1; |
| endcase |
| end |
| function automatic [1:0] sv2v_cast_2; |
| input reg [1:0] inp; |
| sv2v_cast_2 = inp; |
| endfunction |
| always @(*) begin |
| exception_pc = pc_id_i; |
| priv_lvl_d = priv_lvl_q; |
| mstatus_en = 1'b0; |
| mstatus_d = mstatus_q; |
| mie_en = 1'b0; |
| mscratch_en = 1'b0; |
| mepc_en = 1'b0; |
| mepc_d = {csr_wdata_int[31:1], 1'b0}; |
| mcause_en = 1'b0; |
| mcause_d = {csr_wdata_int[31], csr_wdata_int[4:0]}; |
| mtval_en = 1'b0; |
| mtval_d = csr_wdata_int; |
| mtvec_en = csr_mtvec_init_i; |
| mtvec_d = (csr_mtvec_init_i ? {boot_addr_i[31:8], 6'b000000, 2'b01} : {csr_wdata_int[31:8], 6'b000000, 2'b01}); |
| dcsr_en = 1'b0; |
| dcsr_d = dcsr_q; |
| depc_d = {csr_wdata_int[31:1], 1'b0}; |
| depc_en = 1'b0; |
| dscratch0_en = 1'b0; |
| dscratch1_en = 1'b0; |
| mstack_en = 1'b0; |
| mstack_d[2] = mstatus_q[4]; |
| mstack_d[1-:2] = mstatus_q[3-:2]; |
| mstack_epc_d = mepc_q; |
| mstack_cause_d = mcause_q; |
| mcountinhibit_we = 1'b0; |
| mhpmcounter_we = 1'sb0; |
| mhpmcounterh_we = 1'sb0; |
| cpuctrl_we = 1'b0; |
| if (csr_we_int) |
| case (csr_addr_i) |
| 12'h300: begin |
| mstatus_en = 1'b1; |
| mstatus_d = {csr_wdata_int[ibex_pkg_CSR_MSTATUS_MIE_BIT], csr_wdata_int[ibex_pkg_CSR_MSTATUS_MPIE_BIT], sv2v_cast_2(csr_wdata_int[ibex_pkg_CSR_MSTATUS_MPP_BIT_HIGH:ibex_pkg_CSR_MSTATUS_MPP_BIT_LOW]), csr_wdata_int[ibex_pkg_CSR_MSTATUS_MPRV_BIT], csr_wdata_int[ibex_pkg_CSR_MSTATUS_TW_BIT]}; |
| if ((mstatus_d[3-:2] != 2'b11) && (mstatus_d[3-:2] != 2'b00)) |
| mstatus_d[3-:2] = 2'b11; |
| end |
| 12'h304: mie_en = 1'b1; |
| 12'h340: mscratch_en = 1'b1; |
| 12'h341: mepc_en = 1'b1; |
| 12'h342: mcause_en = 1'b1; |
| 12'h343: mtval_en = 1'b1; |
| 12'h305: mtvec_en = 1'b1; |
| 12'h7b0: begin |
| dcsr_d = csr_wdata_int; |
| dcsr_d[31-:4] = 4'd4; |
| if ((dcsr_d[1-:2] != 2'b11) && (dcsr_d[1-:2] != 2'b00)) |
| dcsr_d[1-:2] = 2'b11; |
| dcsr_d[8-:3] = dcsr_q[8-:3]; |
| dcsr_d[11] = 1'b0; |
| dcsr_d[3] = 1'b0; |
| dcsr_d[4] = 1'b0; |
| dcsr_d[10] = 1'b0; |
| dcsr_d[9] = 1'b0; |
| dcsr_d[5] = 1'b0; |
| dcsr_d[14] = 1'b0; |
| dcsr_d[27-:12] = 12'h000; |
| dcsr_en = 1'b1; |
| end |
| 12'h7b1: depc_en = 1'b1; |
| 12'h7b2: dscratch0_en = 1'b1; |
| 12'h7b3: dscratch1_en = 1'b1; |
| 12'h320: mcountinhibit_we = 1'b1; |
| 12'hb00, 12'hb02, 12'hb03, 12'hb04, 12'hb05, 12'hb06, 12'hb07, 12'hb08, 12'hb09, 12'hb0a, 12'hb0b, 12'hb0c, 12'hb0d, 12'hb0e, 12'hb0f, 12'hb10, 12'hb11, 12'hb12, 12'hb13, 12'hb14, 12'hb15, 12'hb16, 12'hb17, 12'hb18, 12'hb19, 12'hb1a, 12'hb1b, 12'hb1c, 12'hb1d, 12'hb1e, 12'hb1f: mhpmcounter_we[mhpmcounter_idx] = 1'b1; |
| 12'hb80, 12'hb82, 12'hb83, 12'hb84, 12'hb85, 12'hb86, 12'hb87, 12'hb88, 12'hb89, 12'hb8a, 12'hb8b, 12'hb8c, 12'hb8d, 12'hb8e, 12'hb8f, 12'hb90, 12'hb91, 12'hb92, 12'hb93, 12'hb94, 12'hb95, 12'hb96, 12'hb97, 12'hb98, 12'hb99, 12'hb9a, 12'hb9b, 12'hb9c, 12'hb9d, 12'hb9e, 12'hb9f: mhpmcounterh_we[mhpmcounter_idx] = 1'b1; |
| 12'h7c0: cpuctrl_we = 1'b1; |
| default: |
| ; |
| endcase |
| case (1'b1) |
| csr_save_cause_i: begin |
| case (1'b1) |
| csr_save_if_i: exception_pc = pc_if_i; |
| csr_save_id_i: exception_pc = pc_id_i; |
| csr_save_wb_i: exception_pc = pc_wb_i; |
| default: |
| ; |
| endcase |
| priv_lvl_d = 2'b11; |
| if (debug_csr_save_i) begin |
| dcsr_d[1-:2] = priv_lvl_q; |
| dcsr_d[8-:3] = debug_cause_i; |
| dcsr_en = 1'b1; |
| depc_d = exception_pc; |
| depc_en = 1'b1; |
| end |
| else if (!debug_mode_i) begin |
| mtval_en = 1'b1; |
| mtval_d = csr_mtval_i; |
| mstatus_en = 1'b1; |
| mstatus_d[5] = 1'b0; |
| mstatus_d[4] = mstatus_q[5]; |
| mstatus_d[3-:2] = priv_lvl_q; |
| mepc_en = 1'b1; |
| mepc_d = exception_pc; |
| mcause_en = 1'b1; |
| mcause_d = {csr_mcause_i}; |
| mstack_en = 1'b1; |
| end |
| end |
| csr_restore_dret_i: priv_lvl_d = dcsr_q[1-:2]; |
| csr_restore_mret_i: begin |
| priv_lvl_d = mstatus_q[3-:2]; |
| mstatus_en = 1'b1; |
| mstatus_d[5] = mstatus_q[4]; |
| if (nmi_mode_i) begin |
| mstatus_d[4] = mstack_q[2]; |
| mstatus_d[3-:2] = mstack_q[1-:2]; |
| mepc_en = 1'b1; |
| mepc_d = mstack_epc_q; |
| mcause_en = 1'b1; |
| mcause_d = mstack_cause_q; |
| end |
| else begin |
| mstatus_d[4] = 1'b1; |
| mstatus_d[3-:2] = 2'b00; |
| end |
| end |
| default: |
| ; |
| endcase |
| end |
| always @(posedge clk_i or negedge rst_ni) |
| if (!rst_ni) |
| priv_lvl_q <= 2'b11; |
| else |
| priv_lvl_q <= priv_lvl_d; |
| assign priv_mode_id_o = priv_lvl_q; |
| assign priv_mode_if_o = priv_lvl_d; |
| assign priv_mode_lsu_o = (mstatus_q[1] ? mstatus_q[3-:2] : priv_lvl_q); |
| always @(*) |
| case (csr_op_i) |
| 2'd1: csr_wdata_int = csr_wdata_i; |
| 2'd2: csr_wdata_int = csr_wdata_i | csr_rdata_o; |
| 2'd3: csr_wdata_int = ~csr_wdata_i & csr_rdata_o; |
| 2'd0: csr_wdata_int = csr_wdata_i; |
| default: csr_wdata_int = csr_wdata_i; |
| endcase |
| assign csr_wr = |{csr_op_i == 2'd1, csr_op_i == 2'd2, csr_op_i == 2'd3}; |
| assign csr_we_int = (csr_wr & csr_op_en_i) & ~illegal_csr_insn_o; |
| assign csr_rdata_o = csr_rdata_int; |
| assign csr_mepc_o = mepc_q; |
| assign csr_depc_o = depc_q; |
| assign csr_mtvec_o = mtvec_q; |
| assign csr_mstatus_mie_o = mstatus_q[5]; |
| assign csr_mstatus_tw_o = mstatus_q[0]; |
| assign debug_single_step_o = dcsr_q[2]; |
| assign debug_ebreakm_o = dcsr_q[15]; |
| assign debug_ebreaku_o = dcsr_q[12]; |
| assign irqs_o = mip & mie_q; |
| assign irq_pending_o = |irqs_o; |
| localparam [5:0] MSTATUS_RST_VAL = 6'b010000; |
| ibex_csr #( |
| .Width(6), |
| .ShadowCopy(ShadowCSR), |
| .ResetValue({MSTATUS_RST_VAL}) |
| ) u_mstatus_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i({mstatus_d}), |
| .wr_en_i(mstatus_en), |
| .rd_data_o(mstatus_q), |
| .rd_error_o(mstatus_err) |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_mepc_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(mepc_d), |
| .wr_en_i(mepc_en), |
| .rd_data_o(mepc_q), |
| .rd_error_o() |
| ); |
| assign mie_d[17] = csr_wdata_int[ibex_pkg_CSR_MSIX_BIT]; |
| assign mie_d[16] = csr_wdata_int[ibex_pkg_CSR_MTIX_BIT]; |
| assign mie_d[15] = csr_wdata_int[ibex_pkg_CSR_MEIX_BIT]; |
| assign mie_d[14-:15] = csr_wdata_int[ibex_pkg_CSR_MFIX_BIT_HIGH:ibex_pkg_CSR_MFIX_BIT_LOW]; |
| ibex_csr #( |
| .Width(18), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_mie_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i({mie_d}), |
| .wr_en_i(mie_en), |
| .rd_data_o(mie_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_mscratch_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(csr_wdata_int), |
| .wr_en_i(mscratch_en), |
| .rd_data_o(mscratch_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(6), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_mcause_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(mcause_d), |
| .wr_en_i(mcause_en), |
| .rd_data_o(mcause_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_mtval_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(mtval_d), |
| .wr_en_i(mtval_en), |
| .rd_data_o(mtval_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(ShadowCSR), |
| .ResetValue(32'd1) |
| ) u_mtvec_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(mtvec_d), |
| .wr_en_i(mtvec_en), |
| .rd_data_o(mtvec_q), |
| .rd_error_o(mtvec_err) |
| ); |
| localparam [31:0] DCSR_RESET_VAL = 32'b01000000000000000000000000000011; |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue({DCSR_RESET_VAL}) |
| ) u_dcsr_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i({dcsr_d}), |
| .wr_en_i(dcsr_en), |
| .rd_data_o(dcsr_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_depc_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(depc_d), |
| .wr_en_i(depc_en), |
| .rd_data_o(depc_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_dscratch0_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(csr_wdata_int), |
| .wr_en_i(dscratch0_en), |
| .rd_data_o(dscratch0_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_dscratch1_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(csr_wdata_int), |
| .wr_en_i(dscratch1_en), |
| .rd_data_o(dscratch1_q), |
| .rd_error_o() |
| ); |
| localparam [2:0] MSTACK_RESET_VAL = 3'b100; |
| ibex_csr #( |
| .Width(3), |
| .ShadowCopy(1'b0), |
| .ResetValue({MSTACK_RESET_VAL}) |
| ) u_mstack_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i({mstack_d}), |
| .wr_en_i(mstack_en), |
| .rd_data_o(mstack_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_mstack_epc_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(mstack_epc_d), |
| .wr_en_i(mstack_en), |
| .rd_data_o(mstack_epc_q), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(6), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_mstack_cause_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(mstack_cause_d), |
| .wr_en_i(mstack_en), |
| .rd_data_o(mstack_cause_q), |
| .rd_error_o() |
| ); |
| localparam [11:0] ibex_pkg_CSR_OFF_PMP_ADDR = 12'h3b0; |
| localparam [11:0] ibex_pkg_CSR_OFF_PMP_CFG = 12'h3a0; |
| generate |
| if (PMPEnable) begin : g_pmp_registers |
| wire [2:0] pmp_mseccfg_q; |
| wire [2:0] pmp_mseccfg_d; |
| wire pmp_mseccfg_we; |
| wire pmp_mseccfg_err; |
| wire [5:0] pmp_cfg [0:PMPNumRegions - 1]; |
| wire [PMPNumRegions - 1:0] pmp_cfg_locked; |
| reg [5:0] pmp_cfg_wdata [0:PMPNumRegions - 1]; |
| wire [PMPAddrWidth - 1:0] pmp_addr [0:PMPNumRegions - 1]; |
| wire [PMPNumRegions - 1:0] pmp_cfg_we; |
| wire [PMPNumRegions - 1:0] pmp_cfg_err; |
| wire [PMPNumRegions - 1:0] pmp_addr_we; |
| wire [PMPNumRegions - 1:0] pmp_addr_err; |
| wire any_pmp_entry_locked; |
| genvar i; |
| for (i = 0; i < ibex_pkg_PMP_MAX_REGIONS; i = i + 1) begin : g_exp_rd_data |
| if (i < PMPNumRegions) begin : g_implemented_regions |
| assign pmp_cfg_rdata[i] = {pmp_cfg[i][5], 2'b00, pmp_cfg[i][4-:2], pmp_cfg[i][2], pmp_cfg[i][1], pmp_cfg[i][0]}; |
| if (PMPGranularity == 0) begin : g_pmp_g0 |
| wire [32:1] sv2v_tmp_646D9; |
| assign sv2v_tmp_646D9 = pmp_addr[i]; |
| always @(*) pmp_addr_rdata[i] = sv2v_tmp_646D9; |
| end |
| else if (PMPGranularity == 1) begin : g_pmp_g1 |
| always @(*) begin |
| pmp_addr_rdata[i] = pmp_addr[i]; |
| if ((pmp_cfg[i][4-:2] == 2'b00) || (pmp_cfg[i][4-:2] == 2'b01)) |
| pmp_addr_rdata[i][PMPGranularity - 1:0] = 1'sb0; |
| end |
| end |
| else begin : g_pmp_g2 |
| always @(*) begin |
| pmp_addr_rdata[i] = {pmp_addr[i], {PMPGranularity - 1 {1'b1}}}; |
| if ((pmp_cfg[i][4-:2] == 2'b00) || (pmp_cfg[i][4-:2] == 2'b01)) |
| pmp_addr_rdata[i][PMPGranularity - 1:0] = 1'sb0; |
| end |
| end |
| end |
| else begin : g_other_regions |
| assign pmp_cfg_rdata[i] = 1'sb0; |
| wire [32:1] sv2v_tmp_96282; |
| assign sv2v_tmp_96282 = 1'sb0; |
| always @(*) pmp_addr_rdata[i] = sv2v_tmp_96282; |
| end |
| end |
| for (i = 0; i < PMPNumRegions; i = i + 1) begin : g_pmp_csrs |
| assign pmp_cfg_we[i] = (csr_we_int & ~pmp_cfg_locked[i]) & (csr_addr == (ibex_pkg_CSR_OFF_PMP_CFG + (i[11:0] >> 2))); |
| wire [1:1] sv2v_tmp_43D04; |
| assign sv2v_tmp_43D04 = csr_wdata_int[((i % 4) * ibex_pkg_PMP_CFG_W) + 7]; |
| always @(*) pmp_cfg_wdata[i][5] = sv2v_tmp_43D04; |
| always @(*) |
| case (csr_wdata_int[((i % 4) * ibex_pkg_PMP_CFG_W) + 3+:2]) |
| 2'b00: pmp_cfg_wdata[i][4-:2] = 2'b00; |
| 2'b01: pmp_cfg_wdata[i][4-:2] = 2'b01; |
| 2'b10: pmp_cfg_wdata[i][4-:2] = (PMPGranularity == 0 ? 2'b10 : 2'b00); |
| 2'b11: pmp_cfg_wdata[i][4-:2] = 2'b11; |
| default: pmp_cfg_wdata[i][4-:2] = 2'b00; |
| endcase |
| wire [1:1] sv2v_tmp_B5F8A; |
| assign sv2v_tmp_B5F8A = csr_wdata_int[((i % 4) * ibex_pkg_PMP_CFG_W) + 2]; |
| always @(*) pmp_cfg_wdata[i][2] = sv2v_tmp_B5F8A; |
| wire [1:1] sv2v_tmp_DA81D; |
| assign sv2v_tmp_DA81D = (pmp_mseccfg_q[0] ? csr_wdata_int[((i % 4) * ibex_pkg_PMP_CFG_W) + 1] : &csr_wdata_int[(i % 4) * ibex_pkg_PMP_CFG_W+:2]); |
| always @(*) pmp_cfg_wdata[i][1] = sv2v_tmp_DA81D; |
| wire [1:1] sv2v_tmp_92290; |
| assign sv2v_tmp_92290 = csr_wdata_int[(i % 4) * ibex_pkg_PMP_CFG_W]; |
| always @(*) pmp_cfg_wdata[i][0] = sv2v_tmp_92290; |
| ibex_csr #( |
| .Width(6), |
| .ShadowCopy(ShadowCSR), |
| .ResetValue(1'sb0) |
| ) u_pmp_cfg_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i({pmp_cfg_wdata[i]}), |
| .wr_en_i(pmp_cfg_we[i]), |
| .rd_data_o(pmp_cfg[i]), |
| .rd_error_o(pmp_cfg_err[i]) |
| ); |
| assign pmp_cfg_locked[i] = pmp_cfg[i][5] & ~pmp_mseccfg_q[2]; |
| if (i < (PMPNumRegions - 1)) begin : g_lower |
| assign pmp_addr_we[i] = ((csr_we_int & ~pmp_cfg_locked[i]) & (~pmp_cfg_locked[i + 1] | (pmp_cfg[i + 1][4-:2] != 2'b01))) & (csr_addr == (ibex_pkg_CSR_OFF_PMP_ADDR + i[11:0])); |
| end |
| else begin : g_upper |
| assign pmp_addr_we[i] = (csr_we_int & ~pmp_cfg_locked[i]) & (csr_addr == (ibex_pkg_CSR_OFF_PMP_ADDR + i[11:0])); |
| end |
| ibex_csr #( |
| .Width(PMPAddrWidth), |
| .ShadowCopy(ShadowCSR), |
| .ResetValue(1'sb0) |
| ) u_pmp_addr_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(csr_wdata_int[31-:PMPAddrWidth]), |
| .wr_en_i(pmp_addr_we[i]), |
| .rd_data_o(pmp_addr[i]), |
| .rd_error_o(pmp_addr_err[i]) |
| ); |
| assign csr_pmp_cfg_o[((PMPNumRegions - 1) - i) * 6+:6] = pmp_cfg[i]; |
| assign csr_pmp_addr_o[((PMPNumRegions - 1) - i) * 34+:34] = {pmp_addr_rdata[i], 2'b00}; |
| end |
| assign pmp_mseccfg_we = csr_we_int & (csr_addr == 12'h747); |
| assign pmp_mseccfg_d[0] = (pmp_mseccfg_q[0] ? 1'b1 : csr_wdata_int[ibex_pkg_CSR_MSECCFG_MML_BIT]); |
| assign pmp_mseccfg_d[1] = (pmp_mseccfg_q[1] ? 1'b1 : csr_wdata_int[ibex_pkg_CSR_MSECCFG_MMWP_BIT]); |
| assign any_pmp_entry_locked = |pmp_cfg_locked; |
| assign pmp_mseccfg_d[2] = (any_pmp_entry_locked ? 1'b0 : csr_wdata_int[ibex_pkg_CSR_MSECCFG_RLB_BIT]); |
| ibex_csr #( |
| .Width(3), |
| .ShadowCopy(ShadowCSR), |
| .ResetValue(1'sb0) |
| ) u_pmp_mseccfg( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(pmp_mseccfg_d), |
| .wr_en_i(pmp_mseccfg_we), |
| .rd_data_o(pmp_mseccfg_q), |
| .rd_error_o(pmp_mseccfg_err) |
| ); |
| assign pmp_csr_err = (|pmp_cfg_err | |pmp_addr_err) | pmp_mseccfg_err; |
| assign pmp_mseccfg = pmp_mseccfg_q; |
| end |
| else begin : g_no_pmp_tieoffs |
| genvar i; |
| for (i = 0; i < ibex_pkg_PMP_MAX_REGIONS; i = i + 1) begin : g_rdata |
| wire [32:1] sv2v_tmp_96282; |
| assign sv2v_tmp_96282 = 1'sb0; |
| always @(*) pmp_addr_rdata[i] = sv2v_tmp_96282; |
| assign pmp_cfg_rdata[i] = 1'sb0; |
| end |
| for (i = 0; i < PMPNumRegions; i = i + 1) begin : g_outputs |
| assign csr_pmp_cfg_o[((PMPNumRegions - 1) - i) * 6+:6] = 6'b000000; |
| assign csr_pmp_addr_o[((PMPNumRegions - 1) - i) * 34+:34] = 1'sb0; |
| end |
| assign pmp_csr_err = 1'b0; |
| assign pmp_mseccfg = 1'sb0; |
| end |
| endgenerate |
| assign csr_pmp_mseccfg_o = pmp_mseccfg; |
| always @(*) begin : mcountinhibit_update |
| if (mcountinhibit_we == 1'b1) |
| mcountinhibit_d = {csr_wdata_int[MHPMCounterNum + 2:2], 1'b0, csr_wdata_int[0]}; |
| else |
| mcountinhibit_d = mcountinhibit_q; |
| end |
| always @(*) begin : gen_mhpmcounter_incr |
| begin : sv2v_autoblock_1 |
| reg [31:0] i; |
| for (i = 0; i < 32; i = i + 1) |
| begin : gen_mhpmcounter_incr_inactive |
| mhpmcounter_incr[i] = 1'b0; |
| end |
| end |
| mhpmcounter_incr[0] = 1'b1; |
| mhpmcounter_incr[1] = 1'b0; |
| mhpmcounter_incr[2] = instr_ret_i; |
| mhpmcounter_incr[3] = dside_wait_i; |
| mhpmcounter_incr[4] = iside_wait_i; |
| mhpmcounter_incr[5] = mem_load_i; |
| mhpmcounter_incr[6] = mem_store_i; |
| mhpmcounter_incr[7] = jump_i; |
| mhpmcounter_incr[8] = branch_i; |
| mhpmcounter_incr[9] = branch_taken_i; |
| mhpmcounter_incr[10] = instr_ret_compressed_i; |
| mhpmcounter_incr[11] = mul_wait_i; |
| mhpmcounter_incr[12] = div_wait_i; |
| end |
| always @(*) begin : gen_mhpmevent |
| begin : sv2v_autoblock_2 |
| reg signed [31:0] i; |
| for (i = 0; i < 32; i = i + 1) |
| begin : gen_mhpmevent_active |
| mhpmevent[i] = 1'sb0; |
| mhpmevent[i][i] = 1'b1; |
| end |
| end |
| mhpmevent[1] = 1'sb0; |
| begin : sv2v_autoblock_3 |
| reg [31:0] i; |
| for (i = 3 + MHPMCounterNum; i < 32; i = i + 1) |
| begin : gen_mhpmevent_inactive |
| mhpmevent[i] = 1'sb0; |
| end |
| end |
| end |
| ibex_counter #(.CounterWidth(64)) mcycle_counter_i( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .counter_inc_i(mhpmcounter_incr[0] & ~mcountinhibit[0]), |
| .counterh_we_i(mhpmcounterh_we[0]), |
| .counter_we_i(mhpmcounter_we[0]), |
| .counter_val_i(csr_wdata_int), |
| .counter_val_o(mhpmcounter[0]), |
| .counter_val_upd_o() |
| ); |
| ibex_counter #( |
| .CounterWidth(64), |
| .ProvideValUpd(1) |
| ) minstret_counter_i( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .counter_inc_i(mhpmcounter_incr[2] & ~mcountinhibit[2]), |
| .counterh_we_i(mhpmcounterh_we[2]), |
| .counter_we_i(mhpmcounter_we[2]), |
| .counter_val_i(csr_wdata_int), |
| .counter_val_o(minstret_raw), |
| .counter_val_upd_o(minstret_next) |
| ); |
| assign mhpmcounter[2] = (instr_ret_spec_i & ~mcountinhibit[2] ? minstret_next : minstret_raw); |
| assign mhpmcounter[1] = 1'sb0; |
| assign unused_mhpmcounter_we_1 = mhpmcounter_we[1]; |
| assign unused_mhpmcounterh_we_1 = mhpmcounterh_we[1]; |
| assign unused_mhpmcounter_incr_1 = mhpmcounter_incr[1]; |
| genvar i; |
| generate |
| for (i = 0; i < 29; i = i + 1) begin : gen_cntrs |
| localparam signed [31:0] Cnt = i + 3; |
| if (i < MHPMCounterNum) begin : gen_imp |
| wire [63:0] mhpmcounter_raw; |
| wire [63:0] mhpmcounter_next; |
| ibex_counter #( |
| .CounterWidth(MHPMCounterWidth), |
| .ProvideValUpd(Cnt == 10) |
| ) mcounters_variable_i( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .counter_inc_i(mhpmcounter_incr[Cnt] & ~mcountinhibit[Cnt]), |
| .counterh_we_i(mhpmcounterh_we[Cnt]), |
| .counter_we_i(mhpmcounter_we[Cnt]), |
| .counter_val_i(csr_wdata_int), |
| .counter_val_o(mhpmcounter_raw), |
| .counter_val_upd_o(mhpmcounter_next) |
| ); |
| if (Cnt == 10) begin : gen_compressed_instr_cnt |
| assign mhpmcounter[Cnt] = (instr_ret_compressed_spec_i & ~mcountinhibit[Cnt] ? mhpmcounter_next : mhpmcounter_raw); |
| end |
| else begin : gen_other_cnts |
| wire [63:0] unused_mhpmcounter_next; |
| assign mhpmcounter[Cnt] = mhpmcounter_raw; |
| assign unused_mhpmcounter_next = mhpmcounter_next; |
| end |
| end |
| else begin : gen_unimp |
| assign mhpmcounter[Cnt] = 1'sb0; |
| if (Cnt == 10) begin : gen_no_compressed_instr_cnt |
| wire unused_instr_ret_compressed_spec_i; |
| assign unused_instr_ret_compressed_spec_i = instr_ret_compressed_spec_i; |
| end |
| end |
| end |
| if (MHPMCounterNum < 29) begin : g_mcountinhibit_reduced |
| wire [(29 - MHPMCounterNum) - 1:0] unused_mhphcounter_we; |
| wire [(29 - MHPMCounterNum) - 1:0] unused_mhphcounterh_we; |
| wire [(29 - MHPMCounterNum) - 1:0] unused_mhphcounter_incr; |
| assign mcountinhibit = {{29 - MHPMCounterNum {1'b1}}, mcountinhibit_q}; |
| assign unused_mhphcounter_we = mhpmcounter_we[31:MHPMCounterNum + 3]; |
| assign unused_mhphcounterh_we = mhpmcounterh_we[31:MHPMCounterNum + 3]; |
| assign unused_mhphcounter_incr = mhpmcounter_incr[31:MHPMCounterNum + 3]; |
| end |
| else begin : g_mcountinhibit_full |
| assign mcountinhibit = mcountinhibit_q; |
| end |
| endgenerate |
| always @(posedge clk_i or negedge rst_ni) |
| if (!rst_ni) |
| mcountinhibit_q <= 1'sb0; |
| else |
| mcountinhibit_q <= mcountinhibit_d; |
| generate |
| if (DbgTriggerEn) begin : gen_trigger_regs |
| localparam [31:0] DbgHwNumLen = (DbgHwBreakNum > 1 ? $clog2(DbgHwBreakNum) : 1); |
| localparam [31:0] MaxTselect = DbgHwBreakNum - 1; |
| wire [DbgHwNumLen - 1:0] tselect_d; |
| wire [DbgHwNumLen - 1:0] tselect_q; |
| wire tmatch_control_d; |
| wire [DbgHwBreakNum - 1:0] tmatch_control_q; |
| wire [31:0] tmatch_value_d; |
| wire [31:0] tmatch_value_q [0:DbgHwBreakNum - 1]; |
| wire selected_tmatch_control; |
| wire [31:0] selected_tmatch_value; |
| wire tselect_we; |
| wire [DbgHwBreakNum - 1:0] tmatch_control_we; |
| wire [DbgHwBreakNum - 1:0] tmatch_value_we; |
| wire [DbgHwBreakNum - 1:0] trigger_match; |
| assign tselect_we = (csr_we_int & debug_mode_i) & (csr_addr_i == 12'h7a0); |
| genvar i; |
| for (i = 0; i < DbgHwBreakNum; i = i + 1) begin : g_dbg_tmatch_we |
| assign tmatch_control_we[i] = (((i[DbgHwNumLen - 1:0] == tselect_q) & csr_we_int) & debug_mode_i) & (csr_addr_i == 12'h7a1); |
| assign tmatch_value_we[i] = (((i[DbgHwNumLen - 1:0] == tselect_q) & csr_we_int) & debug_mode_i) & (csr_addr_i == 12'h7a2); |
| end |
| assign tselect_d = (csr_wdata_int < DbgHwBreakNum ? csr_wdata_int[DbgHwNumLen - 1:0] : MaxTselect[DbgHwNumLen - 1:0]); |
| assign tmatch_control_d = csr_wdata_int[2]; |
| assign tmatch_value_d = csr_wdata_int[31:0]; |
| ibex_csr #( |
| .Width(DbgHwNumLen), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_tselect_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(tselect_d), |
| .wr_en_i(tselect_we), |
| .rd_data_o(tselect_q), |
| .rd_error_o() |
| ); |
| for (i = 0; i < DbgHwBreakNum; i = i + 1) begin : g_dbg_tmatch_reg |
| ibex_csr #( |
| .Width(1), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_tmatch_control_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(tmatch_control_d), |
| .wr_en_i(tmatch_control_we[i]), |
| .rd_data_o(tmatch_control_q[i]), |
| .rd_error_o() |
| ); |
| ibex_csr #( |
| .Width(32), |
| .ShadowCopy(1'b0), |
| .ResetValue(1'sb0) |
| ) u_tmatch_value_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i(tmatch_value_d), |
| .wr_en_i(tmatch_value_we[i]), |
| .rd_data_o(tmatch_value_q[i]), |
| .rd_error_o() |
| ); |
| end |
| localparam [31:0] TSelectRdataPadlen = (DbgHwNumLen >= 32 ? 0 : 32 - DbgHwNumLen); |
| assign tselect_rdata = {{TSelectRdataPadlen {1'b0}}, tselect_q}; |
| if (DbgHwBreakNum > 1) begin : g_dbg_tmatch_multiple_select |
| assign selected_tmatch_control = tmatch_control_q[tselect_q]; |
| assign selected_tmatch_value = tmatch_value_q[tselect_q]; |
| end |
| else begin : g_dbg_tmatch_single_select |
| assign selected_tmatch_control = tmatch_control_q[0]; |
| assign selected_tmatch_value = tmatch_value_q[0]; |
| end |
| assign tmatch_control_rdata = {29'b00101000000000000001000001001, selected_tmatch_control, 1'b0, 1'b0}; |
| assign tmatch_value_rdata = selected_tmatch_value; |
| for (i = 0; i < DbgHwBreakNum; i = i + 1) begin : g_dbg_trigger_match |
| assign trigger_match[i] = tmatch_control_q[i] & (pc_if_i[31:0] == tmatch_value_q[i]); |
| end |
| assign trigger_match_o = |trigger_match; |
| end |
| else begin : gen_no_trigger_regs |
| assign tselect_rdata = 'b0; |
| assign tmatch_control_rdata = 'b0; |
| assign tmatch_value_rdata = 'b0; |
| assign trigger_match_o = 'b0; |
| end |
| endgenerate |
| assign cpuctrl_wdata = csr_wdata_int[5:0]; |
| generate |
| if (DataIndTiming) begin : gen_dit |
| assign cpuctrl_d[1] = cpuctrl_wdata[1]; |
| end |
| else begin : gen_no_dit |
| wire unused_dit; |
| assign unused_dit = cpuctrl_wdata[1]; |
| assign cpuctrl_d[1] = 1'b0; |
| end |
| endgenerate |
| assign data_ind_timing_o = cpuctrl_q[1]; |
| generate |
| if (DummyInstructions) begin : gen_dummy |
| assign cpuctrl_d[2] = cpuctrl_wdata[2]; |
| assign cpuctrl_d[5-:3] = cpuctrl_wdata[5-:3]; |
| assign dummy_instr_seed_en_o = csr_we_int && (csr_addr == 12'h7c1); |
| assign dummy_instr_seed_o = csr_wdata_int; |
| end |
| else begin : gen_no_dummy |
| wire unused_dummy_en; |
| wire [2:0] unused_dummy_mask; |
| assign unused_dummy_en = cpuctrl_wdata[2]; |
| assign unused_dummy_mask = cpuctrl_wdata[5-:3]; |
| assign cpuctrl_d[2] = 1'b0; |
| assign cpuctrl_d[5-:3] = 3'b000; |
| assign dummy_instr_seed_en_o = 1'b0; |
| assign dummy_instr_seed_o = 1'sb0; |
| end |
| endgenerate |
| assign dummy_instr_en_o = cpuctrl_q[2]; |
| assign dummy_instr_mask_o = cpuctrl_q[5-:3]; |
| generate |
| if (ICache) begin : gen_icache_enable |
| assign cpuctrl_d[0] = cpuctrl_wdata[0]; |
| end |
| else begin : gen_no_icache |
| wire unused_icen; |
| assign unused_icen = cpuctrl_wdata[0]; |
| assign cpuctrl_d[0] = 1'b0; |
| end |
| endgenerate |
| assign icache_enable_o = cpuctrl_q[0]; |
| ibex_csr #( |
| .Width(6), |
| .ShadowCopy(ShadowCSR), |
| .ResetValue(1'sb0) |
| ) u_cpuctrl_csr( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .wr_data_i({cpuctrl_d}), |
| .wr_en_i(cpuctrl_we), |
| .rd_data_o(cpuctrl_q), |
| .rd_error_o(cpuctrl_err) |
| ); |
| assign csr_shadow_err_o = ((mstatus_err | mtvec_err) | pmp_csr_err) | cpuctrl_err; |
| endmodule |