diff --git a/Bender.yml b/Bender.yml index d43acd106..3c5df43ce 100644 --- a/Bender.yml +++ b/Bender.yml @@ -113,6 +113,7 @@ sources: # Level 1 - test/tb_axi_addr_test.sv - test/tb_axi_atop_filter.sv + - test/tb_axi_burst_unwrap.sv - test/tb_axi_bus_compare.sv - test/tb_axi_cdc.sv - test/tb_axi_delayer.sv diff --git a/Makefile b/Makefile index 5d97a9542..1e87c5822 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ endif TBS ?= axi_addr_test \ axi_atop_filter \ + axi_burst_unwrap \ axi_cdc axi_delayer \ axi_dw_downsizer \ axi_dw_upsizer \ diff --git a/src/axi_burst_unwrap.sv b/src/axi_burst_unwrap.sv index 427c6c278..e4140c8e6 100644 --- a/src/axi_burst_unwrap.sv +++ b/src/axi_burst_unwrap.sv @@ -465,12 +465,15 @@ module axi_burst_unwrap_ax_chan #( chan_t ax_d, ax_q; logic [10:0] container_size; + logic [AddrWidth-1:0] aligned_addr; logic [AddrWidth-1:0] wrap_boundary; // The total size of this burst (beat_size * burst_length) assign container_size = (ax_i.len + 1) << ax_i.size; // For wrapping bursts, this returns the wrap boundary (container size is power of two according to A.3.4.1) assign wrap_boundary = ax_i.addr & ~(AddrWidth'(container_size) - 1); + // Aligned address of the first transfer + assign aligned_addr = (ax_i.addr >> ax_i.size) << ax_i.size; enum logic {Idle, Busy} state_d, state_q; always_comb begin @@ -484,22 +487,22 @@ module axi_burst_unwrap_ax_chan #( unique case (state_q) Idle: begin if (ax_valid_i && &cnt_alloc_gnt) begin - if (ax_i.burst == axi_pkg::BURST_WRAP && ax_i.addr != wrap_boundary) begin // Splitting required. + if (ax_i.burst == axi_pkg::BURST_WRAP && aligned_addr != wrap_boundary) begin // Splitting required. // Store Ax, allocate a counter, and acknowledge upstream. ax_d = ax_i; ax_d.burst = axi_pkg::BURST_INCR; split_len = 8'd1; - // Allocate second counter only for AwChan - cnt_alloc_req = { AwChan, 1'b1 }; // Try to feed first burst through. ax_o = ax_d; // First (this) incr burst from addr to wrap boundary + container size - ax_o.len = ((wrap_boundary + container_size - ax_i.addr) >> ax_i.size) - 1; + ax_o.len = ((wrap_boundary + container_size - aligned_addr) >> ax_i.size) - 1; // Next incr burst from wrap boundary to addr - ax_d.len = ((ax_i.addr - wrap_boundary) >> ax_i.size) - 1; + ax_d.len = ((aligned_addr - wrap_boundary) >> ax_i.size) - 1; ax_d.addr = wrap_boundary; ax_valid_o = 1'b1; if (ax_ready_i) begin + // Allocate second counter only for AwChan + cnt_alloc_req = { AwChan, 1'b1 }; ax_ready_o = 1'b1; state_d = Busy; end @@ -519,7 +522,7 @@ module axi_burst_unwrap_ax_chan #( end end Busy: begin - // Sent next burst from split. + // Send next burst from split. ax_o = ax_q; ax_valid_o = 1'b1; if (ax_ready_i) begin diff --git a/src/axi_test.sv b/src/axi_test.sv index ce8638343..dbff4bc38 100644 --- a/src/axi_test.sv +++ b/src/axi_test.sv @@ -2006,7 +2006,7 @@ package axi_test; wait (this.aw_sample.size() > 0); aw_beat = this.aw_sample.pop_front(); // This scoreborad only supports this type of burst: - assert (aw_beat.ax_burst == axi_pkg::BURST_INCR || aw_beat.ax_len == '0) else + assert (aw_beat.ax_burst inside {axi_pkg::BURST_INCR, axi_pkg::BURST_WRAP} || aw_beat.ax_len == '0) else $warning("Not supported AW burst: BURST: %0h.", aw_beat.ax_burst); assert (aw_beat.ax_atop == '0) else $warning("Atomic transfers not supported: ATOP: %0h.", aw_beat.ax_atop); @@ -2016,7 +2016,7 @@ package axi_test; beat_addresses[i] = axi_pkg::beat_addr(aw_beat.ax_addr, aw_beat.ax_size, aw_beat.ax_len, aw_beat.ax_burst, i); bus_address = axi_pkg::aligned_addr(beat_addresses[i], BUS_SIZE); - // Check if the memory array is initialyzed at this beat address (aligned on the bus) + // Check if the memory array is initialized at this beat address (aligned on the bus) if (!this.memory_q.exists(bus_address)) begin for (int unsigned j = 0; j < axi_pkg::num_bytes(BUS_SIZE); j++) begin this.memory_q[bus_address+j].push_back(8'bxxxxxxxx); @@ -2082,7 +2082,7 @@ package axi_test; wait (this.ar_sample[id].size() > 0); ar_beat = this.ar_sample[id].pop_front(); // This scoreborad only supports this type of burst: - assert (ar_beat.ax_burst == axi_pkg::BURST_INCR || ar_beat.ax_len == '0) else + assert (ar_beat.ax_burst inside {axi_pkg::BURST_INCR, axi_pkg::BURST_WRAP} || ar_beat.ax_len == '0) else $warning("Not supported AR burst: BURST: %0h.", ar_beat.ax_burst); for (int unsigned i = 0; i <= ar_beat.ax_len; i++) begin