Skip to content
Snippets Groups Projects
Commit f05ffeac authored by Michael Munch's avatar Michael Munch
Browse files

Working on AXI VME bridge.

parent 0e87e37d
No related branches found
No related tags found
No related merge requests found
Pipeline #14037 failed
......@@ -6,7 +6,7 @@ depth 20
smtbmc z3
[script]
ghdl -fpsl --std=08 -gformal=true axi_vme_pkg.vhd axi_vme_mapper.vhd axi_vme_config.vhd axi_vme_bridge.vhd -e axi_vme_bridge
ghdl -fpsl --std=08 -gformal=true axi_vme_bridge.vhd -e axi_vme_bridge
prep -top axi_vme_bridge
[files]
......
......@@ -2,167 +2,241 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.axi_vme_pkg.all;
entity axi_vme_bridge is
generic (
-- Size of a single VME window
C_VME_WINDOW_WIDTH : integer := 20;
-- 2^N VME windows.
C_N_VME_WINDOWS : integer := 9;
-- Configuration AXI interface
C_S00_AXI_DATA_WIDTH : integer := 32;
C_S00_AXI_ADDR_WIDTH : integer := C_N_VME_WINDOWS + 1;
C_VME_WINDOW_SIZE : integer := 20;
C_N_VME_WINDOWS : integer := 10;
-- AXI -> VME mapping
C_S01_AXI_DATA_WIDTH : integer := 32;
C_S01_AXI_ADDR_WIDTH : integer := C_VME_WINDOW_WIDTH + C_N_VME_WINDOWS + 1
);
C_S00_AXI_DATA_WIDTH : integer := 32;
C_S00_AXI_ADDR_WIDTH : integer := C_N_VME_WINDOWS + 2
);
port (
-- Global Clock Signal
S00_AXI_ACLK : in std_logic;
S_AXI_ACLK : in std_logic;
-- Global Reset Signal. This Signal is Active LOW
S00_AXI_ARESETN : in std_logic;
S_AXI_ARESETN : in std_logic;
-- Write address channel.
S00_AXI_AWADDR : in std_logic_vector(31 downto 0);
S00_AXI_AWPROT : in std_logic_vector(2 downto 0);
S00_AXI_AWVALID : in std_logic;
S00_AXI_AWREADY : out std_logic;
S_AXI_AWADDR : in std_logic_vector(31 downto 0);
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
-- Write data channel.
S00_AXI_WDATA : in std_logic_vector(31 downto 0);
S00_AXI_WSTRB : in std_logic_vector(3 downto 0);
S00_AXI_WVALID : in std_logic;
S00_AXI_WREADY : out std_logic;
S_AXI_WDATA : in std_logic_vector(31 downto 0);
S_AXI_WSTRB : in std_logic_vector(3 downto 0);
S_AXI_WVALID : in std_logic;
S_AXI_WREADY : out std_logic;
-- Write response channel.
S00_AXI_BRESP : out std_logic_vector(1 downto 0);
S00_AXI_BVALID : out std_logic;
S00_AXI_BREADY : in std_logic;
S_AXI_BRESP : out std_logic_vector(1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
-- Read address channel.
S00_AXI_ARADDR : in std_logic_vector(31 downto 0);
S00_AXI_ARPROT : in std_logic_vector(2 downto 0);
S00_AXI_ARVALID : in std_logic;
S00_AXI_ARREADY : out std_logic;
S_AXI_ARADDR : in std_logic_vector(31 downto 0);
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
-- Read data channel.
S00_AXI_RDATA : out std_logic_vector(31 downto 0);
S00_AXI_RRESP : out std_logic_vector(1 downto 0);
S00_AXI_RVALID : out std_logic;
S00_AXI_RREADY : in std_logic;
S_AXI_RDATA : out std_logic_vector(31 downto 0);
S_AXI_RRESP : out std_logic_vector(1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic
);
end axi_vme_bridge;
-- Global Clock Signal
S01_AXI_ACLK : in std_logic;
-- Global Reset Signal. This Signal is Active LOW
S01_AXI_ARESETN : in std_logic;
architecture RTL of axi_vme_bridge is
-- signal axi_awaddr : std_logic_vector(31 downto 0);
signal axi_awready : std_logic;
signal axi_wready : std_logic;
signal axi_bresp : std_logic_vector(1 downto 0);
signal axi_bvalid : std_logic;
--signal axi_araddr : std_logic_vector(31 downto 0);
signal axi_arready : std_logic;
signal axi_rdata : std_logic_vector(31 downto 0);
signal axi_rresp : std_logic_vector(1 downto 0);
signal axi_rvalid : std_logic;
-- Write address channel.
S01_AXI_AWADDR : in std_logic_vector(31 downto 0);
S01_AXI_AWPROT : in std_logic_vector(2 downto 0);
S01_AXI_AWVALID : in std_logic;
S01_AXI_AWREADY : out std_logic;
-- Write data channel.
S01_AXI_WDATA : in std_logic_vector(31 downto 0);
S01_AXI_WSTRB : in std_logic_vector(3 downto 0);
S01_AXI_WVALID : in std_logic;
S01_AXI_WREADY : out std_logic;
signal init_sequence : std_logic;
-- Write response channel.
S01_AXI_BRESP : out std_logic_vector(1 downto 0);
S01_AXI_BVALID : out std_logic;
S01_AXI_BREADY : in std_logic;
-- Read address channel.
S01_AXI_ARADDR : in std_logic_vector(31 downto 0);
S01_AXI_ARPROT : in std_logic_vector(2 downto 0);
S01_AXI_ARVALID : in std_logic;
S01_AXI_ARREADY : out std_logic;
signal addr_latch : std_logic_vector(C_N_VME_WINDOWS + 2 downto 2);
-- Read data channel.
S01_AXI_RDATA : out std_logic_vector(31 downto 0);
S01_AXI_RRESP : out std_logic_vector(1 downto 0);
S01_AXI_RVALID : out std_logic;
S01_AXI_RREADY : in std_logic
);
end axi_vme_bridge;
architecture RTL of axi_vme_bridge is
subtype ram_index_t is natural range 0 to 2**C_N_VME_WINDOWS-1;
type ram_t is array (0 to 2**C_N_VME_WINDOWS-1)
of std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
signal ram : ram_t := (others => (others => '0'));
-- BRAM values for config
-- BRAM index
signal ram_config_i : ram_index_t := 0;
-- Value read
signal ram_config_read : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
-- Value to write
signal ram_config_write : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
-- Write enable
signal ram_config_we : std_logic := '0';
-- BRAM values for mapper
-- BRAM index
signal ram_mapper_i : ram_index_t := 0;
-- Value read
signal ram_mapper_read : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
-- Value to write
signal ram_mapper_write : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
-- Write enable
signal ram_mapper_we : std_logic := '0';
signal read_ready0 : std_logic := '0';
signal read_ready1 : std_logic := '0';
begin
config : entity work.axi_vme_config
port map (
-- Global Clock Signal
S_AXI_ACLK => S00_AXI_ACLK,
-- Global Reset Signal. This Signal is Active LOW
S_AXI_ARESETN => S00_AXI_ARESETN,
-- Write address channel.
S_AXI_AWADDR => S00_AXI_AWADDR,
S_AXI_AWPROT => S00_AXI_AWPROT,
S_AXI_AWVALID => S00_AXI_AWVALID,
S_AXI_AWREADY => S00_AXI_AWREADY,
-- Write data channel.
S_AXI_WDATA => S00_AXI_WDATA,
S_AXI_WSTRB => S00_AXI_WSTRB,
S_AXI_WVALID => S00_AXI_WVALID,
S_AXI_WREADY => S00_AXI_WREADY,
-- Write response channel.
S_AXI_BRESP => S00_AXI_BRESP,
S_AXI_BVALID => S00_AXI_BVALID,
S_AXI_BREADY => S00_AXI_BREADY,
-- Read address channel.
S_AXI_ARADDR => S00_AXI_ARADDR,
S_AXI_ARPROT => S00_AXI_ARPROT,
S_AXI_ARVALID => S00_AXI_ARVALID,
S_AXI_ARREADY => S00_AXI_ARREADY,
-- Read data channel.
S_AXI_RDATA => S00_AXI_RDATA,
S_AXI_RRESP => S00_AXI_RRESP,
S_AXI_RVALID => S00_AXI_RVALID,
S_AXI_RREADY => S00_AXI_RREADY,
ram => ram
);
mapper : entity work.axi_vme_mapper
port map (
-- Global Clock Signal
S_AXI_ACLK => S01_AXI_ACLK,
-- Global Reset Signal. This Signal is Active LOW
S_AXI_ARESETN => S01_AXI_ARESETN,
-- Write address channel.
S_AXI_AWADDR => S01_AXI_AWADDR,
S_AXI_AWPROT => S01_AXI_AWPROT,
S_AXI_AWVALID => S01_AXI_AWVALID,
S_AXI_AWREADY => S01_AXI_AWREADY,
-- Write data channel.
S_AXI_WDATA => S01_AXI_WDATA,
S_AXI_WSTRB => S01_AXI_WSTRB,
S_AXI_WVALID => S01_AXI_WVALID,
S_AXI_WREADY => S01_AXI_WREADY,
-- Write response channel.
S_AXI_BRESP => S01_AXI_BRESP,
S_AXI_BVALID => S01_AXI_BVALID,
S_AXI_BREADY => S01_AXI_BREADY,
-- Read address channel.
S_AXI_ARADDR => S01_AXI_ARADDR,
S_AXI_ARPROT => S01_AXI_ARPROT,
S_AXI_ARVALID => S01_AXI_ARVALID,
S_AXI_ARREADY => S01_AXI_ARREADY,
-- Read data channel.
S_AXI_RDATA => S01_AXI_RDATA,
S_AXI_RRESP => S01_AXI_RRESP,
S_AXI_RVALID => S01_AXI_RVALID,
S_AXI_RREADY => S01_AXI_RREADY,
ram => ram
);
ram <= (others => (others => '1'));
-- All reads and writes are always successful
axi_bresp <= "00";
axi_rresp <= "00";
-- I/O Connections assignments
S_AXI_AWREADY <= axi_awready;
S_AXI_WREADY <= axi_wready;
S_AXI_BRESP <= axi_bresp;
S_AXI_BVALID <= axi_bvalid;
S_AXI_ARREADY <= axi_arready;
S_AXI_RDATA <= axi_rdata;
S_AXI_RRESP <= axi_rresp;
S_AXI_RVALID <= axi_rvalid;
process(S_AXI_ACLK)
begin
if (rising_edge(S_AXI_ACLK)) then
ram_config_read <= ram(ram_config_i);
if (ram_config_we = '1') then
ram(ram_config_i) <= ram_config_write;
end if;
end if;
end process;
process(S_AXI_ACLK)
begin
if (rising_edge(S_AXI_ACLK)) then
ram_mapper_read <= ram(ram_mapper_i);
if (ram_mapper_we = '1') then
ram(ram_mapper_i) <= ram_mapper_write;
end if;
end if;
end process;
process(S_AXI_ACLK)
begin
if (rising_edge(S_AXI_ACLK)) then
if (S_AXI_ARESETN = '0') then
axi_awready <= '0';
axi_wready <= '0';
axi_bvalid <= '0';
axi_arready <= '0';
axi_rvalid <= '0';
read_ready0 <= '0';
read_ready1 <= '0';
-- Init the sequences below when reset is left.
init_sequence <= '1';
else
if (init_sequence = '1') then
axi_awready <= '1';
axi_arready <= '1';
init_sequence <= '0';
end if;
-----------------------------------------------------------------
-- Thanks to read being one step ahead of writes, we can
-- do a mutual cross-check that a read does not start if a write
-- is in progress and a write does not start if a read is in progress.
-- It is possible for the write to copy the address and start at the
-- same time as the read, but it will not proceed to actually
-- do the write until the read has completed. This is also why
-- we make an internal copy of the write address, such that
-- it is kept and not overwritten by the read address.
-----------------------------------------------------------------
-- We accept a write address when we are ready and it is present.
if (axi_awready = '1' and S_AXI_AWVALID = '1') then
-- Latch address for our internals.
addr_latch <= S_AXI_AWADDR(addr_latch'range);
-- Do not accept an address until the write has been completed.
axi_awready <= '0';
-- This also makes us ready to take the data.
axi_wready <= '1';
end if;
-- We accept a data word when we are ready and it is present.
if (axi_wready = '1' and S_AXI_WVALID = '1') then
-- Take the latched address.
-- Take the data and tell our internals.
ram(0) <= S_AXI_WDATA;
-- We have taken it, so not accepting any longer.
axi_wready <= '0';
-- We also report success.
axi_bvalid <= '1';
end if;
-- When the outstanding write response has been consumed,
-- we are ready to take the next write.
if (axi_bvalid = '1' and S_AXI_BREADY = '1') then
axi_bvalid <= '0';
axi_awready <= '1';
end if;
-----------------------------------------------------------------
-- We accept a read address when we are ready and it is present.
if (axi_arready = '1' and S_AXI_ARVALID = '1') then
-- Latch address for our internals.
ram_config_i <= to_integer(unsigned(S_AXI_ARADDR(addr_latch'range)));
-- Do not accept an address until the read has been completed.
axi_arready <= '0';
read_ready0 <= '1';
else
read_ready0 <= '0';
end if;
read_ready1 <= read_ready0;
-- The data is available on the second cycle after we told
-- the internals to perform the read.
if (read_ready1 = '1') then
-- Latch the data.
axi_rdata <= ram_config_read;
-- axi_rdata <= (31 downto 20 => '0') & u_ad_reg_latch;
-- Report the data as valid.
axi_rvalid <= '1';
end if;
-- When the read data has been consumed, we are ready to take
-- the next read.
if (axi_rvalid = '1' and S_AXI_RREADY = '1') then
axi_rvalid <= '0';
axi_arready <= '1';
end if;
-----------------------------------------------------------------
end if;
end if;
end process;
end RTL;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment