library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.fixed_float_types.all; use ieee.fixed_pkg.all; use ieee.math_real.all; use std.textio.all; entity low_pass_filter_test is end; architecture basic_test of low_pass_filter_test is signal clock_running : boolean := true; constant integer_bits : natural := 2; constant fraction_bits : natural := 32; subtype datapath_type is sfixed(integer_bits-1 downto -fraction_bits); signal frequency : natural range 1 to 40; signal clock : std_logic; signal reset : std_logic; signal sample : datapath_type; signal sample_ready : std_logic; signal result : datapath_type; signal result_ready : std_logic; signal sample_real : real; signal result_real : real; begin -- clock generator process constant clock_period : time := 250 ns; procedure generate_clock_cycle is constant high_time : time := clock_period / 2; constant low_time : time := clock_period - high_time; begin clock <= '0'; wait for low_time; clock <= '1'; wait for high_time; end; begin -- activate reset on startup for one clock cycle reset <= '1'; generate_clock_cycle; reset <= '0'; -- now run the clock until told to stop while clock_running loop generate_clock_cycle; end loop; -- stop event generation so that simulation can stop wait; end process; -- sample generator process constant sample_period : time := 6.25 us; procedure generate_sample(value : real) is constant ready_time : time := 500 ns; constant wait_time : time := sample_period - ready_time; begin sample_real <= value; sample_ready <= '1'; wait for ready_time; sample_ready <= '0'; wait for wait_time; end; variable step : real := 0.0; variable minmax : real := 0.0; variable l : line; begin -- there are 2 * pi (~6.3) radians in a cycle for f in 1 to 40 loop frequency <= f; -- generate a waveform which ranges from 1 to 40 kHz -- given a sample frequency of 160 kHz -- so converting to radians, step = f/160 * 2 * pi per sample step := real(f) * math_pi / 80.0; minmax := 0.0; for i in 1 to 1600 loop generate_sample(sin(step * real(i))); -- capture maximum absolute value -- allow waveform to stabilise before checking if i > 50 then minmax := realmax(minmax, sign(result_real) * result_real); end if; end loop; write(l, f); write(l, string'(" kHz = ")); write(l, minmax); writeline(output,l); end loop; clock_running <= false; wait; end process; sample <= to_sfixed(sample_real, sample); CUT : entity work.low_pass_filter generic map (integer_bits,fraction_bits) port map (clock, reset, sample, sample_ready, result, result_ready); result_real <= to_real(result); end; architecture noise_test of low_pass_filter_test is signal clock_running : boolean := true; signal frequency : natural range 1 to 40; signal clock : std_logic; signal reset : std_logic; signal sample_real : real; signal sample_ready : std_logic; constant reference_fraction : integer := 32; signal reference_sample : sfixed(1 downto -reference_fraction); signal reference_result : sfixed(1 downto -reference_fraction); signal reference_result_ready : std_logic; signal reference_real : real; constant actual_fraction : integer := 14; signal actual_sample : sfixed(1 downto -actual_fraction); signal actual_result : sfixed(1 downto -actual_fraction); signal actual_result_ready : std_logic; signal actual_real : real; signal difference : real; begin -- clock generator process constant clock_period : time := 250 ns; procedure generate_clock_cycle is constant high_time : time := clock_period / 2; constant low_time : time := clock_period - high_time; begin clock <= '0'; wait for low_time; clock <= '1'; wait for high_time; end; begin -- activate reset on startup for one clock cycle reset <= '1'; generate_clock_cycle; reset <= '0'; -- now run the clock until told to stop while clock_running loop generate_clock_cycle; end loop; -- stop event generation so that simulation can stop wait; end process; -- sample generator process constant sample_period : time := 6.25 us; procedure generate_sample(value : real) is constant ready_time : time := 500 ns; constant wait_time : time := sample_period - ready_time; begin sample_real <= value; sample_ready <= '1'; wait for ready_time; sample_ready <= '0'; wait for wait_time; end; variable step : real := 0.0; variable minmax : real := 0.0; variable l : line; begin -- there are 2 * pi (~6.3) radians in a cycle minmax := 0.0; for f in 1 to 40 loop frequency <= f; -- generate a waveform which ranges from 1 to 40 kHz -- given a sample frequency of 160 kHz -- so converting to radians, step = f/160 * 2 * pi per sample step := real(f) * math_pi / 80.0; for i in 1 to 1600 loop generate_sample(sin(step * real(i))); minmax := realmax(minmax, sign(difference) * difference); end loop; end loop; write(l, string'("2.")); write(l, actual_fraction); write(l, string'(" bits = ")); write(l, minmax); writeline(output,l); clock_running <= false; wait; end process; reference_sample <= to_sfixed(sample_real, reference_sample); reference : entity work.low_pass_filter generic map (2,reference_fraction) port map (clock, reset, reference_sample, sample_ready, reference_result, reference_result_ready); reference_real <= to_real(reference_result); actual_sample <= to_sfixed(sample_real, actual_sample); actual : entity work.low_pass_filter generic map (2,actual_fraction) port map (clock, reset, actual_sample, sample_ready, actual_result, actual_result_ready); actual_real <= to_real(actual_result); difference <= actual_real - reference_real; end;