Skip to content

Commit 1b75b04

Browse files
committed
Prevent bus stalling
Do not stall bus on reading from empty FIFO or writing to full. Reads from empty FIFOs return 0, writes to full FIFOs are ignored. Signed-off-by: Karol Gugala <[email protected]>
1 parent 22c78c6 commit 1b75b04

File tree

8 files changed

+141
-121
lines changed

8 files changed

+141
-121
lines changed

src/hci/tti.sv

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ module tti
6363
output logic tx_desc_queue_reg_rst_o,
6464
input logic tx_desc_queue_reg_rst_we_i,
6565
input logic tx_desc_queue_reg_rst_data_i,
66+
input logic tx_desc_queue_full_i,
6667

6768
// TX data queue
6869
output logic tx_data_queue_req_o,
@@ -77,6 +78,7 @@ module tti
7778
input logic tx_data_queue_full_i,
7879

7980
// In-band Interrupt queue
81+
input logic ibi_queue_full_i,
8082
output logic ibi_queue_req_o,
8183
input logic ibi_queue_ack_i,
8284
output logic [CsrDataWidth-1:0] ibi_queue_data_o,
@@ -153,35 +155,51 @@ module tti
153155
ibi_queue_ready_thld_o = IbiThldWidth'(hwif_tti_i.QUEUE_THLD_CTRL.IBI_THLD.value);
154156
end : wire_hwif_thld
155157

156-
logic tx_data_queue_full_r;
157-
always_ff @(posedge clk_i or negedge rst_ni) begin : register_fifo_status
158-
if (~rst_ni) begin
159-
tx_data_queue_full_r <= '0;
160-
end else begin
161-
tx_data_queue_full_r <= tx_data_queue_full_i;
162-
end
163-
end
164-
165158
always_comb begin : wire_hwif_xfer
166-
rx_desc_queue_req_o = hwif_tti_i.RX_DESC_QUEUE_PORT.req;
167-
hwif_tti_o.RX_DESC_QUEUE_PORT.rd_ack = rx_desc_queue_ack_i;
168-
hwif_tti_o.RX_DESC_QUEUE_PORT.rd_data = rx_desc_queue_data_i;
159+
160+
// RX_DESC_QUEUE_PORT
169161
hwif_tti_o.RESET_CONTROL.RX_DESC_RST.we = rx_desc_queue_reg_rst_we_i;
170162
hwif_tti_o.RESET_CONTROL.RX_DESC_RST.next = rx_desc_queue_reg_rst_data_i;
163+
if (rx_desc_queue_empty_i && hwif_tti_i.RX_DESC_QUEUE_PORT.req) begin
164+
hwif_tti_o.RX_DESC_QUEUE_PORT.rd_ack = hwif_tti_i.RX_DESC_QUEUE_PORT.req & ~hwif_tti_i.RX_DESC_QUEUE_PORT.req_is_wr;
165+
hwif_tti_o.RX_DESC_QUEUE_PORT.rd_data = '0;
166+
rx_desc_queue_req_o = '0;
167+
end else begin
168+
hwif_tti_o.RX_DESC_QUEUE_PORT.rd_ack = rx_desc_queue_ack_i;
169+
hwif_tti_o.RX_DESC_QUEUE_PORT.rd_data = rx_desc_queue_data_i;
170+
rx_desc_queue_req_o = hwif_tti_i.RX_DESC_QUEUE_PORT.req;
171+
end
171172

