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; 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*21; 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 wr : std_logic; signal tx_char : unsigned (7 downto 0); 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 * period, x"00" after 100 * period, x"ff" after 150 * period, x"aa" after 200 * 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 ); -- 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; -- 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;