From 7b2c99e73174f3d09acdbd6061db97fb8609e743 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Thu, 26 Jan 2023 12:58:39 -0800 Subject: [PATCH] Fix unaligned operation handling in AXI to AXIL adapter Signed-off-by: Alex Forencich --- rtl/axi_axil_adapter_rd.v | 33 ++++++++++++--------------------- rtl/axi_axil_adapter_wr.v | 6 +++--- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/rtl/axi_axil_adapter_rd.v b/rtl/axi_axil_adapter_rd.v index 9e029fb..8faf535 100644 --- a/rtl/axi_axil_adapter_rd.v +++ b/rtl/axi_axil_adapter_rd.v @@ -388,11 +388,11 @@ always @* begin burst_size_next = s_axi_arsize; if (s_axi_arsize > AXIL_BURST_SIZE) begin // need to adjust burst size - if ({s_axi_arlen, {AXI_BURST_SIZE-AXIL_BURST_SIZE{1'b1}}} >> (AXI_BURST_SIZE-s_axi_arsize) > 255) begin + if (s_axi_arlen >> (8+AXIL_BURST_SIZE-s_axi_arsize) != 0) begin // limit burst length to max - master_burst_next = 8'd255; + master_burst_next = (8'd255 << (s_axi_arsize-AXIL_BURST_SIZE)) | ((~s_axi_araddr & (8'hff >> (8-s_axi_arsize))) >> AXIL_BURST_SIZE); end else begin - master_burst_next = {s_axi_arlen, {AXI_BURST_SIZE-AXIL_BURST_SIZE{1'b1}}} >> (AXI_BURST_SIZE-s_axi_arsize); + master_burst_next = (s_axi_arlen << (s_axi_arsize-AXIL_BURST_SIZE)) | ((~s_axi_araddr & (8'hff >> (8-s_axi_arsize))) >> AXIL_BURST_SIZE); end master_burst_size_next = AXIL_BURST_SIZE; end else begin @@ -422,13 +422,21 @@ always @* begin s_axi_rlast_next = 1'b0; s_axi_rvalid_next = 1'b0; master_burst_next = master_burst_reg - 1; - addr_next = addr_reg + (1 << master_burst_size_reg); + addr_next = (addr_reg + (1 << master_burst_size_reg)) & ({ADDR_WIDTH{1'b1}} << master_burst_size_reg); + m_axil_araddr_next = addr_next; if (addr_next[burst_size_reg] != addr_reg[burst_size_reg]) begin data_next = {DATA_WIDTH{1'b0}}; burst_next = burst_reg - 1; s_axi_rvalid_next = 1'b1; end if (master_burst_reg == 0) begin + if (burst_next >> (8+AXIL_BURST_SIZE-burst_size_reg) != 0) begin + // limit burst length to max + master_burst_next = 8'd255; + end else begin + master_burst_next = (burst_next << (burst_size_reg-AXIL_BURST_SIZE)) | (8'hff >> (8-burst_size_reg) >> AXIL_BURST_SIZE); + end + if (burst_reg == 0) begin m_axil_rready_next = 1'b0; s_axi_rlast_next = 1'b1; @@ -436,28 +444,11 @@ always @* begin s_axi_arready_next = !m_axil_arvalid; state_next = STATE_IDLE; end else begin - // start new burst - m_axil_araddr_next = addr_next; - if (burst_size_reg > AXIL_BURST_SIZE) begin - // need to adjust burst size - if ({burst_next, {AXI_BURST_SIZE-AXIL_BURST_SIZE{1'b1}}} >> (AXI_BURST_SIZE-burst_size_reg) > 255) begin - // limit burst length to max - master_burst_next = 8'd255; - end else begin - master_burst_next = {burst_next, {AXI_BURST_SIZE-AXIL_BURST_SIZE{1'b1}}} >> (AXI_BURST_SIZE-burst_size_reg); - end - master_burst_size_next = AXIL_BURST_SIZE; - end else begin - // pass through narrow (enough) burst - master_burst_next = burst_next; - master_burst_size_next = burst_size_reg; - end m_axil_arvalid_next = 1'b1; m_axil_rready_next = 1'b0; state_next = STATE_DATA; end end else begin - m_axil_araddr_next = addr_next; m_axil_arvalid_next = 1'b1; m_axil_rready_next = 1'b0; state_next = STATE_DATA; diff --git a/rtl/axi_axil_adapter_wr.v b/rtl/axi_axil_adapter_wr.v index fc65365..52d4be2 100644 --- a/rtl/axi_axil_adapter_wr.v +++ b/rtl/axi_axil_adapter_wr.v @@ -456,7 +456,7 @@ always @* begin m_axil_wvalid_next = 1'b1; burst_next = burst_reg - 1; burst_active_next = burst_reg != 0; - addr_next = addr_reg + (1 << master_burst_size_reg); + addr_next = (addr_reg + (1 << master_burst_size_reg)) & ({ADDR_WIDTH{1'b1}} << master_burst_size_reg); last_segment_next = addr_next[burst_size_reg] != addr_reg[burst_size_reg]; s_axi_wready_next = 1'b0; m_axil_bready_next = !s_axi_bvalid && !m_axil_awvalid; @@ -472,7 +472,7 @@ always @* begin m_axil_wdata_next = data_reg >> (addr_reg[AXI_ADDR_BIT_OFFSET-1:AXIL_ADDR_BIT_OFFSET] * AXIL_DATA_WIDTH); m_axil_wstrb_next = strb_reg >> (addr_reg[AXI_ADDR_BIT_OFFSET-1:AXIL_ADDR_BIT_OFFSET] * AXIL_STRB_WIDTH); m_axil_wvalid_next = 1'b1; - addr_next = addr_reg + (1 << master_burst_size_reg); + addr_next = (addr_reg + (1 << master_burst_size_reg)) & ({ADDR_WIDTH{1'b1}} << master_burst_size_reg); last_segment_next = addr_next[burst_size_reg] != addr_reg[burst_size_reg]; s_axi_wready_next = 1'b0; m_axil_bready_next = !s_axi_bvalid && !m_axil_awvalid; @@ -487,6 +487,7 @@ always @* begin if (m_axil_bready && m_axil_bvalid) begin first_transfer_next = 1'b0; + m_axil_awaddr_next = addr_reg; m_axil_bready_next = 1'b0; s_axi_bid_next = id_reg; if (first_transfer_reg || m_axil_bresp != 0) begin @@ -494,7 +495,6 @@ always @* begin end if (burst_active_reg || !last_segment_reg) begin // burst on slave interface still active; start new burst - m_axil_awaddr_next = addr_reg; m_axil_awvalid_next = 1'b1; if (last_segment_reg) begin s_axi_wready_next = !m_axil_wvalid;