172-
tx_desc_queue_req_o = hwif_tti_i.TX_DESC_QUEUE_PORT.req & hwif_tti_i.TX_DESC_QUEUE_PORT.req_is_wr;
173-
tx_desc_queue_data_o = hwif_tti_i.TX_DESC_QUEUE_PORT.wr_data;
174-
hwif_tti_o.TX_DESC_QUEUE_PORT.wr_ack = tx_desc_queue_ack_i;
173+
// TX_DESC_QUEUE_PORT
175174
hwif_tti_o.RESET_CONTROL.TX_DESC_RST.we = tx_desc_queue_reg_rst_we_i;
176175
hwif_tti_o.RESET_CONTROL.TX_DESC_RST.next = tx_desc_queue_reg_rst_data_i;
176+
if (tx_desc_queue_full_i && hwif_tti_i.TX_DESC_QUEUE_PORT.req) begin
177+
hwif_tti_o.TX_DESC_QUEUE_PORT.wr_ack = hwif_tti_i.TX_DESC_QUEUE_PORT.req & hwif_tti_i.TX_DESC_QUEUE_PORT.req_is_wr;
178+
tx_desc_queue_req_o = '0;
179+
tx_desc_queue_data_o = '0;
180+
end else begin
181+
hwif_tti_o.TX_DESC_QUEUE_PORT.wr_ack = tx_desc_queue_ack_i;
182+
tx_desc_queue_req_o = hwif_tti_i.TX_DESC_QUEUE_PORT.req & hwif_tti_i.TX_DESC_QUEUE_PORT.req_is_wr;
183+
tx_desc_queue_data_o = hwif_tti_i.TX_DESC_QUEUE_PORT.wr_data;
184+
end
177185

178-
rx_data_queue_req_o = hwif_tti_i.RX_DATA_PORT.req;
179-
hwif_tti_o.RX_DATA_PORT.rd_ack = rx_data_queue_ack_i;
180-
hwif_tti_o.RX_DATA_PORT.rd_data = rx_data_queue_data_i;
186+
// RX_DATA_PORT
181187
hwif_tti_o.RESET_CONTROL.RX_DATA_RST.we = rx_data_queue_reg_rst_we_i;
182188
hwif_tti_o.RESET_CONTROL.RX_DATA_RST.next = rx_data_queue_reg_rst_data_i;
189+
if (rx_data_queue_empty_i && hwif_tti_i.RX_DATA_PORT.req) begin
190+
hwif_tti_o.RX_DATA_PORT.rd_ack = hwif_tti_i.RX_DATA_PORT.req & ~hwif_tti_i.RX_DATA_PORT.req_is_wr;;
191+
hwif_tti_o.RX_DATA_PORT.rd_data = '0;
192+
rx_data_queue_req_o = '0;
193+
end else begin
194+
hwif_tti_o.RX_DATA_PORT.rd_ack = rx_data_queue_ack_i;
195+
hwif_tti_o.RX_DATA_PORT.rd_data = rx_data_queue_data_i;
196+
rx_data_queue_req_o = hwif_tti_i.RX_DATA_PORT.req;
197+
end
183198

184-
if (bypass_i3c_core_i & tx_data_queue_full_r) begin
199+
// TX_DATA_PORT
200+
hwif_tti_o.RESET_CONTROL.TX_DATA_RST.we = tx_data_queue_reg_rst_we_i;
201+
hwif_tti_o.RESET_CONTROL.TX_DATA_RST.next = tx_data_queue_reg_rst_data_i;
202+
if (tx_data_queue_full_i && hwif_tti_i.TX_DATA_PORT.req) begin
185203
tx_data_queue_req_o = '0;
186204
tx_data_queue_data_o = '0;
187205
hwif_tti_o.TX_DATA_PORT.wr_ack = hwif_tti_i.TX_DATA_PORT.req & hwif_tti_i.TX_DATA_PORT.req_is_wr;
@@ -190,14 +208,19 @@ module tti
190208
tx_data_queue_data_o = hwif_tti_i.TX_DATA_PORT.wr_data;
191209
hwif_tti_o.TX_DATA_PORT.wr_ack = tx_data_queue_ack_i;
192210
end
193-
hwif_tti_o.RESET_CONTROL.TX_DATA_RST.we = tx_data_queue_reg_rst_we_i;
194-
hwif_tti_o.RESET_CONTROL.TX_DATA_RST.next = tx_data_queue_reg_rst_data_i;
195211

