-------------------------------------------------- -- Name: Lab4_2_tb -- Version: 2.1 -- Description: Test bench for Lab4_2 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity Lab4_2_tb is end entity; architecture sim of Lab4_2_tb is -- Declare the pins of the unit we are going to test: component Lab4_2 is port(clk, clrn : in std_logic; start : in std_logic; cs1,cs2 : out std_logic; addr : out unsigned(3 downto 0); data : in std_logic_vector(3 downto 0); LED : out std_logic; BCD2,BCD1,BCD0 : out unsigned(3 downto 0)); end component; -- Declare the use I/O signals: signal clk, clrn : std_logic := '1'; signal start : std_logic := '0'; signal cs1,cs2 : std_logic; signal addr : unsigned(3 downto 0); signal data : std_logic_vector(3 downto 0); signal LED : std_logic; signal BCD2,BCD1,BCD0 : unsigned(3 downto 0); -- Declare some other signals we need: signal done : boolean := false; signal watchdog : integer := 0; type ROM_t is array (0 to 15) of std_logic_vector(7 downto 0); -- Both ROMs beside each others signal ROM : ROM_t := (others=>(others=>'0')); -- The ROMs starts with just zeros. signal expected_res : integer; begin -- Create clock and timeout signals clk <= not clk after 5 ms when not done; -- 10 ms. This is required in on of the tests. process(clk,clrn) begin if clrn = '0' then watchdog <= 0; elsif rising_edge(clk) then watchdog <= watchdog + 1; if start = '1' then watchdog <= 0; end if; -- If watchdog too big: Report it, and the "severity failure" will kill the simulation. assert watchdog < 1024 report "Watchdog timeout. You did not finish in 1024 clock cycles." severity failure; end if; end process; -- Create stimuli, and check sanity process variable cnt : integer; begin -- Test 0: Just zeros. clrn <= '0', '1' after 12 ms; -- First clear the system, and refine the ROM content. ROM <= (others=>(others=>'0')); -- Meaning: (all rows are: (all bits are: '0')) expected_res <= 0; -- We expect the result to be all-zeros. wait until clrn = '1'; -- Release the clear signal start <= '1' after 12 ms, '0' after 55 ms; -- Define a wave form for the start signal. wait for 55 ms; -- Then wait for a while wait until LED = '0'; -- Wait until the output is ready wait until rising_edge(clk); -- ...and yet another clock cycle. cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); -- cnt is now an integer version of the BCD digits if cnt = expected_res then -- Print the result report "Test 0: OK (archieved = expected = "&integer'image(cnt)&")." severity note; else report "Test 0: NOK (archieved="&integer'image(cnt)&", expected="&integer'image(expected_res)&")." severity warning; end if; -- Test 1: Just ones. ROM <= (others=>(others=>'1')); expected_res <= 128; start <= '1' after 12 ms, '0' after 55 ms; wait for 55 ms; wait until LED = '0'; wait until rising_edge(clk); cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); if cnt = expected_res then report "Test 1: OK (archieved = expected = "&integer'image(cnt)&")." severity note; else report "Test 1: NOK (archieved="&integer'image(cnt)&", expected="&integer'image(expected_res)&")." severity warning; end if; -- Test 2: Random data ROM <= (0=>"00100000", -- 1 = number of ones on this row 1=>"00000000", -- 0 2=>"11000101", -- 4 3=>"10010101", -- 4 4=>"00100011", -- 3 5=>"11111111", -- 8 6=>"01010101", -- 4 7=>"10101001", -- 4 8=>"00010010", -- 2 9=>"10110100", -- 4 10=>"01100101", -- 4 11=>"11010010", -- 4 12=>"10100011", -- 4 13=>"11110000", -- 4 14=>"00100101", -- 3 15=>"10110010");-- 4 expected_res <= 57; wait until rising_edge(clk); start <= '1'; wait until rising_edge(clk); start <= '0'; wait for 55 ms; wait until LED = '0'; wait until rising_edge(clk); cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); if cnt = expected_res then report "Test 2: OK (archieved = expected = "&integer'image(cnt)&")." severity note; else report "Test 2: NOK (archieved="&integer'image(cnt)&", expected="&integer'image(expected_res)&")." severity warning; end if; -- Test 3: 99 ones ROM <= (0=>"01101100", -- 4 4 1=>"01110110", -- 5 9 2=>"00000000", -- 0 9 3=>"11111111", -- 8 17 4=>"11111111", -- 8 25 5=>"11111111", -- 8 33 6=>"11111111", -- 8 41 7=>"11111111", -- 8 49 8=>"11111111", -- 8 57 9=>"01111110", -- 6 63 10=>"01111011", -- 6 69 11=>"10111111", -- 7 76 12=>"11011111", -- 7 83 13=>"11000011", -- 4 87 14=>"10111101", -- 6 93 15=>"01111110");-- 6 99 expected_res <= 99; wait for 12 ms; wait until rising_edge(clk); start <= '1'; wait until rising_edge(clk); start <= '0'; wait for 55 ms; wait until LED = '0'; wait until rising_edge(clk); cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); if cnt = expected_res then report "Test 3: OK (archieved = expected = "&integer'image(cnt)&")." severity note; else report "Test 3: NOK (archieved="&integer'image(cnt)&", expected="&integer'image(expected_res)&")." severity warning; end if; -- Test 4: Corner cases ROM <= (0=>"10011001", 1 to 14=>"00000000", 15=>"10011001"); expected_res <= 8; wait for 12 ms; wait until rising_edge(clk); start <= '1'; wait until rising_edge(clk); start <= '0'; wait for 55 ms; wait until LED = '0'; wait until rising_edge(clk); cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); if cnt = expected_res then report "Test 4: OK (archieved = expected = "&integer'image(cnt)&")." severity note; else report "Test 4: NOK (archieved="&integer'image(cnt)&", expected="&integer'image(expected_res)&")." severity warning; end if; -- Test 5: Here comes misc small tests. Only output when NOK. -- Remember: Clock period is 10 ms -- Test 5a: Synchronous input. -- Give a short start pulse between two clock flanks. This should not start any counting. start <= '1' after 3 ms, '0' after 7 ms; -- Define a pulse around three clock cycles. wait for 5 ms; -- In the middle of the start pulse. cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); assert LED = '0' report "Test 5a1: NOK. LED turned on asynchronous" severity warning; assert cnt = expected_res report "Test 5a2: NOK. BCD changed asynchronous (or prev. test failed)" severity warning; wait for 55 ms; -- by now it should have started, if it detected the start pulse. assert LED = '0' report "Test 5a3: NOK. The start must have been detected assynchronous" severity warning; wait until rising_edge(clk); -- Test 5b: Asynchronous reset. -- Start a new count and pull the reset in the middle. ROM <= (others => "11111111"); -- Fill with ones, to give a quicker count start <= '1' after 3 ms, '0' after 55 ms; wait for 100 ms; -- Wait a few clock cycles, to make sure the counting has reached the output wait until rising_edge(clk); cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); assert LED = '1' and cnt > 0 report "Unexpected: After several clock cycles, LED turned off and count is still zero. Cannot test the reset." severity warning; clrn <= '0' after 2 ms, '1' after 3 ms; -- Asyncronous clear in the middle. wait for 4 ms; cnt := 100*to_integer(BCD2) + 10*to_integer(BCD1) + to_integer(BCD0); assert LED = '0' and cnt = 0 report "Test 5b: NOK. rstn is not asynchronous. LED or cnt not cleared." severity warning; -- Finalize: report "Done" severity note; done <= true; -- stop the clock using this signal wait; -- wait forever (otherwise the process will start over again) end process; -- Emulate the ROM: assert not(cs1 = '0' and cs2 = '0') report "NOK: Trying to address both memories in the same time" severity warning; data <= ROM(to_integer(addr))(7 downto 4) when cs1 = '0' and cs2 = '1' else ROM(to_integer(addr))(3 downto 0) when cs1 = '1' and cs2 = '0' else "XXXX"; -- Instantiate the design under test (DUT): DUT : LAB4_2 port map( clk => clk, -- The "port-signal => local-signal" is a "connected to", regardless of data direction clrn => clrn, start => start, cs1 => cs1, cs2 => cs2, addr => addr, data => data, LED => LED, BCD2 => BCD2, BCD1 => BCD1, BCD0 => BCD0); end architecture;