1 |
11 |
dinesha |
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
2 |
|
|
/// @file
|
3 |
|
|
/// @brief HART Debug Unit (HDU)
|
4 |
|
|
///
|
5 |
|
|
|
6 |
|
|
//------------------------------------------------------------------------------
|
7 |
|
|
//
|
8 |
|
|
//
|
9 |
|
|
// Functionality:
|
10 |
|
|
// - Controls HART state (RUN, Debug RUN, Debug HALTED)
|
11 |
|
|
// - Setups Debug Mode execution
|
12 |
|
|
// - Provides status information about Debug Mode execution
|
13 |
|
|
// - Provides Program Buffer functionality (a few instructions execution while
|
14 |
|
|
// in Debug Mode)
|
15 |
|
|
// - Provides access to Debug CSRs
|
16 |
|
|
//
|
17 |
|
|
// Structure:
|
18 |
|
|
// - Debug state FSM
|
19 |
|
|
// - HART Control logic
|
20 |
|
|
// - HART Status logic
|
21 |
|
|
// - Program Buffer
|
22 |
|
|
// - Debug CSRs
|
23 |
|
|
// - HDU <-> DM interface
|
24 |
|
|
// - HDU <-> EXU interface
|
25 |
|
|
// - HDU <-> IFU interface
|
26 |
|
|
// - HDU <-> CSR interface
|
27 |
|
|
// - HDU <-> TDU interface
|
28 |
|
|
//
|
29 |
|
|
//------------------------------------------------------------------------------
|
30 |
|
|
|
31 |
|
|
`include "scr1_arch_description.svh"
|
32 |
|
|
|
33 |
|
|
`ifdef SCR1_DBG_EN
|
34 |
|
|
`include "scr1_arch_types.svh"
|
35 |
|
|
`include "scr1_riscv_isa_decoding.svh"
|
36 |
|
|
`include "scr1_hdu.svh"
|
37 |
|
|
|
38 |
|
|
module scr1_pipe_hdu #(parameter HART_PBUF_INSTR_REGOUT_EN = 1'b1) (
|
39 |
|
|
// Common signals
|
40 |
|
|
input logic rst_n, // HDU reset
|
41 |
|
|
input logic clk, // HDU clock
|
42 |
|
|
input logic clk_en, // HDU clock enable
|
43 |
|
|
`ifdef SCR1_CLKCTRL_EN
|
44 |
|
|
input logic clk_pipe_en, // Pipeline clock enable
|
45 |
|
|
`endif // SCR1_CLKCTRL_EN
|
46 |
|
|
input logic pipe2hdu_rdc_qlfy_i, // Pipeline RDC qualifier
|
47 |
|
|
|
48 |
|
|
// HDU <-> CSR i/f
|
49 |
|
|
input logic csr2hdu_req_i, // CSR i/f request
|
50 |
|
|
input type_scr1_csr_cmd_sel_e csr2hdu_cmd_i, // CSR i/f command
|
51 |
|
|
input logic [SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0] csr2hdu_addr_i, // CSR i/f address
|
52 |
|
|
input logic [`SCR1_XLEN-1:0] csr2hdu_wdata_i, // CSR i/f write data
|
53 |
|
|
output type_scr1_csr_resp_e hdu2csr_resp_o, // CSR i/f response
|
54 |
|
|
output logic [`SCR1_XLEN-1:0] hdu2csr_rdata_o, // CSR i/f read data
|
55 |
|
|
|
56 |
|
|
// HDU <-> DM i/f
|
57 |
|
|
// HART Run Control i/f
|
58 |
|
|
input logic dm2hdu_cmd_req_i, // DM-HART Command request
|
59 |
|
|
input type_scr1_hdu_dbgstates_e dm2hdu_cmd_i, // DM-HART Command
|
60 |
|
|
output logic hdu2dm_cmd_resp_o, // DM-HART Command response
|
61 |
|
|
output logic hdu2dm_cmd_rcode_o, // DM-HART Command return code: 0 - Ok; 1 - Error
|
62 |
|
|
output logic hdu2dm_hart_event_o, // DM-HART Event: 1 if HART debug state changed
|
63 |
|
|
output type_scr1_hdu_hartstatus_s hdu2dm_hart_status_o, // DM-HART Status
|
64 |
|
|
|
65 |
|
|
// Program Buffer i/f
|
66 |
|
|
output logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] hdu2dm_pbuf_addr_o, // Program Buffer address - so far request only for 1 instruction
|
67 |
|
|
input logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2hdu_pbuf_instr_i, // Program Buffer instruction
|
68 |
|
|
|
69 |
|
|
// HART Abstract Data regs i/f
|
70 |
|
|
output logic hdu2dm_dreg_req_o, // Abstract Data Register request
|
71 |
|
|
output logic hdu2dm_dreg_wr_o, // Abstract Data Register write
|
72 |
|
|
output logic [`SCR1_XLEN-1:0] hdu2dm_dreg_wdata_o, // Abstract Data Register write data
|
73 |
|
|
input logic dm2hdu_dreg_resp_i, // Abstract Data Register response
|
74 |
|
|
input logic dm2hdu_dreg_fail_i, // Abstract Data Register fail
|
75 |
|
|
input logic [`SCR1_XLEN-1:0] dm2hdu_dreg_rdata_i, // Abstract Data Register read data
|
76 |
|
|
|
77 |
|
|
`ifdef SCR1_TDU_EN
|
78 |
|
|
// HDU <-> TDU interface
|
79 |
|
|
output logic hdu2tdu_hwbrk_dsbl_o, // Disables BRKM
|
80 |
|
|
input logic tdu2hdu_dmode_req_i, // Trigger Module requests transition to debug mode
|
81 |
|
|
input logic exu2hdu_ibrkpt_hw_i, // Hardware breakpoint on current instruction
|
82 |
|
|
`endif // SCR1_TDU_EN
|
83 |
|
|
|
84 |
|
|
// HART Run Status
|
85 |
|
|
input logic pipe2hdu_exu_busy_i, // EXU busy
|
86 |
|
|
input logic pipe2hdu_instret_i, // Instruction retired (with or without exception)
|
87 |
|
|
input logic pipe2hdu_init_pc_i, // Reset exit
|
88 |
|
|
|
89 |
|
|
// HART Halt Status
|
90 |
|
|
input logic pipe2hdu_exu_exc_req_i, // Exception request
|
91 |
|
|
input logic pipe2hdu_brkpt_i, // Software Breakpoint (EBREAK)
|
92 |
|
|
|
93 |
|
|
// HDU <-> EXU i/f
|
94 |
|
|
// HART Run Control
|
95 |
|
|
output logic hdu2exu_pbuf_fetch_o, // Fetch instruction from Program Buffer
|
96 |
|
|
output logic hdu2exu_no_commit_o, // Forbid instruction commitment
|
97 |
|
|
output logic hdu2exu_irq_dsbl_o, // Disable IRQ
|
98 |
|
|
output logic hdu2exu_pc_advmt_dsbl_o, // Forbid PC advancement
|
99 |
|
|
output logic hdu2exu_dmode_sstep_en_o, // Enable single-step
|
100 |
|
|
|
101 |
|
|
// HART state
|
102 |
|
|
output logic hdu2exu_dbg_halted_o, // Debug halted state
|
103 |
|
|
output logic hdu2exu_dbg_run2halt_o, // Transition to debug halted state
|
104 |
|
|
output logic hdu2exu_dbg_halt2run_o, // Transition to run state
|
105 |
|
|
output logic hdu2exu_dbg_run_start_o, // First cycle of run state
|
106 |
|
|
|
107 |
|
|
// PC interface
|
108 |
|
|
input logic [`SCR1_XLEN-1:0] pipe2hdu_pc_curr_i, // Current PC
|
109 |
|
|
output logic [`SCR1_XLEN-1:0] hdu2exu_dbg_new_pc_o, // New PC for resume
|
110 |
|
|
|
111 |
|
|
// HDU <-> IFU i/f
|
112 |
|
|
// Program Buffer Instruction interface
|
113 |
|
|
input logic ifu2hdu_pbuf_instr_rdy_i, // Program Buffer Instruction i/f ready
|
114 |
|
|
output logic hdu2ifu_pbuf_instr_vd_o, // Program Buffer Instruction valid
|
115 |
|
|
output logic hdu2ifu_pbuf_instr_err_o, // Program Buffer Instruction i/f error
|
116 |
|
|
output logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr_o // Program Buffer Instruction itself
|
117 |
|
|
);
|
118 |
|
|
|
119 |
|
|
//------------------------------------------------------------------------------
|
120 |
|
|
// Local Parameters
|
121 |
|
|
//------------------------------------------------------------------------------
|
122 |
|
|
|
123 |
|
|
localparam int unsigned SCR1_HDU_TIMEOUT = 64; // must be power of 2
|
124 |
|
|
localparam int unsigned SCR1_HDU_TIMEOUT_WIDTH = $clog2(SCR1_HDU_TIMEOUT);
|
125 |
|
|
|
126 |
|
|
//------------------------------------------------------------------------------
|
127 |
|
|
// Local Signals
|
128 |
|
|
//------------------------------------------------------------------------------
|
129 |
|
|
|
130 |
|
|
// Debug FSM
|
131 |
|
|
//------------------------------------------------------------------------------
|
132 |
|
|
|
133 |
|
|
// FSM control signals
|
134 |
|
|
logic dm_dhalt_req;
|
135 |
|
|
logic dm_run_req;
|
136 |
|
|
|
137 |
|
|
logic dm_cmd_run;
|
138 |
|
|
logic dm_cmd_dhalted;
|
139 |
|
|
logic dm_cmd_drun;
|
140 |
|
|
|
141 |
|
|
// Debug state FSM signals
|
142 |
|
|
type_scr1_hdu_dbgstates_e dbg_state;
|
143 |
|
|
type_scr1_hdu_dbgstates_e dbg_state_next;
|
144 |
|
|
logic dbg_state_dhalted;
|
145 |
|
|
logic dbg_state_drun;
|
146 |
|
|
logic dbg_state_run;
|
147 |
|
|
logic dbg_state_reset;
|
148 |
|
|
|
149 |
|
|
// FSM transition, update and event registers
|
150 |
|
|
logic dfsm_trans;
|
151 |
|
|
logic dfsm_trans_next;
|
152 |
|
|
logic dfsm_update;
|
153 |
|
|
logic dfsm_update_next;
|
154 |
|
|
logic dfsm_event;
|
155 |
|
|
logic dfsm_event_next;
|
156 |
|
|
|
157 |
|
|
// HART Control signals
|
158 |
|
|
//------------------------------------------------------------------------------
|
159 |
|
|
|
160 |
|
|
logic hart_resume_req;
|
161 |
|
|
logic hart_halt_req;
|
162 |
|
|
logic hart_cmd_req;
|
163 |
|
|
|
164 |
|
|
// HART Run Control register
|
165 |
|
|
logic hart_runctrl_upd;
|
166 |
|
|
logic hart_runctrl_clr;
|
167 |
|
|
type_scr1_hdu_runctrl_s hart_runctrl;
|
168 |
|
|
|
169 |
|
|
// HART halt request timeout counter signals
|
170 |
|
|
logic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt;
|
171 |
|
|
logic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt_next;
|
172 |
|
|
logic halt_req_timeout_cnt_en;
|
173 |
|
|
logic halt_req_timeout_flag;
|
174 |
|
|
|
175 |
|
|
// HART Status signals
|
176 |
|
|
//------------------------------------------------------------------------------
|
177 |
|
|
|
178 |
|
|
type_scr1_hdu_haltstatus_s hart_haltstatus;
|
179 |
|
|
type_scr1_hdu_haltcause_e hart_haltcause;
|
180 |
|
|
|
181 |
|
|
logic hart_halt_pnd;
|
182 |
|
|
logic hart_halt_ack;
|
183 |
|
|
|
184 |
|
|
// Debug mode cause decoder signals
|
185 |
|
|
logic dmode_cause_sstep;
|
186 |
|
|
logic dmode_cause_except;
|
187 |
|
|
logic dmode_cause_ebreak;
|
188 |
|
|
logic dmode_cause_any;
|
189 |
|
|
`ifdef SCR1_TDU_EN
|
190 |
|
|
logic dmode_cause_tmreq;
|
191 |
|
|
`endif // SCR1_TDU_EN
|
192 |
|
|
|
193 |
|
|
// Program Buffer FSM
|
194 |
|
|
//------------------------------------------------------------------------------
|
195 |
|
|
|
196 |
|
|
// PBUF FSM control signals
|
197 |
|
|
logic ifu_handshake_done;
|
198 |
|
|
logic pbuf_exc_inj_req;
|
199 |
|
|
logic pbuf_exc_inj_end;
|
200 |
|
|
logic pbuf_start_fetch;
|
201 |
|
|
|
202 |
|
|
// PBUF FSM signals
|
203 |
|
|
type_scr1_hdu_pbufstates_e pbuf_fsm_curr;
|
204 |
|
|
type_scr1_hdu_pbufstates_e pbuf_fsm_next;
|
205 |
|
|
logic pbuf_fsm_idle;
|
206 |
|
|
logic pbuf_fsm_fetch;
|
207 |
|
|
logic pbuf_fsm_excinj;
|
208 |
|
|
|
209 |
|
|
// PBUF address signals
|
210 |
|
|
logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_ff;
|
211 |
|
|
logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_next;
|
212 |
|
|
logic pbuf_addr_end;
|
213 |
|
|
logic pbuf_addr_next_vd;
|
214 |
|
|
|
215 |
|
|
logic pbuf_instr_wait_latching;
|
216 |
|
|
|
217 |
|
|
// Debugs CSRs
|
218 |
|
|
//------------------------------------------------------------------------------
|
219 |
|
|
|
220 |
|
|
// CSRs write/read interface signals
|
221 |
|
|
logic csr_upd_on_halt;
|
222 |
|
|
logic csr_wr;
|
223 |
|
|
logic [`SCR1_XLEN-1:0] csr_wr_data;
|
224 |
|
|
logic [`SCR1_XLEN-1:0] csr_rd_data;
|
225 |
|
|
|
226 |
|
|
// Debug Control and Status register (DCSR)
|
227 |
|
|
logic csr_dcsr_sel;
|
228 |
|
|
logic csr_dcsr_wr;
|
229 |
|
|
type_scr1_hdu_dcsr_s csr_dcsr_in;
|
230 |
|
|
type_scr1_hdu_dcsr_s csr_dcsr_out;
|
231 |
|
|
logic csr_dcsr_ebreakm;
|
232 |
|
|
logic csr_dcsr_stepie;
|
233 |
|
|
logic csr_dcsr_step;
|
234 |
|
|
logic [SCR1_HDU_DCSR_CAUSE_BIT_L-
|
235 |
|
|
SCR1_HDU_DCSR_CAUSE_BIT_R:0] csr_dcsr_cause;
|
236 |
|
|
|
237 |
|
|
// Debug Program Counter register (DPC)
|
238 |
|
|
logic csr_dpc_sel;
|
239 |
|
|
logic csr_dpc_wr;
|
240 |
|
|
logic [`SCR1_XLEN-1:0] csr_dpc_ff;
|
241 |
|
|
logic [`SCR1_XLEN-1:0] csr_dpc_next;
|
242 |
|
|
logic [`SCR1_XLEN-1:0] csr_dpc_out;
|
243 |
|
|
|
244 |
|
|
// Debug Scratch register 0 (DSCRATCH0)
|
245 |
|
|
logic csr_addr_dscratch0;
|
246 |
|
|
logic csr_dscratch0_sel;
|
247 |
|
|
logic csr_dscratch0_wr;
|
248 |
|
|
logic [`SCR1_XLEN-1:0] csr_dscratch0_out;
|
249 |
|
|
type_scr1_csr_resp_e csr_dscratch0_resp;
|
250 |
|
|
|
251 |
|
|
//------------------------------------------------------------------------------
|
252 |
|
|
// Debug state FSM logic
|
253 |
|
|
//------------------------------------------------------------------------------
|
254 |
|
|
//
|
255 |
|
|
// Debug state FSM logic consists of the following functional units:
|
256 |
|
|
// - FSM control logic
|
257 |
|
|
// - Debug state FSM
|
258 |
|
|
// - FSM transition, update and event registers
|
259 |
|
|
//
|
260 |
|
|
|
261 |
|
|
// FSM control logic
|
262 |
|
|
//------------------------------------------------------------------------------
|
263 |
|
|
|
264 |
|
|
assign dm_cmd_dhalted = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DHALTED);
|
265 |
|
|
assign dm_cmd_run = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_RUN);
|
266 |
|
|
assign dm_cmd_drun = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DRUN);
|
267 |
|
|
|
268 |
|
|
assign dm_dhalt_req = dm2hdu_cmd_req_i & dm_cmd_dhalted;
|
269 |
|
|
assign dm_run_req = dm2hdu_cmd_req_i & (dm_cmd_run | dm_cmd_drun);
|
270 |
|
|
|
271 |
|
|
// Debug state FSM
|
272 |
|
|
//------------------------------------------------------------------------------
|
273 |
|
|
|
274 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
275 |
|
|
if (~rst_n) begin
|
276 |
|
|
dbg_state <= SCR1_HDU_DBGSTATE_RESET;
|
277 |
|
|
end else begin
|
278 |
|
|
dbg_state <= dbg_state_next;
|
279 |
|
|
end
|
280 |
|
|
end
|
281 |
|
|
|
282 |
|
|
always_comb begin
|
283 |
|
|
if (~pipe2hdu_rdc_qlfy_i) begin
|
284 |
|
|
dbg_state_next = SCR1_HDU_DBGSTATE_RESET;
|
285 |
|
|
end else begin
|
286 |
|
|
case (dbg_state)
|
287 |
|
|
SCR1_HDU_DBGSTATE_RESET: begin
|
288 |
|
|
dbg_state_next = ~pipe2hdu_init_pc_i ? SCR1_HDU_DBGSTATE_RESET
|
289 |
|
|
: dm_dhalt_req ? SCR1_HDU_DBGSTATE_DHALTED
|
290 |
|
|
: SCR1_HDU_DBGSTATE_RUN;
|
291 |
|
|
end
|
292 |
|
|
SCR1_HDU_DBGSTATE_RUN: begin
|
293 |
|
|
dbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
|
294 |
|
|
: SCR1_HDU_DBGSTATE_RUN;
|
295 |
|
|
end
|
296 |
|
|
SCR1_HDU_DBGSTATE_DHALTED: begin
|
297 |
|
|
dbg_state_next = ~dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
|
298 |
|
|
: dm_cmd_drun ? SCR1_HDU_DBGSTATE_DRUN
|
299 |
|
|
: SCR1_HDU_DBGSTATE_RUN;
|
300 |
|
|
end
|
301 |
|
|
SCR1_HDU_DBGSTATE_DRUN: begin
|
302 |
|
|
dbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
|
303 |
|
|
: SCR1_HDU_DBGSTATE_DRUN;
|
304 |
|
|
end
|
305 |
|
|
default: begin
|
306 |
|
|
`ifdef SCR1_XPROP_EN
|
307 |
|
|
dbg_state_next = SCR1_HDU_DBGSTATE_XXX;
|
308 |
|
|
`else // SCR1_XPROP_EN
|
309 |
|
|
dbg_state_next = dbg_state;
|
310 |
|
|
`endif // SCR1_XPROP_EN
|
311 |
|
|
end
|
312 |
|
|
endcase
|
313 |
|
|
end
|
314 |
|
|
end
|
315 |
|
|
|
316 |
|
|
assign dbg_state_dhalted = (dbg_state == SCR1_HDU_DBGSTATE_DHALTED);
|
317 |
|
|
assign dbg_state_drun = (dbg_state == SCR1_HDU_DBGSTATE_DRUN);
|
318 |
|
|
assign dbg_state_run = (dbg_state == SCR1_HDU_DBGSTATE_RUN);
|
319 |
|
|
assign dbg_state_reset = (dbg_state == SCR1_HDU_DBGSTATE_RESET);
|
320 |
|
|
|
321 |
|
|
// FSM transition, update and event registers
|
322 |
|
|
//------------------------------------------------------------------------------
|
323 |
|
|
|
324 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
325 |
|
|
if (~rst_n) begin
|
326 |
|
|
dfsm_trans <= 1'b0;
|
327 |
|
|
dfsm_update <= 1'b0;
|
328 |
|
|
dfsm_event <= 1'b0;
|
329 |
|
|
end else begin
|
330 |
|
|
dfsm_trans <= dfsm_trans_next;
|
331 |
|
|
dfsm_update <= dfsm_update_next;
|
332 |
|
|
dfsm_event <= dfsm_event_next;
|
333 |
|
|
end
|
334 |
|
|
end
|
335 |
|
|
|
336 |
|
|
always_comb begin
|
337 |
|
|
dfsm_trans_next = 1'b0;
|
338 |
|
|
dfsm_update_next = 1'b0;
|
339 |
|
|
dfsm_event_next = 1'b0;
|
340 |
|
|
|
341 |
|
|
if (~pipe2hdu_rdc_qlfy_i) begin
|
342 |
|
|
dfsm_trans_next = 1'b0;
|
343 |
|
|
dfsm_update_next = 1'b0;
|
344 |
|
|
dfsm_event_next = 1'b1;
|
345 |
|
|
end else begin
|
346 |
|
|
case (dbg_state)
|
347 |
|
|
SCR1_HDU_DBGSTATE_RESET: begin
|
348 |
|
|
dfsm_trans_next = 1'b0;
|
349 |
|
|
dfsm_update_next = 1'b0;
|
350 |
|
|
dfsm_event_next = pipe2hdu_init_pc_i & ~dm2hdu_cmd_req_i;
|
351 |
|
|
end
|
352 |
|
|
|
353 |
|
|
SCR1_HDU_DBGSTATE_RUN,
|
354 |
|
|
SCR1_HDU_DBGSTATE_DRUN: begin
|
355 |
|
|
dfsm_trans_next = ~dfsm_update ? hart_halt_pnd : dfsm_trans;
|
356 |
|
|
dfsm_update_next = ~dfsm_update & hart_halt_ack;
|
357 |
|
|
dfsm_event_next = dfsm_update;
|
358 |
|
|
end
|
359 |
|
|
|
360 |
|
|
SCR1_HDU_DBGSTATE_DHALTED: begin
|
361 |
|
|
dfsm_trans_next = ~dfsm_update ? ~dfsm_trans & dm_run_req
|
362 |
|
|
: dfsm_trans;
|
363 |
|
|
dfsm_update_next = ~dfsm_update & dfsm_trans;
|
364 |
|
|
dfsm_event_next = dfsm_update;
|
365 |
|
|
end
|
366 |
|
|
|
367 |
|
|
default : begin
|
368 |
|
|
dfsm_trans_next = 'X;
|
369 |
|
|
dfsm_update_next = 'X;
|
370 |
|
|
dfsm_event_next = 'X;
|
371 |
|
|
end
|
372 |
|
|
endcase
|
373 |
|
|
end
|
374 |
|
|
end
|
375 |
|
|
|
376 |
|
|
//------------------------------------------------------------------------------
|
377 |
|
|
// HART Control logic
|
378 |
|
|
//------------------------------------------------------------------------------
|
379 |
|
|
//
|
380 |
|
|
// HART Control logic consists of the following functional units:
|
381 |
|
|
// - Control signals
|
382 |
|
|
// - HART Run Control register
|
383 |
|
|
// - HART Halt Request Time-Out counter
|
384 |
|
|
//
|
385 |
|
|
|
386 |
|
|
// Control logic
|
387 |
|
|
always_comb begin
|
388 |
|
|
hart_cmd_req = 1'b0;
|
389 |
|
|
|
390 |
|
|
if (~pipe2hdu_rdc_qlfy_i) begin
|
391 |
|
|
hart_cmd_req = 1'b0;
|
392 |
|
|
end else begin
|
393 |
|
|
case (dbg_state)
|
394 |
|
|
SCR1_HDU_DBGSTATE_RESET : hart_cmd_req = dm2hdu_cmd_req_i;
|
395 |
|
|
SCR1_HDU_DBGSTATE_DHALTED: hart_cmd_req = (dfsm_update | dfsm_trans);
|
396 |
|
|
SCR1_HDU_DBGSTATE_RUN,
|
397 |
|
|
SCR1_HDU_DBGSTATE_DRUN : hart_cmd_req = ~dfsm_update & dfsm_trans;
|
398 |
|
|
default : hart_cmd_req = 'X;
|
399 |
|
|
endcase
|
400 |
|
|
end
|
401 |
|
|
end
|
402 |
|
|
|
403 |
|
|
assign hart_halt_req = dm_cmd_dhalted & hart_cmd_req;
|
404 |
|
|
assign hart_resume_req = (dm_cmd_run | dm_cmd_drun) & hart_cmd_req;
|
405 |
|
|
|
406 |
|
|
// HART Run Control register
|
407 |
|
|
//------------------------------------------------------------------------------
|
408 |
|
|
|
409 |
|
|
assign hart_runctrl_clr = (dbg_state_run | dbg_state_drun)
|
410 |
|
|
& (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);
|
411 |
|
|
assign hart_runctrl_upd = dbg_state_dhalted & dfsm_trans_next;
|
412 |
|
|
|
413 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
414 |
|
|
if (~rst_n) begin
|
415 |
|
|
hart_runctrl.irq_dsbl <= 1'b0;
|
416 |
|
|
hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;
|
417 |
|
|
hart_runctrl.pc_advmt_dsbl <= 1'b0;
|
418 |
|
|
hart_runctrl.hwbrkpt_dsbl <= 1'b0;
|
419 |
|
|
hart_runctrl.redirect <= '0;
|
420 |
|
|
end else if(clk_en) begin
|
421 |
|
|
if (hart_runctrl_clr) begin
|
422 |
|
|
hart_runctrl <= '0;
|
423 |
|
|
end else begin
|
424 |
|
|
if (hart_runctrl_upd) begin
|
425 |
|
|
if (~dm_cmd_drun) begin
|
426 |
|
|
// Case : resume to RUN state
|
427 |
|
|
hart_runctrl.irq_dsbl <= csr_dcsr_step ? ~csr_dcsr_stepie : 1'b0;
|
428 |
|
|
hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;
|
429 |
|
|
hart_runctrl.pc_advmt_dsbl <= 1'b0;
|
430 |
|
|
hart_runctrl.hwbrkpt_dsbl <= 1'b0;
|
431 |
|
|
hart_runctrl.redirect.sstep <= csr_dcsr_step;
|
432 |
|
|
hart_runctrl.redirect.ebreak <= csr_dcsr_ebreakm;
|
433 |
|
|
end else begin
|
434 |
|
|
// Case : resume to DRUN state
|
435 |
|
|
hart_runctrl.irq_dsbl <= 1'b1;
|
436 |
|
|
hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_PBUF;
|
437 |
|
|
hart_runctrl.pc_advmt_dsbl <= 1'b1;
|
438 |
|
|
hart_runctrl.hwbrkpt_dsbl <= 1'b1;
|
439 |
|
|
hart_runctrl.redirect.sstep <= 1'b0;
|
440 |
|
|
hart_runctrl.redirect.ebreak <= 1'b1;
|
441 |
|
|
end
|
442 |
|
|
end
|
443 |
|
|
end
|
444 |
|
|
end
|
445 |
|
|
end
|
446 |
|
|
|
447 |
|
|
// HART Halt Request Time-Out counter
|
448 |
|
|
//------------------------------------------------------------------------------
|
449 |
|
|
// HART goes into halt state only if the halt request is present for timeout period
|
450 |
|
|
// of time
|
451 |
|
|
|
452 |
|
|
assign halt_req_timeout_cnt_en = hdu2exu_dbg_halt2run_o
|
453 |
|
|
| (hart_halt_req & ~hdu2exu_dbg_run2halt_o);
|
454 |
|
|
|
455 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
456 |
|
|
if (~rst_n) begin
|
457 |
|
|
halt_req_timeout_cnt <= '1;
|
458 |
|
|
end else if (halt_req_timeout_cnt_en) begin
|
459 |
|
|
halt_req_timeout_cnt <= halt_req_timeout_cnt_next;
|
460 |
|
|
end
|
461 |
|
|
end
|
462 |
|
|
|
463 |
|
|
assign halt_req_timeout_cnt_next = hdu2exu_dbg_halt2run_o ? '1
|
464 |
|
|
: (hart_halt_req & ~hdu2exu_dbg_run2halt_o) ? halt_req_timeout_cnt - 1'b1
|
465 |
|
|
: halt_req_timeout_cnt;
|
466 |
|
|
|
467 |
|
|
assign halt_req_timeout_flag = ~|halt_req_timeout_cnt;
|
468 |
|
|
|
469 |
|
|
//------------------------------------------------------------------------------
|
470 |
|
|
// HART Status logic
|
471 |
|
|
//------------------------------------------------------------------------------
|
472 |
|
|
//
|
473 |
|
|
// HART Status logic consists of the following functional units:
|
474 |
|
|
// - Debug mode cause decoder
|
475 |
|
|
// - Hart halt status cause encoder
|
476 |
|
|
// - Hart halt status register
|
477 |
|
|
//
|
478 |
|
|
|
479 |
|
|
// Debug mode cause decoder
|
480 |
|
|
//------------------------------------------------------------------------------
|
481 |
|
|
|
482 |
|
|
assign dmode_cause_sstep = hart_runctrl.redirect.sstep & pipe2hdu_instret_i;
|
483 |
|
|
assign dmode_cause_except = dbg_state_drun & pipe2hdu_exu_exc_req_i
|
484 |
|
|
& ~pipe2hdu_brkpt_i
|
485 |
|
|
`ifdef SCR1_TDU_EN
|
486 |
|
|
& ~exu2hdu_ibrkpt_hw_i
|
487 |
|
|
`endif // SCR1_TDU_EN
|
488 |
|
|
;
|
489 |
|
|
assign dmode_cause_ebreak = hart_runctrl.redirect.ebreak & pipe2hdu_brkpt_i;
|
490 |
|
|
`ifdef SCR1_TDU_EN
|
491 |
|
|
assign dmode_cause_tmreq = tdu2hdu_dmode_req_i & exu2hdu_ibrkpt_hw_i;
|
492 |
|
|
`endif // SCR1_TDU_EN
|
493 |
|
|
|
494 |
|
|
assign dmode_cause_any = dmode_cause_sstep | dmode_cause_ebreak | dmode_cause_except
|
495 |
|
|
| hart_halt_req
|
496 |
|
|
`ifdef SCR1_TDU_EN
|
497 |
|
|
| dmode_cause_tmreq
|
498 |
|
|
`endif // SCR1_TDU_EN
|
499 |
|
|
;
|
500 |
|
|
|
501 |
|
|
// HART halt cause encoder
|
502 |
|
|
//------------------------------------------------------------------------------
|
503 |
|
|
|
504 |
|
|
always_comb begin
|
505 |
|
|
case (1'b1)
|
506 |
|
|
`ifdef SCR1_TDU_EN
|
507 |
|
|
dmode_cause_tmreq : hart_haltcause = SCR1_HDU_HALTCAUSE_TMREQ;
|
508 |
|
|
`endif // SCR1_TDU_EN
|
509 |
|
|
dmode_cause_ebreak : hart_haltcause = SCR1_HDU_HALTCAUSE_EBREAK;
|
510 |
|
|
hart_halt_req : hart_haltcause = SCR1_HDU_HALTCAUSE_DMREQ;
|
511 |
|
|
dmode_cause_sstep : hart_haltcause = SCR1_HDU_HALTCAUSE_SSTEP;
|
512 |
|
|
default : hart_haltcause = SCR1_HDU_HALTCAUSE_NONE;
|
513 |
|
|
endcase
|
514 |
|
|
end
|
515 |
|
|
|
516 |
|
|
// HART halt status register
|
517 |
|
|
//------------------------------------------------------------------------------
|
518 |
|
|
|
519 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
520 |
|
|
if (~rst_n) begin
|
521 |
|
|
hart_haltstatus <= '0;
|
522 |
|
|
end else if (hart_halt_ack) begin
|
523 |
|
|
hart_haltstatus.except <= dmode_cause_except;
|
524 |
|
|
hart_haltstatus.cause <= hart_haltcause;
|
525 |
|
|
end
|
526 |
|
|
end
|
527 |
|
|
|
528 |
|
|
assign hart_halt_pnd = (dfsm_trans | dm_dhalt_req) & ~hart_halt_ack;
|
529 |
|
|
assign hart_halt_ack = ~hdu2exu_dbg_halted_o
|
530 |
|
|
& (halt_req_timeout_flag | (~pipe2hdu_exu_busy_i & dmode_cause_any));
|
531 |
|
|
|
532 |
|
|
//------------------------------------------------------------------------------
|
533 |
|
|
// Program Buffer (PBUF) logic
|
534 |
|
|
//------------------------------------------------------------------------------
|
535 |
|
|
//
|
536 |
|
|
// Program Buffer allows to execute small programs in debug mode
|
537 |
|
|
//
|
538 |
|
|
|
539 |
|
|
// To terminate Program Buffer execution exception should be raised. There are 2
|
540 |
|
|
// cases:
|
541 |
|
|
// - One of PBUF instructions raise an exception
|
542 |
|
|
// - No PBUF instruction raise an exception before the last PBUF instruction has
|
543 |
|
|
// been issued. In this case FSM goes into EXCINJECT state and an "Instruction
|
544 |
|
|
// fetch access fault" exception is injected
|
545 |
|
|
|
546 |
|
|
// PBUF FSM
|
547 |
|
|
//------------------------------------------------------------------------------
|
548 |
|
|
|
549 |
|
|
assign ifu_handshake_done = hdu2ifu_pbuf_instr_vd_o & ifu2hdu_pbuf_instr_rdy_i;
|
550 |
|
|
assign pbuf_addr_end = (pbuf_addr_ff == (SCR1_HDU_PBUF_ADDR_SPAN-1));
|
551 |
|
|
|
552 |
|
|
assign pbuf_start_fetch = dbg_state_dhalted & (dbg_state_next == SCR1_HDU_DBGSTATE_DRUN);
|
553 |
|
|
assign pbuf_exc_inj_req = ifu_handshake_done & pbuf_addr_end;
|
554 |
|
|
assign pbuf_exc_inj_end = pipe2hdu_exu_exc_req_i | ifu_handshake_done;
|
555 |
|
|
|
556 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
557 |
|
|
if (~rst_n) begin
|
558 |
|
|
pbuf_fsm_curr <= SCR1_HDU_PBUFSTATE_IDLE;
|
559 |
|
|
end else if(clk_en) begin
|
560 |
|
|
pbuf_fsm_curr <= pbuf_fsm_next;
|
561 |
|
|
end
|
562 |
|
|
end
|
563 |
|
|
|
564 |
|
|
always_comb begin
|
565 |
|
|
case (pbuf_fsm_curr)
|
566 |
|
|
SCR1_HDU_PBUFSTATE_IDLE: begin
|
567 |
|
|
pbuf_fsm_next = pbuf_start_fetch ? SCR1_HDU_PBUFSTATE_FETCH
|
568 |
|
|
: SCR1_HDU_PBUFSTATE_IDLE;
|
569 |
|
|
end
|
570 |
|
|
SCR1_HDU_PBUFSTATE_FETCH: begin
|
571 |
|
|
pbuf_fsm_next = pipe2hdu_exu_exc_req_i ? SCR1_HDU_PBUFSTATE_WAIT4END
|
572 |
|
|
: pbuf_exc_inj_req ? SCR1_HDU_PBUFSTATE_EXCINJECT
|
573 |
|
|
: SCR1_HDU_PBUFSTATE_FETCH;
|
574 |
|
|
end
|
575 |
|
|
SCR1_HDU_PBUFSTATE_EXCINJECT: begin
|
576 |
|
|
pbuf_fsm_next = pbuf_exc_inj_end ? SCR1_HDU_PBUFSTATE_WAIT4END
|
577 |
|
|
: SCR1_HDU_PBUFSTATE_EXCINJECT;
|
578 |
|
|
end
|
579 |
|
|
SCR1_HDU_PBUFSTATE_WAIT4END: begin
|
580 |
|
|
pbuf_fsm_next = hdu2exu_dbg_halted_o ? SCR1_HDU_PBUFSTATE_IDLE
|
581 |
|
|
: SCR1_HDU_PBUFSTATE_WAIT4END;
|
582 |
|
|
end
|
583 |
|
|
endcase
|
584 |
|
|
end
|
585 |
|
|
|
586 |
|
|
assign pbuf_fsm_idle = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_IDLE);
|
587 |
|
|
assign pbuf_fsm_fetch = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_FETCH);
|
588 |
|
|
assign pbuf_fsm_excinj = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_EXCINJECT);
|
589 |
|
|
|
590 |
|
|
// Program Buffer address register
|
591 |
|
|
//------------------------------------------------------------------------------
|
592 |
|
|
|
593 |
|
|
assign pbuf_addr_next_vd = pbuf_fsm_fetch & ifu_handshake_done
|
594 |
|
|
& ~pipe2hdu_exu_exc_req_i & ~pbuf_addr_end;
|
595 |
|
|
|
596 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
597 |
|
|
if (~rst_n) begin
|
598 |
|
|
pbuf_addr_ff <= '0;
|
599 |
|
|
end else if(clk_en) begin
|
600 |
|
|
pbuf_addr_ff <= pbuf_addr_next;
|
601 |
|
|
end
|
602 |
|
|
end
|
603 |
|
|
|
604 |
|
|
assign pbuf_addr_next = pbuf_fsm_idle ? '0
|
605 |
|
|
: pbuf_addr_next_vd ? pbuf_addr_ff + 1'b1
|
606 |
|
|
: pbuf_addr_ff;
|
607 |
|
|
|
608 |
|
|
// Pass instruction from debug program buffer to cpu pipeline with two options:
|
609 |
|
|
// - through register, better for frequency
|
610 |
|
|
// - through wires, better for area
|
611 |
|
|
generate if (HART_PBUF_INSTR_REGOUT_EN) begin
|
612 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
613 |
|
|
if (~rst_n) begin
|
614 |
|
|
pbuf_instr_wait_latching <= 1'b0;
|
615 |
|
|
end else begin
|
616 |
|
|
pbuf_instr_wait_latching <= ifu_handshake_done;
|
617 |
|
|
end
|
618 |
|
|
end
|
619 |
|
|
end else begin
|
620 |
|
|
assign pbuf_instr_wait_latching = 1'b0;
|
621 |
|
|
end endgenerate
|
622 |
|
|
|
623 |
|
|
//------------------------------------------------------------------------------
|
624 |
|
|
// Debug CSRs
|
625 |
|
|
//------------------------------------------------------------------------------
|
626 |
|
|
|
627 |
|
|
assign csr_upd_on_halt = (dbg_state_reset | dbg_state_run)
|
628 |
|
|
& (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);
|
629 |
|
|
|
630 |
|
|
// CSRs select logic
|
631 |
|
|
//------------------------------------------------------------------------------
|
632 |
|
|
|
633 |
|
|
always_comb begin : csr_if_regsel
|
634 |
|
|
csr_dcsr_sel = 1'b0;
|
635 |
|
|
csr_dpc_sel = 1'b0;
|
636 |
|
|
csr_dscratch0_sel = 1'b0;
|
637 |
|
|
//csr_dscratch1_sel = 1'b0;
|
638 |
|
|
|
639 |
|
|
if (csr2hdu_req_i) begin
|
640 |
|
|
case (csr2hdu_addr_i)
|
641 |
|
|
SCR1_HDU_DBGCSR_OFFS_DCSR : csr_dcsr_sel = 1'b1;
|
642 |
|
|
SCR1_HDU_DBGCSR_OFFS_DPC : csr_dpc_sel = 1'b1;
|
643 |
|
|
SCR1_HDU_DBGCSR_OFFS_DSCRATCH0: csr_dscratch0_sel = 1'b1;
|
644 |
|
|
default : begin
|
645 |
|
|
csr_dcsr_sel = 1'bX;
|
646 |
|
|
csr_dpc_sel = 1'bX;
|
647 |
|
|
csr_dscratch0_sel = 1'bX;
|
648 |
|
|
end
|
649 |
|
|
endcase
|
650 |
|
|
end
|
651 |
|
|
end : csr_if_regsel
|
652 |
|
|
|
653 |
|
|
// CSRs read interface
|
654 |
|
|
//------------------------------------------------------------------------------
|
655 |
|
|
|
656 |
|
|
assign csr_rd_data = csr_dcsr_out | csr_dpc_out | csr_dscratch0_out;
|
657 |
|
|
|
658 |
|
|
// CSRs write interface
|
659 |
|
|
//------------------------------------------------------------------------------
|
660 |
|
|
|
661 |
|
|
assign csr_wr = csr2hdu_req_i;
|
662 |
|
|
|
663 |
|
|
always_comb begin : csr_if_write
|
664 |
|
|
csr_wr_data = '0;
|
665 |
|
|
|
666 |
|
|
if (csr2hdu_req_i) begin
|
667 |
|
|
case (csr2hdu_cmd_i)
|
668 |
|
|
SCR1_CSR_CMD_WRITE : csr_wr_data = csr2hdu_wdata_i;
|
669 |
|
|
SCR1_CSR_CMD_SET : csr_wr_data = csr_rd_data | csr2hdu_wdata_i;
|
670 |
|
|
SCR1_CSR_CMD_CLEAR : csr_wr_data = csr_rd_data & (~csr2hdu_wdata_i);
|
671 |
|
|
default : csr_wr_data = 'X;
|
672 |
|
|
endcase
|
673 |
|
|
end
|
674 |
|
|
end : csr_if_write
|
675 |
|
|
|
676 |
|
|
// Debug Control and Status register
|
677 |
|
|
//------------------------------------------------------------------------------
|
678 |
|
|
// Setups the HART behaviour in Debug Mode and holds Debug status information
|
679 |
|
|
|
680 |
|
|
always_comb begin
|
681 |
|
|
csr_dcsr_in = csr_wr_data;
|
682 |
|
|
csr_dcsr_wr = csr_wr & csr_dcsr_sel;
|
683 |
|
|
|
684 |
|
|
csr_dcsr_out = '0;
|
685 |
|
|
if (csr_dcsr_sel) begin
|
686 |
|
|
csr_dcsr_out.xdebugver = SCR1_HDU_DEBUGCSR_DCSR_XDEBUGVER;
|
687 |
|
|
csr_dcsr_out.ebreakm = csr_dcsr_ebreakm;
|
688 |
|
|
csr_dcsr_out.stepie = csr_dcsr_stepie;
|
689 |
|
|
csr_dcsr_out.step = csr_dcsr_step;
|
690 |
|
|
csr_dcsr_out.prv = 2'b11;
|
691 |
|
|
csr_dcsr_out.cause = csr_dcsr_cause;
|
692 |
|
|
end
|
693 |
|
|
end
|
694 |
|
|
|
695 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
696 |
|
|
if (~rst_n) begin
|
697 |
|
|
csr_dcsr_ebreakm <= 1'b0;
|
698 |
|
|
csr_dcsr_stepie <= 1'b0;
|
699 |
|
|
csr_dcsr_step <= 1'b0;
|
700 |
|
|
end else if(clk_en) begin
|
701 |
|
|
if (csr_dcsr_wr) begin
|
702 |
|
|
csr_dcsr_ebreakm <= csr_dcsr_in.ebreakm;
|
703 |
|
|
csr_dcsr_stepie <= csr_dcsr_in.stepie;
|
704 |
|
|
csr_dcsr_step <= csr_dcsr_in.step;
|
705 |
|
|
end
|
706 |
|
|
end
|
707 |
|
|
end
|
708 |
|
|
|
709 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
710 |
|
|
if (~rst_n) begin
|
711 |
|
|
csr_dcsr_cause <= 1'b0;
|
712 |
|
|
end else if(clk_en) begin
|
713 |
|
|
if(csr_upd_on_halt) begin
|
714 |
|
|
csr_dcsr_cause <= hart_haltstatus.cause;
|
715 |
|
|
end
|
716 |
|
|
end
|
717 |
|
|
end
|
718 |
|
|
|
719 |
|
|
// Debug PC register
|
720 |
|
|
//------------------------------------------------------------------------------
|
721 |
|
|
// Saves the virtual address of the next instruction to be executed when Debug
|
722 |
|
|
// Mode is entered. Could be changed by debugger
|
723 |
|
|
|
724 |
|
|
assign csr_dpc_wr = csr_wr & csr_dpc_sel;
|
725 |
|
|
|
726 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
727 |
|
|
if (~rst_n) begin
|
728 |
|
|
csr_dpc_ff <= '0;
|
729 |
|
|
end else if(clk_en) begin
|
730 |
|
|
csr_dpc_ff <= csr_dpc_next;
|
731 |
|
|
end
|
732 |
|
|
end
|
733 |
|
|
|
734 |
|
|
assign csr_dpc_next = csr_upd_on_halt ? pipe2hdu_pc_curr_i
|
735 |
|
|
: csr_dpc_wr ? csr_wr_data
|
736 |
|
|
: csr_dpc_ff;
|
737 |
|
|
assign csr_dpc_out = csr_dpc_sel ? csr_dpc_ff : '0;
|
738 |
|
|
|
739 |
|
|
// Debug Scratch 0 register
|
740 |
|
|
//------------------------------------------------------------------------------
|
741 |
|
|
|
742 |
|
|
assign csr_dscratch0_resp = (~dm2hdu_dreg_resp_i | dm2hdu_dreg_fail_i)
|
743 |
|
|
? SCR1_CSR_RESP_ER
|
744 |
|
|
: SCR1_CSR_RESP_OK;
|
745 |
|
|
assign csr_dscratch0_out = csr_dscratch0_sel ? dm2hdu_dreg_rdata_i : '0;
|
746 |
|
|
|
747 |
|
|
//------------------------------------------------------------------------------
|
748 |
|
|
// HDU <-> DM interface
|
749 |
|
|
//------------------------------------------------------------------------------
|
750 |
|
|
|
751 |
|
|
assign hdu2dm_hart_event_o = dfsm_event;
|
752 |
|
|
|
753 |
|
|
// HART status
|
754 |
|
|
always_comb begin
|
755 |
|
|
hdu2dm_hart_status_o = '0;
|
756 |
|
|
hdu2dm_hart_status_o.dbg_state = dbg_state;
|
757 |
|
|
hdu2dm_hart_status_o.except = dbg_state_dhalted & hart_haltstatus.except;
|
758 |
|
|
hdu2dm_hart_status_o.ebreak = dbg_state_dhalted & (hart_haltstatus.cause == SCR1_HDU_HALTCAUSE_EBREAK);
|
759 |
|
|
end
|
760 |
|
|
|
761 |
|
|
assign hdu2dm_cmd_rcode_o = dbg_state_reset
|
762 |
|
|
? ~pipe2hdu_rdc_qlfy_i | ~pipe2hdu_init_pc_i | ~dm2hdu_cmd_req_i
|
763 |
|
|
: ~pipe2hdu_rdc_qlfy_i | ~dfsm_update;
|
764 |
|
|
|
765 |
|
|
always_comb begin
|
766 |
|
|
hdu2dm_cmd_resp_o = 1'b0;
|
767 |
|
|
|
768 |
|
|
case (dbg_state)
|
769 |
|
|
SCR1_HDU_DBGSTATE_RESET: begin
|
770 |
|
|
hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & pipe2hdu_init_pc_i & dm2hdu_cmd_req_i;
|
771 |
|
|
end
|
772 |
|
|
|
773 |
|
|
SCR1_HDU_DBGSTATE_RUN: begin
|
774 |
|
|
hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & dfsm_update & dm2hdu_cmd_req_i;
|
775 |
|
|
end
|
776 |
|
|
|
777 |
|
|
SCR1_HDU_DBGSTATE_DHALTED: begin
|
778 |
|
|
hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i ? dfsm_update : dm2hdu_cmd_req_i;
|
779 |
|
|
end
|
780 |
|
|
|
781 |
|
|
SCR1_HDU_DBGSTATE_DRUN: begin
|
782 |
|
|
hdu2dm_cmd_resp_o = (~pipe2hdu_rdc_qlfy_i | dfsm_update) & dm2hdu_cmd_req_i;
|
783 |
|
|
end
|
784 |
|
|
|
785 |
|
|
default: begin
|
786 |
|
|
hdu2dm_cmd_resp_o = 'X;
|
787 |
|
|
end
|
788 |
|
|
endcase
|
789 |
|
|
end
|
790 |
|
|
|
791 |
|
|
assign hdu2dm_pbuf_addr_o = pbuf_addr_ff;
|
792 |
|
|
assign hdu2dm_dreg_req_o = csr_dscratch0_sel;
|
793 |
|
|
assign hdu2dm_dreg_wr_o = csr_wr & csr_dscratch0_sel;
|
794 |
|
|
assign hdu2dm_dreg_wdata_o = csr_wr_data;
|
795 |
|
|
|
796 |
|
|
//------------------------------------------------------------------------------
|
797 |
|
|
// HDU <-> EXU interface
|
798 |
|
|
//------------------------------------------------------------------------------
|
799 |
|
|
|
800 |
|
|
assign hdu2exu_dbg_halted_o = (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED)
|
801 |
|
|
| (~pipe2hdu_rdc_qlfy_i & ~dbg_state_run);
|
802 |
|
|
assign hdu2exu_dbg_run_start_o = dbg_state_dhalted & pipe2hdu_rdc_qlfy_i & dfsm_update;
|
803 |
|
|
assign hdu2exu_dbg_halt2run_o = hdu2exu_dbg_halted_o & hart_resume_req
|
804 |
|
|
`ifdef SCR1_CLKCTRL_EN
|
805 |
|
|
& clk_pipe_en
|
806 |
|
|
`endif // SCR1_CLKCTRL_EN
|
807 |
|
|
;
|
808 |
|
|
assign hdu2exu_dbg_run2halt_o = hart_halt_ack;
|
809 |
|
|
|
810 |
|
|
assign hdu2exu_pbuf_fetch_o = hart_runctrl.fetch_src;
|
811 |
|
|
assign hdu2exu_irq_dsbl_o = hart_runctrl.irq_dsbl;
|
812 |
|
|
assign hdu2exu_pc_advmt_dsbl_o = hart_runctrl.pc_advmt_dsbl;
|
813 |
|
|
// No change in arch. state if dmode caused by breakpoint
|
814 |
|
|
assign hdu2exu_no_commit_o = dmode_cause_ebreak
|
815 |
|
|
`ifdef SCR1_TDU_EN
|
816 |
|
|
| dmode_cause_tmreq
|
817 |
|
|
`endif // SCR1_TDU_EN
|
818 |
|
|
;
|
819 |
|
|
assign hdu2exu_dmode_sstep_en_o = hart_runctrl.redirect.sstep;
|
820 |
|
|
assign hdu2exu_dbg_new_pc_o = csr_dpc_ff;
|
821 |
|
|
|
822 |
|
|
//------------------------------------------------------------------------------
|
823 |
|
|
// HDU <-> IFU interface
|
824 |
|
|
//------------------------------------------------------------------------------
|
825 |
|
|
|
826 |
|
|
assign hdu2ifu_pbuf_instr_vd_o = (pbuf_fsm_fetch | pbuf_fsm_excinj)
|
827 |
|
|
& ~pbuf_instr_wait_latching;
|
828 |
|
|
assign hdu2ifu_pbuf_instr_err_o = pbuf_fsm_excinj;
|
829 |
|
|
|
830 |
|
|
generate if (HART_PBUF_INSTR_REGOUT_EN) begin
|
831 |
|
|
always_ff @(posedge clk) begin
|
832 |
|
|
hdu2ifu_pbuf_instr_o <= dm2hdu_pbuf_instr_i;
|
833 |
|
|
end
|
834 |
|
|
end else begin
|
835 |
|
|
assign hdu2ifu_pbuf_instr_o = dm2hdu_pbuf_instr_i;
|
836 |
|
|
end endgenerate
|
837 |
|
|
|
838 |
|
|
//------------------------------------------------------------------------------
|
839 |
|
|
// HDU <-> CSR interface
|
840 |
|
|
//------------------------------------------------------------------------------
|
841 |
|
|
|
842 |
|
|
assign csr_addr_dscratch0 = (csr2hdu_addr_i == SCR1_HDU_DBGCSR_OFFS_DSCRATCH0);
|
843 |
|
|
|
844 |
|
|
assign hdu2csr_resp_o = ~dbg_state_drun ? SCR1_CSR_RESP_ER
|
845 |
|
|
: csr_addr_dscratch0 ? csr_dscratch0_resp
|
846 |
|
|
: csr2hdu_req_i ? SCR1_CSR_RESP_OK
|
847 |
|
|
: SCR1_CSR_RESP_ER;
|
848 |
|
|
assign hdu2csr_rdata_o = csr_rd_data;
|
849 |
|
|
|
850 |
|
|
`ifdef SCR1_TDU_EN
|
851 |
|
|
//------------------------------------------------------------------------------
|
852 |
|
|
// HDU <-> TDU interface
|
853 |
|
|
//------------------------------------------------------------------------------
|
854 |
|
|
|
855 |
|
|
assign hdu2tdu_hwbrk_dsbl_o = hart_runctrl.hwbrkpt_dsbl;
|
856 |
|
|
`endif // SCR1_TDU_EN
|
857 |
|
|
|
858 |
|
|
`ifdef SCR1_TRGT_SIMULATION
|
859 |
|
|
//-------------------------------------------------------------------------------
|
860 |
|
|
// Assertion
|
861 |
|
|
//-------------------------------------------------------------------------------
|
862 |
|
|
|
863 |
|
|
SVA_HDU_XCHECK_COMMON :
|
864 |
|
|
assert property (
|
865 |
|
|
@(negedge clk) disable iff (~rst_n)
|
866 |
|
|
!$isunknown( {rst_n,clk,clk_en,csr2hdu_req_i,pipe2hdu_rdc_qlfy_i} )
|
867 |
|
|
)
|
868 |
|
|
else $error("HDU Error: common signals are in X state");
|
869 |
|
|
|
870 |
|
|
SVA_HDU_XCHECK_CSR_INTF :
|
871 |
|
|
assert property (
|
872 |
|
|
@(negedge clk) disable iff (~rst_n)
|
873 |
|
|
csr2hdu_req_i |-> !$isunknown( {csr2hdu_cmd_i,csr2hdu_addr_i,csr2hdu_wdata_i} )
|
874 |
|
|
)
|
875 |
|
|
else $error("HDU Error: CSR i/f is in X state");
|
876 |
|
|
|
877 |
|
|
SVA_HDU_XCHECK_DM_INTF :
|
878 |
|
|
assert property (
|
879 |
|
|
@(negedge clk) disable iff (~rst_n)
|
880 |
|
|
!$isunknown( {dm2hdu_cmd_req_i,dm2hdu_cmd_i,dm2hdu_dreg_resp_i,
|
881 |
|
|
dm2hdu_dreg_fail_i} )
|
882 |
|
|
)
|
883 |
|
|
else $error("HDU Error: DM i/f is in X state");
|
884 |
|
|
|
885 |
|
|
SVA_HDU_XCHECK_TDU_INTF :
|
886 |
|
|
assert property (
|
887 |
|
|
@(negedge clk) disable iff (~rst_n)
|
888 |
|
|
!$isunknown( {tdu2hdu_dmode_req_i,exu2hdu_ibrkpt_hw_i} )
|
889 |
|
|
)
|
890 |
|
|
else $error("HDU Error: TDU i/f is in X state");
|
891 |
|
|
|
892 |
|
|
SVA_HDU_XCHECK_HART_INTF :
|
893 |
|
|
assert property (
|
894 |
|
|
@(negedge clk) disable iff (~rst_n)
|
895 |
|
|
!$isunknown( {pipe2hdu_exu_busy_i,pipe2hdu_instret_i,pipe2hdu_init_pc_i,pipe2hdu_exu_exc_req_i,pipe2hdu_brkpt_i,
|
896 |
|
|
pipe2hdu_pc_curr_i,ifu2hdu_pbuf_instr_rdy_i} )
|
897 |
|
|
)
|
898 |
|
|
else $error("HDU Error: HART i/f is in X state");
|
899 |
|
|
|
900 |
|
|
`endif // SCR1_TRGT_SIMULATION
|
901 |
|
|
|
902 |
|
|
endmodule : scr1_pipe_hdu
|
903 |
|
|
|
904 |
|
|
`endif // SCR1_DBG_EN
|