1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Fix unaligned operation handling in AXI adapter

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich 2023-01-26 12:58:03 -08:00
parent 3dc4ca92f6
commit 211f674603
2 changed files with 29 additions and 47 deletions

View File

@ -465,11 +465,11 @@ always @* begin
burst_size_next = s_axi_arsize;
if (s_axi_arsize > M_BURST_SIZE) begin
// need to adjust burst size
if ({s_axi_arlen, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_BURST_SIZE-s_axi_arsize) > 255) begin
if (s_axi_arlen >> (8+M_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-M_BURST_SIZE)) | ((~s_axi_araddr & (8'hff >> (8-s_axi_arsize))) >> M_BURST_SIZE);
end else begin
master_burst_next = {s_axi_arlen, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_BURST_SIZE-s_axi_arsize);
master_burst_next = (s_axi_arlen << (s_axi_arsize-M_BURST_SIZE)) | ((~s_axi_araddr & (8'hff >> (8-s_axi_arsize))) >> M_BURST_SIZE);
end
master_burst_size_next = M_BURST_SIZE;
m_axi_arlen_next = master_burst_next;
@ -510,13 +510,22 @@ always @* begin
s_axi_ruser_int = m_axi_ruser;
s_axi_rvalid_int = 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_axi_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_int = 1'b1;
end
if (master_burst_reg == 0) begin
if (burst_next >> (8+M_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-M_BURST_SIZE)) | (8'hff >> (8-burst_size_reg) >> M_BURST_SIZE);
end
m_axi_arlen_next = master_burst_next;
if (burst_reg == 0) begin
m_axi_rready_next = 1'b0;
s_axi_rlast_int = 1'b1;
@ -525,25 +534,6 @@ always @* begin
state_next = STATE_IDLE;
end else begin
// start new burst
m_axi_araddr_next = addr_next;
if (burst_size_reg > M_BURST_SIZE) begin
// need to adjust burst size
if ({burst_next, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_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, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_BURST_SIZE-burst_size_reg);
end
master_burst_size_next = M_BURST_SIZE;
m_axi_arlen_next = master_burst_next;
m_axi_arsize_next = master_burst_size_next;
end else begin
// pass through narrow (enough) burst
master_burst_next = burst_next;
master_burst_size_next = burst_size_reg;
m_axi_arlen_next = burst_next;
m_axi_arsize_next = burst_size_reg;
end
m_axi_arvalid_next = 1'b1;
m_axi_rready_next = 1'b0;
state_next = STATE_DATA;

View File

@ -511,11 +511,11 @@ always @* begin
burst_active_next = 1'b1;
if (s_axi_awsize > M_BURST_SIZE) begin
// need to adjust burst size
if ({s_axi_awlen, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_BURST_SIZE-s_axi_awsize) > 255) begin
if (s_axi_awlen >> (8+M_BURST_SIZE-s_axi_awsize) != 0) begin
// limit burst length to max
master_burst_next = 8'd255;
master_burst_next = (8'd255 << (s_axi_awsize-M_BURST_SIZE)) | ((~s_axi_awaddr & (8'hff >> (8-s_axi_awsize))) >> M_BURST_SIZE);
end else begin
master_burst_next = {s_axi_awlen, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_BURST_SIZE-s_axi_awsize);
master_burst_next = (s_axi_awlen << (s_axi_awsize-M_BURST_SIZE)) | ((~s_axi_awaddr & (8'hff >> (8-s_axi_awsize))) >> M_BURST_SIZE);
end
master_burst_size_next = M_BURST_SIZE;
m_axi_awlen_next = master_burst_next;
@ -556,7 +556,7 @@ always @* begin
burst_next = burst_reg - 1;
burst_active_next = burst_reg != 0;
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);
if (master_burst_reg == 0) begin
s_axi_wready_next = 1'b0;
m_axi_bready_next = !s_axi_bvalid && !s_axi_awvalid;
@ -582,7 +582,7 @@ always @* begin
m_axi_wuser_int = wuser_reg;
m_axi_wvalid_int = 1'b1;
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);
if (master_burst_reg == 0) begin
// burst on master interface finished; transfer response
s_axi_wready_next = 1'b0;
@ -610,27 +610,19 @@ always @* begin
if (first_transfer_reg || m_axi_bresp != 0) begin
s_axi_bresp_next = m_axi_bresp;
end
if (burst_reg >> (8+M_BURST_SIZE-burst_size_reg) != 0) begin
// limit burst length to max
master_burst_next = 8'd255;
end else begin
master_burst_next = (burst_reg << (burst_size_reg-M_BURST_SIZE)) | (8'hff >> (8-burst_size_reg) >> M_BURST_SIZE);
end
master_burst_size_next = M_BURST_SIZE;
m_axi_awaddr_next = addr_reg;
m_axi_awlen_next = master_burst_next;
m_axi_awsize_next = master_burst_size_next;
if (burst_active_reg) begin
// burst on slave interface still active; start new burst
m_axi_awaddr_next = addr_reg;
if (burst_size_reg > M_BURST_SIZE) begin
// need to adjust burst size
if ({burst_reg, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_BURST_SIZE-burst_size_reg) > 255) begin
// limit burst length to max
master_burst_next = 8'd255;
end else begin
master_burst_next = {burst_reg, {S_BURST_SIZE-M_BURST_SIZE{1'b1}}} >> (S_BURST_SIZE-burst_size_reg);
end
master_burst_size_next = M_BURST_SIZE;
m_axi_awlen_next = master_burst_next;
m_axi_awsize_next = master_burst_size_next;
end else begin
// pass through narrow (enough) burst
master_burst_next = burst_reg;
master_burst_size_next = burst_size_reg;
m_axi_awlen_next = burst_reg;
m_axi_awsize_next = burst_size_reg;
end
m_axi_awvalid_next = 1'b1;
state_next = STATE_DATA;
end else begin