| `ifdef RISCV_FORMAL |
| `define RVFI |
| `endif |
| |
| |
| /** |
| * Top level module of the brq RISC-V core |
| */ |
| module brq_core #( |
| parameter bit PMPEnable = 1'b0, |
| parameter int unsigned PMPGranularity = 0, |
| parameter int unsigned PMPNumRegions = 0, |
| parameter int unsigned MHPMCounterNum = 0, |
| parameter int unsigned MHPMCounterWidth = 40, |
| parameter bit RV32E = 1'b0, |
| parameter brq_pkg::rv32m_e RV32M = brq_pkg::RV32MFast, |
| parameter brq_pkg::rv32b_e RV32B = brq_pkg::RV32BNone, |
| parameter brq_pkg::regfile_e RegFile = brq_pkg::RegFileFF, |
| parameter brq_pkg::rvfloat_e RVF = brq_pkg::RV32FSingle, // for floating point |
| parameter int unsigned FloatingPoint = 1'b1, |
| parameter bit BranchTargetALU = 1'b0, |
| parameter bit WritebackStage = 1'b1, |
| parameter bit ICache = 1'b0, |
| parameter bit ICacheECC = 1'b0, |
| parameter bit BranchPredictor = 1'b0, |
| parameter bit DbgTriggerEn = 1'b0, |
| parameter int unsigned DbgHwBreakNum = 1, |
| parameter bit Securebrq = 1'b0, |
| parameter int unsigned DmHaltAddr = 32'h1A110800, |
| parameter int unsigned DmExceptionAddr = 32'h1A110808 |
| ) ( |
| // Clock and Reset |
| input logic clk_i, |
| input logic rst_ni, |
| |
| input logic test_en_i, // enable all clock gates for testing |
| |
| input logic [31:0] hart_id_i, |
| input logic [31:0] boot_addr_i, |
| |
| // Instruction memory interface |
| output logic instr_req_o, |
| input logic instr_gnt_i, |
| input logic instr_rvalid_i, |
| output logic [31:0] instr_addr_o, |
| input logic [31:0] instr_rdata_i, |
| input logic instr_err_i, |
| |
| // Data memory interface |
| output logic data_req_o, |
| input logic data_gnt_i, |
| input logic data_rvalid_i, |
| output logic data_we_o, |
| output logic [3:0] data_be_o, |
| output logic [31:0] data_addr_o, |
| output logic [31:0] data_wdata_o, |
| input logic [31:0] data_rdata_i, |
| input logic data_err_i, |
| |
| // Interrupt inputs |
| input logic irq_software_i, |
| input logic irq_timer_i, |
| input logic irq_external_i, |
| input logic [14:0] irq_fast_i, |
| input logic irq_nm_i, // non-maskeable interrupt |
| |
| // Debug Interface |
| input logic debug_req_i, |
| |
| // RISC-V Formal Interface |
| // Does not comply with the coding standards of _i/_o suffixes, but follows |
| // the convention of RISC-V Formal Interface Specification. |
| `ifdef RVFI |
| output logic rvfi_valid, |
| output logic [63:0] rvfi_order, |
| output logic [31:0] rvfi_insn, |
| output logic rvfi_trap, |
| output logic rvfi_halt, |
| output logic rvfi_intr, |
| output logic [ 1:0] rvfi_mode, |
| output logic [ 1:0] rvfi_ixl, |
| output logic [ 4:0] rvfi_rs1_addr, |
| output logic [ 4:0] rvfi_rs2_addr, |
| output logic [ 4:0] rvfi_rs3_addr, |
| output logic [31:0] rvfi_rs1_rdata, |
| output logic [31:0] rvfi_rs2_rdata, |
| output logic [31:0] rvfi_rs3_rdata, |
| output logic [ 4:0] rvfi_rd_addr, |
| output logic [31:0] rvfi_rd_wdata, |
| output logic [31:0] rvfi_pc_rdata, |
| output logic [31:0] rvfi_pc_wdata, |
| output logic [31:0] rvfi_mem_addr, |
| output logic [ 3:0] rvfi_mem_rmask, |
| output logic [ 3:0] rvfi_mem_wmask, |
| output logic [31:0] rvfi_mem_rdata, |
| output logic [31:0] rvfi_mem_wdata, |
| `endif |
| |
| // CPU Control Signals |
| input logic fetch_enable_i, |
| output logic alert_minor_o, |
| output logic alert_major_o, |
| output logic core_sleep_o |
| ); |
| |
| import brq_pkg::*; |
| |
| // floating point |
| localparam int unsigned W = 32; |
| logic fp_flush; |
| logic in_ready_c2fpu; // ready - from core to FPU |
| logic in_valid_c2fpu; // valid - from FPU to core |
| logic out_ready_fpu2c; // ready - from FPU to core |
| logic out_valid_fpu2c; // valid - from core to FPU |
| logic valid_id_fpu; // select which valid signal will go to dec |
| logic fp_rm_dynamic; |
| logic fp_alu_op_mod; |
| logic [4:0] fp_rf_raddr_a; |
| logic [4:0] fp_rf_raddr_b; |
| logic [4:0] fp_rf_raddr_c; |
| logic [W-1:0] fp_rf_rdata_a; |
| logic [W-1:0] fp_rf_rdata_b; |
| logic [W-1:0] fp_rf_rdata_c; |
| logic fp_rf_wen_id; |
| logic is_fp_instr; |
| logic [2:0][W-1:0] fp_operands; // three operands in fpu |
| logic fp_busy; |
| logic fpu_busy_idu; |
| logic [W-1:0] fp_result; |
| logic [ 31:0] data_wb; |
| logic [4:0] fp_rf_waddr_id; |
| logic [4:0] fp_rf_waddr_wb; |
| logic fp_rf_we; |
| logic fp_rf_wen_wb; |
| logic use_fp_rs1; |
| logic use_fp_rs2; |
| logic use_fp_rd; |
| logic fp_rf_write_wb; |
| logic [31:0] rf_int_fp_lsu; |
| logic fp_swap_oprnds; |
| logic fpu_is_busy; |
| logic fp_load; |
| logic [31:0] fp_rf_wdata_wb; |
| fpnew_pkg::status_t fp_status; |
| fpnew_pkg::operation_e fp_operation; |
| fpnew_pkg::roundmode_e fp_rounding_mode; |
| fpnew_pkg::roundmode_e fp_frm_csr; |
| fpnew_pkg::roundmode_e fp_frm_fpnew; |
| fpnew_pkg::operation_e fp_alu_operator; |
| fpnew_pkg::fp_format_e fp_src_fmt; |
| fpnew_pkg::fp_format_e fp_dst_fmt; |
| |
| // brq |
| localparam int unsigned PMP_NUM_CHAN = 2; |
| localparam bit DataIndTiming = Securebrq; |
| localparam bit DummyInstructions = Securebrq; |
| localparam bit PCIncrCheck = Securebrq; |
| localparam bit ShadowCSR = Securebrq; |
| // Speculative branch option, trades-off performance against timing. |
| // Setting this to 1 eases branch target critical paths significantly but reduces performance |
| // by ~3% (based on CoreMark/MHz score). |
| // Set by default in the max PMP config which has the tightest budget for branch target timing. |
| localparam bit SpecBranch = PMPEnable & (PMPNumRegions == 16); |
| localparam bit RegFileECC = Securebrq; |
| localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; |
| |
| // IF/ID signals |
| logic dummy_instr_id; |
| logic instr_valid_id; |
| logic instr_new_id; |
| logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage |
| logic [31:0] instr_rdata_alu_id; // Instruction sampled inside IF stage (replicated to |
| // ease fan-out) |
| logic [15:0] instr_rdata_c_id; // Compressed instruction sampled inside IF stage |
| logic instr_is_compressed_id; |
| logic instr_perf_count_id; |
| logic instr_bp_taken_id; |
| logic instr_fetch_err; // Bus error on instr fetch |
| logic instr_fetch_err_plus2; // Instruction error is misaligned |
| logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage |
| logic [31:0] pc_if; // Program counter in IF stage |
| logic [31:0] pc_id; // Program counter in ID stage |
| logic [31:0] pc_wb; // Program counter in WB stage |
| logic [33:0] imd_val_d_ex[2]; // Intermediate register for multicycle Ops |
| logic [33:0] imd_val_q_ex[2]; // Intermediate register for multicycle Ops |
| logic [1:0] imd_val_we_ex; |
| |
| logic data_ind_timing; |
| logic dummy_instr_en; |
| logic [2:0] dummy_instr_mask; |
| logic dummy_instr_seed_en; |
| logic [31:0] dummy_instr_seed; |
| logic icache_enable; |
| logic icache_inval; |
| logic pc_mismatch_alert; |
| logic csr_shadow_err; |
| |
| logic instr_first_cycle_id; |
| logic instr_valid_clear; |
| logic pc_set; |
| logic pc_set_spec; |
| logic nt_branch_mispredict; |
| pc_sel_e pc_mux_id; // Mux selector for next PC |
| exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC |
| exc_cause_e exc_cause; // Exception cause |
| |
| logic lsu_load_err; |
| logic lsu_store_err; |
| |
| // LSU signals |
| logic lsu_addr_incr_req; |
| logic [31:0] lsu_addr_last; |
| |
| // Jump and branch target and decision (EX->IF) |
| logic [31:0] branch_target_ex; |
| logic branch_decision; |
| |
| // Core busy signals |
| logic ctrl_busy; |
| logic if_busy; |
| logic lsu_busy; |
| logic core_busy_d, core_busy_q; |
| |
| // Register File |
| logic [4:0] rf_raddr_a; |
| logic [31:0] rf_rdata_a; |
| logic [4:0] rf_raddr_b; |
| logic [31:0] rf_rdata_b; |
| logic rf_ren_a; |
| logic rf_ren_b; |
| logic [4:0] rf_waddr_wb; |
| logic [31:0] rf_wdata_wb; |
| // Writeback register write data that can be used on the forwarding path (doesn't factor in memory |
| // read data as this is too late for the forwarding path) |
| logic [31:0] rf_wdata_fwd_wb; |
| logic [31:0] rf_wdata_lsu; |
| logic rf_we_wb; |
| logic rf_we_lsu; |
| |
| logic [4:0] rf_waddr_id; |
| logic [31:0] rf_wdata_id; |
| logic rf_we_id; |
| logic rf_rd_a_wb_match; |
| logic rf_rd_b_wb_match; |
| |
| // ALU Control |
| alu_op_e alu_operator_ex; |
| logic [31:0] alu_operand_a_ex; |
| logic [31:0] alu_operand_b_ex; |
| |
| logic [31:0] bt_a_operand; |
| logic [31:0] bt_b_operand; |
| |
| logic [31:0] alu_adder_result_ex; // Used to forward computed address to LSU |
| logic [31:0] result_ex; |
| |
| // Multiplier Control |
| logic mult_en_ex; |
| logic div_en_ex; |
| logic mult_sel_ex; |
| logic div_sel_ex; |
| md_op_e multdiv_operator_ex; |
| logic [1:0] multdiv_signed_mode_ex; |
| logic [31:0] multdiv_operand_a_ex; |
| logic [31:0] multdiv_operand_b_ex; |
| logic multdiv_ready_id; |
| |
| // CSR control |
| logic csr_access; |
| csr_op_e csr_op; |
| logic csr_op_en; |
| csr_num_e csr_addr; |
| logic [31:0] csr_rdata; |
| logic [31:0] csr_wdata; |
| logic illegal_csr_insn_id; // CSR access to non-existent register, |
| // with wrong priviledge level, |
| // or missing write permissions |
| |
| // Data Memory Control |
| logic lsu_we; |
| logic [1:0] lsu_type; |
| logic lsu_sign_ext; |
| logic lsu_req; |
| logic [31:0] lsu_wdata; |
| logic lsu_req_done; |
| |
| // stall control |
| logic id_in_ready; |
| logic ex_valid; |
| |
| logic lsu_resp_valid; |
| logic lsu_resp_err; |
| |
| // Signals between instruction core interface and pipe (if and id stages) |
| logic instr_req_int; // Id stage asserts a req to instruction core interface |
| |
| // Writeback stage |
| logic en_wb; |
| wb_instr_type_e instr_type_wb; |
| logic ready_wb; |
| logic rf_write_wb; |
| logic outstanding_load_wb; |
| logic outstanding_store_wb; |
| |
| // Interrupts |
| logic irq_pending; |
| logic nmi_mode; |
| irqs_t irqs; |
| logic csr_mstatus_mie; |
| logic [31:0] csr_mepc, csr_depc; |
| |
| // PMP signals |
| logic [33:0] csr_pmp_addr [PMPNumRegions]; |
| pmp_cfg_t csr_pmp_cfg [PMPNumRegions]; |
| logic pmp_req_err [PMP_NUM_CHAN]; |
| logic instr_req_out; |
| logic data_req_out; |
| |
| logic csr_save_if; |
| logic csr_save_id; |
| logic csr_save_wb; |
| logic csr_restore_mret_id; |
| logic csr_restore_dret_id; |
| logic csr_save_cause; |
| logic csr_mtvec_init; |
| logic [31:0] csr_mtvec; |
| logic [31:0] csr_mtval; |
| logic csr_mstatus_tw; |
| priv_lvl_e priv_mode_id; |
| priv_lvl_e priv_mode_if; |
| priv_lvl_e priv_mode_lsu; |
| |
| // debug mode and dcsr configuration |
| logic debug_mode; |
| dbg_cause_e debug_cause; |
| logic debug_csr_save; |
| logic debug_single_step; |
| logic debug_ebreakm; |
| logic debug_ebreaku; |
| logic trigger_match; |
| |
| // signals relating to instruction movements between pipeline stages |
| // used by performance counters and RVFI |
| logic instr_id_done; |
| logic instr_done_wb; |
| |
| logic perf_instr_ret_wb; |
| logic perf_instr_ret_compressed_wb; |
| logic perf_iside_wait; |
| logic perf_dside_wait; |
| logic perf_mul_wait; |
| logic perf_div_wait; |
| logic perf_jump; |
| logic perf_branch; |
| logic perf_tbranch; |
| logic perf_load; |
| logic perf_store; |
| |
| // for RVFI |
| logic illegal_insn_id, unused_illegal_insn_id; // ID stage sees an illegal instruction |
| |
| // RISC-V Formal Interface signals |
| `ifdef RVFI |
| logic rvfi_instr_new_wb; |
| logic rvfi_intr_d; |
| logic rvfi_intr_q; |
| logic rvfi_set_trap_pc_d; |
| logic rvfi_set_trap_pc_q; |
| logic [31:0] rvfi_insn_id; |
| logic [4:0] rvfi_rs1_addr_d; |
| logic [4:0] rvfi_rs1_addr_q; |
| logic [4:0] rvfi_rs2_addr_d; |
| logic [4:0] rvfi_rs2_addr_q; |
| logic [4:0] rvfi_rs3_addr_d; |
| logic [31:0] rvfi_rs1_data_d; |
| logic [31:0] rvfi_rs1_data_q; |
| logic [31:0] rvfi_rs2_data_d; |
| logic [31:0] rvfi_rs2_data_q; |
| logic [31:0] rvfi_rs3_data_d; |
| logic [4:0] rvfi_rd_addr_wb; |
| logic [4:0] rvfi_rd_addr_q; |
| logic [4:0] rvfi_rd_addr_d; |
| logic [31:0] rvfi_rd_wdata_wb; |
| logic [31:0] rvfi_rd_wdata_d; |
| logic [31:0] rvfi_rd_wdata_q; |
| logic rvfi_rd_we_wb; |
| logic [3:0] rvfi_mem_mask_int; |
| logic [31:0] rvfi_mem_rdata_d; |
| logic [31:0] rvfi_mem_rdata_q; |
| logic [31:0] rvfi_mem_wdata_d; |
| logic [31:0] rvfi_mem_wdata_q; |
| logic [31:0] rvfi_mem_addr_d; |
| logic [31:0] rvfi_mem_addr_q; |
| `endif |
| |
| ////////////////////// |
| // Clock management // |
| ////////////////////// |
| |
| logic clk; |
| |
| logic clock_en; |
| |
| // Before going to sleep, wait for I- and D-side |
| // interfaces to finish ongoing operations. |
| assign core_busy_d = ctrl_busy | if_busy | lsu_busy | fp_busy; |
| |
| always_ff @(posedge clk_i or negedge rst_ni) begin |
| if (!rst_ni) begin |
| core_busy_q <= 1'b0; |
| end else begin |
| core_busy_q <= core_busy_d; |
| end |
| end |
| // capture fetch_enable_i in fetch_enable_q, once for ever |
| logic fetch_enable_q; |
| always_ff @(posedge clk_i or negedge rst_ni) begin |
| if (!rst_ni) begin |
| fetch_enable_q <= 1'b0; |
| end else if (fetch_enable_i) begin |
| fetch_enable_q <= 1'b1; |
| end |
| end |
| |
| assign clock_en = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i); |
| assign core_sleep_o = ~clock_en; |
| |
| // main clock gate of the core |
| // generates all clocks except the one for the debug unit which is |
| // independent |
| prim_clock_gating core_clock_gate_i ( |
| .clk_i ( clk_i ), |
| .en_i ( clock_en ), |
| .test_en_i ( test_en_i ), |
| .clk_o ( clk ) |
| ); |
| |
| ////////////// |
| // IF stage // |
| ////////////// |
| |
| brq_ifu #( |
| .DmHaltAddr ( DmHaltAddr ), |
| .DmExceptionAddr ( DmExceptionAddr ), |
| .DummyInstructions ( DummyInstructions ), |
| .ICache ( ICache ), |
| .ICacheECC ( ICacheECC ), |
| .PCIncrCheck ( PCIncrCheck ), |
| .BranchPredictor ( BranchPredictor ) |
| ) if_stage_i ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| |
| .boot_addr_i ( boot_addr_i ), |
| .req_i ( instr_req_int ), // instruction request control |
| |
| // instruction cache interface |
| .instr_req_o ( instr_req_out ), |
| .instr_addr_o ( instr_addr_o ), |
| .instr_gnt_i ( instr_gnt_i ), |
| .instr_rvalid_i ( instr_rvalid_i ), |
| .instr_rdata_i ( instr_rdata_i ), |
| .instr_err_i ( instr_err_i ), |
| .instr_pmp_err_i ( pmp_req_err[PMP_I] ), |
| |
| // outputs to ID stage |
| .instr_valid_id_o ( instr_valid_id ), |
| .instr_new_id_o ( instr_new_id ), |
| .instr_rdata_id_o ( instr_rdata_id ), |
| .instr_rdata_alu_id_o ( instr_rdata_alu_id ), |
| .instr_rdata_c_id_o ( instr_rdata_c_id ), |
| .instr_is_compressed_id_o ( instr_is_compressed_id ), |
| .instr_bp_taken_o ( instr_bp_taken_id ), |
| .instr_fetch_err_o ( instr_fetch_err ), |
| .instr_fetch_err_plus2_o ( instr_fetch_err_plus2 ), |
| .illegal_c_insn_id_o ( illegal_c_insn_id ), |
| .dummy_instr_id_o ( dummy_instr_id ), |
| .pc_if_o ( pc_if ), |
| .pc_id_o ( pc_id ), |
| |
| // control signals |
| .instr_valid_clear_i ( instr_valid_clear ), |
| .pc_set_i ( pc_set ), |
| .pc_set_spec_i ( pc_set_spec ), |
| .pc_mux_i ( pc_mux_id ), |
| .nt_branch_mispredict_i ( nt_branch_mispredict ), |
| .exc_pc_mux_i ( exc_pc_mux_id ), |
| .exc_cause ( exc_cause ), |
| .dummy_instr_en_i ( dummy_instr_en ), |
| .dummy_instr_mask_i ( dummy_instr_mask ), |
| .dummy_instr_seed_en_i ( dummy_instr_seed_en ), |
| .dummy_instr_seed_i ( dummy_instr_seed ), |
| .icache_enable_i ( icache_enable ), |
| .icache_inval_i ( icache_inval ), |
| |
| // branch targets |
| .branch_target_ex_i ( branch_target_ex ), |
| |
| // CSRs |
| .csr_mepc_i ( csr_mepc ), // exception return address |
| .csr_depc_i ( csr_depc ), // debug return address |
| .csr_mtvec_i ( csr_mtvec ), // trap-vector base address |
| .csr_mtvec_init_o ( csr_mtvec_init ), |
| |
| // pipeline stalls |
| .id_in_ready_i ( id_in_ready ), |
| .pc_mismatch_alert_o ( pc_mismatch_alert ), |
| .if_busy_o ( if_busy ) |
| ); |
| |
| // Core is waiting for the ISide when ID/EX stage is ready for a new instruction but none are |
| // available |
| assign perf_iside_wait = id_in_ready & ~instr_valid_id; |
| |
| // Qualify the instruction request with PMP error |
| assign instr_req_o = instr_req_out & ~pmp_req_err[PMP_I]; |
| |
| ////////////// |
| // ID stage // |
| ////////////// |
| |
| brq_idu #( |
| .RV32E ( RV32E ), |
| .RV32M ( RV32M ), |
| .RV32B ( RV32B ), |
| .BranchTargetALU ( BranchTargetALU ), |
| .DataIndTiming ( DataIndTiming ), |
| .SpecBranch ( SpecBranch ), |
| .WritebackStage ( WritebackStage ), |
| .BranchPredictor ( BranchPredictor ) |
| ) id_stage_i ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| |
| // Processor Enable |
| .ctrl_busy_o ( ctrl_busy ), |
| .illegal_insn_o ( illegal_insn_id ), |
| |
| // from/to IF-ID pipeline register |
| .instr_valid_i ( instr_valid_id ), |
| .instr_rdata_i ( instr_rdata_id ), |
| .instr_rdata_alu_i ( instr_rdata_alu_id ), |
| .instr_rdata_c_i ( instr_rdata_c_id ), |
| .instr_is_compressed_i ( instr_is_compressed_id ), |
| .instr_bp_taken_i ( instr_bp_taken_id ), |
| |
| // Jumps and branches |
| .branch_decision_i ( branch_decision ), |
| |
| // IF and ID control signals |
| .instr_first_cycle_id_o ( instr_first_cycle_id ), |
| .instr_valid_clear_o ( instr_valid_clear ), |
| .id_in_ready_o ( id_in_ready ), |
| .instr_req_o ( instr_req_int ), |
| .pc_set_o ( pc_set ), |
| .pc_set_spec_o ( pc_set_spec ), |
| .pc_mux_o ( pc_mux_id ), |
| .nt_branch_mispredict_o ( nt_branch_mispredict ), |
| .exc_pc_mux_o ( exc_pc_mux_id ), |
| .exc_cause_o ( exc_cause ), |
| .icache_inval_o ( icache_inval ), |
| |
| .instr_fetch_err_i ( instr_fetch_err ), |
| .instr_fetch_err_plus2_i ( instr_fetch_err_plus2 ), |
| .illegal_c_insn_i ( illegal_c_insn_id ), |
| |
| .pc_id_i ( pc_id ), |
| |
| // Stalls |
| .ex_valid_i ( valid_id_fpu ), // changed by zeeshan from |
| // ex_valid to valid_id_fpu |
| // for ready selection |
| .lsu_resp_valid_i ( lsu_resp_valid ), |
| |
| .alu_operator_ex_o ( alu_operator_ex ), |
| .alu_operand_a_ex_o ( alu_operand_a_ex ), |
| .alu_operand_b_ex_o ( alu_operand_b_ex ), |
| |
| .imd_val_q_ex_o ( imd_val_q_ex ), |
| .imd_val_d_ex_i ( imd_val_d_ex ), |
| .imd_val_we_ex_i ( imd_val_we_ex ), |
| |
| .bt_a_operand_o ( bt_a_operand ), |
| .bt_b_operand_o ( bt_b_operand ), |
| |
| .mult_en_ex_o ( mult_en_ex ), |
| .div_en_ex_o ( div_en_ex ), |
| .mult_sel_ex_o ( mult_sel_ex ), |
| .div_sel_ex_o ( div_sel_ex ), |
| .multdiv_operator_ex_o ( multdiv_operator_ex ), |
| .multdiv_signed_mode_ex_o ( multdiv_signed_mode_ex ), |
| .multdiv_operand_a_ex_o ( multdiv_operand_a_ex ), |
| .multdiv_operand_b_ex_o ( multdiv_operand_b_ex ), |
| .multdiv_ready_id_o ( multdiv_ready_id ), |
| |
| // CSR ID/EX |
| .csr_access_o ( csr_access ), |
| .csr_op_o ( csr_op ), |
| .csr_op_en_o ( csr_op_en ), |
| .csr_save_if_o ( csr_save_if ), // control signal to save PC |
| .csr_save_id_o ( csr_save_id ), // control signal to save PC |
| .csr_save_wb_o ( csr_save_wb ), // control signal to save PC |
| .csr_restore_mret_id_o ( csr_restore_mret_id ), // restore mstatus upon MRET |
| .csr_restore_dret_id_o ( csr_restore_dret_id ), // restore mstatus upon MRET |
| .csr_save_cause_o ( csr_save_cause ), |
| .csr_mtval_o ( csr_mtval ), |
| .priv_mode_i ( priv_mode_id ), |
| .csr_mstatus_tw_i ( csr_mstatus_tw ), |
| .illegal_csr_insn_i ( illegal_csr_insn_id ), |
| .data_ind_timing_i ( data_ind_timing ), |
| |
| // LSU |
| .lsu_req_o ( lsu_req ), // to load store unit |
| .lsu_we_o ( lsu_we ), // to load store unit |
| .lsu_type_o ( lsu_type ), // to load store unit |
| .lsu_sign_ext_o ( lsu_sign_ext ), // to load store unit |
| .lsu_wdata_o ( lsu_wdata ), // to load store unit |
| .lsu_req_done_i ( lsu_req_done ), // from load store unit |
| |
| .lsu_addr_incr_req_i ( lsu_addr_incr_req ), |
| .lsu_addr_last_i ( lsu_addr_last ), |
| |
| .lsu_load_err_i ( lsu_load_err ), |
| .lsu_store_err_i ( lsu_store_err ), |
| |
| // Interrupt Signals |
| .csr_mstatus_mie_i ( csr_mstatus_mie ), |
| .irq_pending_i ( irq_pending ), |
| .irqs_i ( irqs ), |
| .irq_nm_i ( irq_nm_i ), |
| .nmi_mode_o ( nmi_mode ), |
| |
| // Debug Signal |
| .debug_mode_o ( debug_mode ), |
| .debug_cause_o ( debug_cause ), |
| .debug_csr_save_o ( debug_csr_save ), |
| .debug_req_i ( debug_req_i ), |
| .debug_single_step_i ( debug_single_step ), |
| .debug_ebreakm_i ( debug_ebreakm ), |
| .debug_ebreaku_i ( debug_ebreaku ), |
| .trigger_match_i ( trigger_match ), |
| |
| // write data to commit in the register file |
| .result_ex_i ( data_wb ), // changed by zeeshan from result_ex |
| // to data_wb for FVCT, FMV.WX ins |
| .csr_rdata_i ( csr_rdata ), |
| |
| .rf_raddr_a_o ( rf_raddr_a ), |
| .rf_rdata_a_i ( rf_rdata_a ), |
| .rf_raddr_b_o ( rf_raddr_b ), |
| .rf_rdata_b_i ( rf_int_fp_lsu ), |
| .rf_ren_a_o ( rf_ren_a ), |
| .rf_ren_b_o ( rf_ren_b ), |
| .rf_waddr_id_o ( rf_waddr_id ), |
| .rf_wdata_id_o ( rf_wdata_id ), |
| .rf_we_id_o ( rf_we_id ), |
| .rf_rd_a_wb_match_o ( rf_rd_a_wb_match ), |
| .rf_rd_b_wb_match_o ( rf_rd_b_wb_match ), |
| |
| .rf_waddr_wb_i ( rf_waddr_wb ), |
| .rf_wdata_fwd_wb_i ( rf_wdata_fwd_wb ), |
| .rf_write_wb_i ( rf_write_wb ), |
| |
| .en_wb_o ( en_wb ), |
| .instr_type_wb_o ( instr_type_wb ), |
| .instr_perf_count_id_o ( instr_perf_count_id ), |
| .ready_wb_i ( ready_wb ), |
| .outstanding_load_wb_i ( outstanding_load_wb ), |
| .outstanding_store_wb_i ( outstanding_store_wb ), |
| |
| // Performance Counters |
| .perf_jump_o ( perf_jump ), |
| .perf_branch_o ( perf_branch ), |
| .perf_tbranch_o ( perf_tbranch ), |
| .perf_dside_wait_o ( perf_dside_wait ), |
| .perf_mul_wait_o ( perf_mul_wait ), |
| .perf_div_wait_o ( perf_div_wait ), |
| .instr_id_done_o ( instr_id_done ), |
| |
| // Floating point extensions IO |
| .fp_rounding_mode_o ( fp_rounding_mode ), // defines the rounding mode |
| .fp_rf_rdata_a_i ( fp_rf_rdata_a ), |
| .fp_rf_rdata_b_i ( fp_rf_rdata_b ), |
| .fp_rf_rdata_c_i ( fp_rf_rdata_c ), |
| .fp_rf_raddr_a_o ( fp_rf_raddr_a ), |
| .fp_rf_raddr_b_o ( fp_rf_raddr_b ), |
| .fp_rf_raddr_c_o ( fp_rf_raddr_c ), |
| .fp_rf_waddr_o ( fp_rf_waddr_id ), |
| .fp_rf_we_o ( fp_rf_wen_id ), |
| .fp_alu_operator_o ( fp_alu_operator ), |
| .fp_alu_op_mod_o ( fp_alu_op_mod ), |
| .fp_src_fmt_o ( fp_src_fmt ), |
| .fp_dst_fmt_o ( fp_dst_fmt ), |
| .fp_rm_dynamic_o ( fp_rm_dynamic ), |
| .fp_flush_o ( fp_flush ), |
| .is_fp_instr_o ( is_fp_instr ), |
| .use_fp_rs1_o ( use_fp_rs1 ), |
| .use_fp_rs2_o ( use_fp_rs2 ), |
| .use_fp_rs3_o ( use_fp_rs3 ), |
| .use_fp_rd_o ( use_fp_rd ), |
| .fpu_busy_i ( fpu_busy_idu ), |
| .fp_rf_write_wb_i ( fp_rf_write_wb ), |
| .fp_rf_wdata_fwd_wb_i ( fp_rf_wdata_wb ), |
| .fp_operands_o ( fp_operands ), |
| .fp_load_o ( fp_load ) |
| ); |
| |
| // for RVFI only |
| assign unused_illegal_insn_id = illegal_insn_id; |
| |
| brq_exu #( |
| .RV32M ( RV32M ), |
| .RV32B ( RV32B ), |
| .BranchTargetALU ( BranchTargetALU ) |
| ) ex_block_i ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| |
| // ALU signal from ID stage |
| .alu_operator_i ( alu_operator_ex ), |
| .alu_operand_a_i ( alu_operand_a_ex ), |
| .alu_operand_b_i ( alu_operand_b_ex ), |
| .alu_instr_first_cycle_i ( instr_first_cycle_id ), |
| |
| // Branch target ALU signal from ID stage |
| .bt_a_operand_i ( bt_a_operand ), |
| .bt_b_operand_i ( bt_b_operand ), |
| |
| // Multipler/Divider signal from ID stage |
| .multdiv_operator_i ( multdiv_operator_ex ), |
| .mult_en_i ( mult_en_ex ), |
| .div_en_i ( div_en_ex ), |
| .mult_sel_i ( mult_sel_ex ), |
| .div_sel_i ( div_sel_ex ), |
| .multdiv_signed_mode_i ( multdiv_signed_mode_ex ), |
| .multdiv_operand_a_i ( multdiv_operand_a_ex ), |
| .multdiv_operand_b_i ( multdiv_operand_b_ex ), |
| .multdiv_ready_id_i ( multdiv_ready_id ), |
| .data_ind_timing_i ( data_ind_timing ), |
| |
| // Intermediate value register |
| .imd_val_we_o ( imd_val_we_ex ), |
| .imd_val_d_o ( imd_val_d_ex ), |
| .imd_val_q_i ( imd_val_q_ex ), |
| |
| // Outputs |
| .alu_adder_result_ex_o ( alu_adder_result_ex ), // to LSU |
| .result_ex_o ( result_ex ), // to ID |
| |
| .branch_target_o ( branch_target_ex ), // to IF |
| .branch_decision_o ( branch_decision ), // to ID |
| |
| .ex_valid_o ( ex_valid ) |
| ); |
| |
| ///////////////////// |
| // Load/store unit // |
| ///////////////////// |
| |
| assign data_req_o = data_req_out & ~pmp_req_err[PMP_D]; |
| assign lsu_resp_err = lsu_load_err | lsu_store_err; |
| |
| brq_lsu load_store_unit_i ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| |
| // data interface |
| .data_req_o ( data_req_out ), |
| .data_gnt_i ( data_gnt_i ), |
| .data_rvalid_i ( data_rvalid_i ), |
| .data_err_i ( data_err_i ), |
| .data_pmp_err_i ( pmp_req_err[PMP_D] ), |
| |
| .data_addr_o ( data_addr_o ), |
| .data_we_o ( data_we_o ), |
| .data_be_o ( data_be_o ), |
| .data_wdata_o ( data_wdata_o ), |
| .data_rdata_i ( data_rdata_i ), |
| |
| // signals to/from ID/EX stage |
| .lsu_we_i ( lsu_we ), |
| .lsu_type_i ( lsu_type ), |
| .lsu_wdata_i ( lsu_wdata ), |
| .lsu_sign_ext_i ( lsu_sign_ext ), |
| |
| .lsu_rdata_o ( rf_wdata_lsu ), |
| .lsu_rdata_valid_o ( rf_we_lsu ), |
| .lsu_req_i ( lsu_req ), |
| .lsu_req_done_o ( lsu_req_done ), |
| |
| .adder_result_ex_i ( alu_adder_result_ex ), |
| |
| .addr_incr_req_o ( lsu_addr_incr_req ), |
| .addr_last_o ( lsu_addr_last ), |
| |
| |
| .lsu_resp_valid_o ( lsu_resp_valid ), |
| |
| // exception signals |
| .load_err_o ( lsu_load_err ), |
| .store_err_o ( lsu_store_err ), |
| |
| .busy_o ( lsu_busy ), |
| |
| .perf_load_o ( perf_load ), |
| .perf_store_o ( perf_store ) |
| ); |
| |
| brq_wbu #( |
| .WritebackStage ( WritebackStage ) |
| ) wb_stage_i ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| .en_wb_i ( en_wb ), |
| .instr_type_wb_i ( instr_type_wb ), |
| .pc_id_i ( pc_id ), |
| .instr_is_compressed_id_i ( instr_is_compressed_id ), |
| .instr_perf_count_id_i ( instr_perf_count_id ), |
| |
| .ready_wb_o ( ready_wb ), |
| .rf_write_wb_o ( rf_write_wb ), |
| .outstanding_load_wb_o ( outstanding_load_wb ), |
| .outstanding_store_wb_o ( outstanding_store_wb ), |
| .pc_wb_o ( pc_wb ), |
| .perf_instr_ret_wb_o ( perf_instr_ret_wb ), |
| .perf_instr_ret_compressed_wb_o ( perf_instr_ret_compressed_wb ), |
| |
| .rf_waddr_id_i ( rf_waddr_id ), |
| .rf_wdata_id_i ( rf_wdata_id ), |
| .rf_we_id_i ( rf_we_id ), |
| |
| .rf_wdata_lsu_i ( rf_wdata_lsu ), |
| .rf_we_lsu_i ( rf_we_lsu ), |
| |
| .rf_wdata_fwd_wb_o ( rf_wdata_fwd_wb ), |
| |
| .rf_waddr_wb_o ( rf_waddr_wb ), |
| .rf_wdata_wb_o ( rf_wdata_wb ), |
| .rf_we_wb_o ( rf_we_wb ), |
| |
| .lsu_resp_valid_i ( lsu_resp_valid ), |
| .lsu_resp_err_i ( lsu_resp_err ), |
| |
| .instr_done_wb_o ( instr_done_wb ), |
| |
| // floating point |
| .fp_rf_write_wb_o ( fp_rf_write_wb ), |
| .fp_rf_wen_wb_o ( fp_rf_wen_wb ), |
| .fp_rf_waddr_wb_o ( fp_rf_waddr_wb ), |
| .fp_rf_wen_id_i ( fp_rf_wen_id ), |
| .fp_rf_waddr_id_i ( fp_rf_waddr_id ), |
| .fp_rf_wdata_wb_o ( fp_rf_wdata_wb ), |
| .fp_load_i ( fp_load ) |
| ); |
| |
| /////////////////////// |
| // Register file ECC // |
| /////////////////////// |
| |
| logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; |
| logic [RegFileDataWidth-1:0] rf_rdata_a_ecc; |
| logic [RegFileDataWidth-1:0] rf_rdata_b_ecc; |
| logic rf_ecc_err_comb; |
| |
| if (RegFileECC) begin : gen_regfile_ecc |
| |
| logic [1:0] rf_ecc_err_a, rf_ecc_err_b; |
| logic rf_ecc_err_a_id, rf_ecc_err_b_id; |
| |
| // ECC checkbit generation for regiter file wdata |
| prim_secded_39_32_enc regfile_ecc_enc ( |
| .in (rf_wdata_wb), |
| .out (rf_wdata_wb_ecc) |
| ); |
| |
| // ECC checking on register file rdata |
| prim_secded_39_32_dec regfile_ecc_dec_a ( |
| .in (rf_rdata_a_ecc), |
| .d_o (), |
| .syndrome_o (), |
| .err_o (rf_ecc_err_a) |
| ); |
| prim_secded_39_32_dec regfile_ecc_dec_b ( |
| .in (rf_rdata_b_ecc), |
| .d_o (), |
| .syndrome_o (), |
| .err_o (rf_ecc_err_b) |
| ); |
| |
| // Assign read outputs - no error correction, just trigger an alert |
| assign rf_rdata_a = rf_rdata_a_ecc[31:0]; |
| assign rf_rdata_b = rf_rdata_b_ecc[31:0]; |
| |
| // Calculate errors - qualify with WB forwarding to avoid xprop into the alert signal |
| assign rf_ecc_err_a_id = |rf_ecc_err_a & rf_ren_a & ~rf_rd_a_wb_match; |
| assign rf_ecc_err_b_id = |rf_ecc_err_b & rf_ren_b & ~rf_rd_b_wb_match; |
| |
| // Combined error |
| assign rf_ecc_err_comb = instr_valid_id & (rf_ecc_err_a_id | rf_ecc_err_b_id); |
| |
| end else begin : gen_no_regfile_ecc |
| logic unused_rf_ren_a, unused_rf_ren_b; |
| logic unused_rf_rd_a_wb_match, unused_rf_rd_b_wb_match; |
| |
| assign unused_rf_ren_a = rf_ren_a; |
| assign unused_rf_ren_b = rf_ren_b; |
| assign unused_rf_rd_a_wb_match = rf_rd_a_wb_match; |
| assign unused_rf_rd_b_wb_match = rf_rd_b_wb_match; |
| assign rf_wdata_wb_ecc = rf_wdata_wb; |
| assign rf_rdata_a = rf_rdata_a_ecc; |
| assign rf_rdata_b = rf_rdata_b_ecc; |
| assign rf_ecc_err_comb = 1'b0; |
| end |
| |
| assign rf_int_fp_lsu = (is_fp_instr & use_fp_rs2) ? fp_rf_rdata_b : rf_rdata_b; |
| |
| if (RegFile == RegFileFF) begin : gen_regfile_ff |
| brq_register_file_ff #( |
| .RV32E ( RV32E ), |
| .DataWidth ( RegFileDataWidth ), |
| .DummyInstructions ( DummyInstructions ) |
| ) register_file_i ( |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni ), |
| |
| .test_en_i ( test_en_i ), |
| .dummy_instr_id_i ( dummy_instr_id ), |
| |
| .raddr_a_i ( rf_raddr_a ), |
| .rdata_a_o ( rf_rdata_a_ecc ), |
| .raddr_b_i ( rf_raddr_b ), |
| .rdata_b_o ( rf_rdata_b_ecc ), |
| .waddr_a_i ( rf_waddr_wb ), |
| .wdata_a_i ( rf_wdata_wb_ecc ), |
| .we_a_i ( rf_we_wb ) |
| ); |
| end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga |
| brq_register_file_fpga #( |
| .RV32E ( RV32E ), |
| .DataWidth ( RegFileDataWidth ), |
| .DummyInstructions ( DummyInstructions ) |
| ) register_file_i ( |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni ), |
| |
| .test_en_i ( test_en_i ), |
| .dummy_instr_id_i ( dummy_instr_id ), |
| |
| .raddr_a_i ( rf_raddr_a ), |
| .rdata_a_o ( rf_rdata_a_ecc ), |
| .raddr_b_i ( rf_raddr_b ), |
| .rdata_b_o ( rf_rdata_b_ecc ), |
| .waddr_a_i ( rf_waddr_wb ), |
| .wdata_a_i ( rf_wdata_wb_ecc ), |
| .we_a_i ( rf_we_wb ) |
| ); |
| end else if (RegFile == RegFileLatch) begin : gen_regfile_latch |
| brq_register_file_latch #( |
| .RV32E ( RV32E ), |
| .DataWidth ( RegFileDataWidth ), |
| .DummyInstructions ( DummyInstructions ) |
| ) register_file_i ( |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni ), |
| |
| .test_en_i ( test_en_i ), |
| .dummy_instr_id_i ( dummy_instr_id ), |
| |
| .raddr_a_i ( rf_raddr_a ), |
| .rdata_a_o ( rf_rdata_a_ecc ), |
| .raddr_b_i ( rf_raddr_b ), |
| .rdata_b_o ( rf_rdata_b_ecc ), |
| .waddr_a_i ( rf_waddr_wb ), |
| .wdata_a_i ( rf_wdata_wb_ecc ), |
| .we_a_i ( rf_we_wb ) |
| ); |
| end |
| |
| if (FloatingPoint) begin : gen_fp_regfile |
| brq_fp_register_file_ff #( |
| .RVF ( RVF ), |
| .DataWidth ( W ) |
| ) fp_register_file ( |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni ), |
| |
| .raddr_a_i ( fp_rf_raddr_a ), |
| .rdata_a_o ( fp_rf_rdata_a ), |
| |
| .raddr_b_i ( fp_rf_raddr_b ), |
| .rdata_b_o ( fp_rf_rdata_b ), |
| |
| .raddr_c_i ( fp_rf_raddr_c ), |
| .rdata_c_o ( fp_rf_rdata_c ), |
| |
| .waddr_a_i ( fp_rf_waddr_wb ), |
| .wdata_a_i ( fp_rf_wdata_wb ), |
| .we_a_i ( fp_rf_wen_wb ) |
| ); |
| end |
| |
| /////////////////// |
| // Alert outputs // |
| /////////////////// |
| |
| // Minor alert - core is in a recoverable state |
| // TODO add I$ ECC errors here |
| assign alert_minor_o = 1'b0; |
| |
| // Major alert - core is unrecoverable |
| assign alert_major_o = (rf_ecc_err_comb | pc_mismatch_alert | csr_shadow_err); |
| |
| |
| |
| // Explict INC_ASSERT block to avoid unused signal lint warnings were asserts are not included |
| `ifdef INC_ASSERT |
| // Signals used for assertions only |
| logic outstanding_load_resp; |
| logic outstanding_store_resp; |
| |
| logic outstanding_load_id; |
| logic outstanding_store_id; |
| |
| assign outstanding_load_id = id_stage_i.instr_executing & id_stage_i.lsu_req_dec & |
| ~id_stage_i.lsu_we; |
| assign outstanding_store_id = id_stage_i.instr_executing & id_stage_i.lsu_req_dec & |
| id_stage_i.lsu_we; |
| |
| if (WritebackStage) begin : gen_wb_stage |
| // When the writeback stage is present a load/store could be in ID or WB. A Load/store in ID can |
| // see a response before it moves to WB when it is unaligned otherwise we should only see |
| // a response when load/store is in WB. |
| assign outstanding_load_resp = outstanding_load_wb | |
| (outstanding_load_id & load_store_unit_i.split_misaligned_access); |
| |
| assign outstanding_store_resp = outstanding_store_wb | |
| (outstanding_store_id & load_store_unit_i.split_misaligned_access); |
| |
| // When writing back the result of a load, the load must have made it to writeback |
| |
| end else begin : gen_no_wb_stage |
| // Without writeback stage only look into whether load or store is in ID to determine if |
| // a response is expected. |
| assign outstanding_load_resp = outstanding_load_id; |
| assign outstanding_store_resp = outstanding_store_id; |
| end |
| `endif |
| |
| |
| //////////////////////// |
| // RF (Register File) // |
| //////////////////////// |
| `ifdef RVFI |
| assign rvfi_rd_addr_wb = rf_waddr_wb; |
| assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu; |
| assign rvfi_rd_we_wb = rf_we_wb | rf_we_lsu; |
| `endif |
| |
| |
| ///////////////////////////////////////// |
| // CSRs (Control and Status Registers) // |
| ///////////////////////////////////////// |
| |
| assign csr_wdata = alu_operand_a_ex; |
| assign csr_addr = csr_num_e'(csr_access ? alu_operand_b_ex[11:0] : 12'b0); |
| |
| brq_cs_registers #( |
| .DbgTriggerEn ( DbgTriggerEn ), |
| .DbgHwBreakNum ( DbgHwBreakNum ), |
| .DataIndTiming ( DataIndTiming ), |
| .DummyInstructions ( DummyInstructions ), |
| .ShadowCSR ( ShadowCSR ), |
| .ICache ( ICache ), |
| .MHPMCounterNum ( MHPMCounterNum ), |
| .MHPMCounterWidth ( MHPMCounterWidth ), |
| .PMPEnable ( PMPEnable ), |
| .PMPGranularity ( PMPGranularity ), |
| .PMPNumRegions ( PMPNumRegions ), |
| .RV32E ( RV32E ), |
| .RV32M ( RV32M ) |
| ) cs_registers_i ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| |
| // Hart ID from outside |
| .hart_id_i ( hart_id_i ), |
| .priv_mode_id_o ( priv_mode_id ), |
| .priv_mode_if_o ( priv_mode_if ), |
| .priv_mode_lsu_o ( priv_mode_lsu ), |
| |
| // mtvec |
| .csr_mtvec_o ( csr_mtvec ), |
| .csr_mtvec_init_i ( csr_mtvec_init ), |
| .boot_addr_i ( boot_addr_i ), |
| |
| // Interface to CSRs ( SRAM like ) |
| .csr_access_i ( csr_access ), |
| .csr_addr_i ( csr_addr ), |
| .csr_wdata_i ( csr_wdata ), |
| .csr_op_i ( csr_op ), |
| .csr_op_en_i ( csr_op_en ), |
| .csr_rdata_o ( csr_rdata ), |
| |
| // Interrupt related control signals |
| .irq_software_i ( irq_software_i ), |
| .irq_timer_i ( irq_timer_i ), |
| .irq_external_i ( irq_external_i ), |
| .irq_fast_i ( irq_fast_i ), |
| .nmi_mode_i ( nmi_mode ), |
| .irq_pending_o ( irq_pending ), |
| .irqs_o ( irqs ), |
| .csr_mstatus_mie_o ( csr_mstatus_mie ), |
| .csr_mstatus_tw_o ( csr_mstatus_tw ), |
| .csr_mepc_o ( csr_mepc ), |
| |
| // PMP |
| .csr_pmp_cfg_o ( csr_pmp_cfg ), |
| .csr_pmp_addr_o ( csr_pmp_addr ), |
| |
| // debug |
| .csr_depc_o ( csr_depc ), |
| .debug_mode_i ( debug_mode ), |
| .debug_cause_i ( debug_cause ), |
| .debug_csr_save_i ( debug_csr_save ), |
| .debug_single_step_o ( debug_single_step ), |
| .debug_ebreakm_o ( debug_ebreakm ), |
| .debug_ebreaku_o ( debug_ebreaku ), |
| .trigger_match_o ( trigger_match ), |
| |
| .pc_if_i ( pc_if ), |
| .pc_id_i ( pc_id ), |
| .pc_wb_i ( pc_wb ), |
| |
| .data_ind_timing_o ( data_ind_timing ), |
| .dummy_instr_en_o ( dummy_instr_en ), |
| .dummy_instr_mask_o ( dummy_instr_mask ), |
| .dummy_instr_seed_en_o ( dummy_instr_seed_en ), |
| .dummy_instr_seed_o ( dummy_instr_seed ), |
| .icache_enable_o ( icache_enable ), |
| .csr_shadow_err_o ( csr_shadow_err ), |
| |
| .csr_save_if_i ( csr_save_if ), |
| .csr_save_id_i ( csr_save_id ), |
| .csr_save_wb_i ( csr_save_wb ), |
| .csr_restore_mret_i ( csr_restore_mret_id ), |
| .csr_restore_dret_i ( csr_restore_dret_id ), |
| .csr_save_cause_i ( csr_save_cause ), |
| .csr_mcause_i ( exc_cause ), |
| .csr_mtval_i ( csr_mtval ), |
| .illegal_csr_insn_o ( illegal_csr_insn_id ), |
| |
| // performance counter related signals |
| .instr_ret_i ( perf_instr_ret_wb ), |
| .instr_ret_compressed_i ( perf_instr_ret_compressed_wb ), |
| .iside_wait_i ( perf_iside_wait ), |
| .jump_i ( perf_jump ), |
| .branch_i ( perf_branch ), |
| .branch_taken_i ( perf_tbranch ), |
| .mem_load_i ( perf_load ), |
| .mem_store_i ( perf_store ), |
| .dside_wait_i ( perf_dside_wait ), |
| .mul_wait_i ( perf_mul_wait ), |
| .div_wait_i ( perf_div_wait ), |
| |
| // floating point |
| .fp_rm_dynamic_i ( fp_rm_dynamic ), |
| .fp_frm_o ( fp_frm_csr ), |
| .fp_status_i ( fp_status ), |
| .is_fp_instr_i ( is_fp_instr ) |
| ); |
| |
| assign fp_frm_fpnew = fp_rm_dynamic ? fp_frm_csr : fp_rounding_mode; |
| assign in_ready_c2fpu = id_in_ready; //multdiv_ready_id; |
| assign in_valid_c2fpu = (instr_valid_id & is_fp_instr); |
| // assign ready_id_fpu = id_in_ready; // (is_fp_instr) ? out_ready_fpu2c : id_in_ready; |
| assign valid_id_fpu = (is_fp_instr) ? out_valid_fpu2c : ex_valid; |
| |
| // FPU instance |
| fpnew_top #( |
| .Features ( fpnew_pkg::RV32F ), |
| .Implementation ( fpnew_pkg::DEFAULT_NOREGS ), |
| .TagType ( logic ) |
| ) i_fpnew_top ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| .operands_i ( fp_operands ), |
| .rnd_mode_i ( fp_frm_fpnew ), |
| .op_i ( fp_alu_operator ), |
| .op_mod_i ( fp_alu_op_mod ), |
| .src_fmt_i ( fp_src_fmt ), |
| .dst_fmt_i ( fp_dst_fmt ), |
| .int_fmt_i ( fpnew_pkg::INT32 ), |
| .vectorial_op_i ( 1'b0 ), |
| .tag_i ( '1 ), |
| .in_valid_i ( in_valid_c2fpu ), |
| .in_ready_o ( out_ready_fpu2c ), |
| .flush_i ( fp_flush ), |
| .result_o ( fp_result ), |
| .status_o ( fp_status ), |
| .tag_o ( ), |
| .out_valid_o ( out_valid_fpu2c ), |
| .out_ready_i ( in_ready_c2fpu ), |
| .busy_o ( fp_busy ) |
| ); |
| |
| assign fpu_busy_idu = fp_busy & (~out_valid_fpu2c); |
| assign data_wb = is_fp_instr ? fp_result : result_ex; |
| |
| // These assertions are in top-level as instr_valid_id required as the enable term |
| |
| if (PMPEnable) begin : g_pmp |
| logic [33:0] pmp_req_addr [PMP_NUM_CHAN]; |
| pmp_req_e pmp_req_type [PMP_NUM_CHAN]; |
| priv_lvl_e pmp_priv_lvl [PMP_NUM_CHAN]; |
| |
| assign pmp_req_addr[PMP_I] = {2'b00,instr_addr_o[31:0]}; |
| assign pmp_req_type[PMP_I] = PMP_ACC_EXEC; |
| assign pmp_priv_lvl[PMP_I] = priv_mode_if; |
| assign pmp_req_addr[PMP_D] = {2'b00,data_addr_o[31:0]}; |
| assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ; |
| assign pmp_priv_lvl[PMP_D] = priv_mode_lsu; |
| |
| brq_pmp #( |
| .PMPGranularity ( PMPGranularity ), |
| .PMPNumChan ( PMP_NUM_CHAN ), |
| .PMPNumRegions ( PMPNumRegions ) |
| ) pmp_i ( |
| .clk_i ( clk ), |
| .rst_ni ( rst_ni ), |
| // Interface to CSRs |
| .csr_pmp_cfg_i ( csr_pmp_cfg ), |
| .csr_pmp_addr_i ( csr_pmp_addr ), |
| .priv_mode_i ( pmp_priv_lvl ), |
| // Access checking channels |
| .pmp_req_addr_i ( pmp_req_addr ), |
| .pmp_req_type_i ( pmp_req_type ), |
| .pmp_req_err_o ( pmp_req_err ) |
| ); |
| end else begin : g_no_pmp |
| // Unused signal tieoff |
| priv_lvl_e unused_priv_lvl_if, unused_priv_lvl_ls; |
| logic [33:0] unused_csr_pmp_addr [PMPNumRegions]; |
| pmp_cfg_t unused_csr_pmp_cfg [PMPNumRegions]; |
| assign unused_priv_lvl_if = priv_mode_if; |
| assign unused_priv_lvl_ls = priv_mode_lsu; |
| assign unused_csr_pmp_addr = csr_pmp_addr; |
| assign unused_csr_pmp_cfg = csr_pmp_cfg; |
| |
| // Output tieoff |
| assign pmp_req_err[PMP_I] = 1'b0; |
| assign pmp_req_err[PMP_D] = 1'b0; |
| end |
| |
| `ifdef RVFI |
| // When writeback stage is present RVFI information is emitted when instruction is finished in |
| // third stage but some information must be captured whilst the instruction is in the second |
| // stage. Without writeback stage RVFI information is all emitted when instruction retires in |
| // second stage. RVFI outputs are all straight from flops. So 2 stage pipeline requires a single |
| // set of flops (instr_info => RVFI_out), 3 stage pipeline requires two sets (instr_info => wb |
| // => RVFI_out) |
| localparam int RVFI_STAGES = WritebackStage ? 2 : 1; |
| |
| logic rvfi_stage_valid [RVFI_STAGES]; |
| logic [63:0] rvfi_stage_order [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_insn [RVFI_STAGES]; |
| logic rvfi_stage_trap [RVFI_STAGES]; |
| logic rvfi_stage_halt [RVFI_STAGES]; |
| logic rvfi_stage_intr [RVFI_STAGES]; |
| logic [ 1:0] rvfi_stage_mode [RVFI_STAGES]; |
| logic [ 1:0] rvfi_stage_ixl [RVFI_STAGES]; |
| logic [ 4:0] rvfi_stage_rs1_addr [RVFI_STAGES]; |
| logic [ 4:0] rvfi_stage_rs2_addr [RVFI_STAGES]; |
| logic [ 4:0] rvfi_stage_rs3_addr [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_rs1_rdata [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_rs2_rdata [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_rs3_rdata [RVFI_STAGES]; |
| logic [ 4:0] rvfi_stage_rd_addr [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_rd_wdata [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_pc_rdata [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_pc_wdata [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_mem_addr [RVFI_STAGES]; |
| logic [ 3:0] rvfi_stage_mem_rmask [RVFI_STAGES]; |
| logic [ 3:0] rvfi_stage_mem_wmask [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_mem_rdata [RVFI_STAGES]; |
| logic [31:0] rvfi_stage_mem_wdata [RVFI_STAGES]; |
| |
| logic rvfi_stage_valid_d [RVFI_STAGES]; |
| |
| assign rvfi_valid = rvfi_stage_valid [RVFI_STAGES-1]; |
| assign rvfi_order = rvfi_stage_order [RVFI_STAGES-1]; |
| assign rvfi_insn = rvfi_stage_insn [RVFI_STAGES-1]; |
| assign rvfi_trap = rvfi_stage_trap [RVFI_STAGES-1]; |
| assign rvfi_halt = rvfi_stage_halt [RVFI_STAGES-1]; |
| assign rvfi_intr = rvfi_stage_intr [RVFI_STAGES-1]; |
| assign rvfi_mode = rvfi_stage_mode [RVFI_STAGES-1]; |
| assign rvfi_ixl = rvfi_stage_ixl [RVFI_STAGES-1]; |
| assign rvfi_rs1_addr = rvfi_stage_rs1_addr [RVFI_STAGES-1]; |
| assign rvfi_rs2_addr = rvfi_stage_rs2_addr [RVFI_STAGES-1]; |
| assign rvfi_rs3_addr = rvfi_stage_rs3_addr [RVFI_STAGES-1]; |
| assign rvfi_rs1_rdata = rvfi_stage_rs1_rdata[RVFI_STAGES-1]; |
| assign rvfi_rs2_rdata = rvfi_stage_rs2_rdata[RVFI_STAGES-1]; |
| assign rvfi_rs3_rdata = rvfi_stage_rs3_rdata[RVFI_STAGES-1]; |
| assign rvfi_rd_addr = rvfi_stage_rd_addr [RVFI_STAGES-1]; |
| assign rvfi_rd_wdata = rvfi_stage_rd_wdata [RVFI_STAGES-1]; |
| assign rvfi_pc_rdata = rvfi_stage_pc_rdata [RVFI_STAGES-1]; |
| assign rvfi_pc_wdata = rvfi_stage_pc_wdata [RVFI_STAGES-1]; |
| assign rvfi_mem_addr = rvfi_stage_mem_addr [RVFI_STAGES-1]; |
| assign rvfi_mem_rmask = rvfi_stage_mem_rmask[RVFI_STAGES-1]; |
| assign rvfi_mem_wmask = rvfi_stage_mem_wmask[RVFI_STAGES-1]; |
| assign rvfi_mem_rdata = rvfi_stage_mem_rdata[RVFI_STAGES-1]; |
| assign rvfi_mem_wdata = rvfi_stage_mem_wdata[RVFI_STAGES-1]; |
| |
| if (WritebackStage) begin : gen_rvfi_wb_stage |
| logic unused_instr_new_id; |
| |
| assign unused_instr_new_id = instr_new_id; |
| |
| // With writeback stage first RVFI stage buffers instruction information captured in ID/EX |
| // awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB |
| // So first stage becomes valid when instruction leaves ID/EX stage and remains valid until |
| // instruction leaves WB |
| assign rvfi_stage_valid_d[0] = (instr_id_done & ~dummy_instr_id) | |
| (rvfi_stage_valid[0] & ~instr_done_wb); |
| // Second stage is output stage so simple valid cycle after instruction leaves WB (and so has |
| // retired) |
| assign rvfi_stage_valid_d[1] = instr_done_wb; |
| |
| // Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB) |
| logic rvfi_instr_new_wb_q; |
| |
| assign rvfi_instr_new_wb = rvfi_instr_new_wb_q; |
| |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (~rst_ni) begin |
| rvfi_instr_new_wb_q <= 0; |
| end else begin |
| rvfi_instr_new_wb_q <= instr_id_done; |
| end |
| end |
| end else begin : gen_rvfi_no_wb_stage |
| // Without writeback stage first RVFI stage is output stage so simply valid the cycle after |
| // instruction leaves ID/EX (and so has retired) |
| assign rvfi_stage_valid_d[0] = instr_id_done & ~dummy_instr_id; |
| // Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly |
| // setup register write signals |
| assign rvfi_instr_new_wb = instr_new_id; |
| end |
| |
| for (genvar i = 0;i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| rvfi_stage_halt[i] <= '0; |
| rvfi_stage_trap[i] <= '0; |
| rvfi_stage_intr[i] <= '0; |
| rvfi_stage_order[i] <= '0; |
| rvfi_stage_insn[i] <= '0; |
| rvfi_stage_mode[i] <= {PRIV_LVL_M}; |
| rvfi_stage_ixl[i] <= CSR_MISA_MXL; |
| rvfi_stage_rs1_addr[i] <= '0; |
| rvfi_stage_rs2_addr[i] <= '0; |
| rvfi_stage_rs3_addr[i] <= '0; |
| rvfi_stage_pc_rdata[i] <= '0; |
| rvfi_stage_pc_wdata[i] <= '0; |
| rvfi_stage_mem_rmask[i] <= '0; |
| rvfi_stage_mem_wmask[i] <= '0; |
| rvfi_stage_valid[i] <= '0; |
| rvfi_stage_rs1_rdata[i] <= '0; |
| rvfi_stage_rs2_rdata[i] <= '0; |
| rvfi_stage_rs3_rdata[i] <= '0; |
| rvfi_stage_rd_wdata[i] <= '0; |
| rvfi_stage_rd_addr[i] <= '0; |
| rvfi_stage_mem_rdata[i] <= '0; |
| rvfi_stage_mem_wdata[i] <= '0; |
| rvfi_stage_mem_addr[i] <= '0; |
| end else begin |
| rvfi_stage_valid[i] <= rvfi_stage_valid_d[i]; |
| |
| if (i == 0) begin |
| if(instr_id_done) begin |
| rvfi_stage_halt[i] <= '0; |
| rvfi_stage_trap[i] <= illegal_insn_id; |
| rvfi_stage_intr[i] <= rvfi_intr_d; |
| rvfi_stage_order[i] <= rvfi_stage_order[i] + 64'(rvfi_stage_valid_d[i]); |
| rvfi_stage_insn[i] <= rvfi_insn_id; |
| rvfi_stage_mode[i] <= {priv_mode_id}; |
| rvfi_stage_ixl[i] <= CSR_MISA_MXL; |
| rvfi_stage_rs1_addr[i] <= rvfi_rs1_addr_d; |
| rvfi_stage_rs2_addr[i] <= rvfi_rs2_addr_d; |
| rvfi_stage_rs3_addr[i] <= rvfi_rs3_addr_d; |
| rvfi_stage_pc_rdata[i] <= pc_id; |
| rvfi_stage_pc_wdata[i] <= pc_set ? branch_target_ex : pc_if; |
| rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int; |
| rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000; |
| rvfi_stage_rs1_rdata[i] <= rvfi_rs1_data_d; |
| rvfi_stage_rs2_rdata[i] <= rvfi_rs2_data_d; |
| rvfi_stage_rs3_rdata[i] <= rvfi_rs3_data_d; |
| rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d; |
| rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d; |
| rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d; |
| rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d; |
| rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d; |
| end |
| end else begin |
| if(instr_done_wb) begin |
| rvfi_stage_halt[i] <= rvfi_stage_halt[i-1]; |
| rvfi_stage_trap[i] <= rvfi_stage_trap[i-1]; |
| rvfi_stage_intr[i] <= rvfi_stage_intr[i-1]; |
| rvfi_stage_order[i] <= rvfi_stage_order[i-1]; |
| rvfi_stage_insn[i] <= rvfi_stage_insn[i-1]; |
| rvfi_stage_mode[i] <= rvfi_stage_mode[i-1]; |
| rvfi_stage_ixl[i] <= rvfi_stage_ixl[i-1]; |
| rvfi_stage_rs1_addr[i] <= rvfi_stage_rs1_addr[i-1]; |
| rvfi_stage_rs2_addr[i] <= rvfi_stage_rs2_addr[i-1]; |
| rvfi_stage_rs3_addr[i] <= rvfi_stage_rs3_addr[i-1]; |
| rvfi_stage_pc_rdata[i] <= rvfi_stage_pc_rdata[i-1]; |
| rvfi_stage_pc_wdata[i] <= rvfi_stage_pc_wdata[i-1]; |
| rvfi_stage_mem_rmask[i] <= rvfi_stage_mem_rmask[i-1]; |
| rvfi_stage_mem_wmask[i] <= rvfi_stage_mem_wmask[i-1]; |
| rvfi_stage_rs1_rdata[i] <= rvfi_stage_rs1_rdata[i-1]; |
| rvfi_stage_rs2_rdata[i] <= rvfi_stage_rs2_rdata[i-1]; |
| rvfi_stage_rs3_rdata[i] <= rvfi_stage_rs3_rdata[i-1]; |
| rvfi_stage_mem_wdata[i] <= rvfi_stage_mem_wdata[i-1]; |
| rvfi_stage_mem_addr[i] <= rvfi_stage_mem_addr[i-1]; |
| |
| // For 2 RVFI_STAGES/Writeback Stage ignore first stage flops for rd_addr, rd_wdata and |
| // mem_rdata. For RF write addr/data actual write happens in writeback so capture |
| // address/data there. For mem_rdata that is only available from the writeback stage. |
| // Previous stage flops still exist in RTL as they are used by the non writeback config |
| rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d; |
| rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d; |
| rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d; |
| end |
| end |
| end |
| end |
| end |
| |
| |
| // Memory adddress/write data available first cycle of ld/st instruction from register read |
| always_comb begin |
| if (instr_first_cycle_id) begin |
| rvfi_mem_addr_d = alu_adder_result_ex; |
| rvfi_mem_wdata_d = lsu_wdata; |
| end else begin |
| rvfi_mem_addr_d = rvfi_mem_addr_q; |
| rvfi_mem_wdata_d = rvfi_mem_wdata_q; |
| end |
| end |
| |
| // Capture read data from LSU when it becomes valid |
| always_comb begin |
| if (lsu_resp_valid) begin |
| rvfi_mem_rdata_d = rf_wdata_lsu; |
| end else begin |
| rvfi_mem_rdata_d = rvfi_mem_rdata_q; |
| end |
| end |
| |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| rvfi_mem_addr_q <= '0; |
| rvfi_mem_rdata_q <= '0; |
| rvfi_mem_wdata_q <= '0; |
| end else begin |
| rvfi_mem_addr_q <= rvfi_mem_addr_d; |
| rvfi_mem_rdata_q <= rvfi_mem_rdata_d; |
| rvfi_mem_wdata_q <= rvfi_mem_wdata_d; |
| end |
| end |
| // Byte enable based on data type |
| always_comb begin |
| unique case (lsu_type) |
| 2'b00: rvfi_mem_mask_int = 4'b1111; |
| 2'b01: rvfi_mem_mask_int = 4'b0011; |
| 2'b10: rvfi_mem_mask_int = 4'b0001; |
| default: rvfi_mem_mask_int = 4'b0000; |
| endcase |
| end |
| |
| always_comb begin |
| if (instr_is_compressed_id) begin |
| rvfi_insn_id = {16'b0, instr_rdata_c_id}; |
| end else begin |
| rvfi_insn_id = instr_rdata_id; |
| end |
| end |
| |
| // Source registers 1 and 2 are read in the first instruction cycle |
| // Source register 3 is read in the second instruction cycle. |
| always_comb begin |
| if (instr_first_cycle_id) begin |
| rvfi_rs1_data_d = rf_ren_a ? multdiv_operand_a_ex : '0; |
| rvfi_rs1_addr_d = rf_ren_a ? rf_raddr_a : '0; |
| rvfi_rs2_data_d = rf_ren_b ? multdiv_operand_b_ex : '0; |
| rvfi_rs2_addr_d = rf_ren_b ? rf_raddr_b : '0; |
| rvfi_rs3_data_d = '0; |
| rvfi_rs3_addr_d = '0; |
| end else begin |
| rvfi_rs1_data_d = rvfi_rs1_data_q; |
| rvfi_rs1_addr_d = rvfi_rs1_addr_q; |
| rvfi_rs2_data_d = rvfi_rs2_data_q; |
| rvfi_rs2_addr_d = rvfi_rs2_addr_q; |
| rvfi_rs3_data_d = multdiv_operand_a_ex; |
| rvfi_rs3_addr_d = rf_raddr_a; |
| end |
| end |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| rvfi_rs1_data_q <= '0; |
| rvfi_rs1_addr_q <= '0; |
| rvfi_rs2_data_q <= '0; |
| rvfi_rs2_addr_q <= '0; |
| |
| end else begin |
| rvfi_rs1_data_q <= rvfi_rs1_data_d; |
| rvfi_rs1_addr_q <= rvfi_rs1_addr_d; |
| rvfi_rs2_data_q <= rvfi_rs2_data_d; |
| rvfi_rs2_addr_q <= rvfi_rs2_addr_d; |
| end |
| end |
| |
| always_comb begin |
| if(rvfi_rd_we_wb) begin |
| // Capture address/data of write to register file |
| rvfi_rd_addr_d = rvfi_rd_addr_wb; |
| // If writing to x0 zero write data as required by RVFI specification |
| if(rvfi_rd_addr_wb == 5'b0) begin |
| rvfi_rd_wdata_d = '0; |
| end else begin |
| rvfi_rd_wdata_d = rvfi_rd_wdata_wb; |
| end |
| end else if(rvfi_instr_new_wb) begin |
| // If no RF write but new instruction in Writeback (when present) or ID/EX (when no writeback |
| // stage present) then zero RF write address/data as required by RVFI specification |
| rvfi_rd_addr_d = '0; |
| rvfi_rd_wdata_d = '0; |
| end else begin |
| // Otherwise maintain previous value |
| rvfi_rd_addr_d = rvfi_rd_addr_q; |
| rvfi_rd_wdata_d = rvfi_rd_wdata_q; |
| end |
| end |
| |
| // RD write register is refreshed only once per cycle and |
| // then it is kept stable for the cycle. |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| rvfi_rd_addr_q <= '0; |
| rvfi_rd_wdata_q <= '0; |
| end else begin |
| rvfi_rd_addr_q <= rvfi_rd_addr_d; |
| rvfi_rd_wdata_q <= rvfi_rd_wdata_d; |
| end |
| end |
| |
| // rvfi_intr must be set for first instruction that is part of a trap handler. |
| // On the first cycle of a new instruction see if a trap PC was set by the previous instruction, |
| // otherwise maintain value. |
| assign rvfi_intr_d = instr_first_cycle_id ? rvfi_set_trap_pc_q : rvfi_intr_q; |
| |
| always_comb begin |
| rvfi_set_trap_pc_d = rvfi_set_trap_pc_q; |
| |
| if (pc_set && pc_mux_id == PC_EXC && |
| (exc_pc_mux_id == EXC_PC_EXC || exc_pc_mux_id == EXC_PC_IRQ)) begin |
| // PC is set to enter a trap handler |
| rvfi_set_trap_pc_d = 1'b1; |
| end else if (rvfi_set_trap_pc_q && instr_id_done) begin |
| // first instruction has been executed after PC is set to trap handler |
| rvfi_set_trap_pc_d = 1'b0; |
| end |
| end |
| |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| rvfi_set_trap_pc_q <= 1'b0; |
| rvfi_intr_q <= 1'b0; |
| end else begin |
| rvfi_set_trap_pc_q <= rvfi_set_trap_pc_d; |
| rvfi_intr_q <= rvfi_intr_d; |
| end |
| end |
| |
| `else |
| logic unused_instr_new_id, unused_instr_done_wb; |
| assign unused_instr_new_id = instr_new_id; |
| assign unused_instr_done_wb = instr_done_wb; |
| `endif |
| |
| |
| |
| endmodule |