196-
ibi_queue_req_o = hwif_tti_i.IBI_PORT.req & hwif_tti_i.IBI_PORT.req_is_wr;
197-
ibi_queue_data_o = hwif_tti_i.IBI_PORT.wr_data;
198-
hwif_tti_o.IBI_PORT.wr_ack = ibi_queue_ack_i;
212+
// IBI_PORT
199213
hwif_tti_o.RESET_CONTROL.IBI_QUEUE_RST.we = ibi_queue_reg_rst_we_i;
200214
hwif_tti_o.RESET_CONTROL.IBI_QUEUE_RST.next = ibi_queue_reg_rst_data_i;
215+
if (ibi_queue_full_i && hwif_tti_i.IBI_PORT.req) begin
216+
ibi_queue_req_o = '0;
217+
ibi_queue_data_o = '0;
218+
hwif_tti_o.IBI_PORT.wr_ack = hwif_tti_i.IBI_PORT.req & hwif_tti_i.IBI_PORT.req_is_wr;
219+
end else begin
220+
ibi_queue_req_o = hwif_tti_i.IBI_PORT.req & hwif_tti_i.IBI_PORT.req_is_wr;
221+
ibi_queue_data_o = hwif_tti_i.IBI_PORT.wr_data;
222+
hwif_tti_o.IBI_PORT.wr_ack = ibi_queue_ack_i;
223+
end
201224
end : wire_hwif_xfer
202225

203226
always_comb begin : wire_hwif_rst

src/i3c.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ module i3c
884884
logic csr_tti_tx_desc_reg_rst;
885885
logic csr_tti_tx_desc_reg_rst_we;
886886
logic csr_tti_tx_desc_reg_rst_data;
887+
logic csr_tti_tx_desc_full;
887888

888889
// TTI RX data queue
889890
logic csr_tti_rx_data_req;
@@ -953,6 +954,7 @@ module i3c
953954
.tx_desc_queue_reg_rst_o (csr_tti_tx_desc_reg_rst),
954955
.tx_desc_queue_reg_rst_we_i (csr_tti_tx_desc_reg_rst_we),
955956
.tx_desc_queue_reg_rst_data_i(csr_tti_tx_desc_reg_rst_data),
957+
.tx_desc_queue_full_i (csr_tti_tx_desc_full),
956958

957959
// TTI RX queue
958960
.rx_data_queue_req_o (csr_tti_rx_data_req),
@@ -983,6 +985,7 @@ module i3c
983985
.tx_data_queue_full_i (csr_tti_tx_data_full),
984986

985987
// TTI In-band Interrupt (IBI) queue
988+
.ibi_queue_full_i (tti_ibi_full),
986989
.ibi_queue_req_o (csr_tti_ibi_req),
987990
.ibi_queue_ack_i (csr_tti_ibi_ack),
988991
.ibi_queue_data_o (csr_tti_ibi_data),
@@ -1064,6 +1067,7 @@ module i3c
10641067
.csr_tti_tx_desc_queue_reg_rst_i (csr_tti_tx_desc_reg_rst),
10651068
.csr_tti_tx_desc_queue_reg_rst_we_o (csr_tti_tx_desc_reg_rst_we),
10661069
.csr_tti_tx_desc_queue_reg_rst_data_o(csr_tti_tx_desc_reg_rst_data),
1070+
.csr_tti_tx_desc_queue_full_o (csr_tti_tx_desc_full),
10671071

10681072
// TTI RX queue
10691073
.csr_tti_rx_data_queue_req_i (csr_tti_rx_data_req),

src/recovery/recovery_handler.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ module recovery_handler
120120
output logic csr_tti_rx_desc_queue_ready_thld_trig_o,
121121

122122
// TX Descriptor queue
123+
output logic csr_tti_tx_desc_queue_full_o,
123124
input logic csr_tti_tx_desc_queue_req_i,
124125
output logic csr_tti_tx_desc_queue_ack_o,
125126
input logic [ CsrDataWidth-1:0] csr_tti_tx_desc_queue_data_i,
@@ -722,6 +723,7 @@ module recovery_handler
722723
// T1MUX disconnects this FIFO from TTI logic
723724
logic exec_tti_tx_desc_queue_clr;
724725

