From 28a740170c433a4668fff86cbcca1ec7ef025d08 Mon Sep 17 00:00:00 2001 From: gbellocchi Date: Fri, 3 Jul 2026 13:25:56 +0200 Subject: [PATCH 1/2] hw: Assign obi rsp in all control paths Fix verilator latch warning due to partial assignment of rw obi responses. --- src/frontend/inst64/idma_inst64_top.sv | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/frontend/inst64/idma_inst64_top.sv b/src/frontend/inst64/idma_inst64_top.sv index 7feff716..731bdb74 100644 --- a/src/frontend/inst64/idma_inst64_top.sv +++ b/src/frontend/inst64/idma_inst64_top.sv @@ -327,10 +327,9 @@ module idma_inst64_top #( ); always_comb begin : gen_obi_response - if (obi_we_q[c]) begin - obi_write_rsp[c].r = obi_res_i[c].r; - end else begin - obi_read_rsp[c].r = obi_res_i[c].r; + assign obi_write_rsp[c].r = obi_res_i[c].r; + assign obi_read_rsp[c].r = obi_res_i[c].r; + end end end From 31c1c6d63e65a537196f39f991872f7cf73fa11d Mon Sep 17 00:00:00 2001 From: gbellocchi Date: Fri, 3 Jul 2026 13:30:36 +0200 Subject: [PATCH 2/2] hw: Extend idma busy condition with axi write completion The per-channel `busy` signal deasserted once the last AXI write beat was *issued*, not once its `B` response was received. Since a subset of Snitch API polls this `busy` signal, Snitch could proceed before the write had actually completed at its destination. Extend the condition so a channel is busy while: (i) the iDMA backend or ND midend are busy, or (ii) at least one issued AXI write is still awaiting its `B` response. A per-channel counter tracks outstanding writes and increments on each `AW` handshake and decrements on each `B` handshake. --- src/frontend/inst64/idma_inst64_top.sv | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/frontend/inst64/idma_inst64_top.sv b/src/frontend/inst64/idma_inst64_top.sv index 731bdb74..e8156e7d 100644 --- a/src/frontend/inst64/idma_inst64_top.sv +++ b/src/frontend/inst64/idma_inst64_top.sv @@ -73,6 +73,7 @@ module idma_inst64_top #( localparam int unsigned NumDim = 32'd2; localparam int unsigned BufferDepth = 32'd3; localparam int unsigned NumRules = 32'd5; + localparam int unsigned AwInFlightCntWidth = (NumAxInFlight < 2) ? 32'd1 : $clog2(NumAxInFlight + 1); // derived constants and types localparam int unsigned StrbWidth = AxiDataWidth / 32'd8; @@ -330,10 +331,23 @@ module idma_inst64_top #( assign obi_write_rsp[c].r = obi_res_i[c].r; assign obi_read_rsp[c].r = obi_res_i[c].r; end + + logic [AwInFlightCntWidth-1:0] aw_inflight_q; // outstanding write counter + logic aw_hs, b_hs; // handshake signals + assign aw_hs = axi_req_o[c].aw_valid & axi_res_i[c].aw_ready; + assign b_hs = axi_res_i[c].b_valid & axi_req_o[c].b_ready; + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_aw_inflight + if (!rst_ni) begin + aw_inflight_q <= '0; + end else if (aw_hs & ~b_hs) begin + aw_inflight_q <= aw_inflight_q + 1'b1; + end else if (b_hs & ~aw_hs) begin + aw_inflight_q <= aw_inflight_q - 1'b1; end end - assign busy_o[c] = (|idma_busy[c]) | idma_nd_busy[c]; + // Keep the channel busy until the iDMA backend or midend are busy, or until there's at least one AXI B response to be received. + assign busy_o[c] = (|idma_busy[c]) | idma_nd_busy[c] | (aw_inflight_q != '0); end