------------------------------------------------------- -- Project : TKT-1212 Digitaalijärjestelmien toteutus -- Author : Petteri Aimonen, student number 205441, group 50 -- Date : 2009-02-28 -- File : tb_audio_ctrl.vhd -- Design: Course exercise 8: Testbench for audio codec controller ------------------------------------------------------ -- Description : Verifies behaviour of audio_ctrl. ------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity tb_audio_ctrl is generic ( data_width_g : integer := 16; clk_freq_g : integer := 18432000; sample_rate_g : integer := 48000; simulation_length_g : time := 2 ms ); end entity; architecture testbench of tb_audio_ctrl is component wave_gen generic ( width_g : integer; step_g : integer ); port ( rst_n : in std_logic; clk : in std_logic; sync_clear_in : in std_logic; value_out : out std_logic_vector(width_g - 1 downto 0) ); end component; component audio_codec_model is generic ( data_width_g : integer ); port ( rst_n : in std_logic; aud_data_in : in std_logic; aud_bclk_in : in std_logic; aud_lrclk_in : in std_logic; value_left_out : out std_logic_vector(data_width_g - 1 downto 0); value_right_out : out std_logic_vector(data_width_g - 1 downto 0); sample_strobe_out : out std_logic ); end component; component audio_ctrl is generic( ref_clk_freq_g : integer; sample_rate_g : integer; data_width_g : integer ); port( clk : in std_logic; rst_n : in std_logic; left_data_in : in std_logic_vector(data_width_g - 1 downto 0); right_data_in : in std_logic_vector(data_width_g - 1 downto 0); aud_bclk_out : out std_logic; aud_data_out : out std_logic; aud_lrclk_out : out std_logic ); end component; -- Half-period of the generated clock signal constant clk_period_c : time := (1 sec) / (2 * clk_freq_g); -- Codec control signals signal aud_bclk : std_logic; signal aud_data : std_logic; signal aud_lrclk : std_logic; -- Generated audio signals signal generated_left : std_logic_vector(data_width_g - 1 downto 0); signal generated_right: std_logic_vector(data_width_g - 1 downto 0); -- Received audio signals signal received_left : std_logic_vector(data_width_g - 1 downto 0); signal received_right : std_logic_vector(data_width_g - 1 downto 0); signal received_strobe: std_logic; -- Clock and reset to devices signal clk_to_dut : std_logic; signal rst_to_dut : std_logic; -- Storage for transmitted samples for comparison -- Sample that will be received next signal receive_next_r : std_logic_vector(2 * data_width_g - 1 downto 0); -- Is this the first sample to be received? If '1', transmit_next_r -- is immediately moved to receive_next_r. signal first_sample_r : std_logic; -- Sample that will be transmitted next -- This is moved to receive_next_r each time a sample is received signal transmit_next_r: std_logic_vector(2 * data_width_g - 1 downto 0); -- Count received samples to verify samplerate signal sample_count_r : integer; -- Previous value of aud_bclk to detect edges in transmit_proc signal bclk_prev_r : std_logic; -- Previous generated values for storing in transmit_proc signal values_prev_r : std_logic_vector(2 * data_width_g - 1 downto 0); begin i_wave_gen_0 : wave_gen generic map (width_g => data_width_g, step_g => 4) port map ( rst_n => rst_to_dut, clk => clk_to_dut, sync_clear_in => '0', value_out => generated_left ); i_wave_gen_1 : wave_gen generic map (width_g => data_width_g, step_g => 2) port map ( rst_n => rst_to_dut, clk => clk_to_dut, sync_clear_in => '0', value_out => generated_right ); i_audio_codec_model : audio_codec_model generic map (data_width_g => data_width_g) port map ( rst_n => rst_to_dut, aud_data_in => aud_data, aud_bclk_in => aud_bclk, aud_lrclk_in => aud_lrclk, value_left_out => received_left, value_right_out => received_right, sample_strobe_out => received_strobe ); i_audio_ctrl : audio_ctrl generic map ( ref_clk_freq_g => clk_freq_g, sample_rate_g => sample_rate_g, data_width_g => data_width_g ) port map ( clk => clk_to_dut, rst_n => rst_to_dut, left_data_in => generated_left, right_data_in => generated_right, aud_bclk_out => aud_bclk, aud_data_out => aud_data, aud_lrclk_out => aud_lrclk ); -- Clock generation process clk_gen_proc: process -- Current time (for ending simulation) variable time_now_v : time := 0 sec; -- We will send simulation_length_g * sample_rate_g samples. -- The last sample will not be received when simulation ends, thus - 1. variable expected_count_c : integer := (simulation_length_g * sample_rate_g) / (1 sec) - 1; begin -- Reset devices rst_to_dut <= '0'; wait for clk_period_c; rst_to_dut <= '1'; -- Generate clock cycles while time_now_v <= simulation_length_g loop clk_to_dut <= '1'; wait for clk_period_c; clk_to_dut <= '0'; wait for clk_period_c; time_now_v := time_now_v + clk_period_c * 2; end loop; -- Check sample count assert sample_count_r = expected_count_c report "Wrong number of samples received: " & integer'image(sample_count_r) & " vs. expected " & integer'image(expected_count_c) & "." severity FAILURE; -- End simulation report "Simulation ended, " & integer'image(sample_count_r) & " samples received." severity NOTE; wait; end process; -- Process to store reference samples transmit_proc: process(clk_to_dut) begin if rst_to_dut = '0' then transmit_next_r <= (others => '0'); values_prev_r <= (others => '0'); elsif rising_edge(clk_to_dut) then if aud_lrclk = '0' and aud_bclk = '0' and bclk_prev_r = '1' then -- audio_ctrl takes samples on the last falling bclk edge before -- switching aud_lrclk. -- However, we can only detect the falling edge on the next cycle, -- so we have to take the values through register. transmit_next_r <= values_prev_r; end if; bclk_prev_r <= aud_bclk; values_prev_r <= generated_left & generated_right; end if; end process; -- Process to check received samples receive_proc: process(aud_bclk) begin if rst_to_dut = '0' then receive_next_r <= (others => '0'); sample_count_r <= 0; first_sample_r <= '1'; elsif rising_edge(aud_bclk) then if first_sample_r = '1' then -- Store first reference sample. Usually this is done when receiving -- a sample. receive_next_r <= transmit_next_r; first_sample_r <= '0'; end if; if received_strobe = '1' then assert receive_next_r = received_left & received_right report "Sample number " & integer'image(sample_count_r) & " received wrong: expected (" & integer'image(to_integer(signed(receive_next_r(2 * data_width_g - 1 downto data_width_g)))) & ", " & integer'image(to_integer(signed(receive_next_r(data_width_g - 1 downto 0)))) & ") but got (" & integer'image(to_integer(signed(received_left))) & ", " & integer'image(to_integer(signed(received_right))) & ")." severity FAILURE; sample_count_r <= sample_count_r + 1; -- Store next reference sample receive_next_r <= transmit_next_r; end if; end if; end process; end architecture;