726+
assign csr_tti_tx_desc_queue_full_o = tti_tx_desc_queue_full;
725727
assign csr_tti_tx_desc_queue_ack_o = tti_tx_desc_queue_ack;
726728
assign csr_tti_tx_desc_queue_reg_rst_we_o = tti_tx_desc_queue_reg_rst_we;
727729
assign csr_tti_tx_desc_queue_reg_rst_data_o = tti_tx_desc_queue_reg_rst_data;

verification/cocotb/block/hci_queues_ahb/hci_queues_wrapper.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ module hci_queues_wrapper
470470
.rx_desc_queue_reg_rst_o (csr_tti_rx_desc_queue_reg_rst),
471471
.rx_desc_queue_reg_rst_we_i (csr_tti_rx_desc_queue_reg_rst_we),
472472
.rx_desc_queue_reg_rst_data_i(csr_tti_rx_desc_queue_reg_rst_data),
473+
.rx_desc_queue_empty_i (tti_rx_desc_empty_o),
473474

474475
// TTI TX descriptors queue
475476
.tx_desc_queue_req_o (csr_tti_tx_desc_queue_req),
@@ -480,6 +481,7 @@ module hci_queues_wrapper
480481
.tx_desc_queue_reg_rst_o (csr_tti_tx_desc_queue_reg_rst),
481482
.tx_desc_queue_reg_rst_we_i (csr_tti_tx_desc_queue_reg_rst_we),
482483
.tx_desc_queue_reg_rst_data_i(csr_tti_tx_desc_queue_reg_rst_data),
484+
.tx_desc_queue_full_i (tti_tx_desc_full_o),
483485

484486
// TTI RX queue
485487
.rx_data_queue_req_o (csr_tti_rx_data_queue_req),
@@ -491,6 +493,7 @@ module hci_queues_wrapper
491493
.rx_data_queue_reg_rst_o (csr_tti_rx_data_queue_reg_rst),
492494
.rx_data_queue_reg_rst_we_i (csr_tti_rx_data_queue_reg_rst_we),
493495
.rx_data_queue_reg_rst_data_i(csr_tti_rx_data_queue_reg_rst_data),
496+
.rx_data_queue_empty_i (tti_rx_empty_o),
494497

495498
// TTI TX queue
496499
.tx_data_queue_req_o (csr_tti_tx_data_queue_req),
@@ -512,6 +515,7 @@ module hci_queues_wrapper
512515
.ibi_queue_reg_rst_o (csr_tti_ibi_queue_reg_rst),
513516
.ibi_queue_reg_rst_we_i (csr_tti_ibi_queue_reg_rst_we),
514517
.ibi_queue_reg_rst_data_i(csr_tti_ibi_queue_reg_rst_data),
518+
.ibi_queue_full_i (tti_ibi_full_o),
515519

516520
.bypass_i3c_core_i,
517521

verification/cocotb/block/hci_queues_axi/hci_queues_wrapper.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ module hci_queues_wrapper
542542
.rx_desc_queue_reg_rst_o (csr_tti_rx_desc_queue_reg_rst),
543543
.rx_desc_queue_reg_rst_we_i (csr_tti_rx_desc_queue_reg_rst_we),
544544
.rx_desc_queue_reg_rst_data_i(csr_tti_rx_desc_queue_reg_rst_data),
545+
.rx_desc_queue_empty_i (tti_rx_desc_empty_o),
545546

546547
// TTI TX descriptors queue
547548
.tx_desc_queue_req_o (csr_tti_tx_desc_queue_req),
@@ -552,6 +553,7 @@ module hci_queues_wrapper
552553
.tx_desc_queue_reg_rst_o (csr_tti_tx_desc_queue_reg_rst),
553554
.tx_desc_queue_reg_rst_we_i (csr_tti_tx_desc_queue_reg_rst_we),
554555
.tx_desc_queue_reg_rst_data_i(csr_tti_tx_desc_queue_reg_rst_data),
556+
.tx_desc_queue_full_i (tti_tx_desc_full_o),
555557

