diff options
author | Tristan Gingold <tgingold@free.fr> | 2022-09-02 18:28:00 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2022-09-02 18:28:00 +0200 |
commit | 0d6b21c3b5639af8b321cc7f85fbf03da78d7edb (patch) | |
tree | 4eeaabab655fbb211620c00a30655ab21bb63535 /testsuite | |
parent | 3d7d926280194cdbc437db869e3e96303109a6ee (diff) | |
download | ghdl-0d6b21c3b5639af8b321cc7f85fbf03da78d7edb.tar.gz ghdl-0d6b21c3b5639af8b321cc7f85fbf03da78d7edb.tar.bz2 ghdl-0d6b21c3b5639af8b321cc7f85fbf03da78d7edb.zip |
testsuite/gna: add a test for #2185
Diffstat (limited to 'testsuite')
-rw-r--r-- | testsuite/gna/issue2185/avm_arbit.vhd | 156 | ||||
-rw-r--r-- | testsuite/gna/issue2185/avm_master.vhd | 198 | ||||
-rw-r--r-- | testsuite/gna/issue2185/avm_master_general.vhd | 124 | ||||
-rw-r--r-- | testsuite/gna/issue2185/avm_memory.vhd | 88 | ||||
-rw-r--r-- | testsuite/gna/issue2185/avm_pause.vhd | 74 | ||||
-rw-r--r-- | testsuite/gna/issue2185/burst_ctrl.vhd | 88 | ||||
-rw-r--r-- | testsuite/gna/issue2185/tb_avm_arbit.vhd | 220 | ||||
-rwxr-xr-x | testsuite/gna/issue2185/testsuite.sh | 21 |
8 files changed, 969 insertions, 0 deletions
diff --git a/testsuite/gna/issue2185/avm_arbit.vhd b/testsuite/gna/issue2185/avm_arbit.vhd new file mode 100644 index 000000000..d1516c669 --- /dev/null +++ b/testsuite/gna/issue2185/avm_arbit.vhd @@ -0,0 +1,156 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.numeric_std_unsigned.all; + +-- This arbitrates fairly between two Masters connected to a single Slave + +entity avm_arbit is + generic ( + G_ADDRESS_SIZE : integer; + G_DATA_SIZE : integer + ); + port ( + clk_i : in std_logic; + rst_i : in std_logic; + + -- Slave interface 0 (input) + s0_avm_write_i : in std_logic; + s0_avm_read_i : in std_logic; + s0_avm_address_i : in std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + s0_avm_writedata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + s0_avm_byteenable_i : in std_logic_vector(G_DATA_SIZE/8-1 downto 0); + s0_avm_burstcount_i : in std_logic_vector(7 downto 0); + s0_avm_readdata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + s0_avm_readdatavalid_o : out std_logic; + s0_avm_waitrequest_o : out std_logic; + + -- Slave interface 1 (input) + s1_avm_write_i : in std_logic; + s1_avm_read_i : in std_logic; + s1_avm_address_i : in std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + s1_avm_writedata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + s1_avm_byteenable_i : in std_logic_vector(G_DATA_SIZE/8-1 downto 0); + s1_avm_burstcount_i : in std_logic_vector(7 downto 0); + s1_avm_readdata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + s1_avm_readdatavalid_o : out std_logic; + s1_avm_waitrequest_o : out std_logic; + + -- Master interface (output) + m_avm_write_o : out std_logic; + m_avm_read_o : out std_logic; + m_avm_address_o : out std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + m_avm_writedata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + m_avm_byteenable_o : out std_logic_vector(G_DATA_SIZE/8-1 downto 0); + m_avm_burstcount_o : out std_logic_vector(7 downto 0); + m_avm_readdata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + m_avm_readdatavalid_i : in std_logic; + m_avm_waitrequest_i : in std_logic + ); +end entity avm_arbit; + +architecture synthesis of avm_arbit is + + signal s0_active_req : std_logic; + signal s1_active_req : std_logic; + + signal s0_active_grant : std_logic := '0'; + signal s1_active_grant : std_logic := '0'; + signal active_grants : std_logic_vector(1 downto 0); + + signal last_grant : std_logic := '0'; + + signal burstcount : std_logic_vector(7 downto 0); + +begin + + s0_avm_waitrequest_o <= not s0_active_grant; + s1_avm_waitrequest_o <= not s1_active_grant; + + s0_active_req <= s0_avm_write_i or s0_avm_read_i; + s1_active_req <= s1_avm_write_i or s1_avm_read_i; + + p_burstcount : process (clk_i) + begin + if rising_edge(clk_i) then + if burstcount = X"00" then + if s0_avm_write_i and not s0_avm_waitrequest_o then + burstcount <= s0_avm_burstcount_i; + end if; + if s1_avm_write_i and not s1_avm_waitrequest_o then + burstcount <= s1_avm_burstcount_i; + end if; + else + if (s0_avm_write_i and not s0_avm_waitrequest_o) or + s0_avm_readdatavalid_o or + (s1_avm_write_i and not s1_avm_waitrequest_o) or + s1_avm_readdatavalid_o then + burstcount <= burstcount - 1; + end if; + end if; + + if rst_i = '1' then + burstcount <= X"00"; + end if; + end if; + end process p_burstcount; + + active_grants <= s0_active_grant & s1_active_grant; + + p_grant : process (clk_i) + begin + if rising_edge(clk_i) then + case active_grants is + when "00" => + if s0_active_req = '1' and last_grant = '1' then + s0_active_grant <= '1'; + last_grant <= '1'; + end if; + if s1_active_req = '1' and last_grant = '0' then + s1_active_grant <= '1'; + last_grant <= '0'; + end if; + + when "01" => + if burstcount = X"01" then + if (s1_avm_write_i and not s1_avm_waitrequest_o) or + s1_avm_readdatavalid_o then + s1_active_grant <= '0'; + end if; + end if; + when "10" => + if burstcount = X"01" then + if (s0_avm_write_i and not s0_avm_waitrequest_o) or + s0_avm_readdatavalid_o then + s0_active_grant <= '0'; + end if; + end if; + + when others => + report "S0 and S1 both active" + severity failure; + end case; + + if rst_i = '1' then + s0_active_grant <= '0'; + s1_active_grant <= '0'; + last_grant <= '0'; + end if; + end if; + end process p_grant; + + m_avm_write_o <= s0_avm_write_i when last_grant = '0' else s1_avm_write_i; + m_avm_read_o <= s0_avm_read_i when last_grant = '0' else s1_avm_read_i; + m_avm_address_o <= s0_avm_address_i when last_grant = '0' else s1_avm_address_i; + m_avm_writedata_o <= s0_avm_writedata_i when last_grant = '0' else s1_avm_writedata_i; + m_avm_byteenable_o <= s0_avm_byteenable_i when last_grant = '0' else s1_avm_byteenable_i; + m_avm_burstcount_o <= s0_avm_burstcount_i when last_grant = '0' else s1_avm_burstcount_i; + + s0_avm_readdata_o <= m_avm_readdata_i; + s0_avm_readdatavalid_o <= m_avm_readdatavalid_i when last_grant = '0' else '0'; + + s1_avm_readdata_o <= m_avm_readdata_i; + s1_avm_readdatavalid_o <= m_avm_readdatavalid_i when last_grant = '1' else '0'; + +end architecture synthesis; + 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; + diff --git a/testsuite/gna/issue2185/avm_master_general.vhd b/testsuite/gna/issue2185/avm_master_general.vhd new file mode 100644 index 000000000..756465ae3 --- /dev/null +++ b/testsuite/gna/issue2185/avm_master_general.vhd @@ -0,0 +1,124 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avm_master_general 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; + m_avm_write_o : out std_logic; + m_avm_read_o : out std_logic; + m_avm_address_o : out std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + m_avm_writedata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + m_avm_byteenable_o : out std_logic_vector(G_DATA_SIZE/8-1 downto 0); + m_avm_burstcount_o : out std_logic_vector(7 downto 0); + m_avm_readdata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + m_avm_readdatavalid_i : in std_logic; + m_avm_waitrequest_i : in std_logic + ); +end entity avm_master_general; + +architecture synthesis of avm_master_general is + + signal avm_start : std_logic; + signal avm_wait : std_logic; + signal avm_write_burstcount : std_logic_vector(7 downto 0); + signal avm_read_burstcount : std_logic_vector(7 downto 0); + signal avm_write : std_logic; + signal avm_read : std_logic; + signal avm_address : std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + signal avm_writedata : std_logic_vector(G_DATA_SIZE-1 downto 0); + signal avm_byteenable : std_logic_vector(G_DATA_SIZE/8-1 downto 0); + signal avm_burstcount : std_logic_vector(7 downto 0); + signal avm_readdata : std_logic_vector(G_DATA_SIZE-1 downto 0); + signal avm_readdatavalid : std_logic; + signal avm_waitrequest : std_logic; + +begin + + --------------------------------------------------------- + -- Instantiate burst controller + --------------------------------------------------------- + + i_burst_ctrl : entity work.burst_ctrl + port map ( + clk_i => clk_i, + rst_i => rst_i, + start_i => start_i, + wait_o => wait_o, + start_o => avm_start, + wait_i => avm_wait, + write_burstcount_o => avm_write_burstcount, + read_burstcount_o => avm_read_burstcount + ); -- i_burst_ctrl + + + --------------------------------------------------------- + -- Instantiate Master + --------------------------------------------------------- + + i_avm_master : entity work.avm_master + generic map ( + G_ADDRESS_SIZE => G_ADDRESS_SIZE, + G_DATA_SIZE => G_DATA_SIZE + ) + port map ( + clk_i => clk_i, + rst_i => rst_i, + start_i => avm_start, + wait_o => avm_wait, + write_burstcount_i => avm_write_burstcount, + read_burstcount_i => avm_read_burstcount, + avm_write_o => avm_write, + avm_read_o => avm_read, + avm_address_o => avm_address, + avm_writedata_o => avm_writedata, + avm_byteenable_o => avm_byteenable, + avm_burstcount_o => avm_burstcount, + avm_readdata_i => avm_readdata, + avm_readdatavalid_i => avm_readdatavalid, + avm_waitrequest_i => avm_waitrequest + ); -- i_avm_master + + + --------------------------------------------------------- + -- Generate pauses in master trafic + --------------------------------------------------------- + + i_avm_pause_master : entity work.avm_pause + generic map ( + G_PAUSE => 0, + G_ADDRESS_SIZE => G_ADDRESS_SIZE, + G_DATA_SIZE => G_DATA_SIZE + ) + port map ( + clk_i => clk_i, + rst_i => rst_i, + s_avm_write_i => avm_write, + s_avm_read_i => avm_read, + s_avm_address_i => avm_address, + s_avm_writedata_i => avm_writedata, + s_avm_byteenable_i => avm_byteenable, + s_avm_burstcount_i => avm_burstcount, + s_avm_readdata_o => avm_readdata, + s_avm_readdatavalid_o => avm_readdatavalid, + s_avm_waitrequest_o => avm_waitrequest, + m_avm_write_o => m_avm_write_o, + m_avm_read_o => m_avm_read_o, + m_avm_address_o => m_avm_address_o, + m_avm_writedata_o => m_avm_writedata_o, + m_avm_byteenable_o => m_avm_byteenable_o, + m_avm_burstcount_o => m_avm_burstcount_o, + m_avm_readdata_i => m_avm_readdata_i, + m_avm_readdatavalid_i => m_avm_readdatavalid_i, + m_avm_waitrequest_i => m_avm_waitrequest_i + ); -- i_avm_pause_master + +end architecture synthesis; + diff --git a/testsuite/gna/issue2185/avm_memory.vhd b/testsuite/gna/issue2185/avm_memory.vhd new file mode 100644 index 000000000..9c045d7cb --- /dev/null +++ b/testsuite/gna/issue2185/avm_memory.vhd @@ -0,0 +1,88 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avm_memory 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; + avm_write_i : in std_logic; + avm_read_i : in std_logic; + avm_address_i : in std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + avm_writedata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + avm_byteenable_i : in std_logic_vector(G_DATA_SIZE/8-1 downto 0); + avm_burstcount_i : in std_logic_vector(7 downto 0); + avm_readdata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + avm_readdatavalid_o : out std_logic; + avm_waitrequest_o : out std_logic + ); +end entity avm_memory; + +architecture simulation of avm_memory is + + -- This defines a type containing an array of bytes + type mem_t is array (0 to 2**G_ADDRESS_SIZE-1) of std_logic_vector(G_DATA_SIZE-1 downto 0); + + signal write_burstcount : std_logic_vector(7 downto 0); + signal write_address : std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + + signal read_burstcount : std_logic_vector(7 downto 0); + signal read_address : std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + + signal mem_write_burstcount : std_logic_vector(7 downto 0); + signal mem_read_burstcount : std_logic_vector(7 downto 0); + signal mem_write_address : std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + signal mem_read_address : std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + +begin + + mem_write_address <= avm_address_i when write_burstcount = X"00" else write_address; + mem_read_address <= avm_address_i when read_burstcount = X"00" else read_address; + mem_write_burstcount <= avm_burstcount_i when write_burstcount = X"00" else write_burstcount; + mem_read_burstcount <= avm_burstcount_i when read_burstcount = X"00" else read_burstcount; + + avm_waitrequest_o <= '0' when unsigned(read_burstcount) = 0 else '1'; + + p_mem : process (clk_i) + variable mem : mem_t; + begin + if rising_edge(clk_i) then + avm_readdatavalid_o <= '0'; + + if avm_write_i = '1' and avm_waitrequest_o = '0' then + write_address <= std_logic_vector(unsigned(mem_write_address) + 1); + write_burstcount <= std_logic_vector(unsigned(mem_write_burstcount) - 1); + + report "Writing 0x" & to_hstring(avm_writedata_i) & " to 0x" & to_hstring(mem_write_address) & + " with burstcount " & to_hstring(write_burstcount); + for b in 0 to G_DATA_SIZE/8-1 loop + if avm_byteenable_i(b) = '1' then + mem(to_integer(unsigned(mem_write_address)))(8*b+7 downto 8*b) := avm_writedata_i(8*b+7 downto 8*b); + end if; + end loop; + end if; + + if (avm_read_i = '1' and avm_waitrequest_o = '0') or to_integer(unsigned(read_burstcount)) > 0 then + read_address <= std_logic_vector(unsigned(mem_read_address) + 1); + read_burstcount <= std_logic_vector(unsigned(mem_read_burstcount) - 1); + + avm_readdata_o <= mem(to_integer(unsigned(mem_read_address))); + avm_readdatavalid_o <= '1'; + + report "Reading 0x" & to_hstring(mem(to_integer(unsigned(mem_read_address)))) & " from 0x" & to_hstring(mem_read_address) & + " with burstcount " & to_hstring(read_burstcount); + end if; + + if rst_i = '1' then + write_burstcount <= (others => '0'); + read_burstcount <= (others => '0'); + end if; + end if; + end process p_mem; + +end architecture simulation; + diff --git a/testsuite/gna/issue2185/avm_pause.vhd b/testsuite/gna/issue2185/avm_pause.vhd new file mode 100644 index 000000000..6cd8baba6 --- /dev/null +++ b/testsuite/gna/issue2185/avm_pause.vhd @@ -0,0 +1,74 @@ +-- This module inserts empty wait cycles into an Avalon Memory Map stream. +-- The throughput is 1 - 1/G_PAUSE. +-- So a value of 4 results in a 75% throughput. +-- +-- 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_pause is + generic ( + G_PAUSE : integer; + 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; + s_avm_write_i : in std_logic; + s_avm_read_i : in std_logic; + s_avm_address_i : in std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + s_avm_writedata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + s_avm_byteenable_i : in std_logic_vector(G_DATA_SIZE/8-1 downto 0); + s_avm_burstcount_i : in std_logic_vector(7 downto 0); + s_avm_readdata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + s_avm_readdatavalid_o : out std_logic; + s_avm_waitrequest_o : out std_logic; + m_avm_write_o : out std_logic; + m_avm_read_o : out std_logic; + m_avm_address_o : out std_logic_vector(G_ADDRESS_SIZE-1 downto 0); + m_avm_writedata_o : out std_logic_vector(G_DATA_SIZE-1 downto 0); + m_avm_byteenable_o : out std_logic_vector(G_DATA_SIZE/8-1 downto 0); + m_avm_burstcount_o : out std_logic_vector(7 downto 0); + m_avm_readdata_i : in std_logic_vector(G_DATA_SIZE-1 downto 0); + m_avm_readdatavalid_i : in std_logic; + m_avm_waitrequest_i : in std_logic + ); +end entity avm_pause; + +architecture synthesis of avm_pause is + + signal cnt : integer range 0 to G_PAUSE; + signal allow : std_logic; + +begin + + p_cnt : process (clk_i) + begin + if rising_edge(clk_i) then + if m_avm_waitrequest_i = '0' then + cnt <= (cnt + 1) mod G_PAUSE; + end if; + + if rst_i = '1' then + cnt <= 0; + end if; + end if; + end process p_cnt; + + allow <= '1' when cnt /= 0 or G_PAUSE = 0 else '0'; + + m_avm_write_o <= s_avm_write_i and allow; + m_avm_read_o <= s_avm_read_i and allow; + m_avm_address_o <= s_avm_address_i; + m_avm_writedata_o <= s_avm_writedata_i; + m_avm_byteenable_o <= s_avm_byteenable_i; + m_avm_burstcount_o <= s_avm_burstcount_i; + s_avm_readdata_o <= m_avm_readdata_i; + s_avm_readdatavalid_o <= m_avm_readdatavalid_i; + s_avm_waitrequest_o <= m_avm_waitrequest_i or not allow; + +end architecture synthesis; + diff --git a/testsuite/gna/issue2185/burst_ctrl.vhd b/testsuite/gna/issue2185/burst_ctrl.vhd new file mode 100644 index 000000000..56559dd2c --- /dev/null +++ b/testsuite/gna/issue2185/burst_ctrl.vhd @@ -0,0 +1,88 @@ +-- This generates a sequence of commands with varying values +-- of write_burstcount and read_burstcount. +-- Signals start_i and wait_o are connected "upstream", in this case +-- to the keyboard LEDs, while start_o and wait_i are connected "downstream", +-- in this case to the avm_master entity. +-- +-- 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 burst_ctrl is + port ( + clk_i : in std_logic; + rst_i : in std_logic; + -- Connect "upstream", i.e. to keyboard and LED + start_i : in std_logic; + wait_o : out std_logic; + -- Connect "downstream", i.e. to avm_master + start_o : out std_logic; + wait_i : in std_logic; + write_burstcount_o : out std_logic_vector(7 downto 0); + read_burstcount_o : out std_logic_vector(7 downto 0) + ); +end entity burst_ctrl; + +architecture synthesis of burst_ctrl is + + constant C_MAX_BURST : std_logic_vector(7 downto 0) := X"08"; + + type state_t is ( + IDLE_ST, + BUSY_ST + ); + + signal state : state_t; + +begin + + p_fsm : process (clk_i) + begin + if rising_edge(clk_i) then + -- Clear outgoing request when accepted + if wait_i = '0' then + start_o <= '0'; + end if; + + case state is + when IDLE_ST => + if start_i = '1' then + start_o <= '1'; + state <= BUSY_ST; + end if; + + when BUSY_ST => + if wait_i = '0' and start_o = '0' then + start_o <= '1'; + + if write_burstcount_o /= C_MAX_BURST then + write_burstcount_o <= write_burstcount_o(6 downto 0) & "0"; + else + write_burstcount_o <= X"01"; + if read_burstcount_o /= C_MAX_BURST then + read_burstcount_o <= read_burstcount_o(6 downto 0) & "0"; + else + read_burstcount_o <= X"01"; + start_o <= '0'; + state <= IDLE_ST; + report "Test completed"; + end if; + end if; + end if; + end case; + + if rst_i = '1' then + start_o <= '0'; + write_burstcount_o <= X"01"; + read_burstcount_o <= X"01"; + end if; + + end if; + end process p_fsm; + + wait_o <= '0' when state = IDLE_ST else '1'; + +end architecture synthesis; + diff --git a/testsuite/gna/issue2185/tb_avm_arbit.vhd b/testsuite/gna/issue2185/tb_avm_arbit.vhd new file mode 100644 index 000000000..a4e386c08 --- /dev/null +++ b/testsuite/gna/issue2185/tb_avm_arbit.vhd @@ -0,0 +1,220 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity tb_avm_arbit is +end entity tb_avm_arbit; + +architecture simulation of tb_avm_arbit is + + constant C_DATA_SIZE : integer := 16; + constant C_ADDRESS_SIZE : integer := 4; + + signal clk : std_logic; + signal rst : std_logic; + signal tb_start : std_logic; + signal tb_wait : std_logic; + signal stop_test : std_logic := '0'; + + signal m0_avm_wait : std_logic; + signal m0_avm_write : std_logic; + signal m0_avm_read : std_logic; + signal m0_avm_address : std_logic_vector(C_ADDRESS_SIZE-1 downto 0); + signal m0_avm_writedata : std_logic_vector(C_DATA_SIZE-1 downto 0); + signal m0_avm_byteenable : std_logic_vector(C_DATA_SIZE/8-1 downto 0); + signal m0_avm_burstcount : std_logic_vector(7 downto 0); + signal m0_avm_readdata : std_logic_vector(C_DATA_SIZE-1 downto 0); + signal m0_avm_readdatavalid : std_logic; + signal m0_avm_waitrequest : std_logic; + + signal m1_avm_wait : std_logic; + signal m1_avm_write : std_logic; + signal m1_avm_read : std_logic; + signal m1_avm_address : std_logic_vector(C_ADDRESS_SIZE-1 downto 0); + signal m1_avm_writedata : std_logic_vector(C_DATA_SIZE-1 downto 0); + signal m1_avm_byteenable : std_logic_vector(C_DATA_SIZE/8-1 downto 0); + signal m1_avm_burstcount : std_logic_vector(7 downto 0); + signal m1_avm_readdata : std_logic_vector(C_DATA_SIZE-1 downto 0); + signal m1_avm_readdatavalid : std_logic; + signal m1_avm_waitrequest : std_logic; + + signal s_avm_write : std_logic; + signal s_avm_read : std_logic; + signal s_avm_address : std_logic_vector(C_ADDRESS_SIZE-1 downto 0); + signal s_avm_writedata : std_logic_vector(C_DATA_SIZE-1 downto 0); + signal s_avm_byteenable : std_logic_vector(C_DATA_SIZE/8-1 downto 0); + signal s_avm_burstcount : std_logic_vector(7 downto 0); + signal s_avm_readdata : std_logic_vector(C_DATA_SIZE-1 downto 0); + signal s_avm_readdatavalid : std_logic; + signal s_avm_waitrequest : std_logic; + + constant C_CLK_PERIOD : time := 10 ns; + +begin + + --------------------------------------------------------- + -- Controller clock and reset + --------------------------------------------------------- + + p_clk : process + begin + clk <= '1'; + wait for C_CLK_PERIOD/2; + clk <= '0'; + wait for C_CLK_PERIOD/2; + if stop_test = '1' then + wait; + end if; + end process p_clk; + + p_rst : process + begin + rst <= '1'; + wait for 10*C_CLK_PERIOD; + wait until clk = '1'; + rst <= '0'; + wait; + end process p_rst; + + + p_tb_start : process + begin + tb_start <= '0'; + wait until rst = '0'; + wait until clk = '1'; + tb_start <= '1'; + wait until clk = '1'; + tb_start <= '0'; + wait; + end process p_tb_start; + + p_stop_test : process + begin + wait until tb_start = '1'; + wait until m0_avm_wait = '0' and m1_avm_wait = '0'; + wait until clk = '1'; + stop_test <= '1'; + wait; + end process p_stop_test; + + + + --------------------------------------------------------- + -- Instantiate Master 0 + --------------------------------------------------------- + + i_avm_master_general0 : entity work.avm_master_general + generic map ( + G_ADDRESS_SIZE => C_ADDRESS_SIZE, + G_DATA_SIZE => C_DATA_SIZE + ) + port map ( + clk_i => clk, + rst_i => rst, + start_i => tb_start, + wait_o => m0_avm_wait, + m_avm_write_o => m0_avm_write, + m_avm_read_o => m0_avm_read, + m_avm_address_o => m0_avm_address, + m_avm_writedata_o => m0_avm_writedata, + m_avm_byteenable_o => m0_avm_byteenable, + m_avm_burstcount_o => m0_avm_burstcount, + m_avm_readdata_i => m0_avm_readdata, + m_avm_readdatavalid_i => m0_avm_readdatavalid, + m_avm_waitrequest_i => m0_avm_waitrequest + ); -- i_avm_master_general0 + + + --------------------------------------------------------- + -- Instantiate Master 1 + --------------------------------------------------------- + + i_avm_master_general1 : entity work.avm_master_general + generic map ( + G_ADDRESS_SIZE => C_ADDRESS_SIZE, + G_DATA_SIZE => C_DATA_SIZE + ) + port map ( + clk_i => clk, + rst_i => rst, + start_i => tb_start, + wait_o => m1_avm_wait, + m_avm_write_o => m1_avm_write, + m_avm_read_o => m1_avm_read, + m_avm_address_o => m1_avm_address, + m_avm_writedata_o => m1_avm_writedata, + m_avm_byteenable_o => m1_avm_byteenable, + m_avm_burstcount_o => m1_avm_burstcount, + m_avm_readdata_i => m1_avm_readdata, + m_avm_readdatavalid_i => m1_avm_readdatavalid, + m_avm_waitrequest_i => m1_avm_waitrequest + ); -- i_avm_master_general1 + + + --------------------------------------------------------- + -- DUT + --------------------------------------------------------- + + i_avm_arbit : entity work.avm_arbit + generic map ( + G_ADDRESS_SIZE => C_ADDRESS_SIZE, + G_DATA_SIZE => C_DATA_SIZE + ) + port map ( + clk_i => clk, + rst_i => rst, + s0_avm_write_i => m0_avm_write , + s0_avm_read_i => m0_avm_read , + s0_avm_address_i => m0_avm_address , + s0_avm_writedata_i => m0_avm_writedata , + s0_avm_byteenable_i => m0_avm_byteenable , + s0_avm_burstcount_i => m0_avm_burstcount , + s0_avm_readdata_o => m0_avm_readdata , + s0_avm_readdatavalid_o => m0_avm_readdatavalid , + s0_avm_waitrequest_o => m0_avm_waitrequest , + s1_avm_write_i => m1_avm_write , + s1_avm_read_i => m1_avm_read , + s1_avm_address_i => m1_avm_address , + s1_avm_writedata_i => m1_avm_writedata , + s1_avm_byteenable_i => m1_avm_byteenable , + s1_avm_burstcount_i => m1_avm_burstcount , + s1_avm_readdata_o => m1_avm_readdata , + s1_avm_readdatavalid_o => m1_avm_readdatavalid , + s1_avm_waitrequest_o => m1_avm_waitrequest , + m_avm_write_o => s_avm_write , + m_avm_read_o => s_avm_read , + m_avm_address_o => s_avm_address , + m_avm_writedata_o => s_avm_writedata , + m_avm_byteenable_o => s_avm_byteenable , + m_avm_burstcount_o => s_avm_burstcount , + m_avm_readdata_i => s_avm_readdata , + m_avm_readdatavalid_i => s_avm_readdatavalid , + m_avm_waitrequest_i => s_avm_waitrequest + ); -- i_avm_arbit + + + --------------------------------------------------------- + -- Instantiate Slave + --------------------------------------------------------- + + i_avm_memory : entity work.avm_memory + generic map ( + G_ADDRESS_SIZE => C_ADDRESS_SIZE, + G_DATA_SIZE => C_DATA_SIZE + ) + port map ( + clk_i => clk, + rst_i => rst, + avm_write_i => s_avm_write, + avm_read_i => s_avm_read, + avm_address_i => s_avm_address, + avm_writedata_i => s_avm_writedata, + avm_byteenable_i => s_avm_byteenable, + avm_burstcount_i => s_avm_burstcount, + avm_readdata_o => s_avm_readdata, + avm_readdatavalid_o => s_avm_readdatavalid, + avm_waitrequest_o => s_avm_waitrequest + ); -- i_avm_memory + +end architecture simulation; + diff --git a/testsuite/gna/issue2185/testsuite.sh b/testsuite/gna/issue2185/testsuite.sh new file mode 100755 index 000000000..5c3a46d9a --- /dev/null +++ b/testsuite/gna/issue2185/testsuite.sh @@ -0,0 +1,21 @@ +#! /bin/sh + +. ../../testenv.sh + +export GHDL_STD_FLAGS=--std=08 + +FILES=" +burst_ctrl.vhd +avm_master.vhd +avm_pause.vhd +avm_master_general.vhd +avm_arbit.vhd +avm_memory.vhd +tb_avm_arbit.vhd +" +analyze $FILES +elab_simulate_failure tb_avm_arbit --assert-level=error --stop-time=50us + +clean + +echo "Test successful" |