library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use IEEE.math_real.all; entity async_8n1_tx_tb is end entity; architecture beh of async_8n1_tx_tb is component generic_prescaler is generic ( prescaler_bits : integer := 13 ); port( clk : in std_logic; rst : in std_logic; en : in std_logic; load : in std_logic; prescaler_value : in unsigned (prescaler_bits - 1 downto 0); en_out : out std_logic ); end component; component async_8n1_tx is port ( clk : in std_logic; rst : in std_logic; en : in std_logic; wr : in std_logic; data_in : in unsigned (7 downto 0); rdy : out std_logic; data_out : out std_logic ); end component; component async_8n1_tx_v2 is port ( clk : in std_logic; rst : in std_logic; en : in std_logic; wr : in std_logic; data_in : in unsigned (7 downto 0); rdy : out std_logic; data_out : out std_logic ); end component; component async_8n1_rx is port ( clk : in std_logic; rst : in std_logic; en : in std_logic; read : in std_logic; data_in : in std_logic; data_available : out std_logic; frame_error : out std_logic; overflow_error : out std_logic; data_out : out unsigned (7 downto 0) ); end component; constant freq : integer := 50; -- MHz constant period : time := 1000 / freq * 1 ns; constant half_period : time := period / 2; signal num_rising_edges : integer := 0; constant simulation_periods : integer := 5155*121; signal clock : std_logic := '0'; signal enable : std_logic; signal reset : std_logic; signal prescaled_clk_en : std_logic; constant prescaler_value : integer := 5154; constant prescaler_num_bits : integer := integer(ceil(log2(real(prescaler_value)))); signal running : boolean := true; signal tx1 : std_logic; signal rdy1 : std_logic; signal tx2 : std_logic; signal rdy2 : std_logic; signal rx_available : std_logic; signal rx_read : std_logic := '0'; signal wr : std_logic; signal tx_char : unsigned (7 downto 0); signal rx_char : unsigned (7 downto 0); type hex_arr is array (0 to 3) of unsigned(7 downto 0); signal tx_char_buffer : hex_arr := (x"aa", x"55", x"00", x"ff"); begin running <= true, false after simulation_periods * period; reset <= '0', '1' after 2 * period, '0' after 3 * period; enable <= '0', '1' after 5 * period; wr <= '0', '1' after 10 * period, '1' after 11 * period; --tx_char <= to_unsigned(character'pos('a'), 8); --tx_char <= x"aa", -- x"55" after 50 * prescaler_value * period, -- x"00" after 100 * prescaler_value * period, -- x"ff" after 150 * prescaler_value * period, -- x"aa" after 200 * prescaler_value * period; i_prescaler : generic_prescaler generic map( prescaler_bits => prescaler_num_bits ) port map( clk => clock, rst => reset, en => enable, load => '1', prescaler_value => to_unsigned(prescaler_value, prescaler_num_bits), en_out => prescaled_clk_en ); DUT1 : async_8n1_tx port map( clk => clock, rst => reset, en => prescaled_clk_en, wr => wr, data_in => tx_char, rdy => rdy1, data_out => tx1 ); DUT2 : async_8n1_tx_v2 port map( clk => clock, rst => reset, en => prescaled_clk_en, wr => wr, data_in => tx_char, rdy => rdy2, data_out => tx2 ); DUT3 : async_8n1_rx port map( clk => clock, rst => reset, en => prescaled_clk_en, read => rx_read, data_in => tx2, data_available => rx_available, frame_error => open, overflow_error => open, data_out => rx_char ); -- clock process process is begin if running then wait for half_period; clock <= not clock; else report "End of simulation!"; wait; end if; end process; process(tx_char) is begin --wait for half_period; --report time'image(period); report "Tx-char: " & integer'image(to_integer(tx_char)); --wait; end process; -- simulate a read operation after every received byte process is begin wait until rx_available = '1'; wait for prescaler_value * period; rx_read <= '1'; wait until rx_available = '0'; wait for prescaler_value * period; rx_read <= '0'; end process; -- Loop through the tx char buffer everythime a transceiver is ready process is begin for i in tx_char_buffer'range loop wait until rdy1 = '1'; tx_char <= tx_char_buffer(i); wait until rdy1 = '0'; end loop; end process; -- Rising edge counter process(clock) is begin if rising_edge(clock) then if reset = '1' then num_rising_edges <= 0; elsif enable = '1' then num_rising_edges <= num_rising_edges+1; else -- Explicit no change num_rising_edges <= num_rising_edges; end if; end if; end process; -- Automated checks process(clock) is begin if rising_edge(clock) and num_rising_edges > 1 then assert not (num_rising_edges mod prescaler_value = 0 and prescaled_clk_en /= '1') report "Prescaler not working!" severity error; assert tx1 = tx2 report "Transciever tx disagreement" severity error; assert rdy1 = rdy2 report "Transciever rdy disagreement" severity error; end if; end process; end architecture;