URL
https://opencores.org/ocsvn/yifive/yifive/trunk
Subversion Repositories yifive
[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [syntacore/] [scr1/] [src/] [core/] [pipeline/] [scr1_pipe_hdu.sv] - Rev 11
Compare with Previous | Blame | View Log
/// @file <scr1_pipe_hdu.sv>/// @brief HART Debug Unit (HDU)/////------------------------------------------------------------------------------////// Functionality:// - Controls HART state (RUN, Debug RUN, Debug HALTED)// - Setups Debug Mode execution// - Provides status information about Debug Mode execution// - Provides Program Buffer functionality (a few instructions execution while// in Debug Mode)// - Provides access to Debug CSRs//// Structure:// - Debug state FSM// - HART Control logic// - HART Status logic// - Program Buffer// - Debug CSRs// - HDU <-> DM interface// - HDU <-> EXU interface// - HDU <-> IFU interface// - HDU <-> CSR interface// - HDU <-> TDU interface////------------------------------------------------------------------------------`include "scr1_arch_description.svh"`ifdef SCR1_DBG_EN`include "scr1_arch_types.svh"`include "scr1_riscv_isa_decoding.svh"`include "scr1_hdu.svh"module scr1_pipe_hdu #(parameter HART_PBUF_INSTR_REGOUT_EN = 1'b1) (// Common signalsinput logic rst_n, // HDU resetinput logic clk, // HDU clockinput logic clk_en, // HDU clock enable`ifdef SCR1_CLKCTRL_ENinput logic clk_pipe_en, // Pipeline clock enable`endif // SCR1_CLKCTRL_ENinput logic pipe2hdu_rdc_qlfy_i, // Pipeline RDC qualifier// HDU <-> CSR i/finput logic csr2hdu_req_i, // CSR i/f requestinput type_scr1_csr_cmd_sel_e csr2hdu_cmd_i, // CSR i/f commandinput logic [SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0] csr2hdu_addr_i, // CSR i/f addressinput logic [`SCR1_XLEN-1:0] csr2hdu_wdata_i, // CSR i/f write dataoutput type_scr1_csr_resp_e hdu2csr_resp_o, // CSR i/f responseoutput logic [`SCR1_XLEN-1:0] hdu2csr_rdata_o, // CSR i/f read data// HDU <-> DM i/f// HART Run Control i/finput logic dm2hdu_cmd_req_i, // DM-HART Command requestinput type_scr1_hdu_dbgstates_e dm2hdu_cmd_i, // DM-HART Commandoutput logic hdu2dm_cmd_resp_o, // DM-HART Command responseoutput logic hdu2dm_cmd_rcode_o, // DM-HART Command return code: 0 - Ok; 1 - Erroroutput logic hdu2dm_hart_event_o, // DM-HART Event: 1 if HART debug state changedoutput type_scr1_hdu_hartstatus_s hdu2dm_hart_status_o, // DM-HART Status// Program Buffer i/foutput logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] hdu2dm_pbuf_addr_o, // Program Buffer address - so far request only for 1 instructioninput logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2hdu_pbuf_instr_i, // Program Buffer instruction// HART Abstract Data regs i/foutput logic hdu2dm_dreg_req_o, // Abstract Data Register requestoutput logic hdu2dm_dreg_wr_o, // Abstract Data Register writeoutput logic [`SCR1_XLEN-1:0] hdu2dm_dreg_wdata_o, // Abstract Data Register write datainput logic dm2hdu_dreg_resp_i, // Abstract Data Register responseinput logic dm2hdu_dreg_fail_i, // Abstract Data Register failinput logic [`SCR1_XLEN-1:0] dm2hdu_dreg_rdata_i, // Abstract Data Register read data`ifdef SCR1_TDU_EN// HDU <-> TDU interfaceoutput logic hdu2tdu_hwbrk_dsbl_o, // Disables BRKMinput logic tdu2hdu_dmode_req_i, // Trigger Module requests transition to debug modeinput logic exu2hdu_ibrkpt_hw_i, // Hardware breakpoint on current instruction`endif // SCR1_TDU_EN// HART Run Statusinput logic pipe2hdu_exu_busy_i, // EXU busyinput logic pipe2hdu_instret_i, // Instruction retired (with or without exception)input logic pipe2hdu_init_pc_i, // Reset exit// HART Halt Statusinput logic pipe2hdu_exu_exc_req_i, // Exception requestinput logic pipe2hdu_brkpt_i, // Software Breakpoint (EBREAK)// HDU <-> EXU i/f// HART Run Controloutput logic hdu2exu_pbuf_fetch_o, // Fetch instruction from Program Bufferoutput logic hdu2exu_no_commit_o, // Forbid instruction commitmentoutput logic hdu2exu_irq_dsbl_o, // Disable IRQoutput logic hdu2exu_pc_advmt_dsbl_o, // Forbid PC advancementoutput logic hdu2exu_dmode_sstep_en_o, // Enable single-step// HART stateoutput logic hdu2exu_dbg_halted_o, // Debug halted stateoutput logic hdu2exu_dbg_run2halt_o, // Transition to debug halted stateoutput logic hdu2exu_dbg_halt2run_o, // Transition to run stateoutput logic hdu2exu_dbg_run_start_o, // First cycle of run state// PC interfaceinput logic [`SCR1_XLEN-1:0] pipe2hdu_pc_curr_i, // Current PCoutput logic [`SCR1_XLEN-1:0] hdu2exu_dbg_new_pc_o, // New PC for resume// HDU <-> IFU i/f// Program Buffer Instruction interfaceinput logic ifu2hdu_pbuf_instr_rdy_i, // Program Buffer Instruction i/f readyoutput logic hdu2ifu_pbuf_instr_vd_o, // Program Buffer Instruction validoutput logic hdu2ifu_pbuf_instr_err_o, // Program Buffer Instruction i/f erroroutput logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr_o // Program Buffer Instruction itself);//------------------------------------------------------------------------------// Local Parameters//------------------------------------------------------------------------------localparam int unsigned SCR1_HDU_TIMEOUT = 64; // must be power of 2localparam int unsigned SCR1_HDU_TIMEOUT_WIDTH = $clog2(SCR1_HDU_TIMEOUT);//------------------------------------------------------------------------------// Local Signals//------------------------------------------------------------------------------// Debug FSM//------------------------------------------------------------------------------// FSM control signalslogic dm_dhalt_req;logic dm_run_req;logic dm_cmd_run;logic dm_cmd_dhalted;logic dm_cmd_drun;// Debug state FSM signalstype_scr1_hdu_dbgstates_e dbg_state;type_scr1_hdu_dbgstates_e dbg_state_next;logic dbg_state_dhalted;logic dbg_state_drun;logic dbg_state_run;logic dbg_state_reset;// FSM transition, update and event registerslogic dfsm_trans;logic dfsm_trans_next;logic dfsm_update;logic dfsm_update_next;logic dfsm_event;logic dfsm_event_next;// HART Control signals//------------------------------------------------------------------------------logic hart_resume_req;logic hart_halt_req;logic hart_cmd_req;// HART Run Control registerlogic hart_runctrl_upd;logic hart_runctrl_clr;type_scr1_hdu_runctrl_s hart_runctrl;// HART halt request timeout counter signalslogic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt;logic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt_next;logic halt_req_timeout_cnt_en;logic halt_req_timeout_flag;// HART Status signals//------------------------------------------------------------------------------type_scr1_hdu_haltstatus_s hart_haltstatus;type_scr1_hdu_haltcause_e hart_haltcause;logic hart_halt_pnd;logic hart_halt_ack;// Debug mode cause decoder signalslogic dmode_cause_sstep;logic dmode_cause_except;logic dmode_cause_ebreak;logic dmode_cause_any;`ifdef SCR1_TDU_ENlogic dmode_cause_tmreq;`endif // SCR1_TDU_EN// Program Buffer FSM//------------------------------------------------------------------------------// PBUF FSM control signalslogic ifu_handshake_done;logic pbuf_exc_inj_req;logic pbuf_exc_inj_end;logic pbuf_start_fetch;// PBUF FSM signalstype_scr1_hdu_pbufstates_e pbuf_fsm_curr;type_scr1_hdu_pbufstates_e pbuf_fsm_next;logic pbuf_fsm_idle;logic pbuf_fsm_fetch;logic pbuf_fsm_excinj;// PBUF address signalslogic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_ff;logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_next;logic pbuf_addr_end;logic pbuf_addr_next_vd;logic pbuf_instr_wait_latching;// Debugs CSRs//------------------------------------------------------------------------------// CSRs write/read interface signalslogic csr_upd_on_halt;logic csr_wr;logic [`SCR1_XLEN-1:0] csr_wr_data;logic [`SCR1_XLEN-1:0] csr_rd_data;// Debug Control and Status register (DCSR)logic csr_dcsr_sel;logic csr_dcsr_wr;type_scr1_hdu_dcsr_s csr_dcsr_in;type_scr1_hdu_dcsr_s csr_dcsr_out;logic csr_dcsr_ebreakm;logic csr_dcsr_stepie;logic csr_dcsr_step;logic [SCR1_HDU_DCSR_CAUSE_BIT_L-SCR1_HDU_DCSR_CAUSE_BIT_R:0] csr_dcsr_cause;// Debug Program Counter register (DPC)logic csr_dpc_sel;logic csr_dpc_wr;logic [`SCR1_XLEN-1:0] csr_dpc_ff;logic [`SCR1_XLEN-1:0] csr_dpc_next;logic [`SCR1_XLEN-1:0] csr_dpc_out;// Debug Scratch register 0 (DSCRATCH0)logic csr_addr_dscratch0;logic csr_dscratch0_sel;logic csr_dscratch0_wr;logic [`SCR1_XLEN-1:0] csr_dscratch0_out;type_scr1_csr_resp_e csr_dscratch0_resp;//------------------------------------------------------------------------------// Debug state FSM logic//------------------------------------------------------------------------------//// Debug state FSM logic consists of the following functional units:// - FSM control logic// - Debug state FSM// - FSM transition, update and event registers//// FSM control logic//------------------------------------------------------------------------------assign dm_cmd_dhalted = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DHALTED);assign dm_cmd_run = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_RUN);assign dm_cmd_drun = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DRUN);assign dm_dhalt_req = dm2hdu_cmd_req_i & dm_cmd_dhalted;assign dm_run_req = dm2hdu_cmd_req_i & (dm_cmd_run | dm_cmd_drun);// Debug state FSM//------------------------------------------------------------------------------always_ff @(negedge rst_n, posedge clk) beginif (~rst_n) begindbg_state <= SCR1_HDU_DBGSTATE_RESET;end else begindbg_state <= dbg_state_next;endendalways_comb beginif (~pipe2hdu_rdc_qlfy_i) begindbg_state_next = SCR1_HDU_DBGSTATE_RESET;end else begincase (dbg_state)SCR1_HDU_DBGSTATE_RESET: begindbg_state_next = ~pipe2hdu_init_pc_i ? SCR1_HDU_DBGSTATE_RESET: dm_dhalt_req ? SCR1_HDU_DBGSTATE_DHALTED: SCR1_HDU_DBGSTATE_RUN;endSCR1_HDU_DBGSTATE_RUN: begindbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED: SCR1_HDU_DBGSTATE_RUN;endSCR1_HDU_DBGSTATE_DHALTED: begindbg_state_next = ~dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED: dm_cmd_drun ? SCR1_HDU_DBGSTATE_DRUN: SCR1_HDU_DBGSTATE_RUN;endSCR1_HDU_DBGSTATE_DRUN: begindbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED: SCR1_HDU_DBGSTATE_DRUN;enddefault: begin`ifdef SCR1_XPROP_ENdbg_state_next = SCR1_HDU_DBGSTATE_XXX;`else // SCR1_XPROP_ENdbg_state_next = dbg_state;`endif // SCR1_XPROP_ENendendcaseendendassign dbg_state_dhalted = (dbg_state == SCR1_HDU_DBGSTATE_DHALTED);assign dbg_state_drun = (dbg_state == SCR1_HDU_DBGSTATE_DRUN);assign dbg_state_run = (dbg_state == SCR1_HDU_DBGSTATE_RUN);assign dbg_state_reset = (dbg_state == SCR1_HDU_DBGSTATE_RESET);// FSM transition, update and event registers//------------------------------------------------------------------------------always_ff @(negedge rst_n, posedge clk) beginif (~rst_n) begindfsm_trans <= 1'b0;dfsm_update <= 1'b0;dfsm_event <= 1'b0;end else begindfsm_trans <= dfsm_trans_next;dfsm_update <= dfsm_update_next;dfsm_event <= dfsm_event_next;endendalways_comb begindfsm_trans_next = 1'b0;dfsm_update_next = 1'b0;dfsm_event_next = 1'b0;if (~pipe2hdu_rdc_qlfy_i) begindfsm_trans_next = 1'b0;dfsm_update_next = 1'b0;dfsm_event_next = 1'b1;end else begincase (dbg_state)SCR1_HDU_DBGSTATE_RESET: begindfsm_trans_next = 1'b0;dfsm_update_next = 1'b0;dfsm_event_next = pipe2hdu_init_pc_i & ~dm2hdu_cmd_req_i;endSCR1_HDU_DBGSTATE_RUN,SCR1_HDU_DBGSTATE_DRUN: begindfsm_trans_next = ~dfsm_update ? hart_halt_pnd : dfsm_trans;dfsm_update_next = ~dfsm_update & hart_halt_ack;dfsm_event_next = dfsm_update;endSCR1_HDU_DBGSTATE_DHALTED: begindfsm_trans_next = ~dfsm_update ? ~dfsm_trans & dm_run_req: dfsm_trans;dfsm_update_next = ~dfsm_update & dfsm_trans;dfsm_event_next = dfsm_update;enddefault : begindfsm_trans_next = 'X;dfsm_update_next = 'X;dfsm_event_next = 'X;endendcaseendend//------------------------------------------------------------------------------// HART Control logic//------------------------------------------------------------------------------//// HART Control logic consists of the following functional units:// - Control signals// - HART Run Control register// - HART Halt Request Time-Out counter//// Control logicalways_comb beginhart_cmd_req = 1'b0;if (~pipe2hdu_rdc_qlfy_i) beginhart_cmd_req = 1'b0;end else begincase (dbg_state)SCR1_HDU_DBGSTATE_RESET : hart_cmd_req = dm2hdu_cmd_req_i;SCR1_HDU_DBGSTATE_DHALTED: hart_cmd_req = (dfsm_update | dfsm_trans);SCR1_HDU_DBGSTATE_RUN,SCR1_HDU_DBGSTATE_DRUN : hart_cmd_req = ~dfsm_update & dfsm_trans;default : hart_cmd_req = 'X;endcaseendendassign hart_halt_req = dm_cmd_dhalted & hart_cmd_req;assign hart_resume_req = (dm_cmd_run | dm_cmd_drun) & hart_cmd_req;// HART Run Control register//------------------------------------------------------------------------------assign hart_runctrl_clr = (dbg_state_run | dbg_state_drun)& (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);assign hart_runctrl_upd = dbg_state_dhalted & dfsm_trans_next;always_ff @(negedge rst_n, posedge clk) beginif (~rst_n) beginhart_runctrl.irq_dsbl <= 1'b0;hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;hart_runctrl.pc_advmt_dsbl <= 1'b0;hart_runctrl.hwbrkpt_dsbl <= 1'b0;hart_runctrl.redirect <= '0;end else if(clk_en) beginif (hart_runctrl_clr) beginhart_runctrl <= '0;end else beginif (hart_runctrl_upd) beginif (~dm_cmd_drun) begin// Case : resume to RUN statehart_runctrl.irq_dsbl <= csr_dcsr_step ? ~csr_dcsr_stepie : 1'b0;hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;hart_runctrl.pc_advmt_dsbl <= 1'b0;hart_runctrl.hwbrkpt_dsbl <= 1'b0;hart_runctrl.redirect.sstep <= csr_dcsr_step;hart_runctrl.redirect.ebreak <= csr_dcsr_ebreakm;end else begin// Case : resume to DRUN statehart_runctrl.irq_dsbl <= 1'b1;hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_PBUF;hart_runctrl.pc_advmt_dsbl <= 1'b1;hart_runctrl.hwbrkpt_dsbl <= 1'b1;hart_runctrl.redirect.sstep <= 1'b0;hart_runctrl.redirect.ebreak <= 1'b1;endendendendend// HART Halt Request Time-Out counter//------------------------------------------------------------------------------// HART goes into halt state only if the halt request is present for timeout period// of timeassign halt_req_timeout_cnt_en = hdu2exu_dbg_halt2run_o| (hart_halt_req & ~hdu2exu_dbg_run2halt_o);always_ff @(posedge clk, negedge rst_n) beginif (~rst_n) beginhalt_req_timeout_cnt <= '1;end else if (halt_req_timeout_cnt_en) beginhalt_req_timeout_cnt <= halt_req_timeout_cnt_next;endendassign halt_req_timeout_cnt_next = hdu2exu_dbg_halt2run_o ? '1: (hart_halt_req & ~hdu2exu_dbg_run2halt_o) ? halt_req_timeout_cnt - 1'b1: halt_req_timeout_cnt;assign halt_req_timeout_flag = ~|halt_req_timeout_cnt;//------------------------------------------------------------------------------// HART Status logic//------------------------------------------------------------------------------//// HART Status logic consists of the following functional units:// - Debug mode cause decoder// - Hart halt status cause encoder// - Hart halt status register//// Debug mode cause decoder//------------------------------------------------------------------------------assign dmode_cause_sstep = hart_runctrl.redirect.sstep & pipe2hdu_instret_i;assign dmode_cause_except = dbg_state_drun & pipe2hdu_exu_exc_req_i& ~pipe2hdu_brkpt_i`ifdef SCR1_TDU_EN& ~exu2hdu_ibrkpt_hw_i`endif // SCR1_TDU_EN;assign dmode_cause_ebreak = hart_runctrl.redirect.ebreak & pipe2hdu_brkpt_i;`ifdef SCR1_TDU_ENassign dmode_cause_tmreq = tdu2hdu_dmode_req_i & exu2hdu_ibrkpt_hw_i;`endif // SCR1_TDU_ENassign dmode_cause_any = dmode_cause_sstep | dmode_cause_ebreak | dmode_cause_except| hart_halt_req`ifdef SCR1_TDU_EN| dmode_cause_tmreq`endif // SCR1_TDU_EN;// HART halt cause encoder//------------------------------------------------------------------------------always_comb begincase (1'b1)`ifdef SCR1_TDU_ENdmode_cause_tmreq : hart_haltcause = SCR1_HDU_HALTCAUSE_TMREQ;`endif // SCR1_TDU_ENdmode_cause_ebreak : hart_haltcause = SCR1_HDU_HALTCAUSE_EBREAK;hart_halt_req : hart_haltcause = SCR1_HDU_HALTCAUSE_DMREQ;dmode_cause_sstep : hart_haltcause = SCR1_HDU_HALTCAUSE_SSTEP;default : hart_haltcause = SCR1_HDU_HALTCAUSE_NONE;endcaseend// HART halt status register//------------------------------------------------------------------------------always_ff @(posedge clk, negedge rst_n) beginif (~rst_n) beginhart_haltstatus <= '0;end else if (hart_halt_ack) beginhart_haltstatus.except <= dmode_cause_except;hart_haltstatus.cause <= hart_haltcause;endendassign hart_halt_pnd = (dfsm_trans | dm_dhalt_req) & ~hart_halt_ack;assign hart_halt_ack = ~hdu2exu_dbg_halted_o& (halt_req_timeout_flag | (~pipe2hdu_exu_busy_i & dmode_cause_any));//------------------------------------------------------------------------------// Program Buffer (PBUF) logic//------------------------------------------------------------------------------//// Program Buffer allows to execute small programs in debug mode//// To terminate Program Buffer execution exception should be raised. There are 2// cases:// - One of PBUF instructions raise an exception// - No PBUF instruction raise an exception before the last PBUF instruction has// been issued. In this case FSM goes into EXCINJECT state and an "Instruction// fetch access fault" exception is injected// PBUF FSM//------------------------------------------------------------------------------assign ifu_handshake_done = hdu2ifu_pbuf_instr_vd_o & ifu2hdu_pbuf_instr_rdy_i;assign pbuf_addr_end = (pbuf_addr_ff == (SCR1_HDU_PBUF_ADDR_SPAN-1));assign pbuf_start_fetch = dbg_state_dhalted & (dbg_state_next == SCR1_HDU_DBGSTATE_DRUN);assign pbuf_exc_inj_req = ifu_handshake_done & pbuf_addr_end;assign pbuf_exc_inj_end = pipe2hdu_exu_exc_req_i | ifu_handshake_done;always_ff @(negedge rst_n, posedge clk) beginif (~rst_n) beginpbuf_fsm_curr <= SCR1_HDU_PBUFSTATE_IDLE;end else if(clk_en) beginpbuf_fsm_curr <= pbuf_fsm_next;endendalways_comb begincase (pbuf_fsm_curr)SCR1_HDU_PBUFSTATE_IDLE: beginpbuf_fsm_next = pbuf_start_fetch ? SCR1_HDU_PBUFSTATE_FETCH: SCR1_HDU_PBUFSTATE_IDLE;endSCR1_HDU_PBUFSTATE_FETCH: beginpbuf_fsm_next = pipe2hdu_exu_exc_req_i ? SCR1_HDU_PBUFSTATE_WAIT4END: pbuf_exc_inj_req ? SCR1_HDU_PBUFSTATE_EXCINJECT: SCR1_HDU_PBUFSTATE_FETCH;endSCR1_HDU_PBUFSTATE_EXCINJECT: beginpbuf_fsm_next = pbuf_exc_inj_end ? SCR1_HDU_PBUFSTATE_WAIT4END: SCR1_HDU_PBUFSTATE_EXCINJECT;endSCR1_HDU_PBUFSTATE_WAIT4END: beginpbuf_fsm_next = hdu2exu_dbg_halted_o ? SCR1_HDU_PBUFSTATE_IDLE: SCR1_HDU_PBUFSTATE_WAIT4END;endendcaseendassign pbuf_fsm_idle = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_IDLE);assign pbuf_fsm_fetch = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_FETCH);assign pbuf_fsm_excinj = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_EXCINJECT);// Program Buffer address register//------------------------------------------------------------------------------assign pbuf_addr_next_vd = pbuf_fsm_fetch & ifu_handshake_done& ~pipe2hdu_exu_exc_req_i & ~pbuf_addr_end;always_ff @(negedge rst_n, posedge clk) beginif (~rst_n) beginpbuf_addr_ff <= '0;end else if(clk_en) beginpbuf_addr_ff <= pbuf_addr_next;endendassign pbuf_addr_next = pbuf_fsm_idle ? '0: pbuf_addr_next_vd ? pbuf_addr_ff + 1'b1: pbuf_addr_ff;// Pass instruction from debug program buffer to cpu pipeline with two options:// - through register, better for frequency// - through wires, better for areagenerate if (HART_PBUF_INSTR_REGOUT_EN) beginalways_ff @(posedge clk, negedge rst_n) beginif (~rst_n) beginpbuf_instr_wait_latching <= 1'b0;end else beginpbuf_instr_wait_latching <= ifu_handshake_done;endendend else beginassign pbuf_instr_wait_latching = 1'b0;end endgenerate//------------------------------------------------------------------------------// Debug CSRs//------------------------------------------------------------------------------assign csr_upd_on_halt = (dbg_state_reset | dbg_state_run)& (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);// CSRs select logic//------------------------------------------------------------------------------always_comb begin : csr_if_regselcsr_dcsr_sel = 1'b0;csr_dpc_sel = 1'b0;csr_dscratch0_sel = 1'b0;//csr_dscratch1_sel = 1'b0;if (csr2hdu_req_i) begincase (csr2hdu_addr_i)SCR1_HDU_DBGCSR_OFFS_DCSR : csr_dcsr_sel = 1'b1;SCR1_HDU_DBGCSR_OFFS_DPC : csr_dpc_sel = 1'b1;SCR1_HDU_DBGCSR_OFFS_DSCRATCH0: csr_dscratch0_sel = 1'b1;default : begincsr_dcsr_sel = 1'bX;csr_dpc_sel = 1'bX;csr_dscratch0_sel = 1'bX;endendcaseendend : csr_if_regsel// CSRs read interface//------------------------------------------------------------------------------assign csr_rd_data = csr_dcsr_out | csr_dpc_out | csr_dscratch0_out;// CSRs write interface//------------------------------------------------------------------------------assign csr_wr = csr2hdu_req_i;always_comb begin : csr_if_writecsr_wr_data = '0;if (csr2hdu_req_i) begincase (csr2hdu_cmd_i)SCR1_CSR_CMD_WRITE : csr_wr_data = csr2hdu_wdata_i;SCR1_CSR_CMD_SET : csr_wr_data = csr_rd_data | csr2hdu_wdata_i;SCR1_CSR_CMD_CLEAR : csr_wr_data = csr_rd_data & (~csr2hdu_wdata_i);default : csr_wr_data = 'X;endcaseendend : csr_if_write// Debug Control and Status register//------------------------------------------------------------------------------// Setups the HART behaviour in Debug Mode and holds Debug status informationalways_comb begincsr_dcsr_in = csr_wr_data;csr_dcsr_wr = csr_wr & csr_dcsr_sel;csr_dcsr_out = '0;if (csr_dcsr_sel) begincsr_dcsr_out.xdebugver = SCR1_HDU_DEBUGCSR_DCSR_XDEBUGVER;csr_dcsr_out.ebreakm = csr_dcsr_ebreakm;csr_dcsr_out.stepie = csr_dcsr_stepie;csr_dcsr_out.step = csr_dcsr_step;csr_dcsr_out.prv = 2'b11;csr_dcsr_out.cause = csr_dcsr_cause;endendalways_ff @(negedge rst_n, posedge clk) beginif (~rst_n) begincsr_dcsr_ebreakm <= 1'b0;csr_dcsr_stepie <= 1'b0;csr_dcsr_step <= 1'b0;end else if(clk_en) beginif (csr_dcsr_wr) begincsr_dcsr_ebreakm <= csr_dcsr_in.ebreakm;csr_dcsr_stepie <= csr_dcsr_in.stepie;csr_dcsr_step <= csr_dcsr_in.step;endendendalways_ff @(negedge rst_n, posedge clk) beginif (~rst_n) begincsr_dcsr_cause <= 1'b0;end else if(clk_en) beginif(csr_upd_on_halt) begincsr_dcsr_cause <= hart_haltstatus.cause;endendend// Debug PC register//------------------------------------------------------------------------------// Saves the virtual address of the next instruction to be executed when Debug// Mode is entered. Could be changed by debuggerassign csr_dpc_wr = csr_wr & csr_dpc_sel;always_ff @(posedge clk, negedge rst_n) beginif (~rst_n) begincsr_dpc_ff <= '0;end else if(clk_en) begincsr_dpc_ff <= csr_dpc_next;endendassign csr_dpc_next = csr_upd_on_halt ? pipe2hdu_pc_curr_i: csr_dpc_wr ? csr_wr_data: csr_dpc_ff;assign csr_dpc_out = csr_dpc_sel ? csr_dpc_ff : '0;// Debug Scratch 0 register//------------------------------------------------------------------------------assign csr_dscratch0_resp = (~dm2hdu_dreg_resp_i | dm2hdu_dreg_fail_i)? SCR1_CSR_RESP_ER: SCR1_CSR_RESP_OK;assign csr_dscratch0_out = csr_dscratch0_sel ? dm2hdu_dreg_rdata_i : '0;//------------------------------------------------------------------------------// HDU <-> DM interface//------------------------------------------------------------------------------assign hdu2dm_hart_event_o = dfsm_event;// HART statusalways_comb beginhdu2dm_hart_status_o = '0;hdu2dm_hart_status_o.dbg_state = dbg_state;hdu2dm_hart_status_o.except = dbg_state_dhalted & hart_haltstatus.except;hdu2dm_hart_status_o.ebreak = dbg_state_dhalted & (hart_haltstatus.cause == SCR1_HDU_HALTCAUSE_EBREAK);endassign hdu2dm_cmd_rcode_o = dbg_state_reset? ~pipe2hdu_rdc_qlfy_i | ~pipe2hdu_init_pc_i | ~dm2hdu_cmd_req_i: ~pipe2hdu_rdc_qlfy_i | ~dfsm_update;always_comb beginhdu2dm_cmd_resp_o = 1'b0;case (dbg_state)SCR1_HDU_DBGSTATE_RESET: beginhdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & pipe2hdu_init_pc_i & dm2hdu_cmd_req_i;endSCR1_HDU_DBGSTATE_RUN: beginhdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & dfsm_update & dm2hdu_cmd_req_i;endSCR1_HDU_DBGSTATE_DHALTED: beginhdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i ? dfsm_update : dm2hdu_cmd_req_i;endSCR1_HDU_DBGSTATE_DRUN: beginhdu2dm_cmd_resp_o = (~pipe2hdu_rdc_qlfy_i | dfsm_update) & dm2hdu_cmd_req_i;enddefault: beginhdu2dm_cmd_resp_o = 'X;endendcaseendassign hdu2dm_pbuf_addr_o = pbuf_addr_ff;assign hdu2dm_dreg_req_o = csr_dscratch0_sel;assign hdu2dm_dreg_wr_o = csr_wr & csr_dscratch0_sel;assign hdu2dm_dreg_wdata_o = csr_wr_data;//------------------------------------------------------------------------------// HDU <-> EXU interface//------------------------------------------------------------------------------assign hdu2exu_dbg_halted_o = (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED)| (~pipe2hdu_rdc_qlfy_i & ~dbg_state_run);assign hdu2exu_dbg_run_start_o = dbg_state_dhalted & pipe2hdu_rdc_qlfy_i & dfsm_update;assign hdu2exu_dbg_halt2run_o = hdu2exu_dbg_halted_o & hart_resume_req`ifdef SCR1_CLKCTRL_EN& clk_pipe_en`endif // SCR1_CLKCTRL_EN;assign hdu2exu_dbg_run2halt_o = hart_halt_ack;assign hdu2exu_pbuf_fetch_o = hart_runctrl.fetch_src;assign hdu2exu_irq_dsbl_o = hart_runctrl.irq_dsbl;assign hdu2exu_pc_advmt_dsbl_o = hart_runctrl.pc_advmt_dsbl;// No change in arch. state if dmode caused by breakpointassign hdu2exu_no_commit_o = dmode_cause_ebreak`ifdef SCR1_TDU_EN| dmode_cause_tmreq`endif // SCR1_TDU_EN;assign hdu2exu_dmode_sstep_en_o = hart_runctrl.redirect.sstep;assign hdu2exu_dbg_new_pc_o = csr_dpc_ff;//------------------------------------------------------------------------------// HDU <-> IFU interface//------------------------------------------------------------------------------assign hdu2ifu_pbuf_instr_vd_o = (pbuf_fsm_fetch | pbuf_fsm_excinj)& ~pbuf_instr_wait_latching;assign hdu2ifu_pbuf_instr_err_o = pbuf_fsm_excinj;generate if (HART_PBUF_INSTR_REGOUT_EN) beginalways_ff @(posedge clk) beginhdu2ifu_pbuf_instr_o <= dm2hdu_pbuf_instr_i;endend else beginassign hdu2ifu_pbuf_instr_o = dm2hdu_pbuf_instr_i;end endgenerate//------------------------------------------------------------------------------// HDU <-> CSR interface//------------------------------------------------------------------------------assign csr_addr_dscratch0 = (csr2hdu_addr_i == SCR1_HDU_DBGCSR_OFFS_DSCRATCH0);assign hdu2csr_resp_o = ~dbg_state_drun ? SCR1_CSR_RESP_ER: csr_addr_dscratch0 ? csr_dscratch0_resp: csr2hdu_req_i ? SCR1_CSR_RESP_OK: SCR1_CSR_RESP_ER;assign hdu2csr_rdata_o = csr_rd_data;`ifdef SCR1_TDU_EN//------------------------------------------------------------------------------// HDU <-> TDU interface//------------------------------------------------------------------------------assign hdu2tdu_hwbrk_dsbl_o = hart_runctrl.hwbrkpt_dsbl;`endif // SCR1_TDU_EN`ifdef SCR1_TRGT_SIMULATION//-------------------------------------------------------------------------------// Assertion//-------------------------------------------------------------------------------SVA_HDU_XCHECK_COMMON :assert property (@(negedge clk) disable iff (~rst_n)!$isunknown( {rst_n,clk,clk_en,csr2hdu_req_i,pipe2hdu_rdc_qlfy_i} ))else $error("HDU Error: common signals are in X state");SVA_HDU_XCHECK_CSR_INTF :assert property (@(negedge clk) disable iff (~rst_n)csr2hdu_req_i |-> !$isunknown( {csr2hdu_cmd_i,csr2hdu_addr_i,csr2hdu_wdata_i} ))else $error("HDU Error: CSR i/f is in X state");SVA_HDU_XCHECK_DM_INTF :assert property (@(negedge clk) disable iff (~rst_n)!$isunknown( {dm2hdu_cmd_req_i,dm2hdu_cmd_i,dm2hdu_dreg_resp_i,dm2hdu_dreg_fail_i} ))else $error("HDU Error: DM i/f is in X state");SVA_HDU_XCHECK_TDU_INTF :assert property (@(negedge clk) disable iff (~rst_n)!$isunknown( {tdu2hdu_dmode_req_i,exu2hdu_ibrkpt_hw_i} ))else $error("HDU Error: TDU i/f is in X state");SVA_HDU_XCHECK_HART_INTF :assert property (@(negedge clk) disable iff (~rst_n)!$isunknown( {pipe2hdu_exu_busy_i,pipe2hdu_instret_i,pipe2hdu_init_pc_i,pipe2hdu_exu_exc_req_i,pipe2hdu_brkpt_i,pipe2hdu_pc_curr_i,ifu2hdu_pbuf_instr_rdy_i} ))else $error("HDU Error: HART i/f is in X state");`endif // SCR1_TRGT_SIMULATIONendmodule : scr1_pipe_hdu`endif // SCR1_DBG_EN
