diff options
Diffstat (limited to 'testsuite/gna/issue2185/avm_master.vhd')
-rw-r--r-- | testsuite/gna/issue2185/avm_master.vhd | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/testsuite/gna/issue2185/avm_master.vhd b/testsuite/gna/issue2185/avm_master.vhd new file mode 100644 index 000000000..b7de25a72 --- /dev/null +++ b/testsuite/gna/issue2185/avm_master.vhd @@ -0,0 +1,198 @@ +-- This module is a simple kind of RAM test. +-- +-- It generates first a sequence of WRITE operations (writing pseudo-random data), +-- and then a corresponding sequence of READ operations, verifying that the +-- correct values are read back again. +-- +-- Created by Michael Jørgensen in 2022 (mjoergen.github.io/HyperRAM). + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avm_master is + generic ( + G_ADDRESS_SIZE : integer; -- Number of bits + G_DATA_SIZE : integer -- Number of bits + ); + port ( + clk_i : in std_logic; + rst_i : in std_logic; + start_i : in std_logic; + wait_o : out std_logic; + write_burstcount_i : in std_logic_vector(7 downto 0); + read_burstcount_i : in std_logic_vector(7 downto 0); + + avm_write_o : out std_logic; + avm_read_o : out std_logic; + avm_address_o : out std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + avm_writedata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + avm_byteenable_o : out std_logic_vector(G_DATA_SIZE/8-1 downto 0); + avm_burstcount_o : out std_logic_vector(7 downto 0); + avm_readdata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + avm_readdatavalid_i : in std_logic; + avm_waitrequest_i : in std_logic; + -- Debug output + address_o : out std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + data_exp_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + data_read_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + error_o : out std_logic + ); +end entity avm_master; + +architecture synthesis of avm_master is + + constant C_DATA_INIT : std_logic_vector(63 downto 0) := X"CAFEBABEDEADBEEF"; + + signal data_init : std_logic_vector(63 downto 0); + + signal wr_data : std_logic_vector(63 downto 0); + signal rd_data : std_logic_vector(63 downto 0); + signal burstcount : std_logic_vector(7 downto 0); + signal read_burstcount : std_logic_vector(7 downto 0); + signal wordcount : integer range 0 to 255; + signal new_address : std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + signal new_burstcount : std_logic_vector(7 downto 0); + + type state_t is ( + INIT_ST, + WRITING_ST, + READING_ST + ); + + signal state : state_t := INIT_ST; + signal reset_verify : std_logic; + + -- The pseudo-random data is generated using a 64-bit maximal-period Galois LFSR, + -- see http://users.ece.cmu.edu/~koopman/lfsr/64.txt + function lfsr (constant old : std_logic_vector(63 downto 0)) return std_logic_vector is + begin + if old(63) = '1' then + return (old(62 downto 0) & "0") xor x"000000000000001b"; + else + return (old(62 downto 0) & "0"); + end if; + end function lfsr; + +begin + + new_address <= avm_address_o when unsigned(avm_burstcount_o) > 1 else + std_logic_vector(unsigned(avm_address_o) + wordcount); + new_burstcount <= std_logic_vector(unsigned(avm_burstcount_o) - 1) when unsigned(avm_burstcount_o) > 1 else + burstcount; + + p_verifier : process (clk_i) + begin + if rising_edge(clk_i) then + if avm_readdatavalid_i = '1' then + data_read_o <= avm_readdata_i; + data_exp_o <= rd_data(G_DATA_SIZE-1 downto 0); + + if avm_readdata_i /= rd_data(G_DATA_SIZE-1 downto 0) then + report "ERROR: Expected " & to_hstring(rd_data(G_DATA_SIZE-1 downto 0)) & ", read " & to_hstring(avm_readdata_i) + severity failure; + error_o <= '1'; + else + rd_data <= lfsr(rd_data); + end if; + end if; + + if reset_verify = '1' then + rd_data <= data_init; + error_o <= '0'; + end if; + + if rst_i = '1' then + error_o <= '0'; + end if; + end if; + end process p_verifier; + + p_fsm : process (clk_i) + begin + if rising_edge(clk_i) then + reset_verify <= '0'; + + if avm_waitrequest_i = '0' then + avm_write_o <= '0'; + avm_read_o <= '0'; + end if; + + case state is + when INIT_ST => + if start_i = '1' then + wait_o <= '1'; + wr_data <= C_DATA_INIT xor ( + write_burstcount_i & read_burstcount_i & + write_burstcount_i & read_burstcount_i & + write_burstcount_i & read_burstcount_i & + write_burstcount_i & read_burstcount_i); + data_init <= C_DATA_INIT xor ( + write_burstcount_i & read_burstcount_i & + write_burstcount_i & read_burstcount_i & + write_burstcount_i & read_burstcount_i & + write_burstcount_i & read_burstcount_i); + avm_write_o <= '1'; + avm_read_o <= '0'; + avm_address_o <= (others => '0'); + avm_byteenable_o <= (others => '1'); + avm_burstcount_o <= write_burstcount_i; + burstcount <= write_burstcount_i; + read_burstcount <= read_burstcount_i; + wordcount <= to_integer(unsigned(write_burstcount_i)); + state <= WRITING_ST; + end if; + + when WRITING_ST => + if avm_waitrequest_i = '0' then + avm_write_o <= '1'; + avm_read_o <= '0'; + avm_address_o <= new_address; + avm_byteenable_o <= (others => '1'); + avm_burstcount_o <= new_burstcount; + + wr_data <= lfsr(wr_data); + + if signed(avm_address_o) = -wordcount and unsigned(avm_burstcount_o) = 1 then + wr_data <= data_init; + avm_write_o <= '0'; + avm_address_o <= (others => '0'); + avm_read_o <= '1'; + avm_burstcount_o <= read_burstcount; + burstcount <= read_burstcount; + wordcount <= to_integer(unsigned(read_burstcount)); + data_read_o <= (others => '0'); + data_exp_o <= (others => '0'); + reset_verify <= '1'; + state <= READING_ST; + end if; + end if; + + when READING_ST => + if avm_waitrequest_i = '0' then + + if signed(avm_address_o) = -wordcount then + wait_o <= '0'; + state <= INIT_ST; + else + avm_address_o <= std_logic_vector(unsigned(avm_address_o) + wordcount); + avm_read_o <= '1'; + end if; + end if; + + end case; + + if rst_i = '1' then + avm_write_o <= '0'; + avm_read_o <= '0'; + wait_o <= '0'; + state <= INIT_ST; + end if; + end if; + end process p_fsm; + + avm_writedata_o <= wr_data(G_DATA_SIZE-1 downto 0); + address_o <= avm_address_o; + +end architecture synthesis; + |