URL
https://opencores.org/ocsvn/yifive/yifive/trunk
Subversion Repositories yifive
[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [syntacore/] [scr1/] [src/] [core/] [pipeline/] [scr1_pipe_exu.sv] - Rev 21
Compare with Previous | Blame | View Log
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details/// @file <scr1_pipe_exu.sv>/// @brief Execution Unit (EXU)/////------------------------------------------------------------------------------//// Functionality:// - Performs instructions execution:// - Prevents instructions from execution if the HART is in WFI or Debug Halted// state// - Fetches operands for IALU// - Calculates operation results via IALU// - Stores IALU results in MPRF// - Performs LOAD/STORE operations via LSU// - Handles exceptions:// - Generates exception request// - Encodes exception code// - Calculates exception trap value// - Controls WFI instruction execution// - Calculates PC value:// - Initializes PC on reset// - Stores the current PC value// - Calculates a New PC value and generates a New PC request to IFU//// Structure:// - Instruction queue// - Integer Arithmetic Logic Unit (IALU)// - Exceptions logic// - WFI logic// - Program Counter logic// - Load-Store Unit (LSU)// - EXU status logic// - EXU <-> MPRF i/f// - EXU <-> CSR i/f// - EXU <-> TDU i/f////------------------------------------------------------------------------------`include "scr1_arch_description.svh"`include "scr1_arch_types.svh"`include "scr1_memif.svh"`include "scr1_riscv_isa_decoding.svh"`include "scr1_csr.svh"`ifdef SCR1_DBG_EN`include "scr1_hdu.svh"`endif // SCR1_DBG_EN`ifdef SCR1_TDU_EN`include "scr1_tdu.svh"`endif // SCR1_TDU_ENmodule scr1_pipe_exu (// Commoninput logic rst_n, // EXU resetinput logic clk, // Gated EXU clock`ifdef SCR1_CLKCTRL_ENinput logic clk_alw_on, // Not-gated EXU clockinput logic clk_pipe_en, // EXU clock enabled flag`endif // SCR1_CLKCTRL_EN// EXU <-> IDU interfaceinput logic idu2exu_req_i, // Request form IDU to EXUoutput logic exu2idu_rdy_o, // EXU ready for new data from IDUinput type_scr1_exu_cmd_s idu2exu_cmd_i, // EXU commandinput logic idu2exu_use_rs1_i, // Clock gating on rs1_addr fieldinput logic idu2exu_use_rs2_i, // Clock gating on rs2_addr field`ifndef SCR1_NO_EXE_STAGEinput logic idu2exu_use_rd_i, // Clock gating on rd_addr fieldinput logic idu2exu_use_imm_i, // Clock gating on imm field`endif // SCR1_NO_EXE_STAGE// EXU <-> MPRF interfaceoutput logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr_o, // MPRF rs1 read addressinput logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data_i, // MPRF rs1 read dataoutput logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr_o, // MPRF rs2 read addressinput logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data_i, // MPRF rs2 read dataoutput logic exu2mprf_w_req_o, // MPRF write requestoutput logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr_o, // MPRF rd write addressoutput logic [`SCR1_XLEN-1:0] exu2mprf_rd_data_o, // MPRF rd write data// EXU <-> CSR read/write interfaceoutput logic [SCR1_CSR_ADDR_WIDTH-1:0] exu2csr_rw_addr_o, // CSR read/write addressoutput logic exu2csr_r_req_o, // CSR read requestinput logic [`SCR1_XLEN-1:0] csr2exu_r_data_i, // CSR read dataoutput logic exu2csr_w_req_o, // CSR write requestoutput type_scr1_csr_cmd_sel_e exu2csr_w_cmd_o, // CSR write commandoutput logic [`SCR1_XLEN-1:0] exu2csr_w_data_o, // CSR write datainput logic csr2exu_rw_exc_i, // CSR read/write access exception// EXU <-> CSR events interfaceoutput logic exu2csr_take_irq_o, // Take IRQ trapoutput logic exu2csr_take_exc_o, // Take exception trapoutput logic exu2csr_mret_update_o, // MRET update CSRoutput logic exu2csr_mret_instr_o, // MRET instructionoutput logic [SCR1_EXC_CODE_WIDTH_E-1:0] exu2csr_exc_code_o, // Exception code (see scr1_arch_types.svh) - cp.7output logic [`SCR1_XLEN-1:0] exu2csr_trap_val_o, // Trap valueinput logic [`SCR1_XLEN-1:0] csr2exu_new_pc_i, // Exception/IRQ/MRET new PCinput logic csr2exu_irq_i, // IRQ requestinput logic csr2exu_ip_ie_i, // Some IRQ pending and locally enabledinput logic csr2exu_mstatus_mie_up_i, // MSTATUS or MIE update in the current cycle// EXU <-> DMEM interfaceoutput logic exu2dmem_req_o, // Data memory requestoutput logic exu2dmem_cmd_o, // Data memory command - cp.7output logic [1:0] exu2dmem_width_o, // Data memory widthoutput logic [`SCR1_DMEM_AWIDTH-1:0] exu2dmem_addr_o, // Data memory addressoutput logic [`SCR1_DMEM_DWIDTH-1:0] exu2dmem_wdata_o, // Data memory write datainput logic dmem2exu_req_ack_i, // Data memory request acknowledgeinput logic [`SCR1_DMEM_DWIDTH-1:0] dmem2exu_rdata_i, // Data memory read datainput logic [1:0] dmem2exu_resp_i, // Data memory response - cp.7// EXU controloutput logic exu2pipe_exc_req_o, // Exception on last instructionoutput logic exu2pipe_brkpt_o, // Software Breakpoint (EBREAK)output logic exu2pipe_init_pc_o, // Reset exitoutput logic exu2pipe_wfi_run2halt_o, // Transition to WFI halted stateoutput logic exu2pipe_instret_o, // Instruction retired (with or without exception)output logic exu2csr_instret_no_exc_o, // Instruction retired (without exception)output logic exu2pipe_exu_busy_o, // EXU busy`ifdef SCR1_DBG_EN// EXU <-> HDU interfaceinput logic hdu2exu_no_commit_i, // Forbid instruction commitmentinput logic hdu2exu_irq_dsbl_i, // Disable IRQinput logic hdu2exu_pc_advmt_dsbl_i, // Forbid PC advancementinput logic hdu2exu_dmode_sstep_en_i, // Enable single-stepinput logic hdu2exu_pbuf_fetch_i, // Take instructions from Program Bufferinput logic hdu2exu_dbg_halted_i, // Debug halted stateinput logic hdu2exu_dbg_run2halt_i, // Transition to debug halted stateinput logic hdu2exu_dbg_halt2run_i, // Transition to run stateinput logic hdu2exu_dbg_run_start_i, // First cycle of run stateinput logic [`SCR1_XLEN-1:0] hdu2exu_dbg_new_pc_i, // New PC as starting point for HART Resume`endif // SCR1_DBG_EN`ifdef SCR1_TDU_EN// EXU <-> TDU interfaceoutput type_scr1_brkm_instr_mon_s exu2tdu_imon_o, // Instruction monitorinput logic [SCR1_TDU_ALLTRIG_NUM-1:0] tdu2exu_ibrkpt_match_i, // Instruction breakpoint(s) matchinput logic tdu2exu_ibrkpt_exc_req_i, // Instruction breakpoint exceptionoutput type_scr1_brkm_lsu_mon_s lsu2tdu_dmon_o, // Data monitorinput logic tdu2lsu_ibrkpt_exc_req_i, // Instruction breakpoint exceptioninput logic [SCR1_TDU_MTRIG_NUM-1:0] tdu2lsu_dbrkpt_match_i, // Data breakpoint(s) matchinput logic tdu2lsu_dbrkpt_exc_req_i, // Data breakpoint exceptionoutput logic [SCR1_TDU_ALLTRIG_NUM-1:0] exu2tdu_ibrkpt_ret_o, // Instruction with breakpoint flag retireoutput logic exu2hdu_ibrkpt_hw_o, // Hardware breakpoint on current instruction`endif // SCR1_TDU_EN// PC interface`ifdef SCR1_CLKCTRL_ENoutput logic exu2pipe_wfi_halted_o, // WFI halted state`endif // SCR1_CLKCTRL_ENoutput logic [`SCR1_XLEN-1:0] exu2pipe_pc_curr_o, // Current PCoutput logic [`SCR1_XLEN-1:0] exu2csr_pc_next_o, // Next PCoutput logic exu2ifu_pc_new_req_o, // New PC requestoutput logic [`SCR1_XLEN-1:0] exu2ifu_pc_new_o // New PC data);//------------------------------------------------------------------------------// Local parameters declaration//------------------------------------------------------------------------------localparam SCR1_JUMP_MASK = `SCR1_XLEN'hFFFF_FFFE;//------------------------------------------------------------------------------// Local types declaration//------------------------------------------------------------------------------//typedef enum logic {parameter SCR1_CSR_INIT = 1'b0;parameter SCR1_CSR_RDY = 1'b1;//} scr1_csr_access_e;//------------------------------------------------------------------------------// Local signals declaration//------------------------------------------------------------------------------// Instruction queue signals//------------------------------------------------------------------------------logic exu_queue_vd;type_scr1_exu_cmd_s exu_queue;logic exu_queue_barrier;`ifdef SCR1_DBG_ENlogic dbg_run_start_npbuf;`endif // SCR1_DBG_ENlogic exu_queue_en;logic [`SCR1_XLEN-1:0] exu_illegal_instr;`ifndef SCR1_NO_EXE_STAGElogic idu2exu_use_rs1_ff;logic idu2exu_use_rs2_ff;// EXU queue valid flag register signalslogic exu_queue_vd_upd;logic exu_queue_vd_ff;logic exu_queue_vd_next;`endif // SCR1_NO_EXE_STAGE// IALU signals//------------------------------------------------------------------------------`ifdef SCR1_RVM_EXTlogic ialu_rdy;logic ialu_vd;`endif // SCR1_RVM_EXTlogic [`SCR1_XLEN-1:0] ialu_main_op1;logic [`SCR1_XLEN-1:0] ialu_main_op2;logic [`SCR1_XLEN-1:0] ialu_main_res;logic [`SCR1_XLEN-1:0] ialu_addr_op1;logic [`SCR1_XLEN-1:0] ialu_addr_op2;logic [`SCR1_XLEN-1:0] ialu_addr_res;logic ialu_cmp;// Exceptions signals//------------------------------------------------------------------------------logic exu_exc_req;`ifdef SCR1_DBG_ENlogic exu_exc_req_ff;logic exu_exc_req_next;`endif // SCR1_DBG_ENlogic [SCR1_EXC_CODE_WIDTH_E-1:0] exc_code; // cp.7logic [`SCR1_XLEN-1:0] exc_trap_val;logic instr_fault_rvi_hi;// WFI signals//------------------------------------------------------------------------------// WFI control signalslogic wfi_halt_cond;logic wfi_run_req;logic wfi_halt_req;// WFI Run Start registerlogic wfi_run_start_ff;logic wfi_run_start_next;// WFI halted registerlogic wfi_halted_upd;logic wfi_halted_ff;logic wfi_halted_next;// PC signals//------------------------------------------------------------------------------logic [3:0] init_pc_v;logic init_pc;logic [`SCR1_XLEN-1:0] inc_pc;logic branch_taken;logic jb_taken;logic [`SCR1_XLEN-1:0] jb_new_pc;`ifndef SCR1_RVC_EXTlogic jb_misalign;`endif// Current PC registerlogic pc_curr_upd;logic [`SCR1_XLEN-1:0] pc_curr_ff;logic [`SCR1_XLEN-1:0] pc_curr_next;// LSU signals//------------------------------------------------------------------------------logic lsu_req;logic lsu_rdy;logic [`SCR1_XLEN-1:0] lsu_l_data;logic lsu_exc_req;logic [SCR1_EXC_CODE_WIDTH_E-1:0] lsu_exc_code; // cp.7// EXU status signals//------------------------------------------------------------------------------logic exu_rdy;// MPRF signals//------------------------------------------------------------------------------logic mprf_rs1_req;logic mprf_rs2_req;logic [`SCR1_MPRF_AWIDTH-1:0] mprf_rs1_addr;logic [`SCR1_MPRF_AWIDTH-1:0] mprf_rs2_addr;// CSR signals//------------------------------------------------------------------------------// CSR access registerlogic csr_access_ff;logic csr_access_next;logic csr_access_init;//------------------------------------------------------------------------------// Instruction execution queue//------------------------------------------------------------------------------//// Instruction execution queue consists of the following functional units:// - EXU queue control logic// - EXU queue valid flag register// - EXU queue register// - EXU queue status logic//`ifdef SCR1_DBG_ENassign dbg_run_start_npbuf = hdu2exu_dbg_run_start_i & ~hdu2exu_pbuf_fetch_i;`endif // SCR1_DBG_EN`ifndef SCR1_NO_EXE_STAGE// EXU queue control logic//------------------------------------------------------------------------------assign exu_queue_barrier = wfi_halted_ff | wfi_halt_req | wfi_run_start_ff`ifdef SCR1_DBG_EN| hdu2exu_dbg_halted_i | hdu2exu_dbg_run2halt_i| dbg_run_start_npbuf`endif // SCR1_DBG_EN;assign exu_queue_en = exu2idu_rdy_o & idu2exu_req_i;// EXU queue valid flag register//------------------------------------------------------------------------------assign exu_queue_vd_upd = exu_queue_barrier | exu_rdy;always_ff @(posedge clk, negedge rst_n) beginif (~rst_n) beginexu_queue_vd_ff <= 1'b0;end else if (exu_queue_vd_upd) beginexu_queue_vd_ff <= exu_queue_vd_next;endendassign exu_queue_vd_next = ~exu_queue_barrier & idu2exu_req_i & ~exu2ifu_pc_new_req_o;assign exu_queue_vd = exu_queue_vd_ff;// EXU queue register//------------------------------------------------------------------------------always_ff @(posedge clk) beginif (exu_queue_en) beginexu_queue.instr_rvc <= idu2exu_cmd_i.instr_rvc;exu_queue.ialu_op <= idu2exu_cmd_i.ialu_op;exu_queue.ialu_cmd <= idu2exu_cmd_i.ialu_cmd;exu_queue.sum2_op <= idu2exu_cmd_i.sum2_op;exu_queue.lsu_cmd <= idu2exu_cmd_i.lsu_cmd;exu_queue.csr_op <= idu2exu_cmd_i.csr_op;exu_queue.csr_cmd <= idu2exu_cmd_i.csr_cmd;exu_queue.rd_wb_sel <= idu2exu_cmd_i.rd_wb_sel;exu_queue.jump_req <= idu2exu_cmd_i.jump_req;exu_queue.branch_req <= idu2exu_cmd_i.branch_req;exu_queue.mret_req <= idu2exu_cmd_i.mret_req;exu_queue.fencei_req <= idu2exu_cmd_i.fencei_req;exu_queue.wfi_req <= idu2exu_cmd_i.wfi_req;exu_queue.exc_req <= idu2exu_cmd_i.exc_req;exu_queue.exc_code <= idu2exu_cmd_i.exc_code;idu2exu_use_rs1_ff <= idu2exu_use_rs1_i;idu2exu_use_rs2_ff <= idu2exu_use_rs2_i;if (idu2exu_use_rs1_i) beginexu_queue.rs1_addr <= idu2exu_cmd_i.rs1_addr;endif (idu2exu_use_rs2_i) beginexu_queue.rs2_addr <= idu2exu_cmd_i.rs2_addr;endif (idu2exu_use_rd_i) beginexu_queue.rd_addr <= idu2exu_cmd_i.rd_addr;endif (idu2exu_use_imm_i) beginexu_queue.imm <= idu2exu_cmd_i.imm;endendend`else // ~SCR1_NO_EXE_STAGEassign exu_queue_barrier = wfi_halted_ff | wfi_run_start_ff`ifdef SCR1_DBG_EN| hdu2exu_dbg_halted_i | dbg_run_start_npbuf`endif // SCR1_DBG_EN;assign exu_queue_vd = idu2exu_req_i & ~exu_queue_barrier;assign exu_queue = idu2exu_cmd_i;`endif // ~SCR1_NO_EXE_STAGE//------------------------------------------------------------------------------// Integer Arithmetic Logic Unit (IALU)//------------------------------------------------------------------------------//// Functionality:// - Performs addition/subtraction and arithmetic and branch comparisons// - Performs logical operations (AND(I), OR(I), XOR(I))// - Performs address calculation for branch, jump, DMEM load and store and AUIPC// instructions// - Performs shift operations// - Performs MUL/DIV operations////------------------------------------------------------------------------------// IALU main operands fetch//------------------------------------------------------------------------------`ifdef SCR1_RVM_EXTassign ialu_vd = exu_queue_vd & (exu_queue.ialu_cmd != SCR1_IALU_CMD_NONE)`ifdef SCR1_TDU_EN& ~tdu2exu_ibrkpt_exc_req_i`endif // SCR1_TDU_EN;`endif // SCR1_RVM_EXTalways_comb begin`ifdef SCR1_RVM_EXTif (~ialu_vd) beginialu_main_op1 = '0;ialu_main_op2 = '0;end else begin`endif // SCR1_RVM_EXTif (exu_queue.ialu_op == SCR1_IALU_OP_REG_REG) beginialu_main_op1 = mprf2exu_rs1_data_i;ialu_main_op2 = mprf2exu_rs2_data_i;end else beginialu_main_op1 = mprf2exu_rs1_data_i;ialu_main_op2 = exu_queue.imm;end`ifdef SCR1_RVM_EXTend`endif // SCR1_RVM_EXTend// IALU address operands fetch//------------------------------------------------------------------------------always_comb beginif (exu_queue.sum2_op == SCR1_SUM2_OP_REG_IMM) beginialu_addr_op1 = mprf2exu_rs1_data_i;ialu_addr_op2 = exu_queue.imm;end else beginialu_addr_op1 = pc_curr_ff;ialu_addr_op2 = exu_queue.imm;endend// IALU module instantiation//------------------------------------------------------------------------------scr1_pipe_ialu i_ialu(`ifdef SCR1_RVM_EXT// Common.clk (clk ),.rst_n (rst_n ),.exu2ialu_rvm_cmd_vd_i (ialu_vd ),.ialu2exu_rvm_res_rdy_o (ialu_rdy ),`endif // SCR1_RVM_EXT// IALU.exu2ialu_main_op1_i (ialu_main_op1 ),.exu2ialu_main_op2_i (ialu_main_op2 ),.exu2ialu_cmd_i (exu_queue.ialu_cmd),.ialu2exu_main_res_o (ialu_main_res ),.ialu2exu_cmp_res_o (ialu_cmp ),// Address adder signals.exu2ialu_addr_op1_i (ialu_addr_op1 ),.exu2ialu_addr_op2_i (ialu_addr_op2 ),.ialu2exu_addr_res_o (ialu_addr_res ));//------------------------------------------------------------------------------// Exceptions logic//------------------------------------------------------------------------------//// Exceptions logic consists of the following functional units:// - Exception request logic// - Exception code encoder// - Exception trap value multiplexer////`ifndef SCR1_RVC_EXTassign jb_misalign = exu_queue_vd & jb_taken & |jb_new_pc[1:0];`endif // ~SCR1_RVC_EXT// Exception requestassign exu_exc_req = exu_queue_vd & (exu_queue.exc_req | lsu_exc_req| csr2exu_rw_exc_i`ifndef SCR1_RVC_EXT| jb_misalign`endif // ~SCR1_RVC_EXT`ifdef SCR1_TDU_EN| exu2hdu_ibrkpt_hw_o`endif // SCR1_TDU_EN);// EXU exception request register//------------------------------------------------------------------------------`ifdef SCR1_DBG_ENalways_ff @(posedge clk, negedge rst_n) beginif (~rst_n) beginexu_exc_req_ff <= 1'b0;end else beginexu_exc_req_ff <= exu_exc_req_next;endendassign exu_exc_req_next = hdu2exu_dbg_halt2run_i ? 1'b0 : exu_exc_req;`endif // SCR1_DBG_EN// Exception code encoder//------------------------------------------------------------------------------always_comb begincase (1'b1)`ifdef SCR1_TDU_ENexu2hdu_ibrkpt_hw_o: exc_code = SCR1_EXC_CODE_BREAKPOINT;`endif // SCR1_TDU_ENexu_queue.exc_req : exc_code = exu_queue.exc_code;lsu_exc_req : exc_code = lsu_exc_code;csr2exu_rw_exc_i : exc_code = SCR1_EXC_CODE_ILLEGAL_INSTR;`ifndef SCR1_RVC_EXTjb_misalign : exc_code = SCR1_EXC_CODE_INSTR_MISALIGN;`endif // ~SCR1_RVC_EXTdefault : exc_code = SCR1_EXC_CODE_ECALL_M;endcase // 1'b1end// Exception trap value multiplexer//------------------------------------------------------------------------------assign instr_fault_rvi_hi = exu_queue.instr_rvc;assign exu_illegal_instr = {exu2csr_rw_addr_o, // CSR address5'(exu_queue.rs1_addr), // rs1 / zimmexu_queue.imm[14:12], // funct35'(exu_queue.rd_addr), // rdSCR1_OPCODE_SYSTEM,SCR1_INSTR_RVI};// If Instruction Access Fault occurred on high part of RVI instruction trap// value is set to point on the high part of the instruction (inc_pc=pc+2)always_comb begincase (exc_code)`ifndef SCR1_RVC_EXTSCR1_EXC_CODE_INSTR_MISALIGN : exc_trap_val = jb_new_pc;`endif // SCR1_RVC_EXTSCR1_EXC_CODE_INSTR_ACCESS_FAULT: exc_trap_val = instr_fault_rvi_hi? inc_pc: pc_curr_ff;`ifdef SCR1_MTVAL_ILLEGAL_INSTR_ENSCR1_EXC_CODE_ILLEGAL_INSTR : exc_trap_val = exu_queue.exc_req? exu_queue.imm: exu_illegal_instr;`else // SCR1_MTVAL_ILLEGAL_INSTR_ENSCR1_EXC_CODE_ILLEGAL_INSTR : exc_trap_val = '0;`endif // SCR1_MTVAL_ILLEGAL_INSTR_EN`ifdef SCR1_TDU_ENSCR1_EXC_CODE_BREAKPOINT: begincase (1'b1)tdu2exu_ibrkpt_exc_req_i: exc_trap_val = pc_curr_ff;tdu2lsu_dbrkpt_exc_req_i: exc_trap_val = ialu_addr_res;default : exc_trap_val = '0;endcaseend`endif // SCR1_TDU_ENSCR1_EXC_CODE_LD_ADDR_MISALIGN,SCR1_EXC_CODE_LD_ACCESS_FAULT,SCR1_EXC_CODE_ST_ADDR_MISALIGN,SCR1_EXC_CODE_ST_ACCESS_FAULT : exc_trap_val = ialu_addr_res;default : exc_trap_val = '0;endcase // exc_codeend//------------------------------------------------------------------------------// WFI logic//------------------------------------------------------------------------------//// Wait for interrupt (WFI) logic consists of the following functional units:// - WFI control logic// - WFI Run Start register// - WFI Halted flag register// - WFI status signals//// WFI control logic//------------------------------------------------------------------------------assign wfi_halt_cond = ~csr2exu_ip_ie_i& ((exu_queue_vd & exu_queue.wfi_req) | wfi_run_start_ff)`ifdef SCR1_DBG_EN& ~hdu2exu_no_commit_i & ~hdu2exu_dmode_sstep_en_i & ~hdu2exu_dbg_run2halt_i`endif // SCR1_DBG_EN;assign wfi_halt_req = ~wfi_halted_ff & wfi_halt_cond;// HART will exit WFI halted state if the event that causes the HART to resume// execution occurs even if it doesn't cause an interrupt to be takenassign wfi_run_req = wfi_halted_ff & (csr2exu_ip_ie_i`ifdef SCR1_DBG_EN| hdu2exu_dbg_halt2run_i`endif // SCR1_DBG_EN);// WFI Run Start register//------------------------------------------------------------------------------`ifndef SCR1_CLKCTRL_ENalways_ff @(negedge rst_n, posedge clk) begin`else // SCR1_CLKCTRL_ENalways_ff @(negedge rst_n, posedge clk_alw_on) begin`endif // SCR1_CLKCTRL_ENif (~rst_n) beginwfi_run_start_ff <= 1'b0;end else beginwfi_run_start_ff <= wfi_run_start_next;endendassign wfi_run_start_next = wfi_halted_ff & csr2exu_ip_ie_i & ~exu2csr_take_irq_o;// WFI halted flag register//------------------------------------------------------------------------------assign wfi_halted_upd = wfi_halt_req | wfi_run_req;`ifndef SCR1_CLKCTRL_ENalways_ff @(negedge rst_n, posedge clk) begin`else // SCR1_CLKCTRL_ENalways_ff @(negedge rst_n, posedge clk_alw_on) begin`endif // SCR1_CLKCTRL_ENif (~rst_n) beginwfi_halted_ff <= 1'b0;end else if (wfi_halted_upd) beginwfi_halted_ff <= wfi_halted_next;endendassign wfi_halted_next = wfi_halt_req | ~wfi_run_req;// WFI status signals//------------------------------------------------------------------------------assign exu2pipe_wfi_run2halt_o = wfi_halt_req;`ifdef SCR1_CLKCTRL_ENassign exu2pipe_wfi_halted_o = wfi_halted_ff;`endif // SCR1_CLKCTRL_EN//------------------------------------------------------------------------------// Program Counter logic//------------------------------------------------------------------------------//// PC logic consists of the following functional units:// - PC initialization logic// - Current PC register// - New PC multiplexer// PC initialization logic//------------------------------------------------------------------------------// Generates a New PC request to set PC to reset valuealways_ff @(posedge clk, negedge rst_n) beginif (~rst_n) begininit_pc_v <= '0;end else beginif (~&init_pc_v) begininit_pc_v <= {init_pc_v[2:0], 1'b1};endendendassign init_pc = ~init_pc_v[3] & init_pc_v[2];// Current PC register//------------------------------------------------------------------------------assign pc_curr_upd = ((exu2pipe_instret_o | exu2csr_take_irq_o`ifdef SCR1_DBG_EN| dbg_run_start_npbuf) & ( ~hdu2exu_pc_advmt_dsbl_i& ~hdu2exu_no_commit_i`endif // SCR1_DBG_EN));always_ff @(negedge rst_n, posedge clk) beginif (~rst_n) beginpc_curr_ff <= SCR1_RST_VECTOR;end else if (pc_curr_upd) beginpc_curr_ff <= pc_curr_next;endend`ifdef SCR1_RVC_EXTassign inc_pc = pc_curr_ff + (exu_queue.instr_rvc ? `SCR1_XLEN'd2 : `SCR1_XLEN'd4);`else // ~SCR1_RVC_EXTassign inc_pc = pc_curr_ff + `SCR1_XLEN'd4;`endif // ~SCR1_RVC_EXTassign pc_curr_next = exu2ifu_pc_new_req_o ? exu2ifu_pc_new_o: (inc_pc[6] ^ pc_curr_ff[6]) ? inc_pc: {pc_curr_ff[`SCR1_XLEN-1:6], inc_pc[5:0]};// New PC multiplexer//------------------------------------------------------------------------------always_comb begincase (1'b1)init_pc : exu2ifu_pc_new_o = SCR1_RST_VECTOR;exu2csr_take_exc_o,exu2csr_take_irq_o,exu2csr_mret_instr_o: exu2ifu_pc_new_o = csr2exu_new_pc_i;`ifdef SCR1_DBG_ENdbg_run_start_npbuf : exu2ifu_pc_new_o = hdu2exu_dbg_new_pc_i;`endif // SCR1_DBG_ENwfi_run_start_ff : exu2ifu_pc_new_o = pc_curr_ff;exu_queue.fencei_req: exu2ifu_pc_new_o = inc_pc;default : exu2ifu_pc_new_o = ialu_addr_res & SCR1_JUMP_MASK;endcaseendassign exu2ifu_pc_new_req_o = init_pc // reset| exu2csr_take_irq_o| exu2csr_take_exc_o| (exu2csr_mret_instr_o & ~csr2exu_mstatus_mie_up_i)| (exu_queue_vd & exu_queue.fencei_req)| (wfi_run_start_ff`ifdef SCR1_CLKCTRL_EN& clk_pipe_en`endif // SCR1_CLKCTRL_EN)`ifdef SCR1_DBG_EN| dbg_run_start_npbuf`endif // SCR1_DBG_EN| (exu_queue_vd & jb_taken);// Jump/branch signalsassign branch_taken = exu_queue.branch_req & ialu_cmp;assign jb_taken = exu_queue.jump_req | branch_taken;assign jb_new_pc = ialu_addr_res & SCR1_JUMP_MASK;// PC to be loaded on MRET from interrupt trapassign exu2csr_pc_next_o = ~exu_queue_vd ? pc_curr_ff: jb_taken ? jb_new_pc: inc_pc;assign exu2pipe_pc_curr_o = pc_curr_ff;//------------------------------------------------------------------------------// Load/Store Unit (LSU)//------------------------------------------------------------------------------//// Functionality:// - Performs load and store operations in Data Memory// - Generates DMEM address misalign and access fault exceptions// - Passes DMEM operations information to TDU and generates LSU breakpoint exception////------------------------------------------------------------------------------assign lsu_req = ((exu_queue.lsu_cmd != SCR1_LSU_CMD_NONE) & exu_queue_vd);scr1_pipe_lsu i_lsu(.rst_n (rst_n ),.clk (clk ),// EXU <-> LSU interface.exu2lsu_req_i (lsu_req ), // Request to LSU.exu2lsu_cmd_i (exu_queue.lsu_cmd ), // LSU command.exu2lsu_addr_i (ialu_addr_res ), // DMEM address.exu2lsu_sdata_i (mprf2exu_rs2_data_i ), // Data for store to DMEM.lsu2exu_rdy_o (lsu_rdy ), // LSU ready.lsu2exu_ldata_o (lsu_l_data ), // Loaded data form DMEM.lsu2exu_exc_o (lsu_exc_req ), // LSU exception.lsu2exu_exc_code_o (lsu_exc_code ), // LSU exception code`ifdef SCR1_TDU_EN// TDU <-> LSU interface.lsu2tdu_dmon_o (lsu2tdu_dmon_o ),.tdu2lsu_ibrkpt_exc_req_i (tdu2lsu_ibrkpt_exc_req_i),.tdu2lsu_dbrkpt_exc_req_i (tdu2lsu_dbrkpt_exc_req_i),`endif // SCR1_TDU_EN// Data memory interface.lsu2dmem_req_o (exu2dmem_req_o ), // DMEM request.lsu2dmem_cmd_o (exu2dmem_cmd_o ), // DMEM command.lsu2dmem_width_o (exu2dmem_width_o ), // DMEM width.lsu2dmem_addr_o (exu2dmem_addr_o ), // DMEM address.lsu2dmem_wdata_o (exu2dmem_wdata_o ), // DMEM write data.dmem2lsu_req_ack_i (dmem2exu_req_ack_i ), // DMEM request acknowledge.dmem2lsu_rdata_i (dmem2exu_rdata_i ), // DMEM read data.dmem2lsu_resp_i (dmem2exu_resp_i ) // DMEM response);//------------------------------------------------------------------------------// EXU status logic//------------------------------------------------------------------------------// EXU ready flagalways_comb begincase (1'b1)lsu_req : exu_rdy = lsu_rdy | lsu_exc_req;`ifdef SCR1_RVM_EXTialu_vd : exu_rdy = ialu_rdy;`endif // SCR1_RVM_EXTcsr2exu_mstatus_mie_up_i: exu_rdy = 1'b0;default : exu_rdy = 1'b1;endcaseendassign exu2pipe_init_pc_o = init_pc;assign exu2idu_rdy_o = exu_rdy & ~exu_queue_barrier;assign exu2pipe_exu_busy_o = exu_queue_vd & ~exu_rdy;assign exu2pipe_instret_o = exu_queue_vd & exu_rdy;assign exu2csr_instret_no_exc_o = exu2pipe_instret_o & ~exu_exc_req;// Exceptions`ifdef SCR1_DBG_ENassign exu2pipe_exc_req_o = exu_queue_vd ? exu_exc_req : exu_exc_req_ff;`else // SCR1_DBG_ENassign exu2pipe_exc_req_o = exu_exc_req;`endif // SCR1_DBG_EN// Breakpointsassign exu2pipe_brkpt_o = exu_queue_vd & (exu_queue.exc_code == SCR1_EXC_CODE_BREAKPOINT);`ifdef SCR1_TDU_ENassign exu2hdu_ibrkpt_hw_o = tdu2exu_ibrkpt_exc_req_i | tdu2lsu_dbrkpt_exc_req_i;`endif // SCR1_TDU_EN//------------------------------------------------------------------------------// EXU <-> MPRF interface//------------------------------------------------------------------------------// Operands fetching stage//------------------------------------------------------------------------------`ifdef SCR1_NO_EXE_STAGEassign mprf_rs1_req = exu_queue_vd & idu2exu_use_rs1_i;assign mprf_rs2_req = exu_queue_vd & idu2exu_use_rs2_i;`else // SCR1_NO_EXE_STAGE`ifdef SCR1_MPRF_RAMassign mprf_rs1_req = exu_queue_en? (exu_queue_vd_next & idu2exu_use_rs1_i): (exu_queue_vd & idu2exu_use_rs1_ff);assign mprf_rs2_req = exu_queue_en? (exu_queue_vd_next & idu2exu_use_rs2_i): (exu_queue_vd & idu2exu_use_rs2_ff);`else // SCR1_MPRF_RAMassign mprf_rs1_req = exu_queue_vd & idu2exu_use_rs1_ff;assign mprf_rs2_req = exu_queue_vd & idu2exu_use_rs2_ff;`endif // SCR1_MPRF_RAM`endif // SCR1_NO_EXE_STAGE// If exu_queue isn't enabled we need previous addresses and usage flags because// RAM blocks read operation is SYNCHRONOUS`ifdef SCR1_MPRF_RAMassign mprf_rs1_addr = exu_queue_en ? idu2exu_cmd_i.rs1_addr : exu_queue.rs1_addr;assign mprf_rs2_addr = exu_queue_en ? idu2exu_cmd_i.rs2_addr : exu_queue.rs2_addr;`else // SCR1_MPRF_RAMassign mprf_rs1_addr = exu_queue.rs1_addr;assign mprf_rs2_addr = exu_queue.rs2_addr;`endif // SCR1_MPRF_RAMassign exu2mprf_rs1_addr_o = mprf_rs1_req ? `SCR1_MPRF_AWIDTH'(mprf_rs1_addr) : '0;assign exu2mprf_rs2_addr_o = mprf_rs2_req ? `SCR1_MPRF_AWIDTH'(mprf_rs2_addr) : '0;// Write back stage//------------------------------------------------------------------------------assign exu2mprf_w_req_o = (exu_queue.rd_wb_sel != SCR1_RD_WB_NONE) & exu_queue_vd & ~exu_exc_req`ifdef SCR1_DBG_EN& ~hdu2exu_no_commit_i`endif // SCR1_DBG_EN& ((exu_queue.rd_wb_sel == SCR1_RD_WB_CSR) ? csr_access_init : exu_rdy);assign exu2mprf_rd_addr_o = `SCR1_MPRF_AWIDTH'(exu_queue.rd_addr);// MRPF RD data multiplexeralways_comb begincase (exu_queue.rd_wb_sel)SCR1_RD_WB_SUM2 : exu2mprf_rd_data_o = ialu_addr_res;SCR1_RD_WB_IMM : exu2mprf_rd_data_o = exu_queue.imm;SCR1_RD_WB_INC_PC: exu2mprf_rd_data_o = inc_pc;SCR1_RD_WB_LSU : exu2mprf_rd_data_o = lsu_l_data;SCR1_RD_WB_CSR : exu2mprf_rd_data_o = csr2exu_r_data_i;default : exu2mprf_rd_data_o = ialu_main_res;endcaseend//------------------------------------------------------------------------------// EXU <-> CSR interface//------------------------------------------------------------------------------//// EXU <-> CSR interface consists of the following functional units:// - CSR write/read interface// - CSR access FSM// - CSR events interface:// - Exceptions signals// - Interrupts signals// - MRET signals//// CSRs write/read interface//------------------------------------------------------------------------------// CSR write/read request signals calculationalways_comb beginif (~exu_queue_vd`ifdef SCR1_TDU_EN| tdu2exu_ibrkpt_exc_req_i`endif // SCR1_TDU_EN) beginexu2csr_r_req_o = 1'b0;exu2csr_w_req_o = 1'b0;end else begincase (exu_queue.csr_cmd)SCR1_CSR_CMD_WRITE : beginexu2csr_r_req_o = |exu_queue.rd_addr;exu2csr_w_req_o = csr_access_init;endSCR1_CSR_CMD_SET,SCR1_CSR_CMD_CLEAR : beginexu2csr_r_req_o = 1'b1;exu2csr_w_req_o = |exu_queue.rs1_addr & csr_access_init;enddefault : beginexu2csr_r_req_o = 1'b0;exu2csr_w_req_o = 1'b0;endendcaseendendassign exu2csr_w_cmd_o = exu_queue.csr_cmd;assign exu2csr_rw_addr_o = exu_queue.imm[SCR1_CSR_ADDR_WIDTH-1:0];assign exu2csr_w_data_o = (exu_queue.csr_op == SCR1_CSR_OP_REG)? mprf2exu_rs1_data_i: {'0, exu_queue.rs1_addr}; // zimm// CSR access FSM//------------------------------------------------------------------------------always_ff @(posedge clk, negedge rst_n) beginif (~rst_n) begincsr_access_ff <= SCR1_CSR_INIT;end else begincsr_access_ff <= csr_access_next;endendassign csr_access_next = (csr_access_init & csr2exu_mstatus_mie_up_i)? SCR1_CSR_RDY: SCR1_CSR_INIT;assign csr_access_init = (csr_access_ff == SCR1_CSR_INIT);// CSR events interface//------------------------------------------------------------------------------// Exceptions signalsassign exu2csr_take_exc_o = exu_exc_req`ifdef SCR1_DBG_EN& ~hdu2exu_dbg_halted_i`endif // SCR1_DBG_EN;assign exu2csr_exc_code_o = exc_code;assign exu2csr_trap_val_o = exc_trap_val;// Interrupts signalsassign exu2csr_take_irq_o = csr2exu_irq_i & ~exu2pipe_exu_busy_o`ifdef SCR1_DBG_EN& ~hdu2exu_irq_dsbl_i& ~hdu2exu_dbg_halted_i`endif // SCR1_DBG_EN`ifdef SCR1_CLKCTRL_EN& clk_pipe_en`endif // SCR1_CLKCTRL_EN;// MRET signals// MRET instruction flagassign exu2csr_mret_instr_o = exu_queue_vd & exu_queue.mret_req`ifdef SCR1_TDU_EN& ~tdu2exu_ibrkpt_exc_req_i`endif // SCR1_TDU_EN`ifdef SCR1_DBG_EN& ~hdu2exu_dbg_halted_i`endif // SCR1_DBG_EN;assign exu2csr_mret_update_o = exu2csr_mret_instr_o & csr_access_init;`ifdef SCR1_TDU_EN//------------------------------------------------------------------------------// EXU <-> TDU interface//------------------------------------------------------------------------------// Instruction monitorassign exu2tdu_imon_o.vd = exu_queue_vd;assign exu2tdu_imon_o.req = exu2pipe_instret_o;assign exu2tdu_imon_o.addr = pc_curr_ff;always_comb beginexu2tdu_ibrkpt_ret_o = '0;if (exu_queue_vd) beginexu2tdu_ibrkpt_ret_o = tdu2exu_ibrkpt_match_i;if (lsu_req) beginexu2tdu_ibrkpt_ret_o[SCR1_TDU_MTRIG_NUM-1:0] |= tdu2lsu_dbrkpt_match_i;endendend`endif // SCR1_TDU_EN`ifdef SCR1_TRGT_SIMULATION//------------------------------------------------------------------------------// Tracelog signals//------------------------------------------------------------------------------logic [`SCR1_XLEN-1:0] update_pc;logic update_pc_en;assign update_pc_en = (init_pc | exu2pipe_instret_o | exu2csr_take_irq_o)`ifdef SCR1_DBG_EN& ~hdu2exu_pc_advmt_dsbl_i & ~hdu2exu_no_commit_i`endif // SCR1_DBG_EN;assign update_pc = exu2ifu_pc_new_req_o ? exu2ifu_pc_new_o : inc_pc;//------------------------------------------------------------------------------// Assertion//------------------------------------------------------------------------------// X checksSCR1_SVA_EXU_XCHECK_CTRL : assert property (@(negedge clk) disable iff (~rst_n)!$isunknown({idu2exu_req_i, csr2exu_irq_i, csr2exu_ip_ie_i, lsu_req, lsu_rdy, exu_exc_req})) else $error("EXU Error: unknown control values");SCR1_SVA_EXU_XCHECK_QUEUE : assert property (@(negedge clk) disable iff (~rst_n)idu2exu_req_i |-> !$isunknown(idu2exu_cmd_i)) else $error("EXU Error: unknown values in queue");SCR1_SVA_EXU_XCHECK_CSR_RDATA : assert property (@(negedge clk) disable iff (~rst_n)exu2csr_r_req_o |-> !$isunknown({csr2exu_r_data_i, csr2exu_rw_exc_i})) else $error("EXU Error: unknown values from CSR");// Behavior checksSCR1_SVA_EXU_ONEHOT : assert property (@(negedge clk) disable iff (~rst_n)$onehot0({exu_queue.jump_req, exu_queue.branch_req, lsu_req})) else $error("EXU Error: illegal combination of control signals");SCR1_SVA_EXU_ONEHOT_EXC : assert property (@(negedge clk) disable iff (~rst_n)exu_queue_vd |->$onehot0({exu_queue.exc_req, lsu_exc_req, csr2exu_rw_exc_i`ifndef SCR1_RVC_EXT, jb_misalign`endif})) else $error("EXU Error: exceptions $onehot0 failed");`endif // SCR1_TRGT_SIMULATIONendmodule : scr1_pipe_exu