556558
// TTI RX queue
557559
.rx_data_queue_req_o (csr_tti_rx_data_queue_req),
@@ -563,6 +565,7 @@ module hci_queues_wrapper
563565
.rx_data_queue_reg_rst_o (csr_tti_rx_data_queue_reg_rst),
564566
.rx_data_queue_reg_rst_we_i (csr_tti_rx_data_queue_reg_rst_we),
565567
.rx_data_queue_reg_rst_data_i(csr_tti_rx_data_queue_reg_rst_data),
568+
.rx_data_queue_empty_i (tti_rx_empty_o),
566569

567570
// TTI TX queue
568571
.tx_data_queue_req_o (csr_tti_tx_data_queue_req),
@@ -584,6 +587,7 @@ module hci_queues_wrapper
584587
.ibi_queue_reg_rst_o (csr_tti_ibi_queue_reg_rst),
585588
.ibi_queue_reg_rst_we_i (csr_tti_ibi_queue_reg_rst_we),
586589
.ibi_queue_reg_rst_data_i(csr_tti_ibi_queue_reg_rst_data),
590+
.ibi_queue_full_i (tti_ibi_full_o),
587591

588592
.bypass_i3c_core_i,
589593

verification/cocotb/block/lib_hci_queues/test_read_write_ports.py

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -254,26 +254,6 @@ async def write_read_tti_tx_desc_queue(dut: SimHandleBase):
254254
await ClockCycles(tb.clk, 10)
255255

256256

257-
@cocotb.test()
258-
async def overflow_tti_tx_desc_queue(dut: SimHandleBase):
259-
"""
260-
Enqueue multiple transfers through COMMAND_PORT and verify
261-
whether the data matches after fetching it from the controller
262-
"""
263-
tb = TTIQueuesTestInterface(dut)
264-
await tb.setup()
265-
266-
data = [randint(1, 2**32 - 1) for _ in range(QUEUE_SIZE + TEST_SIZE)]
267-
await test_write(data[:-TEST_SIZE], tb.put_tx_desc)
268-
269-
write_coroutine = cocotb.start_soon(test_write(data[-TEST_SIZE:], tb.put_tx_desc))
270-
await ClockCycles(tb.clk, 10)
271-
272-
read_coroutine = cocotb.start_soon(test_read(data, tb.get_tx_desc))
273-
274-
await Combine(write_coroutine, read_coroutine)
275-
await ClockCycles(tb.clk, 10)
276-
277257

278258
@cocotb.test()
279259
async def underflow_tti_tx_desc_queue(dut: SimHandleBase):
@@ -307,27 +287,6 @@ async def write_read_tti_tx_queue(dut: SimHandleBase):
307287
await ClockCycles(tb.clk, 10)
308288

309289

