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

removed unused code

parent 28ff4e33
No related branches found
No related tags found
2 merge requests!319Resolve HPR-87,!315Resolve HPR-87
Pipeline #46799 passed
......@@ -9,12 +9,10 @@ synth_files =
src/vhdl/axi4_stream_pkg.vhd
src/vhdl/axi4_stream_dp_bridge.vhd
src/vhdl/axi4_lite_mm_bridge.vhd
src/vhdl/mem_to_axi4_lite.vhd
test_bench_files =
tb/vhdl/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 =
tb/vhdl/tb_tb_axi4_stream_dp_bridge.vhd
......
......@@ -83,16 +83,6 @@ PACKAGE axi4_lite_pkg IS
rvalid : std_logic; -- read valid
END RECORD;
TYPE t_register_address IS RECORD
base_address : NATURAL;
address : NATURAL;
offset : NATURAL;
width : NATURAL;
name : STRING(1 TO c_max_string);
END RECORD;
TYPE t_register_address_array IS ARRAY (INTEGER RANGE <>) OF t_register_address;
CONSTANT c_axi4_lite_copi_rst : t_axi4_lite_copi := ((OTHERS=>'0'), (OTHERS=>'0'), '0', (OTHERS=>'0'), (OTHERS=>'0'), '0', '0', (OTHERS=>'0'), (OTHERS=>'0'), '0', '0');
CONSTANT c_axi4_lite_cipo_rst : t_axi4_lite_cipo := ('0', '0', (OTHERS=>'0'), '0', '0', (OTHERS=>'0'), (OTHERS=>'0'), '0');
......@@ -105,635 +95,8 @@ PACKAGE axi4_lite_pkg IS
CONSTANT c_axi4_lite_resp_slverr : STD_LOGIC_VECTOR(c_axi4_lite_resp_w-1 DOWNTO 0) := "10"; -- peripheral error
CONSTANT c_axi4_lite_resp_decerr : STD_LOGIC_VECTOR(c_axi4_lite_resp_w-1 DOWNTO 0) := "11"; -- decode error
-- Resize functions to fit an integer or an SLV in the corresponding t_axi4_lite_cipo or t_axi4_lite_copi field width
FUNCTION TO_AXI4_LITE_ADDRESS(n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, use integer to support 32 bit range
FUNCTION TO_AXI4_LITE_DATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, alias of TO_AXI4_LITE_DATA()
FUNCTION TO_AXI4_LITE_UDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, use integer to support 32 bit range
FUNCTION TO_AXI4_LITE_SDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- sign extended
FUNCTION RESIZE_AXI4_LITE_ADDRESS(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned
FUNCTION RESIZE_AXI4_LITE_DATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned, alias of RESIZE_AXI4_LITE_UDATA
FUNCTION RESIZE_AXI4_LITE_UDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned
FUNCTION RESIZE_AXI4_LITE_SDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- sign extended
FUNCTION RESIZE_AXI4_LITE_XDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- set unused MSBits to 'X'
CONSTANT c_axi4_lite_reg_rd_latency : NATURAL := 0;
CONSTANT c_axi4_lite_reg : t_c_mem := (latency => c_axi4_lite_reg_rd_latency,
adr_w => 1,
dat_w => 32,
nof_dat => 1,
init_sl => 'X');
CONSTANT c_axi4_lite_reg_init_w : NATURAL := 1*256*32; -- >= largest expected value of dat_w*nof_dat (256 * 32 bit = 1k byte)
CONSTANT c_mask_ones : t_slv_32_arr(0 TO 0) := (OTHERS => (OTHERS => '1'));
CONSTANT c_mask_zeros : t_slv_32_arr(0 TO 0) := (OTHERS => (OTHERS => '0'));
FUNCTION pad(str: STRING; width: NATURAL; pad_char: CHARACTER) RETURN STRING;
FUNCTION pad(str: STRING) RETURN STRING;
FUNCTION strip(str: STRING) RETURN STRING;
--PROCEDURE axi_lite_blockwrite (SIGNAL mm_clk : IN STD_LOGIC;
-- SIGNAL axi_cipo : IN t_axi4_lite_cipo;
-- SIGNAL axi_copi : OUT t_axi4_lite_copi;
-- register_addr : NATURAL;
-- dataFileName : STRING;
-- name : STRING := pad("");
-- expected_fail : BOOLEAN := false;
-- fail_on_error : BOOLEAN := false);
-- Multiple variants of the same function
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC; SIGNAL axi_cipo : IN t_axi4_lite_cipo; SIGNAL axi_copi : OUT t_axi4_lite_copi; register_addr : NATURAL; write_reg : BOOLEAN; data : t_slv_32_arr; validate : boolean := false; mask : t_slv_32_arr := c_mask_zeros; expected_fail : BOOLEAN := false; fail_on_error : BOOLEAN := false);
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC; SIGNAL axi_cipo : IN t_axi4_lite_cipo; SIGNAL axi_copi : OUT t_axi4_lite_copi; register_addr : t_register_address; write_reg : BOOLEAN; data : t_slv_32_arr; validate : boolean := false; mask : t_slv_32_arr := c_mask_zeros; expected_fail : BOOLEAN := false; fail_on_error : BOOLEAN := false);
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC; SIGNAL axi_cipo : IN t_axi4_lite_cipo; SIGNAL axi_copi : OUT t_axi4_lite_copi; register_addr : t_register_address; write_reg : BOOLEAN; data : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0); validate : boolean := false; mask : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0) := (OTHERS => '0'); expected_fail : BOOLEAN := false; fail_on_error : BOOLEAN := false);
-- Base function
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi;
register_addr : NATURAL;
write_reg : BOOLEAN;
data : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0);
validate : boolean := false;
mask : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0) := (OTHERS => '0');
offset : NATURAL := 0;
width : NATURAL := 32;
name : STRING := pad("");
expected_fail : BOOLEAN := false;
fail_on_error : BOOLEAN := false);
PROCEDURE axi_lite_init (SIGNAL mm_rst : IN STD_LOGIC; SIGNAL mm_clk : IN STD_LOGIC; SIGNAL axi_cipo : IN t_axi4_lite_cipo; SIGNAL axi_copi : OUT t_axi4_lite_copi);
--PROCEDURE axi_lite_wait (SIGNAL mm_clk : IN STD_LOGIC; SIGNAL axi_cipo : IN t_axi4_lite_cipo; SIGNAL axi_copi : OUT t_axi4_lite_copi; register_addr : t_register_address; data : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0); fail_on_error : BOOLEAN := TRUE);
END axi4_lite_pkg;
PACKAGE BODY axi4_lite_pkg IS
FUNCTION pad(str: STRING; width: NATURAL; pad_char: CHARACTER) RETURN STRING IS
VARIABLE v_str : STRING(1 TO width) := (OTHERS => pad_char);
BEGIN
v_str(width-str'LENGTH+1 TO width) := str;
RETURN v_str;
END;
FUNCTION pad(str: STRING) RETURN STRING IS
VARIABLE v_str : STRING(1 TO c_max_string) := (OTHERS => ' ');
BEGIN
v_str(1 TO str'LENGTH) := str;
RETURN v_str;
END;
FUNCTION strip(str: STRING) RETURN STRING IS
BEGIN
FOR i IN str'REVERSE_RANGE LOOP
IF str(i) /= ' ' THEN
RETURN str(1 TO i);
END IF;
END LOOP;
RETURN str;
END;
-- Resize functions to fit an integer or an SLV in the corresponding t_axi4_lite_cipo or t_axi4_lite_copi field width
FUNCTION TO_AXI4_LITE_ADDRESS(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_axi4_lite_address_w);
END TO_AXI4_LITE_ADDRESS;
FUNCTION TO_AXI4_LITE_DATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN TO_AXI4_LITE_UDATA(n);
END TO_AXI4_LITE_DATA;
FUNCTION TO_AXI4_LITE_UDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_axi4_lite_data_w);
END TO_AXI4_LITE_UDATA;
FUNCTION TO_AXI4_LITE_SDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_SVEC(TO_SVEC(n, 32), c_axi4_lite_data_w);
END TO_AXI4_LITE_SDATA;
FUNCTION RESIZE_AXI4_LITE_ADDRESS(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_UVEC(vec, c_axi4_lite_address_w);
END RESIZE_AXI4_LITE_ADDRESS;
FUNCTION RESIZE_AXI4_LITE_DATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_AXI4_LITE_UDATA(vec);
END RESIZE_AXI4_LITE_DATA;
FUNCTION RESIZE_AXI4_LITE_UDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_UVEC(vec, c_axi4_lite_data_w);
END RESIZE_AXI4_LITE_UDATA;
FUNCTION RESIZE_AXI4_LITE_SDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_SVEC(vec, c_axi4_lite_data_w);
END RESIZE_AXI4_LITE_SDATA;
FUNCTION RESIZE_AXI4_LITE_XDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
VARIABLE v_vec : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0) := (OTHERS=>'X');
BEGIN
v_vec(vec'LENGTH-1 DOWNTO 0) := vec;
RETURN v_vec;
END RESIZE_AXI4_LITE_XDATA;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
PROCEDURE axi_lite_init (SIGNAL mm_rst : IN STD_LOGIC;
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi) is
BEGIN
axi_copi <= c_axi4_lite_copi_rst;
-- wait for reset to be released
WAIT UNTIL to_x01(mm_rst) = '0';
WAIT UNTIL rising_edge(mm_clk);
WAIT UNTIL rising_edge(mm_clk);
END PROCEDURE;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi;
register_addr : NATURAL;
write_reg : BOOLEAN;
data : t_slv_32_arr;
validate : BOOLEAN := false;
mask : t_slv_32_arr := c_mask_zeros;
expected_fail : BOOLEAN := false;
fail_on_error : BOOLEAN := false) is
VARIABLE mask_unit : STD_LOGIC_VECTOR(31 DOWNTO 0);
BEGIN
data_write_loop: FOR i IN data'RANGE LOOP
IF mask'LENGTH = data'LENGTH THEN
mask_unit := mask(i);
ELSE
mask_unit := mask(0);
END IF;
axi_lite_transaction(mm_clk, axi_cipo, axi_copi, register_addr+i, write_reg, data(i), validate, mask_unit, 0, 32, pad(""), expected_fail, fail_on_error);
END LOOP;
END PROCEDURE;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi;
register_addr : t_register_address;
write_reg : BOOLEAN;
data : t_slv_32_arr;
validate : BOOLEAN := false;
mask : t_slv_32_arr := c_mask_zeros;
expected_fail : BOOLEAN := false;
fail_on_error : BOOLEAN := false) is
VARIABLE mask_unit : STD_LOGIC_VECTOR(31 DOWNTO 0);
BEGIN
data_write_loop: FOR i IN data'RANGE LOOP
IF mask'LENGTH = data'LENGTH THEN
mask_unit := mask(i);
ELSE
mask_unit := mask(0);
END IF;
axi_lite_transaction(mm_clk, axi_cipo, axi_copi, register_addr.base_address+register_addr.address+i, write_reg, data(i), validate, mask_unit, register_addr.offset, register_addr.width, register_addr.name, expected_fail, fail_on_error);
END LOOP;
END PROCEDURE;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi;
register_addr : t_register_address;
write_reg : BOOLEAN;
data : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0);
validate : BOOLEAN := false;
mask : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0) := (OTHERS => '0');
expected_fail : BOOLEAN := false;
fail_on_error : BOOLEAN := false) is
BEGIN
axi_lite_transaction(mm_clk, axi_cipo, axi_copi, register_addr.base_address+register_addr.address, write_reg, data, validate, mask, register_addr.offset, register_addr.width, register_addr.name, expected_fail, fail_on_error);
END PROCEDURE;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
PROCEDURE axi_lite_transaction (SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi;
register_addr : NATURAL;
write_reg : BOOLEAN;
data : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0);
validate : BOOLEAN := false;
mask : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0) := (OTHERS => '0');
offset : NATURAL := 0;
width : NATURAL := 32;
name : STRING := pad("");
expected_fail : BOOLEAN := false;
fail_on_error : BOOLEAN := false) is
VARIABLE stdio : line;
VARIABLE result : STD_LOGIC_VECTOR(31 DOWNTO 0);
BEGIN
-- Start transaction
WAIT UNTIL rising_edge(mm_clk);
IF write_reg = false THEN
-- Setup read address
axi_copi.arvalid <= '1';
axi_copi.araddr <= std_logic_vector(to_unsigned(register_addr*4, 32));
axi_copi.rready <= '1';
read_address_wait: LOOP
WAIT UNTIL rising_edge(mm_clk);
IF axi_cipo.arready = '1' THEN
axi_copi.arvalid <= '0';
axi_copi.araddr <= (OTHERS => '0');
END IF;
IF axi_cipo.rvalid = '1' THEN
EXIT;
END IF;
END LOOP;
write(stdio, string'("INFO: AXI Lite read of register "));
IF name(1) /= ' ' THEN
write(stdio, strip(name));
ELSE
write(stdio, (register_addr));
END IF;
write(stdio, string'(" returned "));
-- Read response
IF axi_cipo.rresp = "00" THEN
write(stdio, string'("OK "));
ELSIF axi_cipo.rresp = "01" THEN
write(stdio, string'("exclusive access error "));
ELSIF axi_cipo.rresp = "10" THEN
write(stdio, string'("peripheral error "));
ELSIF axi_cipo.rresp = "11" THEN
write(stdio, string'("address decode error "));
END IF;
write(stdio, string'("with data 0x"));
hwrite(stdio, axi_cipo.rdata(offset+width-1 DOWNTO offset));
writeline(output, stdio);
IF validate = TRUE THEN
IF (axi_cipo.rdata(offset+width-1 DOWNTO offset) AND mask(width-1 DOWNTO 0)) /= (data(width-1 DOWNTO 0) AND mask(width-1 DOWNTO 0) ) THEN
IF expected_fail THEN
write(stdio, string'("INFO (Expected Error)"));
ELSE
write(stdio, string'("ERROR"));
END IF;
write(stdio, string'(": Return data doesn't match mask"));
writeline(output, stdio);
ASSERT NOT(fail_on_error) REPORT "Return data doesn't match mask" SEVERITY ERROR;
END IF;
END IF;
WAIT UNTIL rising_edge(mm_clk);
axi_copi.rready <= '0';
ELSE
-- Needs to actually do a read first to perform a RMW on the shared fields
axi_copi.arvalid <= '1';
axi_copi.araddr <= std_logic_vector(to_unsigned(register_addr*4, 32));
axi_copi.rready <= '1';
rmw_address_wait: LOOP
WAIT UNTIL rising_edge(mm_clk);
IF axi_cipo.arready = '1' THEN
axi_copi.arvalid <= '0';
axi_copi.araddr <= (OTHERS => '0');
EXIT;
END IF;
END LOOP;
rmw_response_wait: WHILE axi_cipo.rvalid = '0' LOOP
WAIT UNTIL rising_edge(mm_clk);
END LOOP;
result := axi_cipo.rdata;
IF axi_cipo.rresp /= "00" THEN
IF expected_fail THEN
write(stdio, string'("INFO (Expected Error)"));
ELSE
write(stdio, string'("ERROR"));
END IF;
write(stdio, string'(": Failure to read during write of register "));
IF name(1) /= ' ' THEN
write(stdio, strip(name));
ELSE
write(stdio, (register_addr));
END IF;
write(stdio, string'(" got "));
write(stdio, to_integer(unsigned(axi_cipo.rresp)));
writeline(output, stdio);
ASSERT NOT(fail_on_error and not expected_fail) REPORT "Failure to read during write of register" SEVERITY ERROR;
END IF;
WAIT UNTIL rising_edge(mm_clk);
axi_copi.rready <= '0';
-- Setup write address, data, & reponse ready
axi_copi.awvalid <= '1';
axi_copi.awaddr <= std_logic_vector(to_unsigned(register_addr*4, 32));
axi_copi.bready <= '1';
axi_copi.wvalid <= '1';
FOR i IN 0 TO 31 LOOP
IF (i >= offset) and (i < (offset+width)) THEN
axi_copi.wdata(i) <= (result(i) AND mask(i-offset)) OR data(i-offset);
ELSE
axi_copi.wdata(i) <= result(i);
END IF;
END LOOP;
axi_copi.wstrb <= X"f";
write_address_wait: LOOP
WAIT UNTIL rising_edge(mm_clk);
IF axi_cipo.wready = '1' THEN
axi_copi.wvalid <= '0';
END IF;
IF axi_cipo.awready = '1' THEN
axi_copi.awvalid <= '0';
axi_copi.awaddr <= (OTHERS => '0');
END IF;
IF axi_cipo.awready = '1' AND axi_cipo.wready = '1' THEN
EXIT;
END IF;
END LOOP;
response_wait: WHILE axi_cipo.bvalid = '0' LOOP
WAIT UNTIL rising_edge(mm_clk);
END LOOP;
IF axi_cipo.bresp = "00" THEN
write(stdio, string'("INFO"));
ELSE
IF expected_fail THEN
write(stdio, string'("INFO (Expected Error)"));
ELSE
write(stdio, string'("ERROR"));
END IF;
END IF;
write(stdio, string'(": AXI Lite write of register "));
IF name(1) /= ' ' THEN
write(stdio, strip(name));
ELSE
write(stdio, (register_addr));
END IF;
write(stdio, string'(" returned "));
-- Print response
IF axi_cipo.bresp = "00" THEN
write(stdio, string'("OK"));
ELSIF axi_cipo.bresp = "01" THEN
write(stdio, string'("exclusive access error "));
ASSERT NOT(fail_on_error and not expected_fail) REPORT "AXI LIte error code exclusive access error" SEVERITY ERROR;
ELSIF axi_cipo.bresp = "10" THEN
write(stdio, string'("peripheral error "));
ASSERT NOT(fail_on_error and not expected_fail) REPORT "AXI LIte error code peripheral error" SEVERITY ERROR;
ELSIF axi_cipo.bresp = "11" THEN
write(stdio, string'("address decode error "));
ASSERT NOT(fail_on_error and not expected_fail) REPORT "AXI LIte error code address decode error" SEVERITY ERROR;
END IF;
writeline(output, stdio);
WAIT UNTIL rising_edge(mm_clk);
axi_copi.bready <= '0';
END IF;
END PROCEDURE;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- Write a block of values from a file starting at a given address.
PROCEDURE axi_lite_blockwrite (SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi;
register_addr : NATURAL;
dataFileName : STRING;
name : STRING := pad("");
expected_fail : BOOLEAN := false;
fail_on_error : BOOLEAN := false) is
VARIABLE stdio : line;
VARIABLE result : STD_LOGIC_VECTOR(31 DOWNTO 0);
variable wrData : std_logic_vector(31 downto 0);
variable wrCount : natural := 0; -- which word we are up to
file dataFile : TEXT;
variable lineIn : line;
variable good : boolean;
BEGIN
FILE_OPEN(dataFile,dataFileName,READ_MODE);
while (not endfile(dataFile)) loop
-- Get the data to write
readline(dataFile, lineIn);
while (not endfile(dataFile)) and ((lineIn'length = 0) or (lineIn(lineIn'left) = '#')) loop
readline(dataFile, lineIn); -- skip empty lines or lines starting with a comment character ('#')
end loop;
if endfile(dataFile) and ((lineIn'length = 0) or (lineIn(lineIn'left) = '#')) then
exit;
end if;
hread(lineIn,wrData,good);
assert good
report "text IO Read error" severity ERROR;
-- Start transaction
WAIT UNTIL rising_edge(mm_clk);
axi_copi.rready <= '0';
-- Setup write address, data, & response ready
axi_copi.awvalid <= '1';
axi_copi.awaddr <= std_logic_vector(to_unsigned((register_addr + wrCount)*4, 32));
axi_copi.bready <= '1';
axi_copi.wvalid <= '1';
axi_copi.wdata <= wrData;
axi_copi.wstrb <= X"f";
write_address_wait: LOOP
WAIT UNTIL rising_edge(mm_clk);
IF axi_cipo.wready = '1' THEN
axi_copi.wvalid <= '0';
END IF;
IF axi_cipo.awready = '1' THEN
axi_copi.awvalid <= '0';
axi_copi.awaddr <= (OTHERS => '0');
END IF;
IF axi_cipo.awready = '1' AND axi_cipo.wready = '1' THEN
EXIT;
END IF;
END LOOP;
response_wait: WHILE axi_cipo.bvalid = '0' LOOP
WAIT UNTIL rising_edge(mm_clk);
END LOOP;
IF axi_cipo.bresp /= "00" THEN
IF expected_fail THEN
write(stdio, string'("INFO (Expected Error)"));
ELSE
write(stdio, string'("ERROR"));
END IF;
write(stdio, string'(": AXI Lite write of register "));
IF name(1) /= ' ' THEN
write(stdio, strip(name));
ELSE
write(stdio, (register_addr));
END IF;
write(stdio, string'(" returned "));
-- Print response
IF axi_cipo.bresp = "00" THEN
write(stdio, string'("OK"));
ELSIF axi_cipo.bresp = "01" THEN
write(stdio, string'("exclusive access error "));
ASSERT NOT(fail_on_error and not expected_fail) REPORT "AXI LIte error code exclusive access error" SEVERITY ERROR;
ELSIF axi_cipo.bresp = "10" THEN
write(stdio, string'("peripheral error "));
ASSERT NOT(fail_on_error and not expected_fail) REPORT "AXI LIte error code peripheral error" SEVERITY ERROR;
ELSIF axi_cipo.bresp = "11" THEN
write(stdio, string'("address decode error "));
ASSERT NOT(fail_on_error and not expected_fail) REPORT "AXI LIte error code address decode error" SEVERITY ERROR;
END IF;
writeline(output, stdio);
end if;
WAIT UNTIL rising_edge(mm_clk);
axi_copi.bready <= '0';
wrCount := wrCount + 1;
end loop;
END PROCEDURE;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
PROCEDURE axi_lite_wait (SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL axi_cipo : IN t_axi4_lite_cipo;
SIGNAL axi_copi : OUT t_axi4_lite_copi;
register_addr : t_register_address;
data : STD_LOGIC_VECTOR(c_axi4_lite_data_w-1 DOWNTO 0);
fail_on_error : BOOLEAN := TRUE) is
VARIABLE response : STD_LOGIC_VECTOR(1 DOWNTO 0);
VARIABLE stdio : LINE;
VARIABLE timeout : INTEGER := 100000; -- 100K iteration limit, about 50M clocks
BEGIN
wait_loop: LOOP
-- Start transaction
WAIT UNTIL rising_edge(mm_clk);
-- Setup read address
axi_copi.arvalid <= '1';
axi_copi.araddr <= std_logic_vector(to_unsigned((register_addr.base_address+register_addr.address)*4, 32));
axi_copi.rready <= '1';
read_address_wait: LOOP
WAIT UNTIL rising_edge(mm_clk);
IF axi_cipo.arready = '1' THEN
axi_copi.arvalid <= '0';
axi_copi.araddr <= (OTHERS => '0');
END IF;
IF axi_cipo.rvalid = '1' THEN
EXIT;
END IF;
END LOOP;
response := axi_cipo.rresp;
IF (axi_cipo.rdata(register_addr.offset+register_addr.width-1 DOWNTO register_addr.offset) = data(register_addr.width-1 DOWNTO 0)) OR response /= "00" THEN
EXIT;
END IF;
WAIT UNTIL rising_edge(mm_clk);
axi_copi.rready <= '0';
delay_loop: FOR i IN 0 TO 500 LOOP
WAIT UNTIL rising_edge(mm_clk);
END LOOP;
timeout := timeout - 1;
IF timeout = 0 THEN
EXIT;
END IF;
END LOOP;
IF timeout = 0 THEN
write(stdio, string'("ERROR: AXI Lite wait on register "));
write(stdio, strip(register_addr.name));
write(stdio, string'("failed"));
ASSERT not fail_on_error REPORT "AXI LIte wait timed out" SEVERITY ERROR;
ELSE
write(stdio, string'("INFO: AXI Lite wait on register "));
write(stdio, strip(register_addr.name));
write(stdio, string'(" completed with response "));
IF response = "00" THEN
write(stdio, string'("OK "));
ELSIF response = "01" THEN
write(stdio, string'("exclusive access error "));
ELSIF response = "10" THEN
write(stdio, string'("peripheral error "));
ELSIF response = "11" THEN
write(stdio, string'("address decode error "));
END IF;
END IF;
writeline(output, stdio);
END PROCEDURE;
END axi4_lite_pkg;
-------------------------------------------------------------------------------
--
-- 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 c_mm_clk_period : TIME := 40 ns;
CONSTANT c_usr_clk_period : TIME := 10 ns;
CONSTANT c_reset_len : NATURAL := 16;
CONSTANT c_dat_w : INTEGER := 32;
CONSTANT c_adr_w : INTEGER := 8;
CONSTANT c_mm_usr_ram : t_c_mem := (latency => 1,
c_adr_w => 5,
c_dat_w => 8,
nof_dat => 32,
init_sl => '0');
CONSTANT c_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(c_dat_w-1 DOWNTO 0);
SIGNAL wr_dat : STD_LOGIC_VECTOR(c_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(c_adr_w-1 DOWNTO 0);
SIGNAL rd_adr : STD_LOGIC_VECTOR(c_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.c_adr_w-1 DOWNTO 0);
SIGNAL ram_rd_dat : STD_LOGIC_VECTOR(c_mm_usr_ram.c_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 c_mm_clk_period/2;
mm_rst <= '1', '0' AFTER c_mm_clk_period*c_reset_len;
usr_clk <= NOT usr_clk OR sim_finished AFTER c_usr_clk_period/2;
usr_rst <= '1', '0' AFTER c_usr_clk_period*c_reset_len;
u_mem_to_axi4_lite : ENTITY work.mem_to_axi4_lite
GENERIC MAP (
g_c_adr_w => c_adr_w,
g_c_dat_w => c_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(c_ram_addr_base = UNSIGNED(wr_adr(wr_adr'LENGTH-1 DOWNTO c_mm_usr_ram.c_adr_w)));
ram_rd_en <= reg_rden AND is_true(c_ram_addr_base = UNSIGNED(rd_adr(rd_adr'LENGTH-1 DOWNTO c_mm_usr_ram.c_adr_w)));
ram_adr <= wr_adr(c_mm_usr_ram.c_adr_w-1 DOWNTO 0) WHEN ram_wr_en = '1' ELSE rd_adr(c_mm_usr_ram.c_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.c_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_c_dat_w => 1,
g_out_c_dat_w => 1
)
PORT MAP (
clk => mm_clk,
clken => '1',
in_dat(0) => ram_wr_en,
out_dat(0) => wr_val
);
rd_dat <= RESIZE_UVEC(ram_rd_dat, c_dat_w) WHEN rd_val = '1' ELSE (OTHERS => '0');
-- Testbench writes a number of words to memory and then reads them back trough the AXI interface.
-- It uses the axi_lite_transaction to write, read and verify the data.
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.
Please register or to comment