Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : // Copyright 2020 Western Digital Corporation or its affiliates.
3 : //
4 : // Licensed under the Apache License, Version 2.0 (the "License");
5 : // you may not use this file except in compliance with the License.
6 : // You may obtain a copy of the License at
7 : //
8 : // http://www.apache.org/licenses/LICENSE-2.0
9 : //
10 : // Unless required by applicable law or agreed to in writing, software
11 : // distributed under the License is distributed on an "AS IS" BASIS,
12 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : // See the License for the specific language governing permissions and
14 : // limitations under the License.
15 : //********************************************************************************
16 : // $Id$
17 : //
18 : // Function: Top level VeeR core file to control the debug mode
19 : // Comments: Responsible to put the rest of the core in quiesce mode,
20 : // Send the commands/address. sends WrData and Recieve read Data.
21 : // And then Resume the core to do the normal mode
22 : // Author :
23 : //********************************************************************************
24 : module el2_dbg
25 : import el2_pkg::*;
26 : #(
27 : `include "el2_param.vh"
28 : )(
29 : // outputs to the core for command and data interface
30 14 : output logic [31:0] dbg_cmd_addr,
31 128 : output logic [31:0] dbg_cmd_wrdata,
32 2562 : output logic dbg_cmd_valid,
33 300 : output logic dbg_cmd_write, // 1: write command, 0: read_command
34 1456 : output logic [1:0] dbg_cmd_type, // 0:gpr 1:csr 2: memory
35 1162 : output logic [1:0] dbg_cmd_size, // size of the abstract mem access debug command
36 339 : output logic dbg_core_rst_l, // core reset from dm
37 :
38 : // inputs back from the core/dec
39 314101 : input logic [31:0] core_dbg_rddata,
40 2562 : input logic core_dbg_cmd_done, // This will be treated like a valid signal
41 4 : input logic core_dbg_cmd_fail, // Exception during command run
42 :
43 : // Signals to dma to get a bubble
44 2562 : output logic dbg_dma_bubble, // Debug needs a bubble to send a valid
45 2562 : input logic dma_dbg_ready, // DMA is ready to accept debug request
46 :
47 : // interface with the rest of the core to halt/resume handshaking
48 8 : output logic dbg_halt_req, // This is a pulse
49 10 : output logic dbg_resume_req, // Debug sends a resume requests. Pulse
50 118 : input logic dec_tlu_debug_mode, // Core is in debug mode
51 120 : input logic dec_tlu_dbg_halted, // The core has finished the queiscing sequence. Core is halted now
52 108 : input logic dec_tlu_mpc_halted_only, // Only halted due to MPC
53 10 : input logic dec_tlu_resume_ack, // core sends back an ack for the resume (pulse)
54 :
55 : // inputs from the JTAG
56 16994 : input logic dmi_reg_en, // read or write
57 0 : input logic [6:0] dmi_reg_addr, // address of DM register
58 6308 : input logic dmi_reg_wr_en, // write instruction
59 86 : input logic [31:0] dmi_reg_wdata, // write data
60 :
61 : // output
62 114 : output logic [31:0] dmi_reg_rdata, // read data
63 :
64 : // AXI Write Channels
65 244 : output logic sb_axi_awvalid,
66 1148 : input logic sb_axi_awready,
67 : /* exclude signals that are tied to constant value in this file */
68 : /*verilator coverage_off*/
69 : output logic [pt.SB_BUS_TAG-1:0] sb_axi_awid,
70 : /*verilator coverage_on*/
71 4 : output logic [31:0] sb_axi_awaddr,
72 196 : output logic [3:0] sb_axi_awregion,
73 : /* exclude signals that are tied to constant value in this file */
74 : /*verilator coverage_off*/
75 : output logic [7:0] sb_axi_awlen,
76 : /*verilator coverage_on*/
77 0 : output logic [2:0] sb_axi_awsize,
78 : /* exclude signals that are tied to constant value in this file */
79 : /*verilator coverage_off*/
80 : output logic [1:0] sb_axi_awburst,
81 : output logic sb_axi_awlock,
82 : output logic [3:0] sb_axi_awcache,
83 : output logic [2:0] sb_axi_awprot,
84 : output logic [3:0] sb_axi_awqos,
85 : /*verilator coverage_on*/
86 :
87 244 : output logic sb_axi_wvalid,
88 1148 : input logic sb_axi_wready,
89 62 : output logic [63:0] sb_axi_wdata,
90 536 : output logic [7:0] sb_axi_wstrb,
91 339 : output logic sb_axi_wlast,
92 :
93 244 : input logic sb_axi_bvalid,
94 339 : output logic sb_axi_bready,
95 0 : input logic [1:0] sb_axi_bresp,
96 :
97 : // AXI Read Channels
98 1504 : output logic sb_axi_arvalid,
99 1646 : input logic sb_axi_arready,
100 : /* exclude signals that are tied to constant value in this file */
101 : /*verilator coverage_off*/
102 : output logic [pt.SB_BUS_TAG-1:0] sb_axi_arid,
103 : /*verilator coverage_on*/
104 4 : output logic [31:0] sb_axi_araddr,
105 196 : output logic [3:0] sb_axi_arregion,
106 : /* exclude signals that are tied to constant value in this file */
107 : /*verilator coverage_off*/
108 : output logic [7:0] sb_axi_arlen,
109 : /*verilator coverage_on*/
110 0 : output logic [2:0] sb_axi_arsize,
111 : /* exclude signals that are tied to constant value in this file */
112 : /*verilator coverage_off*/
113 : output logic [1:0] sb_axi_arburst,
114 : output logic sb_axi_arlock,
115 : output logic [3:0] sb_axi_arcache,
116 : output logic [2:0] sb_axi_arprot,
117 : output logic [3:0] sb_axi_arqos,
118 : /*verilator coverage_on*/
119 :
120 1504 : input logic sb_axi_rvalid,
121 : /* exclude signals that are tied to constant value in this file */
122 : /*verilator coverage_off*/
123 : output logic sb_axi_rready,
124 : /*verilator coverage_on*/
125 15 : input logic [63:0] sb_axi_rdata,
126 0 : input logic [1:0] sb_axi_rresp,
127 :
128 338 : input logic dbg_bus_clk_en,
129 :
130 : // general inputs
131 69840565 : input logic clk,
132 69840565 : input logic free_clk,
133 338 : input logic rst_l, // This includes both top rst and debug rst
134 338 : input logic dbg_rst_l,
135 2 : input logic clk_override,
136 : // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
137 : /*verilator coverage_off*/
138 : input logic scan_mode
139 : /*verilator coverage_on*/
140 : );
141 :
142 :
143 : typedef enum logic [3:0] {IDLE=4'h0, HALTING=4'h1, HALTED=4'h2, CORE_CMD_START=4'h3, CORE_CMD_WAIT=4'h4, SB_CMD_START=4'h5, SB_CMD_SEND=4'h6, SB_CMD_RESP=4'h7, CMD_DONE=4'h8, RESUMING=4'h9} state_t;
144 : typedef enum logic [3:0] {SBIDLE=4'h0, WAIT_RD=4'h1, WAIT_WR=4'h2, CMD_RD=4'h3, CMD_WR=4'h4, CMD_WR_ADDR=4'h5, CMD_WR_DATA=4'h6, RSP_RD=4'h7, RSP_WR=4'h8, DONE=4'h9} sb_state_t;
145 :
146 4274 : state_t dbg_state;
147 4288 : state_t dbg_nxtstate;
148 9426 : logic dbg_state_en;
149 : // these are the registers that the debug module implements
150 2 : logic [31:0] dmstatus_reg; // [26:24]-dmerr, [17:16]-resume ack, [9:8]-halted, [3:0]-version
151 0 : logic [31:0] dmcontrol_reg; // dmcontrol register has only 6 bits implemented. 31: haltreq, 30: resumereq, 29: haltreset, 28: ackhavereset, 1: ndmreset, 0: dmactive.
152 10 : logic [31:0] command_reg;
153 4 : logic [31:0] abstractcs_reg; // bits implemted are [12] - busy and [10:8]= command error
154 0 : logic [31:0] haltsum0_reg;
155 128 : logic [31:0] data0_reg;
156 0 : logic [31:0] data1_reg;
157 :
158 : // data 0
159 146 : logic [31:0] data0_din;
160 396 : logic data0_reg_wren, data0_reg_wren0, data0_reg_wren1, data0_reg_wren2;
161 : // data 1
162 0 : logic [31:0] data1_din;
163 1458 : logic data1_reg_wren, data1_reg_wren0, data1_reg_wren1;
164 : // abstractcs
165 8556 : logic abstractcs_busy_wren;
166 4290 : logic abstractcs_busy_din;
167 0 : logic [2:0] abstractcs_error_din;
168 0 : logic abstractcs_error_sel0, abstractcs_error_sel1, abstractcs_error_sel2, abstractcs_error_sel3, abstractcs_error_sel4, abstractcs_error_sel5, abstractcs_error_sel6;
169 0 : logic dbg_sb_bus_error;
170 : // abstractauto
171 0 : logic abstractauto_reg_wren;
172 0 : logic [1:0] abstractauto_reg;
173 :
174 : // dmstatus
175 16 : logic dmstatus_resumeack_wren;
176 10 : logic dmstatus_resumeack_din;
177 8 : logic dmstatus_haveresetn_wren;
178 8 : logic dmstatus_resumeack;
179 677 : logic dmstatus_unavail;
180 350 : logic dmstatus_running;
181 12 : logic dmstatus_halted;
182 4 : logic dmstatus_havereset, dmstatus_haveresetn;
183 :
184 : // dmcontrol
185 10 : logic resumereq;
186 60 : logic dmcontrol_wren, dmcontrol_wren_Q;
187 : // command
188 4278 : logic execute_command_ns, execute_command;
189 4278 : logic command_wren, command_regno_wren;
190 2572 : logic command_transfer_din;
191 34 : logic command_postexec_din;
192 22 : logic [31:0] command_din;
193 0 : logic [3:0] dbg_cmd_addr_incr;
194 14 : logic [31:0] dbg_cmd_curr_addr;
195 14 : logic [31:0] dbg_cmd_next_addr;
196 :
197 : // needed to send the read data back for dmi reads
198 192 : logic [31:0] dmi_reg_rdata_din;
199 :
200 36 : sb_state_t sb_state;
201 36 : sb_state_t sb_nxtstate;
202 90 : logic sb_state_en;
203 :
204 : //System bus section
205 36 : logic sbcs_wren;
206 72 : logic sbcs_sbbusy_wren;
207 375 : logic sbcs_sbbusy_din;
208 0 : logic sbcs_sbbusyerror_wren;
209 339 : logic sbcs_sbbusyerror_din;
210 :
211 0 : logic sbcs_sberror_wren;
212 36 : logic [2:0] sbcs_sberror_din;
213 0 : logic sbcs_unaligned;
214 0 : logic sbcs_illegal_size;
215 0 : logic [19:15] sbcs_reg_int;
216 :
217 : // data
218 20 : logic sbdata0_reg_wren0;
219 16 : logic sbdata0_reg_wren1;
220 36 : logic sbdata0_reg_wren;
221 12 : logic [31:0] sbdata0_din;
222 :
223 0 : logic sbdata1_reg_wren0;
224 16 : logic sbdata1_reg_wren1;
225 16 : logic sbdata1_reg_wren;
226 0 : logic [31:0] sbdata1_din;
227 :
228 36 : logic sbaddress0_reg_wren0;
229 36 : logic sbaddress0_reg_wren1;
230 72 : logic sbaddress0_reg_wren;
231 8 : logic [31:0] sbaddress0_reg_din;
232 0 : logic [3:0] sbaddress0_incr;
233 16 : logic sbreadonaddr_access;
234 0 : logic sbreadondata_access;
235 20 : logic sbdata0wr_access;
236 :
237 1712 : logic sb_abmem_cmd_done_in, sb_abmem_data_done_in;
238 5990 : logic sb_abmem_cmd_done_en, sb_abmem_data_done_en;
239 1712 : logic sb_abmem_cmd_done, sb_abmem_data_done;
240 0 : logic [31:0] abmem_addr;
241 0 : logic abmem_addr_in_dccm_region, abmem_addr_in_iccm_region, abmem_addr_in_pic_region;
242 2 : logic abmem_addr_core_local;
243 341 : logic abmem_addr_external;
244 :
245 1712 : logic sb_cmd_pending, sb_abmem_cmd_pending;
246 300 : logic sb_abmem_cmd_write;
247 0 : logic [2:0] sb_abmem_cmd_size;
248 0 : logic [31:0] sb_abmem_cmd_addr;
249 128 : logic [31:0] sb_abmem_cmd_wdata;
250 :
251 0 : logic [2:0] sb_cmd_size;
252 4 : logic [31:0] sb_cmd_addr;
253 4 : logic [63:0] sb_cmd_wdata;
254 :
255 240 : logic sb_bus_cmd_read, sb_bus_cmd_write_addr, sb_bus_cmd_write_data;
256 240 : logic sb_bus_rsp_read, sb_bus_rsp_write;
257 0 : logic sb_bus_rsp_error;
258 434 : logic [63:0] sb_bus_rdata;
259 :
260 : //registers
261 0 : logic [31:0] sbcs_reg;
262 4 : logic [31:0] sbaddress0_reg;
263 4 : logic [31:0] sbdata0_reg;
264 0 : logic [31:0] sbdata1_reg;
265 :
266 224 : logic sb_abmem_cmd_arvalid, sb_abmem_cmd_awvalid, sb_abmem_cmd_wvalid;
267 1488 : logic sb_abmem_read_pend;
268 16 : logic sb_cmd_awvalid, sb_cmd_wvalid, sb_cmd_arvalid;
269 16 : logic sb_read_pend;
270 4 : logic [31:0] sb_axi_addr;
271 60 : logic [63:0] sb_axi_wrdata;
272 0 : logic [2:0] sb_axi_size;
273 :
274 4 : logic dbg_dm_rst_l;
275 338 : logic rst_l_sync;
276 :
277 : //clken
278 456 : logic dbg_free_clken;
279 69840565 : logic dbg_free_clk;
280 :
281 16996 : logic sb_free_clken;
282 69840565 : logic sb_free_clk;
283 :
284 : // clocking
285 : // used for the abstract commands.
286 : assign dbg_free_clken = dmi_reg_en | execute_command | (dbg_state != IDLE) | dbg_state_en | dec_tlu_dbg_halted | dec_tlu_mpc_halted_only | dec_tlu_debug_mode | dbg_halt_req | clk_override;
287 :
288 : // used for the system bus
289 : assign sb_free_clken = dmi_reg_en | execute_command | sb_state_en | (sb_state != SBIDLE) | clk_override;
290 :
291 : rvoclkhdr dbg_free_cgc (.en(dbg_free_clken), .l1clk(dbg_free_clk), .*);
292 : rvoclkhdr sb_free_cgc (.en(sb_free_clken), .l1clk(sb_free_clk), .*);
293 :
294 : // end clocking section
295 :
296 : // Reset logic
297 : assign dbg_dm_rst_l = dbg_rst_l & (dmcontrol_reg[0] | scan_mode);
298 : assign dbg_core_rst_l = ~dmcontrol_reg[1] | scan_mode;
299 :
300 : // synchronize the rst
301 : rvsyncss #(1) rstl_syncff (.din(rst_l), .dout(rst_l_sync), .clk(free_clk), .rst_l(dbg_rst_l));
302 :
303 : // system bus register
304 : // sbcs[31:29], sbcs - [22]:sbbusyerror, [21]: sbbusy, [20]:sbreadonaddr, [19:17]:sbaccess, [16]:sbautoincrement, [15]:sbreadondata, [14:12]:sberror, sbsize=32, 128=0, 64/32/16/8 are legal
305 : assign sbcs_reg[31:29] = 3'b1;
306 : assign sbcs_reg[28:23] = '0;
307 : assign sbcs_reg[19:15] = {sbcs_reg_int[19], ~sbcs_reg_int[18], sbcs_reg_int[17:15]};
308 : assign sbcs_reg[11:5] = 7'h20;
309 : assign sbcs_reg[4:0] = 5'b01111;
310 : assign sbcs_wren = (dmi_reg_addr == 7'h38) & dmi_reg_en & dmi_reg_wr_en & (sb_state == SBIDLE);
311 : assign sbcs_sbbusyerror_wren = (sbcs_wren & dmi_reg_wdata[22]) |
312 : (sbcs_reg[21] & dmi_reg_en & ((dmi_reg_wr_en & (dmi_reg_addr == 7'h39)) | (dmi_reg_addr == 7'h3c) | (dmi_reg_addr == 7'h3d)));
313 : assign sbcs_sbbusyerror_din = ~(sbcs_wren & dmi_reg_wdata[22]); // Clear when writing one
314 :
315 : rvdffs #(1) sbcs_sbbusyerror_reg (.din(sbcs_sbbusyerror_din), .dout(sbcs_reg[22]), .en(sbcs_sbbusyerror_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
316 : rvdffs #(1) sbcs_sbbusy_reg (.din(sbcs_sbbusy_din), .dout(sbcs_reg[21]), .en(sbcs_sbbusy_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
317 : rvdffs #(1) sbcs_sbreadonaddr_reg (.din(dmi_reg_wdata[20]), .dout(sbcs_reg[20]), .en(sbcs_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
318 : rvdffs #(5) sbcs_misc_reg (.din({dmi_reg_wdata[19],~dmi_reg_wdata[18],dmi_reg_wdata[17:15]}),
319 : .dout(sbcs_reg_int[19:15]), .en(sbcs_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
320 : rvdffs #(3) sbcs_error_reg (.din(sbcs_sberror_din[2:0]), .dout(sbcs_reg[14:12]), .en(sbcs_sberror_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
321 :
322 : assign sbcs_unaligned = ((sbcs_reg[19:17] == 3'b001) & sbaddress0_reg[0]) |
323 : ((sbcs_reg[19:17] == 3'b010) & (|sbaddress0_reg[1:0])) |
324 : ((sbcs_reg[19:17] == 3'b011) & (|sbaddress0_reg[2:0]));
325 :
326 : assign sbcs_illegal_size = sbcs_reg[19]; // Anything bigger than 64 bits is illegal
327 :
328 : assign sbaddress0_incr[3:0] = ({4{(sbcs_reg[19:17] == 3'h0)}} & 4'b0001) |
329 : ({4{(sbcs_reg[19:17] == 3'h1)}} & 4'b0010) |
330 : ({4{(sbcs_reg[19:17] == 3'h2)}} & 4'b0100) |
331 : ({4{(sbcs_reg[19:17] == 3'h3)}} & 4'b1000);
332 :
333 : // sbdata
334 : assign sbdata0_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3c); // write data only when single read is 0
335 : assign sbdata0_reg_wren1 = (sb_state == RSP_RD) & sb_state_en & ~sbcs_sberror_wren;
336 : assign sbdata0_reg_wren = sbdata0_reg_wren0 | sbdata0_reg_wren1;
337 :
338 : assign sbdata1_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3d); // write data only when single read is 0;
339 : assign sbdata1_reg_wren1 = (sb_state == RSP_RD) & sb_state_en & ~sbcs_sberror_wren;
340 : assign sbdata1_reg_wren = sbdata1_reg_wren0 | sbdata1_reg_wren1;
341 :
342 : assign sbdata0_din[31:0] = ({32{sbdata0_reg_wren0}} & dmi_reg_wdata[31:0]) |
343 : ({32{sbdata0_reg_wren1}} & sb_bus_rdata[31:0]);
344 : assign sbdata1_din[31:0] = ({32{sbdata1_reg_wren0}} & dmi_reg_wdata[31:0]) |
345 : ({32{sbdata1_reg_wren1}} & sb_bus_rdata[63:32]);
346 :
347 : rvdffe #(32) dbg_sbdata0_reg (.*, .din(sbdata0_din[31:0]), .dout(sbdata0_reg[31:0]), .en(sbdata0_reg_wren), .rst_l(dbg_dm_rst_l));
348 : rvdffe #(32) dbg_sbdata1_reg (.*, .din(sbdata1_din[31:0]), .dout(sbdata1_reg[31:0]), .en(sbdata1_reg_wren), .rst_l(dbg_dm_rst_l));
349 :
350 : // sbaddress
351 : assign sbaddress0_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h39);
352 : assign sbaddress0_reg_wren = sbaddress0_reg_wren0 | sbaddress0_reg_wren1;
353 : assign sbaddress0_reg_din[31:0]= ({32{sbaddress0_reg_wren0}} & dmi_reg_wdata[31:0]) |
354 : ({32{sbaddress0_reg_wren1}} & (32'(sbaddress0_reg[31:0] + {28'b0,sbaddress0_incr[3:0]})));
355 : rvdffe #(32) dbg_sbaddress0_reg (.*, .din(sbaddress0_reg_din[31:0]), .dout(sbaddress0_reg[31:0]), .en(sbaddress0_reg_wren), .rst_l(dbg_dm_rst_l));
356 :
357 : assign sbreadonaddr_access = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h39) & sbcs_reg[20]; // if readonaddr is set the next command will start upon writing of addr0
358 : assign sbreadondata_access = dmi_reg_en & ~dmi_reg_wr_en & (dmi_reg_addr == 7'h3c) & sbcs_reg[15]; // if readondata is set the next command will start upon reading of data0
359 : assign sbdata0wr_access = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3c); // write to sbdata0 will start write command to system bus
360 :
361 : // memory mapped registers
362 : // dmcontrol register has only 5 bits implemented. 31: haltreq, 30: resumereq, 28: ackhavereset, 1: ndmreset, 0: dmactive.
363 : // rest all the bits are zeroed out
364 : // dmactive flop is reset based on core rst_l, all other flops use dm_rst_l
365 : assign dmcontrol_wren = (dmi_reg_addr == 7'h10) & dmi_reg_en & dmi_reg_wr_en;
366 : assign dmcontrol_reg[29] = '0;
367 : assign dmcontrol_reg[27:2] = '0;
368 : assign resumereq = dmcontrol_reg[30] & ~dmcontrol_reg[31] & dmcontrol_wren_Q;
369 : rvdffs #(4) dmcontrolff (.din({dmi_reg_wdata[31:30],dmi_reg_wdata[28],dmi_reg_wdata[1]}), .dout({dmcontrol_reg[31:30], dmcontrol_reg[28], dmcontrol_reg[1]}), .en(dmcontrol_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
370 : rvdffs #(1) dmcontrol_dmactive_ff (.din(dmi_reg_wdata[0]), .dout(dmcontrol_reg[0]), .en(dmcontrol_wren), .rst_l(dbg_rst_l), .clk(dbg_free_clk));
371 : rvdff #(1) dmcontrol_wrenff(.din(dmcontrol_wren), .dout(dmcontrol_wren_Q), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
372 :
373 : // dmstatus register bits that are implemented
374 : // [19:18]-havereset,[17:16]-resume ack, [9:8]-halted, [3:0]-version
375 : // rest all the bits are zeroed out
376 : //assign dmstatus_wren = (dmi_reg_addr[31:0] == 32'h11) & dmi_reg_en;
377 : assign dmstatus_reg[31:20] = '0;
378 : assign dmstatus_reg[19:18] = {2{dmstatus_havereset}};
379 : assign dmstatus_reg[15:14] = '0;
380 : assign dmstatus_reg[7] = '1;
381 : assign dmstatus_reg[6:4] = '0;
382 : assign dmstatus_reg[17:16] = {2{dmstatus_resumeack}};
383 : assign dmstatus_reg[13:12] = {2{dmstatus_unavail}};
384 : assign dmstatus_reg[11:10] = {2{dmstatus_running}};
385 : assign dmstatus_reg[9:8] = {2{dmstatus_halted}};
386 : assign dmstatus_reg[3:0] = 4'h2;
387 :
388 : assign dmstatus_resumeack_wren = ((dbg_state == RESUMING) & dec_tlu_resume_ack) | (dmstatus_resumeack & resumereq & dmstatus_halted);
389 : assign dmstatus_resumeack_din = (dbg_state == RESUMING) & dec_tlu_resume_ack;
390 :
391 : assign dmstatus_haveresetn_wren = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en & dmcontrol_reg[0]; // clear the havereset
392 : assign dmstatus_havereset = ~dmstatus_haveresetn;
393 :
394 : assign dmstatus_unavail = dmcontrol_reg[1] | ~rst_l_sync;
395 : assign dmstatus_running = ~(dmstatus_unavail | dmstatus_halted);
396 :
397 : rvdffs #(1) dmstatus_resumeack_reg (.din(dmstatus_resumeack_din), .dout(dmstatus_resumeack), .en(dmstatus_resumeack_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
398 : rvdff #(1) dmstatus_halted_reg (.din(dec_tlu_dbg_halted & ~dec_tlu_mpc_halted_only), .dout(dmstatus_halted), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
399 : rvdffs #(1) dmstatus_haveresetn_reg (.din(1'b1), .dout(dmstatus_haveresetn), .en(dmstatus_haveresetn_wren), .rst_l(rst_l), .clk(dbg_free_clk));
400 :
401 : // haltsum0 register
402 : assign haltsum0_reg[31:1] = '0;
403 : assign haltsum0_reg[0] = dmstatus_halted;
404 :
405 : // abstractcs register
406 : // bits implemted are [12] - busy and [10:8]= command error
407 : assign abstractcs_reg[31:13] = '0;
408 : assign abstractcs_reg[11] = '0;
409 : assign abstractcs_reg[7:4] = '0;
410 : assign abstractcs_reg[3:0] = 4'h2; // One data register
411 :
412 : assign abstractcs_error_sel0 = abstractcs_reg[12] & ~(|abstractcs_reg[10:8]) & dmi_reg_en & ((dmi_reg_wr_en & ((dmi_reg_addr == 7'h16) | (dmi_reg_addr == 7'h17)) | (dmi_reg_addr == 7'h18)) |
413 : (dmi_reg_addr == 7'h4) | (dmi_reg_addr == 7'h5));
414 : assign abstractcs_error_sel1 = execute_command & ~(|abstractcs_reg[10:8]) &
415 : ((~((command_reg[31:24] == 8'b0) | (command_reg[31:24] == 8'h2))) | // Illegal command
416 : (((command_reg[22:20] == 3'b011) | (command_reg[22])) & (command_reg[31:24] == 8'h2)) | // Illegal abstract memory size (can't be DW or higher)
417 : ((command_reg[22:20] != 3'b010) & ((command_reg[31:24] == 8'h0) & command_reg[17])) | // Illegal abstract reg size
418 : ((command_reg[31:24] == 8'h0) & command_reg[18])); //postexec for abstract register access
419 : assign abstractcs_error_sel2 = ((core_dbg_cmd_done & core_dbg_cmd_fail) | // exception from core
420 : (execute_command & (command_reg[31:24] == 8'h0) & // unimplemented regs
421 : (((command_reg[15:12] == 4'h1) & (command_reg[11:5] != 0)) | (command_reg[15:13] != 0)))) & ~(|abstractcs_reg[10:8]);
422 : assign abstractcs_error_sel3 = execute_command & (dbg_state != HALTED) & ~(|abstractcs_reg[10:8]);
423 : assign abstractcs_error_sel4 = dbg_sb_bus_error & dbg_bus_clk_en & ~(|abstractcs_reg[10:8]);// sb bus error for abstract memory command
424 : assign abstractcs_error_sel5 = execute_command & (command_reg[31:24] == 8'h2) & ~(|abstractcs_reg[10:8]) &
425 : (((command_reg[22:20] == 3'b001) & data1_reg[0]) | ((command_reg[22:20] == 3'b010) & (|data1_reg[1:0]))); //Unaligned address for abstract memory
426 : assign abstractcs_error_sel6 = (dmi_reg_addr == 7'h16) & dmi_reg_en & dmi_reg_wr_en;
427 :
428 : assign abstractcs_error_din[2:0] = abstractcs_error_sel0 ? 3'b001 : // writing command or abstractcs while a command was executing. Or accessing data0
429 : abstractcs_error_sel1 ? 3'b010 : // writing a illegal command type to cmd field of command
430 : abstractcs_error_sel2 ? 3'b011 : // exception while running command
431 : abstractcs_error_sel3 ? 3'b100 : // writing a comnand when not in the halted state
432 : abstractcs_error_sel4 ? 3'b101 : // Bus error
433 : abstractcs_error_sel5 ? 3'b111 : // unaligned or illegal size abstract memory command
434 : abstractcs_error_sel6 ? (~dmi_reg_wdata[10:8] & abstractcs_reg[10:8]) : //W1C
435 : abstractcs_reg[10:8]; //hold
436 :
437 : rvdffs #(1) dmabstractcs_busy_reg (.din(abstractcs_busy_din), .dout(abstractcs_reg[12]), .en(abstractcs_busy_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
438 : rvdff #(3) dmabstractcs_error_reg (.din(abstractcs_error_din[2:0]), .dout(abstractcs_reg[10:8]), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
439 :
440 : // abstract auto reg
441 : assign abstractauto_reg_wren = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h18) & ~abstractcs_reg[12];
442 : rvdffs #(2) dbg_abstractauto_reg (.*, .din(dmi_reg_wdata[1:0]), .dout(abstractauto_reg[1:0]), .en(abstractauto_reg_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
443 :
444 : // command register - implemented all the bits in this register
445 : // command[16] = 1: write, 0: read
446 : assign execute_command_ns = command_wren |
447 : (dmi_reg_en & ~abstractcs_reg[12] & (((dmi_reg_addr == 7'h4) & abstractauto_reg[0]) | ((dmi_reg_addr == 7'h5) & abstractauto_reg[1])));
448 : assign command_wren = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en;
449 : assign command_regno_wren = command_wren | ((command_reg[31:24] == 8'h0) & command_reg[19] & (dbg_state == CMD_DONE) & ~(|abstractcs_reg[10:8])); // aarpostincrement
450 : assign command_postexec_din = (dmi_reg_wdata[31:24] == 8'h0) & dmi_reg_wdata[18];
451 : assign command_transfer_din = (dmi_reg_wdata[31:24] == 8'h0) & dmi_reg_wdata[17];
452 : assign command_din[31:16] = {dmi_reg_wdata[31:24],1'b0,dmi_reg_wdata[22:19],command_postexec_din,command_transfer_din, dmi_reg_wdata[16]};
453 : assign command_din[15:0] = command_wren ? dmi_reg_wdata[15:0] : dbg_cmd_next_addr[15:0];
454 : rvdff #(1) execute_commandff (.*, .din(execute_command_ns), .dout(execute_command), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l));
455 : rvdffe #(16) dmcommand_reg (.*, .din(command_din[31:16]), .dout(command_reg[31:16]), .en(command_wren), .rst_l(dbg_dm_rst_l));
456 : rvdffe #(16) dmcommand_regno_reg (.*, .din(command_din[15:0]), .dout(command_reg[15:0]), .en(command_regno_wren), .rst_l(dbg_dm_rst_l));
457 :
458 : // data0 reg
459 : assign data0_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h4) & (dbg_state == HALTED) & ~abstractcs_reg[12]);
460 : assign data0_reg_wren1 = core_dbg_cmd_done & (dbg_state == CORE_CMD_WAIT) & ~command_reg[16];
461 : assign data0_reg_wren = data0_reg_wren0 | data0_reg_wren1 | data0_reg_wren2;
462 :
463 : assign data0_din[31:0] = ({32{data0_reg_wren0}} & dmi_reg_wdata[31:0]) |
464 : ({32{data0_reg_wren1}} & core_dbg_rddata[31:0]) |
465 : ({32{data0_reg_wren2}} & sb_bus_rdata[31:0]);
466 :
467 : rvdffe #(32) dbg_data0_reg (.*, .din(data0_din[31:0]), .dout(data0_reg[31:0]), .en(data0_reg_wren), .rst_l(dbg_dm_rst_l));
468 :
469 : // data 1
470 : assign data1_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h5) & (dbg_state == HALTED) & ~abstractcs_reg[12]);
471 : assign data1_reg_wren1 = (dbg_state == CMD_DONE) & (command_reg[31:24] == 8'h2) & command_reg[19] & ~(|abstractcs_reg[10:8]); // aampostincrement
472 : assign data1_reg_wren = data1_reg_wren0 | data1_reg_wren1;
473 :
474 : assign data1_din[31:0] = ({32{data1_reg_wren0}} & dmi_reg_wdata[31:0]) |
475 : ({32{data1_reg_wren1}} & dbg_cmd_next_addr[31:0]);
476 :
477 : rvdffe #(32) dbg_data1_reg (.*, .din(data1_din[31:0]), .dout(data1_reg[31:0]), .en(data1_reg_wren), .rst_l(dbg_dm_rst_l));
478 :
479 : rvdffs #(1) sb_abmem_cmd_doneff (.din(sb_abmem_cmd_done_in), .dout(sb_abmem_cmd_done), .en(sb_abmem_cmd_done_en), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l), .*);
480 : rvdffs #(1) sb_abmem_data_doneff (.din(sb_abmem_data_done_in), .dout(sb_abmem_data_done), .en(sb_abmem_data_done_en), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l), .*);
481 :
482 : // FSM to control the debug mode entry, command send/recieve, and Resume flow.
483 339 : always_comb begin
484 339 : dbg_nxtstate = IDLE;
485 339 : dbg_state_en = 1'b0;
486 339 : abstractcs_busy_wren = 1'b0;
487 339 : abstractcs_busy_din = 1'b0;
488 339 : dbg_halt_req = dmcontrol_wren_Q & dmcontrol_reg[31]; // single pulse output to the core. Need to drive every time this register is written since core might be halted due to MPC
489 339 : dbg_resume_req = 1'b0; // single pulse output to the core
490 339 : dbg_sb_bus_error = 1'b0;
491 339 : data0_reg_wren2 = 1'b0;
492 339 : sb_abmem_cmd_done_in = 1'b0;
493 339 : sb_abmem_data_done_in = 1'b0;
494 339 : sb_abmem_cmd_done_en = 1'b0;
495 339 : sb_abmem_data_done_en = 1'b0;
496 :
497 339 : case (dbg_state)
498 24864363 : IDLE: begin
499 24864363 : dbg_nxtstate = (dmstatus_reg[9] | dec_tlu_mpc_halted_only) ? HALTED : HALTING; // initiate the halt command to the core
500 24864363 : dbg_state_en = dmcontrol_reg[31] | dmstatus_reg[9] | dec_tlu_mpc_halted_only; // when the jtag writes the halt bit in the DM register, OR when the status indicates H
501 24864363 : dbg_halt_req = dmcontrol_reg[31]; // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes
502 : end
503 16 : HALTING : begin
504 16 : dbg_nxtstate = HALTED; // Goto HALTED once the core sends an ACK
505 16 : dbg_state_en = dmstatus_reg[9] | dec_tlu_mpc_halted_only; // core indicates halted
506 : end
507 3393487 : HALTED: begin
508 : // wait for halted to go away before send to resume. Else start of new command
509 3393487 : dbg_nxtstate = dmstatus_reg[9] ? (resumereq ? RESUMING : (((command_reg[31:24] == 8'h2) & abmem_addr_external) ? SB_CMD_START : CORE_CMD_START)) :
510 3393487 : (dmcontrol_reg[31] ? HALTING : IDLE); // This is MPC halted case
511 3393487 : dbg_state_en = (dmstatus_reg[9] & resumereq) | execute_command | ~(dmstatus_reg[9] | dec_tlu_mpc_halted_only);
512 3393487 : abstractcs_busy_wren = dbg_state_en & ((dbg_nxtstate == CORE_CMD_START) | (dbg_nxtstate == SB_CMD_START)); // write busy when a new command was written by jtag
513 3393487 : abstractcs_busy_din = 1'b1;
514 3393487 : dbg_resume_req = dbg_state_en & (dbg_nxtstate == RESUMING); // single cycle pulse to core if resuming
515 : end
516 832 : CORE_CMD_START: begin
517 : // Don't execute the command if cmderror or transfer=0 for abstract register access
518 832 : dbg_nxtstate = ((|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17])) ? CMD_DONE : CORE_CMD_WAIT; // new command sent to the core
519 832 : dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17]);
520 : end
521 1660 : CORE_CMD_WAIT: begin
522 1660 : dbg_nxtstate = CMD_DONE;
523 1660 : dbg_state_en = core_dbg_cmd_done; // go to done state for one cycle after completing current command
524 : end
525 605 : SB_CMD_START: begin
526 605 : dbg_nxtstate = (|abstractcs_reg[10:8]) ? CMD_DONE : SB_CMD_SEND;
527 605 : dbg_state_en = (dbg_bus_clk_en & ~sb_cmd_pending) | (|abstractcs_reg[10:8]);
528 : end
529 1607 : SB_CMD_SEND: begin
530 1607 : sb_abmem_cmd_done_in = 1'b1;
531 1607 : sb_abmem_data_done_in= 1'b1;
532 1607 : sb_abmem_cmd_done_en = (sb_bus_cmd_read | sb_bus_cmd_write_addr) & dbg_bus_clk_en;
533 1607 : sb_abmem_data_done_en= (sb_bus_cmd_read | sb_bus_cmd_write_data) & dbg_bus_clk_en;
534 1607 : dbg_nxtstate = SB_CMD_RESP;
535 1607 : dbg_state_en = (sb_abmem_cmd_done | sb_abmem_cmd_done_en) & (sb_abmem_data_done | sb_abmem_data_done_en) & dbg_bus_clk_en;
536 : end
537 1871 : SB_CMD_RESP: begin
538 1871 : dbg_nxtstate = CMD_DONE;
539 1871 : dbg_state_en = (sb_bus_rsp_read | sb_bus_rsp_write) & dbg_bus_clk_en;
540 1871 : dbg_sb_bus_error = (sb_bus_rsp_read | sb_bus_rsp_write) & sb_bus_rsp_error & dbg_bus_clk_en;
541 1871 : data0_reg_wren2 = dbg_state_en & ~sb_abmem_cmd_write & ~dbg_sb_bus_error;
542 : end
543 1437 : CMD_DONE: begin
544 1437 : dbg_nxtstate = HALTED;
545 1437 : dbg_state_en = 1'b1;
546 1437 : abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 )
547 1437 : abstractcs_busy_din = 1'b0;
548 1437 : sb_abmem_cmd_done_in = 1'b0;
549 1437 : sb_abmem_data_done_in= 1'b0;
550 1437 : sb_abmem_cmd_done_en = 1'b1;
551 1437 : sb_abmem_data_done_en= 1'b1;
552 : end
553 6 : RESUMING : begin
554 6 : dbg_nxtstate = IDLE;
555 6 : dbg_state_en = dmstatus_reg[17]; // resume ack has been updated in the dmstatus register
556 : end
557 : /* All legal values are handled above. Exclude the default part from coverage. */
558 : /*verilator coverage_off*/
559 : default : begin
560 : dbg_nxtstate = IDLE;
561 : dbg_state_en = 1'b0;
562 : abstractcs_busy_wren = 1'b0;
563 : abstractcs_busy_din = 1'b0;
564 : dbg_halt_req = 1'b0; // single pulse output to the core
565 : dbg_resume_req = 1'b0; // single pulse output to the core
566 : dbg_sb_bus_error = 1'b0;
567 : data0_reg_wren2 = 1'b0;
568 : sb_abmem_cmd_done_in = 1'b0;
569 : sb_abmem_data_done_in = 1'b0;
570 : sb_abmem_cmd_done_en = 1'b0;
571 : sb_abmem_data_done_en = 1'b0;
572 : end
573 : /*verilator coverage_on*/
574 : endcase
575 : end // always_comb begin
576 :
577 : assign dmi_reg_rdata_din[31:0] = ({32{dmi_reg_addr == 7'h4}} & data0_reg[31:0]) |
578 : ({32{dmi_reg_addr == 7'h5}} & data1_reg[31:0]) |
579 : ({32{dmi_reg_addr == 7'h10}} & {2'b0,dmcontrol_reg[29],1'b0,dmcontrol_reg[27:0]}) | // Read0 to Write only bits
580 : ({32{dmi_reg_addr == 7'h11}} & dmstatus_reg[31:0]) |
581 : ({32{dmi_reg_addr == 7'h16}} & abstractcs_reg[31:0]) |
582 : ({32{dmi_reg_addr == 7'h17}} & command_reg[31:0]) |
583 : ({32{dmi_reg_addr == 7'h18}} & {30'h0,abstractauto_reg[1:0]}) |
584 : ({32{dmi_reg_addr == 7'h40}} & haltsum0_reg[31:0]) |
585 : ({32{dmi_reg_addr == 7'h38}} & sbcs_reg[31:0]) |
586 : ({32{dmi_reg_addr == 7'h39}} & sbaddress0_reg[31:0]) |
587 : ({32{dmi_reg_addr == 7'h3c}} & sbdata0_reg[31:0]) |
588 : ({32{dmi_reg_addr == 7'h3d}} & sbdata1_reg[31:0]);
589 :
590 :
591 : rvdffs #($bits(state_t)) dbg_state_reg (.din(dbg_nxtstate), .dout({dbg_state}), .en(dbg_state_en), .rst_l(dbg_dm_rst_l & rst_l), .clk(dbg_free_clk));
592 : rvdffe #(32) dmi_rddata_reg (.din(dmi_reg_rdata_din[31:0]), .dout(dmi_reg_rdata[31:0]), .en(dmi_reg_en), .rst_l(dbg_dm_rst_l), .clk(clk), .*);
593 :
594 : assign abmem_addr[31:0] = data1_reg[31:0];
595 : assign abmem_addr_core_local = (abmem_addr_in_dccm_region | abmem_addr_in_iccm_region | abmem_addr_in_pic_region);
596 : assign abmem_addr_external = ~abmem_addr_core_local;
597 :
598 : assign abmem_addr_in_dccm_region = (abmem_addr[31:28] == pt.DCCM_REGION) & pt.DCCM_ENABLE;
599 : assign abmem_addr_in_iccm_region = (abmem_addr[31:28] == pt.ICCM_REGION) & pt.ICCM_ENABLE;
600 : assign abmem_addr_in_pic_region = (abmem_addr[31:28] == pt.PIC_REGION);
601 :
602 : // interface for the core
603 : assign dbg_cmd_addr[31:0] = (command_reg[31:24] == 8'h2) ? data1_reg[31:0] : {20'b0, command_reg[11:0]};
604 : assign dbg_cmd_wrdata[31:0] = data0_reg[31:0];
605 : assign dbg_cmd_valid = (dbg_state == CORE_CMD_START) & ~((|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17]) | ((command_reg[31:24] == 8'h2) & abmem_addr_external)) & dma_dbg_ready;
606 : assign dbg_cmd_write = command_reg[16];
607 : assign dbg_cmd_type[1:0] = (command_reg[31:24] == 8'h2) ? 2'b10 : {1'b0, (command_reg[15:12] == 4'b0)};
608 : assign dbg_cmd_size[1:0] = command_reg[21:20];
609 :
610 : assign dbg_cmd_addr_incr[3:0] = (command_reg[31:24] == 8'h2) ? (4'h1 << sb_abmem_cmd_size[1:0]) : 4'h1;
611 : assign dbg_cmd_curr_addr[31:0] = (command_reg[31:24] == 8'h2) ? data1_reg[31:0] : {16'b0, command_reg[15:0]};
612 : assign dbg_cmd_next_addr[31:0] = dbg_cmd_curr_addr[31:0] + {28'h0,dbg_cmd_addr_incr[3:0]};
613 :
614 : // Ask DMA to stop taking bus trxns since debug request is done
615 : assign dbg_dma_bubble = ((dbg_state == CORE_CMD_START) & ~(|abstractcs_reg[10:8])) | (dbg_state == CORE_CMD_WAIT);
616 :
617 : assign sb_cmd_pending = (sb_state == CMD_RD) | (sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR) | (sb_state == CMD_WR_DATA) | (sb_state == RSP_RD) | (sb_state == RSP_WR);
618 : assign sb_abmem_cmd_pending = (dbg_state == SB_CMD_START) | (dbg_state == SB_CMD_SEND) | (dbg_state== SB_CMD_RESP);
619 :
620 :
621 : // system bus FSM
622 339 : always_comb begin
623 339 : sb_nxtstate = SBIDLE;
624 339 : sb_state_en = 1'b0;
625 339 : sbcs_sbbusy_wren = 1'b0;
626 339 : sbcs_sbbusy_din = 1'b0;
627 339 : sbcs_sberror_wren = 1'b0;
628 339 : sbcs_sberror_din[2:0] = 3'b0;
629 339 : sbaddress0_reg_wren1 = 1'b0;
630 339 : case (sb_state)
631 28265744 : SBIDLE: begin
632 28265744 : sb_nxtstate = sbdata0wr_access ? WAIT_WR : WAIT_RD;
633 28265744 : sb_state_en = (sbdata0wr_access | sbreadondata_access | sbreadonaddr_access) & ~(|sbcs_reg[14:12]) & ~sbcs_reg[22];
634 28265744 : sbcs_sbbusy_wren = sb_state_en; // set the single read bit if it is a singlread command
635 28265744 : sbcs_sbbusy_din = 1'b1;
636 28265744 : sbcs_sberror_wren = sbcs_wren & (|dmi_reg_wdata[14:12]); // write to clear the error bits
637 28265744 : sbcs_sberror_din[2:0] = ~dmi_reg_wdata[14:12] & sbcs_reg[14:12];
638 : end
639 8 : WAIT_RD: begin
640 8 : sb_nxtstate = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_RD;
641 8 : sb_state_en = (dbg_bus_clk_en & ~sb_abmem_cmd_pending) | sbcs_unaligned | sbcs_illegal_size;
642 8 : sbcs_sberror_wren = sbcs_unaligned | sbcs_illegal_size;
643 8 : sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100;
644 : end
645 10 : WAIT_WR: begin
646 10 : sb_nxtstate = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_WR;
647 10 : sb_state_en = (dbg_bus_clk_en & ~sb_abmem_cmd_pending) | sbcs_unaligned | sbcs_illegal_size;
648 10 : sbcs_sberror_wren = sbcs_unaligned | sbcs_illegal_size;
649 10 : sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100;
650 : end
651 20 : CMD_RD : begin
652 20 : sb_nxtstate = RSP_RD;
653 20 : sb_state_en = sb_bus_cmd_read & dbg_bus_clk_en;
654 : end
655 25 : CMD_WR : begin
656 25 : sb_nxtstate = (sb_bus_cmd_write_addr & sb_bus_cmd_write_data) ? RSP_WR : (sb_bus_cmd_write_data ? CMD_WR_ADDR : CMD_WR_DATA);
657 25 : sb_state_en = (sb_bus_cmd_write_addr | sb_bus_cmd_write_data) & dbg_bus_clk_en;
658 : end
659 0 : CMD_WR_ADDR : begin
660 0 : sb_nxtstate = RSP_WR;
661 0 : sb_state_en = sb_bus_cmd_write_addr & dbg_bus_clk_en;
662 : end
663 0 : CMD_WR_DATA : begin
664 0 : sb_nxtstate = RSP_WR;
665 0 : sb_state_en = sb_bus_cmd_write_data & dbg_bus_clk_en;
666 : end
667 24 : RSP_RD: begin
668 24 : sb_nxtstate = DONE;
669 24 : sb_state_en = sb_bus_rsp_read & dbg_bus_clk_en;
670 24 : sbcs_sberror_wren = sb_state_en & sb_bus_rsp_error;
671 24 : sbcs_sberror_din[2:0] = 3'b010;
672 : end
673 35 : RSP_WR: begin
674 35 : sb_nxtstate = DONE;
675 35 : sb_state_en = sb_bus_rsp_write & dbg_bus_clk_en;
676 35 : sbcs_sberror_wren = sb_state_en & sb_bus_rsp_error;
677 35 : sbcs_sberror_din[2:0] = 3'b010;
678 : end
679 18 : DONE: begin
680 18 : sb_nxtstate = SBIDLE;
681 18 : sb_state_en = 1'b1;
682 18 : sbcs_sbbusy_wren = 1'b1; // reset the single read
683 18 : sbcs_sbbusy_din = 1'b0;
684 18 : sbaddress0_reg_wren1 = sbcs_reg[16] & (sbcs_reg[14:12] == 3'b0); // auto increment was set and no error. Update to new address after completing the current command
685 : end
686 : /* All legal values are handled above. Exclude the default part from coverage. */
687 : /*verilator coverage_off*/
688 : default : begin
689 : sb_nxtstate = SBIDLE;
690 : sb_state_en = 1'b0;
691 : sbcs_sbbusy_wren = 1'b0;
692 : sbcs_sbbusy_din = 1'b0;
693 : sbcs_sberror_wren = 1'b0;
694 : sbcs_sberror_din[2:0] = 3'b0;
695 : sbaddress0_reg_wren1 = 1'b0;
696 : end
697 : /*verilator coverage_on*/
698 : endcase
699 : end // always_comb begin
700 :
701 : rvdffs #($bits(sb_state_t)) sb_state_reg (.din(sb_nxtstate), .dout({sb_state}), .en(sb_state_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
702 :
703 : assign sb_abmem_cmd_write = command_reg[16];
704 : assign sb_abmem_cmd_size[2:0] = {1'b0, command_reg[21:20]};
705 : assign sb_abmem_cmd_addr[31:0] = abmem_addr[31:0];
706 : assign sb_abmem_cmd_wdata[31:0] = data0_reg[31:0];
707 :
708 : assign sb_cmd_size[2:0] = sbcs_reg[19:17];
709 : assign sb_cmd_wdata[63:0] = {sbdata1_reg[31:0], sbdata0_reg[31:0]};
710 : assign sb_cmd_addr[31:0] = sbaddress0_reg[31:0];
711 :
712 : assign sb_abmem_cmd_awvalid = (dbg_state == SB_CMD_SEND) & sb_abmem_cmd_write & ~sb_abmem_cmd_done;
713 : assign sb_abmem_cmd_wvalid = (dbg_state == SB_CMD_SEND) & sb_abmem_cmd_write & ~sb_abmem_data_done;
714 : assign sb_abmem_cmd_arvalid = (dbg_state == SB_CMD_SEND) & ~sb_abmem_cmd_write & ~sb_abmem_cmd_done & ~sb_abmem_data_done;
715 : assign sb_abmem_read_pend = (dbg_state == SB_CMD_RESP) & ~sb_abmem_cmd_write;
716 :
717 : assign sb_cmd_awvalid = ((sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR));
718 : assign sb_cmd_wvalid = ((sb_state == CMD_WR) | (sb_state == CMD_WR_DATA));
719 : assign sb_cmd_arvalid = (sb_state == CMD_RD);
720 : assign sb_read_pend = (sb_state == RSP_RD);
721 :
722 : assign sb_axi_size[2:0] = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid | sb_abmem_cmd_arvalid | sb_abmem_read_pend) ? sb_abmem_cmd_size[2:0] : sb_cmd_size[2:0];
723 : assign sb_axi_addr[31:0] = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid | sb_abmem_cmd_arvalid | sb_abmem_read_pend) ? sb_abmem_cmd_addr[31:0] : sb_cmd_addr[31:0];
724 : assign sb_axi_wrdata[63:0] = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid) ? {2{sb_abmem_cmd_wdata[31:0]}} : sb_cmd_wdata[63:0];
725 :
726 : // Generic bus response signals
727 : assign sb_bus_cmd_read = sb_axi_arvalid & sb_axi_arready;
728 : assign sb_bus_cmd_write_addr = sb_axi_awvalid & sb_axi_awready;
729 : assign sb_bus_cmd_write_data = sb_axi_wvalid & sb_axi_wready;
730 :
731 : assign sb_bus_rsp_read = sb_axi_rvalid & sb_axi_rready;
732 : assign sb_bus_rsp_write = sb_axi_bvalid & sb_axi_bready;
733 : assign sb_bus_rsp_error = (sb_bus_rsp_read & (|(sb_axi_rresp[1:0]))) | (sb_bus_rsp_write & (|(sb_axi_bresp[1:0])));
734 :
735 : // AXI Request signals
736 : assign sb_axi_awvalid = sb_abmem_cmd_awvalid | sb_cmd_awvalid;
737 : assign sb_axi_awaddr[31:0] = sb_axi_addr[31:0];
738 : assign sb_axi_awid[pt.SB_BUS_TAG-1:0] = '0;
739 : assign sb_axi_awsize[2:0] = sb_axi_size[2:0];
740 : assign sb_axi_awprot[2:0] = 3'b001;
741 : assign sb_axi_awcache[3:0] = 4'b1111;
742 : assign sb_axi_awregion[3:0] = sb_axi_addr[31:28];
743 : assign sb_axi_awlen[7:0] = '0;
744 : assign sb_axi_awburst[1:0] = 2'b01;
745 : assign sb_axi_awqos[3:0] = '0;
746 : assign sb_axi_awlock = '0;
747 :
748 : assign sb_axi_wvalid = sb_abmem_cmd_wvalid | sb_cmd_wvalid;
749 : assign sb_axi_wdata[63:0] = ({64{(sb_axi_size[2:0] == 3'h0)}} & {8{sb_axi_wrdata[7:0]}}) |
750 : ({64{(sb_axi_size[2:0] == 3'h1)}} & {4{sb_axi_wrdata[15:0]}}) |
751 : ({64{(sb_axi_size[2:0] == 3'h2)}} & {2{sb_axi_wrdata[31:0]}}) |
752 : ({64{(sb_axi_size[2:0] == 3'h3)}} & {sb_axi_wrdata[63:0]});
753 : assign sb_axi_wstrb[7:0] = ({8{(sb_axi_size[2:0] == 3'h0)}} & (8'h1 << sb_axi_addr[2:0])) |
754 : ({8{(sb_axi_size[2:0] == 3'h1)}} & (8'h3 << {sb_axi_addr[2:1],1'b0})) |
755 : ({8{(sb_axi_size[2:0] == 3'h2)}} & (8'hf << {sb_axi_addr[2],2'b0})) |
756 : ({8{(sb_axi_size[2:0] == 3'h3)}} & 8'hff);
757 : assign sb_axi_wlast = '1;
758 :
759 : assign sb_axi_arvalid = sb_abmem_cmd_arvalid | sb_cmd_arvalid;
760 : assign sb_axi_araddr[31:0] = sb_axi_addr[31:0];
761 : assign sb_axi_arid[pt.SB_BUS_TAG-1:0] = '0;
762 : assign sb_axi_arsize[2:0] = sb_axi_size[2:0];
763 : assign sb_axi_arprot[2:0] = 3'b001;
764 : assign sb_axi_arcache[3:0] = 4'b0;
765 : assign sb_axi_arregion[3:0] = sb_axi_addr[31:28];
766 : assign sb_axi_arlen[7:0] = '0;
767 : assign sb_axi_arburst[1:0] = 2'b01;
768 : assign sb_axi_arqos[3:0] = '0;
769 : assign sb_axi_arlock = '0;
770 :
771 : // AXI Response signals
772 : assign sb_axi_bready = 1'b1;
773 :
774 : assign sb_axi_rready = 1'b1;
775 : assign sb_bus_rdata[63:0] = ({64{sb_axi_size == 3'h0}} & ((sb_axi_rdata[63:0] >> 8*sb_axi_addr[2:0]) & 64'hff)) |
776 : ({64{sb_axi_size == 3'h1}} & ((sb_axi_rdata[63:0] >> 16*sb_axi_addr[2:1]) & 64'hffff)) |
777 : ({64{sb_axi_size == 3'h2}} & ((sb_axi_rdata[63:0] >> 32*sb_axi_addr[2]) & 64'hffff_ffff)) |
778 : ({64{sb_axi_size == 3'h3}} & sb_axi_rdata[63:0]);
779 :
780 : `ifdef RV_ASSERT_ON
781 : // assertion.
782 : // when the resume_ack is asserted then the dec_tlu_dbg_halted should be 0
783 : dm_check_resume_and_halted: assert property (@(posedge clk) disable iff(~rst_l) (~dec_tlu_resume_ack | ~dec_tlu_dbg_halted));
784 :
785 : assert_b2b_haltreq: assert property (@(posedge clk) disable iff (~(rst_l)) (##1 dbg_halt_req |=> ~dbg_halt_req)); // One cycle delay to fix weird issue around reset
786 : assert_halt_resume_onehot: assert #0 ($onehot0({dbg_halt_req, dbg_resume_req}));
787 : `endif
788 : endmodule
|