Skip to content
Snippets Groups Projects
Commit c5e4601d authored by Pepping's avatar Pepping
Browse files

Copy fromold tree

parent c7ceeff3
Branches
No related tags found
No related merge requests found
-- Author: Harm Jan Pepping : HJP at astron.nl: April 2012
--------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--------------------------------------------------------------------------------
--
-- Purpose: Test bench for the single channel Poly Phase Filter unit
--
-- The testbech inserts an impulse on every band. The output
-- is verified by checking if the output values equal the
-- filter coefficients: It verifies the impulse-response.
--
-- Usage:
-- > run -all
-- > testbench is selftesting. The first four spectrums are verified.
--
library ieee, common_lib, dp_lib, diag_lib;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_textio.all;
use STD.textio.all;
use common_lib.common_pkg.all;
use common_lib.common_mem_pkg.ALL;
use common_lib.tb_common_pkg.all;
use common_lib.tb_common_mem_pkg.ALL;
use dp_lib.dp_stream_pkg.ALL;
use work.fil_pkg.all;
entity tb_fil_ppf_single is
generic(
-- generics for tb
g_fil_ppf_pipeline : t_fil_ppf_pipeline := (1, 1, 1, 1, 1, 1, 0);
-- type t_fil_pipeline is record
-- -- generic for the taps and coefficients memory
-- mem_delay : natural; -- = 2
-- -- generics for the multiplier in in the filter unit
-- mult_input : natural; -- = 1
-- mult_product : natural; -- = 1
-- mult_output : natural; -- = 1
-- -- generics for the adder tree in in the filter unit
-- adder_stage : natural; -- = 1
-- -- generics for the requantizer in the filter unit
-- requant_remove_lsb : natural; -- = 1
-- requant_remove_msb : natural; -- = 0
-- end record;
g_fil_ppf : t_fil_ppf := (1, 2, 512, 16, 4, 8, 23, 16);
-- type t_fil_ppf is record
-- wb_factor : natural; -- = 1, the wideband factor
-- nof_chan : natural; -- = default 0, defines the number of channels (=time-multiplexed input signals): nof channels = 2**nof_chan
-- nof_bands : natural; -- = 512, the number of subbands is N/2 (N=nof_points of the FFT)
-- nof_taps : natural; -- = 16, the number of FIR taps per subband
-- nof_streams : natural; -- = 1, the number of streams that are served by the same coefficients.
-- in_dat_w : natural; -- = 8, number of input bits per stream
-- out_dat_w : natural; -- = 23, number of output bits (per stream). It is set to 23 to be sure the requantizer does not remove
-- any of the data in order to be able to verify with the original coefficients values.
-- coef_dat_w : natural; -- = 16, data width of the FIR coefficients
-- end record;
g_file_index_arr : t_nat_natural_arr := array_init(0, 128, 1);
g_coefs_file_prefix : string := "../../data/coef"
);
end entity tb_fil_ppf_single;
architecture tb of tb_fil_ppf_single is
constant c_clk_period : time := 10 ns;
constant c_nof_coefs : natural := g_fil_ppf.nof_taps*g_fil_ppf.nof_bands*2**g_fil_ppf.nof_chan;
-- input/output data width
constant c_in_dat_w : natural := g_fil_ppf.in_dat_w;
constant c_out_dat_w : natural := g_fil_ppf.out_dat_w;
-- signal definitions
signal tb_end : std_logic := '0';
signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal ram_coefs_mosi : t_mem_mosi;
signal ram_coefs_miso : t_mem_miso;
signal in_dat : std_logic_vector(c_in_dat_w*g_fil_ppf.nof_streams-1 downto 0);
signal in_val : std_logic;
signal out_dat : std_logic_vector(c_out_dat_w*g_fil_ppf.nof_streams-1 downto 0);
signal out_val : std_logic;
signal ref_dat_arr : t_integer_arr(c_nof_coefs-1 downto 0);
signal ref_arr : t_integer_arr(g_fil_ppf.nof_bands-1 downto 0);
signal ref_dat : integer;
signal ref_index : natural;
begin
clk <= (not clk) or tb_end after c_clk_period/2;
rst <= '1', '0' after c_clk_period*7;
ram_coefs_mosi <= c_mem_mosi_rst; -- Reset the master out interface
---------------------------------------------------------------
-- SEND IMPULSE TO THE DATA INPUT
---------------------------------------------------------------
p_send_impulse : PROCESS
BEGIN
tb_end <= '0';
in_dat <= (OTHERS => '0');
in_val <= '0';
proc_common_wait_until_low(clk, rst); -- Wait until reset has finished
proc_common_wait_some_cycles(clk, 10); -- Wait an additional amount of cycles
FOR I IN 0 TO g_fil_ppf.nof_bands*(2**g_fil_ppf.nof_chan)-1 LOOP
FOR J in 0 To g_fil_ppf.nof_streams-1 LOOP
in_dat((J+1)*c_in_dat_w-1 DOWNTO J*c_in_dat_w) <= TO_UVEC(1, c_in_dat_w);
END LOOP;
in_val <= '1';
proc_common_wait_some_cycles(clk, 1);
END LOOP;
FOR J IN 0 TO g_fil_ppf.nof_taps-2 + 2 LOOP
FOR I IN 0 TO g_fil_ppf.nof_bands-1 LOOP
in_dat <= (OTHERS => '0');
in_val <= '1';
proc_common_wait_some_cycles(clk, 1);
END LOOP;
END LOOP;
in_dat <= (OTHERS => '0');
in_val <= '0';
proc_common_wait_some_cycles(clk, 10);
tb_end <= '1';
WAIT;
END PROCESS;
---------------------------------------------------------------
-- CREATE REFERENCE ARRAY
---------------------------------------------------------------
p_create_ref : PROCESS
begin
for J in 0 to g_fil_ppf.nof_taps-1 loop
proc_common_read_mif_file(g_coefs_file_prefix & "_" & integer'image(J) & ".mif", ref_arr);
wait for 1 ns;
for I in 0 to g_fil_ppf.nof_bands-1 loop
for K in 0 to 2**g_fil_ppf.nof_chan-1 loop
ref_dat_arr(J*g_fil_ppf.nof_bands*2**g_fil_ppf.nof_chan + I*2**g_fil_ppf.nof_chan + K) <= TO_SINT(TO_UVEC(ref_arr(I), 16));
end loop;
end loop;
end loop;
wait;
end process;
---------------------------------------------------------------
-- MAKE THE REFERENCE STREAM
---------------------------------------------------------------
ref_index <= ref_index + 1 when rising_edge(clk) and out_val='1' and ref_index < c_nof_coefs-1;
ref_dat <= ref_dat_arr(ref_index);
---------------------------------------------------------------
-- DUT = Device Under Test
---------------------------------------------------------------
u_dut : entity work.fil_ppf_single
generic map (
g_fil_ppf => g_fil_ppf,
g_fil_ppf_pipeline => g_fil_ppf_pipeline,
g_file_index_arr => g_file_index_arr,
g_coefs_file_prefix => g_coefs_file_prefix
)
port map (
dp_clk => clk,
dp_rst => rst,
mm_clk => clk,
mm_rst => rst,
ram_coefs_mosi => ram_coefs_mosi,
ram_coefs_miso => ram_coefs_miso,
in_dat => in_dat,
in_val => in_val,
out_dat => out_dat,
out_val => out_val
);
-- Verify the output of the DUT with the expected output from the reference array
p_verify_output : process(clk)
begin
-- Compare
if rising_edge(clk) then
if out_val='1' and ref_index < c_nof_coefs-1 then
for I in 0 to g_fil_ppf.nof_streams-1 loop
assert TO_SINT(out_dat((I+1)*g_fil_ppf.out_dat_w-1 downto I*g_fil_ppf.out_dat_w)) = ref_dat report "Output data error" severity error;
end loop;
end if;
end if;
end process;
end tb;
\ No newline at end of file
-- Author: Harm Jan Pepping : HJP at astron.nl: April 2012
--------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--------------------------------------------------------------------------------
--
-- Purpose: Test bench for the multi channel Poly Phase PreFilter unit
--
-- The testbech inserts an impulse on every band. The output
-- is verified by checking if the output values equal the
-- filter coefficients: It verifies the impulse-response.
--
-- It is possible to vary wb_factor, nof_chan, nof_bands, nof_taps
-- and nof_streams.
-- Note that for each specific combination of wb_factor, nof_bands
-- and nof_taps a new set of mif-files must be created. The mif-files
-- are used to initially load the coefficients in the rams.
-- Use the script ../../src/python/create_mifs.py to create the required
-- mif files.
-- For wb_factor = 2, nof_bands = 1024, nof_taps = 8 the script
-- should be called like this:
--
-- > create_mifs.py -t 8 -b 1024 -w 2
--
-- The generated mif files will be placed in ../../build/data/
--
--
-- Usage:
-- > run -all
-- > testbench is selftesting.
--
library ieee, common_lib, dp_lib, diag_lib;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_textio.all;
use STD.textio.all;
use common_lib.common_pkg.all;
use common_lib.common_mem_pkg.ALL;
use common_lib.tb_common_pkg.all;
use common_lib.tb_common_mem_pkg.ALL;
use dp_lib.dp_stream_pkg.ALL;
use work.fil_pkg.all;
entity tb_fil_ppf_wide is
generic(
-- generics for tb
g_fil_ppf_pipeline : t_fil_ppf_pipeline := (1, 1, 1, 1, 1, 1, 0);
-- type t_fil_pipeline is record
-- -- generic for the taps and coefficients memory
-- mem_delay : natural; -- = 1
-- -- generics for the multiplier in in the filter unit
-- mult_input : natural; -- = 1
-- mult_product : natural; -- = 1
-- mult_output : natural; -- = 1
-- -- generics for the adder tree in in the filter unit
-- adder_stage : natural; -- = 1
-- end record;
-- type t_fil_pipeline is record
-- -- generic for the taps and coefficients memory
-- mem_delay : natural; -- = 2
-- -- generics for the multiplier in in the filter unit
-- mult_input : natural; -- = 1
-- mult_product : natural; -- = 1
-- mult_output : natural; -- = 1
-- -- generics for the adder tree in in the filter unit
-- adder_stage : natural; -- = 1
-- -- generics for the requantizer in the filter unit
-- requant_remove_lsb : natural; -- = 1
-- requant_remove_msb : natural; -- = 0
-- end record;
g_fil_ppf : t_fil_ppf := (4, 2, 1024, 16, 2, 8, 23, 16);
-- type t_fil_ppf is record
-- wb_factor : natural; -- = 4, the wideband factor
-- nof_chan : natural; -- = default 0, defines the number of channels (=time-multiplexed input signals): nof channels = 2**nof_chan
-- nof_bands : natural; -- = 1024, the number of subbands is N/2 (N=nof_points of the FFT)
-- nof_taps : natural; -- = 16, the number of FIR taps per subband
-- nof_streams : natural; -- = 1, the number of streams that are served by the same coefficients.
-- in_dat_w : natural; -- = 8, number of input bits per stream
-- out_dat_w : natural; -- = 23, number of output bits. It is set to 23 to be sure the requantizer does not removes
-- any of the data in order to be able to verify with the original coefficients values.
-- coef_dat_w : natural; -- = 16, data width of the FIR coefficients
-- end record;
g_file_index_arr : t_nat_natural_arr := array_init(0, 128, 1);
g_coefs_file_prefix : string := "../../data/coefs_wide"
);
end entity tb_fil_ppf_wide;
architecture tb of tb_fil_ppf_wide is
constant c_clk_period : time := 10 ns;
constant c_nof_coefs : natural := g_fil_ppf.nof_taps*g_fil_ppf.nof_bands;
constant c_coefs_file_prefix : string := g_coefs_file_prefix & natural'image(g_fil_ppf.wb_factor) & "_p"& natural'image(g_fil_ppf.nof_bands) & "_t"& natural'image(g_fil_ppf.nof_taps);
-- input/output data width
constant c_in_dat_w : natural := g_fil_ppf.in_dat_w;
constant c_out_dat_w : natural := g_fil_ppf.in_dat_w + g_fil_ppf.coef_dat_w + ceil_log2(g_fil_ppf.nof_taps);
constant c_nof_bands_per_stream : natural := g_fil_ppf.nof_bands / g_fil_ppf.wb_factor;
constant c_nof_chan : natural := 2**g_fil_ppf.nof_chan;
type t_integer_arr2 is array(integer range <> ) of t_integer_arr(c_nof_coefs/g_fil_ppf.wb_factor-1 downto 0);
-- signal definitions
signal tb_end : std_logic := '0';
signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal ram_coefs_mosi : t_mem_mosi;
signal ram_coefs_miso : t_mem_miso;
signal coefs_arr : t_integer_arr (c_nof_bands_per_stream-1 downto 0);
signal in_dat_arr : t_fil_slv_arr(g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 downto 0);
signal in_val : std_logic;
signal out_dat_arr : t_fil_slv_arr(g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 downto 0);
signal out_val : std_logic;
signal ref_dat_arr : t_integer_arr (g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 downto 0);
signal ref_dat_arr2 : t_integer_arr2(g_fil_ppf.wb_factor-1 downto 0);
signal ref_arr : t_integer_arr (c_nof_bands_per_stream-1 downto 0);
signal ref_index : natural := 0;
signal chn_index : natural := 0;
signal coefs_mem_write : boolean := FALSE;
begin
clk <= (not clk) or tb_end after c_clk_period/2;
rst <= '1', '0' after c_clk_period*7;
---------------------------------------------------------------
-- WRITE THE COEFFICIENTS TO THE COEFS MEMORY
---------------------------------------------------------------
p_coefs_memory_write : process
begin
coefs_mem_write <= FALSE;
ram_coefs_mosi <= c_mem_mosi_rst; -- Reset the master out interface
for K in 0 to g_fil_ppf.wb_factor-1 loop
for J in 0 to g_fil_ppf.nof_taps-1 loop
proc_common_read_mif_file(c_coefs_file_prefix & "_" & integer'image(k*g_fil_ppf.nof_taps+J) & ".mif", coefs_arr);
wait for 1 ns;
for I in 0 to c_nof_bands_per_stream-1 loop
proc_mem_mm_bus_wr(K*c_nof_bands_per_stream*g_fil_ppf.nof_taps + J*c_nof_bands_per_stream + I, coefs_arr(I), clk, ram_coefs_mosi); -- Write the coefficient to the memory
end loop;
end loop;
end loop;
coefs_mem_write <= TRUE;
wait;
end process;
---------------------------------------------------------------
-- SEND IMPULSE TO THE DATA INPUT
---------------------------------------------------------------
p_send_impulse : process
begin
tb_end <= '0';
for I in 0 to g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 loop
in_dat_arr(I) <= (others => '0');
end loop;
in_val <= '0';
proc_common_wait_until_low(clk, rst); -- Wait until reset has finished
proc_common_wait_some_cycles(clk, 10); -- Wait an additional amount of cycles
wait until coefs_mem_write = TRUE;
for J in 0 to c_nof_chan*c_nof_bands_per_stream-1 loop
for I in 0 to g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 loop
in_dat_arr(I) <= TO_UVEC(1, in_dat_arr(I)'LENGTH);
in_val <= '1';
end loop;
proc_common_wait_some_cycles(clk, 1);
end loop;
for K in 0 to g_fil_ppf.nof_taps-2 + 2 loop
for J in 0 to c_nof_chan*c_nof_bands_per_stream-1 loop
for I in 0 to g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 loop
in_dat_arr(I) <= (others => '0');
in_val <= '1';
end loop;
proc_common_wait_some_cycles(clk, 1);
end loop;
end loop;
for I in 0 to g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 loop
in_dat_arr(I) <= (others => '0');
in_val <= '0';
end loop;
proc_common_wait_some_cycles(clk, 10);
tb_end <= '1';
wait;
end process;
---------------------------------------------------------------
-- CREATE REFERENCE ARRAY
---------------------------------------------------------------
p_create_ref : process
begin
for K in 0 to g_fil_ppf.wb_factor-1 loop
for J in 0 to g_fil_ppf.nof_taps-1 loop
proc_common_read_mif_file(c_coefs_file_prefix & "_" & integer'image(k*g_fil_ppf.nof_taps+J) & ".mif", ref_arr);
wait for 1 ns;
for I in 0 to c_nof_bands_per_stream-1 loop
ref_dat_arr2(K)(J*c_nof_bands_per_stream + I) <= TO_SINT(TO_UVEC(ref_arr(I), 16));
end loop;
end loop;
end loop;
wait;
end process;
---------------------------------------------------------------
-- MAKE THE REFERENCE STREAM
---------------------------------------------------------------
chn_index <= chn_index + 1 when (falling_edge(clk) and out_val='1') else 0 when (chn_index = c_nof_chan);
ref_index <= ref_index + 1 when rising_edge(clk) and out_val='1' and ref_index < c_nof_coefs/g_fil_ppf.wb_factor-1 and chn_index = 0;
assign_ref_dat_arr_wb : for I in 0 to g_fil_ppf.wb_factor-1 generate
assign_ref_dat_arr_streams : for J in 0 to g_fil_ppf.nof_streams-1 generate
ref_dat_arr(I*g_fil_ppf.nof_streams+J) <= ref_dat_arr2(I)(ref_index);
end generate;
end generate;
---------------------------------------------------------------
-- DUT = Device Under Test
---------------------------------------------------------------
u_dut : entity work.fil_ppf_wide
generic map (
g_fil_ppf => g_fil_ppf,
g_fil_ppf_pipeline => g_fil_ppf_pipeline,
g_file_index_arr => g_file_index_arr,
g_coefs_file_prefix => c_coefs_file_prefix
)
port map (
dp_clk => clk,
dp_rst => rst,
mm_clk => clk,
mm_rst => rst,
ram_coefs_mosi => ram_coefs_mosi,
ram_coefs_miso => ram_coefs_miso,
in_dat_arr => in_dat_arr,
in_val => in_val,
out_dat_arr => out_dat_arr,
out_val => out_val
);
-- Verify the output of the DUT with the expected output from the reference array
p_verify_output : process(clk)
begin
-- Compare
if rising_edge(clk) then
if out_val='1' and ref_index < c_nof_coefs/g_fil_ppf.wb_factor-1 then
for I in 0 to g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 loop
assert TO_SINT(out_dat_arr(I)(g_fil_ppf.out_dat_w-1 DOWNTO 0)) = ref_dat_arr(I) report "Output data error" severity error;
end loop;
end if;
end if;
end process;
end tb;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment