Skip to content
Snippets Groups Projects
Commit 478ef67f authored by Reinier van der Walle's avatar Reinier van der Walle
Browse files

ported axi4-lite components from gemini

parent 28bfcd09
No related branches found
No related tags found
2 merge requests!319Resolve HPR-87,!315Resolve HPR-87
Pipeline #46034 failed
...@@ -5,15 +5,19 @@ hdl_lib_uses_sim = ...@@ -5,15 +5,19 @@ hdl_lib_uses_sim =
hdl_lib_technology = hdl_lib_technology =
synth_files = synth_files =
src/vhdl/axi4_lite_pkg.vhd
src/vhdl/axi4_stream_pkg.vhd src/vhdl/axi4_stream_pkg.vhd
src/vhdl/axi4_stream_dp_bridge.vhd src/vhdl/axi4_stream_dp_bridge.vhd
src/vhdl/mem_to_axi4_lite.vhd
test_bench_files = test_bench_files =
tb/vhdl/tb_axi4_stream_dp_bridge.vhd tb/vhdl/tb_axi4_stream_dp_bridge.vhd
tb/vhdl/tb_tb_axi4_stream_dp_bridge.vhd tb/vhdl/tb_tb_axi4_stream_dp_bridge.vhd
tb/vhdl/tb_axi4_lite_ram.vhd
regression_test_vhdl = regression_test_vhdl =
tb/vhdl/tb_tb_axi4_stream_dp_bridge.vhd tb/vhdl/tb_tb_axi4_stream_dp_bridge.vhd
tb/vhdl/tb_axi4_lite_ram.vhd
[modelsim_project_file] [modelsim_project_file]
......
This diff is collapsed.
-------------------------------------------------------------------------------
--
-- Copyright 2023
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author : R vd Walle
-- Purpose:
-- Translate AXI4-Lite to standard memory interface
-- Description:
-- Ported from:
-- https://git.astron.nl/desp/gemini/-/blob/master/libraries/base/axi4/src/vhdl/mem_to_axi4_lite.vhd
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE work.axi4_lite_pkg.ALL;
ENTITY mem_to_axi4_lite IS
GENERIC (
g_adr_w : NATURAL := 8;
g_dat_w : NATURAL := 32;
g_timeout : NATURAL := 6); -- 2^clocks for transaction timeout. Needs to be longer than 3* slowest clock on AXI bus
PORT (
rst : IN STD_LOGIC; -- reset synchronous with mm_clk
clk : IN STD_LOGIC; -- memory-mapped bus clock
-- Memory Mapped Peripheral in mm_clk domain
axi4_lite_in : IN t_axi4_lite_copi;
axi4_lite_out : OUT t_axi4_lite_cipo;
wren : OUT STD_LOGIC;
rden : OUT STD_LOGIC;
wr_adr : OUT STD_LOGIC_VECTOR(g_adr_w-1 DOWNTO 0);
wr_dat : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
rd_adr : OUT STD_LOGIC_VECTOR(g_adr_w-1 DOWNTO 0);
rd_dat : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
rd_busy : IN STD_LOGIC;
rd_val : IN STD_LOGIC;
wr_busy : IN STD_LOGIC;
wr_val : IN STD_LOGIC);
END mem_to_axi4_lite;
ARCHITECTURE str OF mem_to_axi4_lite IS
SIGNAL i_axi4_lite_out : t_axi4_lite_cipo;
SIGNAL write_pending : STD_LOGIC := '0';
SIGNAL write_counter : UNSIGNED(g_timeout-1 DOWNTO 0);
SIGNAL write_trans_valid : STD_LOGIC;
SIGNAL i_wren_d : STD_LOGIC;
SIGNAL i_wren : STD_LOGIC;
SIGNAL read_pending : STD_LOGIC := '0';
SIGNAL read_counter : UNSIGNED(g_timeout-1 DOWNTO 0);
SIGNAL read_trans_valid : STD_LOGIC;
SIGNAL i_rden : STD_LOGIC;
SIGNAL i_rden_d : STD_LOGIC;
SIGNAL rresp : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL rresp_r : STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
axi4_lite_out <= i_axi4_lite_out;
---------------------------------------------------------------------------
-- Write Channel --
---------------------------------------------------------------------------
write_timeout: PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
i_wren_d <= i_wren;
IF write_pending = '0' THEN
IF axi4_lite_in.awvalid = '1' AND wr_busy = '0' THEN
write_counter <= (OTHERS => '1');
write_pending <= '1';
END IF;
ELSE
-- Once the whole transaction is complete release pending and allow next
IF i_axi4_lite_out.bvalid = '1' AND axi4_lite_in.bready = '1' THEN
write_pending <= '0';
ELSE
write_counter <= write_counter - 1;
END IF;
END IF;
END IF;
END PROCESS;
write_trans_valid <= '1' WHEN write_pending = '1' AND (write_counter = 0 OR wr_val = '1') ELSE '0';
-- Assert ready after the transaction has been (or should have been) acknowledged
i_axi4_lite_out.wready <= write_trans_valid;
i_axi4_lite_out.awready <= write_trans_valid;
-- Write when data path and address path are valid (make it a single clock for neatness)
i_wren <= axi4_lite_in.wvalid AND axi4_lite_in.awvalid AND NOT wr_busy;
wren <= i_wren AND NOT i_wren_d;
wr_adr <= axi4_lite_in.awaddr(g_adr_w+1 DOWNTO 2); -- Correct for byte addressing, ARSG uses dword addressing
wr_dat <= axi4_lite_in.wdata(g_dat_w-1 DOWNTO 0);
-- Need to latch response code in case ready is asserted on response bus
write_response_latch: PROCESS(CLK)
BEGIN
IF RISING_EDGE(CLK) THEN
IF RST = '1' THEN
i_axi4_lite_out.bvalid <= '0';
ELSE
IF i_axi4_lite_out.bvalid = '1' THEN
IF axi4_lite_in.bready = '1' THEN
i_axi4_lite_out.bvalid <= '0';
END IF;
ELSE
IF write_trans_valid = '1' THEN
i_axi4_lite_out.bvalid <= '1';
IF wr_val = '1' THEN
i_axi4_lite_out.bresp <= c_axi4_lite_resp_okay;
ELSE
i_axi4_lite_out.bresp <= c_axi4_lite_resp_slverr;
END IF;
END IF;
END IF;
END IF;
END IF;
END PROCESS;
---------------------------------------------------------------------------
-- Read Channel --
---------------------------------------------------------------------------
read_timeout: PROCESS(clk)
BEGIN
IF RISING_EDGE(clk) THEN
i_rden_d <= i_rden;
IF read_pending = '0' THEN
IF axi4_lite_in.arvalid = '1' AND rd_busy = '0' THEN
read_counter <= (OTHERS => '1');
read_pending <= '1';
END IF;
ELSE
IF read_trans_valid = '1' THEN
read_pending <= '0';
ELSE
read_counter <= read_counter - 1;
END IF;
END IF;
END IF;
END PROCESS;
read_trans_valid <= '1' WHEN read_pending = '1' and (read_counter = 0 or rd_val = '1') ELSE '0';
-- Acknowledge read when response is ready
i_axi4_lite_out.arready <= read_trans_valid;
-- Map read address bus
rd_adr <= axi4_lite_in.araddr(g_adr_w+1 DOWNTO 2);
-- Read Enable when address is valid
i_rden <= read_pending;
rden <= i_rden and not(i_rden_d);
-- Assert data valid after the transaction has been (or should have been) acknowledged
i_axi4_lite_out.rvalid <= read_trans_valid;
i_axi4_lite_out.rdata(g_dat_w-1 DOWNTO 0) <= rd_dat;
-- If the address was decoded return OK otherwise error. Need to latch status as AXI clock
-- crossing IP for AXI4Lite assumes values are static after the valid is deasserted
rresp <= c_axi4_lite_resp_okay WHEN rd_val = '1' ELSE
c_axi4_lite_resp_slverr;
u_pipe_rresp : ENTITY common_lib.common_pipeline
GENERIC MAP (
g_pipeline => 1,
g_in_dat_w => 2,
g_out_dat_w => 2)
PORT MAP (
clk => clk,
clken => read_trans_valid,
in_dat => rresp,
out_dat => rresp_r);
i_axi4_lite_out.rresp <= rresp WHEN read_trans_valid = '1' ELSE rresp_r;
END str;
-------------------------------------------------------------------------------
--
-- Copyright 2023
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author : R vd Walle
-- Purpose:
-- TB for testing mem_to_axi4_lite using common_ram_crw_crw
-- Description:
-- Ported from:
-- https://git.astron.nl/desp/gemini/-/blob/master/libraries/base/axi4/tb/vhdl/tb_axi4_lite_ram.vhd
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE IEEE.std_logic_textio.ALL;
USE STD.textio.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE work.axi4_lite_pkg.ALL;
ENTITY tb_axi4_lite_ram IS
END tb_axi4_lite_ram;
ARCHITECTURE tb OF tb_axi4_lite_ram IS
CONSTANT mm_clk_period : TIME := 40 ns;
CONSTANT usr_clk_period : TIME := 10 ns;
CONSTANT c_reset_len : NATURAL := 16;
CONSTANT dat_w : INTEGER := 32;
CONSTANT adr_w : INTEGER := 8;
CONSTANT c_mm_usr_ram : t_c_mem := (latency => 1,
adr_w => 5,
dat_w => 8,
nof_dat => 32,
init_sl => '0');
CONSTANT ram_addr_base : NATURAL := to_integer(shift_right(to_unsigned(0, 32), ceil_log2(c_mm_usr_ram.nof_dat))) ;
SIGNAL mm_rst : STD_LOGIC;
SIGNAL mm_clk : STD_LOGIC := '0';
SIGNAL usr_rst : STD_LOGIC;
SIGNAL usr_clk : STD_LOGIC := '0';
SIGNAL sim_finished : STD_LOGIC := '0';
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL rd_dat : STD_LOGIC_VECTOR(dat_w-1 DOWNTO 0);
SIGNAL wr_dat : STD_LOGIC_VECTOR(dat_w-1 DOWNTO 0);
SIGNAL wr_val : STD_LOGIC;
SIGNAL rd_val : STD_LOGIC;
SIGNAL reg_wren : STD_LOGIC;
SIGNAL reg_rden : STD_LOGIC;
SIGNAL wr_adr : STD_LOGIC_VECTOR(adr_w-1 DOWNTO 0);
SIGNAL rd_adr : STD_LOGIC_VECTOR(adr_w-1 DOWNTO 0);
SIGNAL ram_wr_en : STD_LOGIC;
SIGNAL ram_rd_en : STD_LOGIC;
SIGNAL ram_adr : STD_LOGIC_VECTOR(c_mm_usr_ram.adr_w-1 DOWNTO 0);
SIGNAL ram_rd_dat : STD_LOGIC_VECTOR(c_mm_usr_ram.dat_w-1 DOWNTO 0);
SIGNAL axi_copi : t_axi4_lite_copi;
SIGNAL axi_cipo : t_axi4_lite_cipo;
BEGIN
mm_clk <= NOT mm_clk OR sim_finished AFTER mm_clk_period/2;
mm_rst <= '1', '0' AFTER mm_clk_period*c_reset_len;
usr_clk <= NOT usr_clk OR sim_finished AFTER usr_clk_period/2;
usr_rst <= '1', '0' AFTER usr_clk_period*c_reset_len;
u_mem_to_axi4_lite : ENTITY work.mem_to_axi4_lite
GENERIC MAP (
g_adr_w => adr_w,
g_dat_w => dat_w)
PORT MAP (
rst => mm_rst,
clk => mm_clk,
axi4_lite_in => axi_copi,
axi4_lite_out => axi_cipo,
wren => reg_wren,
rden => reg_rden,
wr_adr => wr_adr,
wr_dat => wr_dat,
wr_val => wr_val,
wr_busy => '0',
rd_adr => rd_adr,
rd_dat => rd_dat,
rd_busy => '0',
rd_val => rd_val);
ram_wr_en <= reg_wren AND is_true(ram_addr_base = unsigned(wr_adr(wr_adr'length-1 downto c_mm_usr_ram.adr_w)));
ram_rd_en <= reg_rden AND is_true(ram_addr_base = unsigned(rd_adr(rd_adr'length-1 downto c_mm_usr_ram.adr_w)));
ram_adr <= wr_adr(c_mm_usr_ram.adr_w-1 downto 0) WHEN ram_wr_en = '1' ELSE
rd_adr(c_mm_usr_ram.adr_w-1 downto 0);
u_ram : ENTITY common_lib.common_ram_crw_crw
GENERIC MAP (
g_ram => c_mm_usr_ram,
g_true_dual_port => TRUE)
PORT MAP (
rst_a => mm_rst,
rst_b => usr_rst,
clk_a => mm_clk,
clk_b => usr_clk,
clken_a => '1',
clken_b => '1',
wr_en_a => ram_wr_en,
wr_dat_a => wr_dat(c_mm_usr_ram.dat_w-1 downto 0),
adr_a => ram_adr,
rd_en_a => ram_rd_en,
rd_dat_a => ram_rd_dat,
rd_val_a => rd_val,
wr_en_b => '0',
wr_dat_b => X"00",
adr_b => "00000",
rd_en_b => '0',
rd_dat_b => OPEN,
rd_val_b => OPEN
);
u_ram_wr_val : ENTITY common_lib.common_pipeline
GENERIC MAP (
g_pipeline => c_mm_usr_ram.latency,
g_in_dat_w => 1,
g_out_dat_w => 1)
PORT MAP (
clk => mm_clk,
clken => '1',
in_dat(0) => ram_wr_en,
out_dat(0) => wr_val);
rd_dat <= "000000000000000000000000" & ram_rd_dat WHEN rd_val = '1' ELSE (OTHERS => '0');
--
tb : PROCESS
variable data_in : t_slv_32_arr(0 TO 10);
BEGIN
axi_lite_init (mm_rst, mm_clk, axi_cipo, axi_copi);
-- Read and write a number of words to memory
for i in 0 to 10 loop
data_in(i) := std_logic_vector(to_unsigned(57+i, 32));
end loop;
axi_lite_transaction (mm_clk, axi_cipo, axi_copi, 0, true, data_in, mask => c_mask_zeros);
for i in 0 to 10 loop
data_in(i) := std_logic_vector(to_unsigned(57+i, 32));
end loop;
axi_lite_transaction (mm_clk, axi_cipo, axi_copi, 0, false, data_in, validate => true);
sim_finished <= '1';
tb_end <= '1';
wait for 1 us;
REPORT "Finished Simulation" SEVERITY FAILURE;
WAIT;
END PROCESS tb;
END tb;
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