[axi4-bridge] allow back-to-back (atomic) transfers

This commit is contained in:
stnolting 2025-01-18 22:43:24 +01:00
parent 71d22cd5a6
commit 041f9d61a3

View file

@ -1,16 +1,15 @@
-- ================================================================================ --
-- NEORV32 SoC - XBUS to AXI4-Lite Bridge (single non-overlapping transfers only) --
-- NEORV32 SoC - XBUS to AXI4-Lite Bridge --
-- -------------------------------------------------------------------------------- --
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
-- Copyright (c) NEORV32 contributors. --
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
-- SPDX-License-Identifier: BSD-3-Clause --
-- ================================================================================ --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity xbus2axi4lite_bridge is
port (
@ -57,8 +56,7 @@ end entity;
architecture xbus2axi4lite_bridge_rtl of xbus2axi4lite_bridge is
signal ready : std_ulogic_vector(2 downto 0);
signal xbus_rd_ack, xbus_rd_err, xbus_wr_ack, xbus_wr_err : std_ulogic;
signal arvalid, awvalid, wvalid, xbus_rd_ack, xbus_rd_err, xbus_wr_ack, xbus_wr_err : std_ulogic;
begin
@ -66,21 +64,24 @@ begin
axi_handshake: process(resetn, clk)
begin
if (resetn = '0') then
ready <= (others => '0');
arvalid <= '0';
awvalid <= '0';
wvalid <= '0';
elsif rising_edge(clk) then
ready(0) <= xbus_cyc_i and (ready(0) or std_ulogic(m_axi_arready));
ready(1) <= xbus_cyc_i and (ready(1) or std_ulogic(m_axi_awready));
ready(2) <= xbus_cyc_i and (ready(2) or std_ulogic(m_axi_wready));
-- /------------- Set ------------\ /-------- Hold -------\ /---------- Clear ----------\
arvalid <= (xbus_stb_i and (not xbus_we_i)) or (arvalid and xbus_cyc_i and std_ulogic(not m_axi_arready));
awvalid <= (xbus_stb_i and ( xbus_we_i)) or (awvalid and xbus_cyc_i and std_ulogic(not m_axi_awready));
wvalid <= (xbus_stb_i and ( xbus_we_i)) or (wvalid and xbus_cyc_i and std_ulogic(not m_axi_wready));
end if;
end process axi_handshake;
-- AXI read address channel --
m_axi_araddr <= std_logic_vector(xbus_adr_i);
m_axi_arprot <= std_logic_vector(xbus_tag_i);
m_axi_arvalid <= std_logic(xbus_cyc_i and (not xbus_we_i) and (not ready(0)));
m_axi_arvalid <= std_logic(arvalid);
-- AXI read data channel --
m_axi_rready <= std_logic(xbus_cyc_i and (not xbus_we_i));
m_axi_rready <= '1';
xbus_dat_o <= std_ulogic_vector(m_axi_rdata);
xbus_rd_ack <= '1' when (m_axi_rvalid = '1') and (m_axi_rresp = "00") else '0';
xbus_rd_err <= '1' when (m_axi_rvalid = '1') and (m_axi_rresp /= "00") else '0';
@ -88,20 +89,20 @@ begin
-- AXI write address channel --
m_axi_awaddr <= std_logic_vector(xbus_adr_i);
m_axi_awprot <= std_logic_vector(xbus_tag_i);
m_axi_awvalid <= std_logic(xbus_cyc_i and xbus_we_i and (not ready(1)));
m_axi_awvalid <= std_logic(awvalid);
-- AXI write data channel --
m_axi_wdata <= std_logic_vector(xbus_dat_i);
m_axi_wstrb <= std_logic_vector(xbus_sel_i);
m_axi_wvalid <= std_logic(xbus_cyc_i and xbus_we_i and (not ready(2)));
m_axi_wvalid <= std_logic(wvalid);
-- AXI write response channel --
m_axi_bready <= std_logic(xbus_cyc_i and xbus_we_i);
m_axi_bready <= '1';
xbus_wr_ack <= '1' when (m_axi_bvalid = '1') and (m_axi_bresp = "00") else '0';
xbus_wr_err <= '1' when (m_axi_bvalid = '1') and (m_axi_bresp /= "00") else '0';
-- XBUS response --
xbus_ack_o <= xbus_rd_ack when (xbus_we_i = '0') else xbus_wr_ack;
xbus_err_o <= xbus_rd_err when (xbus_we_i = '0') else xbus_wr_err;
xbus_ack_o <= xbus_rd_ack or xbus_wr_ack;
xbus_err_o <= xbus_rd_err or xbus_wr_err;
end architecture xbus2axi4lite_bridge_rtl;