310-
@cocotb.test()
311-
async def overflow_tti_tx_queue(dut: SimHandleBase):
312-
"""
313-
Place TX data through XFER_DATA_PORT (and overflow it) & verify it from the
314-
other (controller's) side of the queue
315-
"""
316-
tb = TTIQueuesTestInterface(dut)
317-
await tb.setup()
318-
319-
tx_data = [randint(1, 2**32 - 1) for _ in range(QUEUE_SIZE + TEST_SIZE)]
320-
await test_write(tx_data[:-TEST_SIZE], tb.put_tx_data)
321-
322-
write_coroutine = cocotb.start_soon(test_write(tx_data[-TEST_SIZE:], tb.put_tx_data))
323-
await ClockCycles(tb.clk, 10)
324-
325-
read_coroutine = cocotb.start_soon(test_read(tx_data, tb.get_tx_data))
326-
327-
await Combine(write_coroutine, read_coroutine)
328-
await ClockCycles(tb.clk, 10)
329-
330-
331290
@cocotb.test()
332291
async def underflow_tti_tx_queue(dut: SimHandleBase):
333292
"""
@@ -379,24 +338,6 @@ async def overflow_tti_rx_queue(dut: SimHandleBase):
379338
await ClockCycles(tb.clk, 10)
380339

381340

382-
@cocotb.test()
383-
async def underflow_tti_rx_queue(dut: SimHandleBase):
384-
"""
385-
Fetch data from RX Queue to cause underflow and write the data to ensure
386-
it's correct when available
387-
"""
388-
tb = TTIQueuesTestInterface(dut)
389-
await tb.setup()
390-
391-
rx_data = [randint(1, 2**32 - 1) for _ in range(TEST_SIZE)]
392-
read_coroutine = cocotb.start_soon(test_read(rx_data, tb.get_rx_data))
393-
await ClockCycles(tb.clk, 10)
394-
write_coroutine = cocotb.start_soon(test_write(rx_data, tb.put_rx_data))
395-
396-
await Combine(write_coroutine, read_coroutine)
397-
await ClockCycles(tb.clk, 10)
398-
399-
400341
@cocotb.test()
401342
async def fetch_response_from_tti_rx_desc_port(dut: SimHandleBase):
402343
"""
@@ -432,24 +373,6 @@ async def overflow_tti_rx_desc_queue(dut: SimHandleBase):
432373
await ClockCycles(tb.clk, 10)
433374

434375

435-
@cocotb.test()
436-
async def underflow_tti_rx_desc_queue(dut: SimHandleBase):
437-
"""
438-
Fetch data from Response Queue to cause underflow and write the data to ensure
439-
it's correct when available
440-
"""
441-
tb = TTIQueuesTestInterface(dut)
442-
await tb.setup()
443-
444-
data = [randint(1, 2**32 - 1) for _ in range(TEST_SIZE)]
445-
read_coroutine = cocotb.start_soon(test_read(data, tb.get_rx_desc))
446-
await ClockCycles(tb.clk, 10)
447-
write_coroutine = cocotb.start_soon(test_write(data, tb.put_rx_desc))
448-
449-
await Combine(write_coroutine, read_coroutine)
450-
await ClockCycles(tb.clk, 10)
451-
452-
453376
@cocotb.test()
454377
async def write_read_ibi_queue(dut: SimHandleBase):
455378
"""
@@ -463,26 +386,6 @@ async def write_read_ibi_queue(dut: SimHandleBase):
463386
await ClockCycles(tb.clk, 10)
464387

465388

466-
@cocotb.test()
467-
async def overflow_ibi_queue(dut: SimHandleBase):
468-
"""
469-
Put read data onto the IBI queue (and overflow it) & fetch it through IBI_PORT
470-
"""
471-
tb = HCIQueuesTestInterface(dut)
472-
await tb.setup()
473-
474-
ibi_data = [randint(1, 2**32 - 1) for _ in range(QUEUE_SIZE + TEST_SIZE)]
475-
await test_write(ibi_data[:-TEST_SIZE], tb.put_ibi_data)
476-
477-
write_coroutine = cocotb.start_soon(test_write(ibi_data[-TEST_SIZE:], tb.put_ibi_data))
478-
await ClockCycles(tb.clk, 10)
479-
480-
read_coroutine = cocotb.start_soon(test_read(ibi_data, tb.get_ibi_data))
481-
482-
await Combine(write_coroutine, read_coroutine)
483-
await ClockCycles(tb.clk, 10)
484-
485-
486389
@cocotb.test()
487390
async def underflow_ibi_queue(dut: SimHandleBase):
488391
"""

verification/cocotb/block/lib_hci_queues/tti_queues.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ async def setup(self):
3131
self.dut.tti_tx_flush_i.value = 0
3232
self.dut.bypass_i3c_core_i.value = 0
3333

34+
if hasattr(self.dut, "disable_id_filtering_i"):
35+
self.dut.disable_id_filtering_i.value = 1
36+
3437
await super()._setup(get_frontend_bus_if())
3538

3639
async def reset(self):

0 commit comments

Comments
 (0)