Wolf-LITE/FPGA/rx_ciccomp_sim/rx_ciccomp_tb.vhd

473 wiersze
17 KiB
VHDL

-- (C) 2001-2018 Intel Corporation. All rights reserved.
-- Your use of Intel Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files from any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Intel Program License Subscription
-- Agreement, Intel FPGA IP License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Intel and sold by
-- Intel or its authorized distributors. Please refer to the applicable
-- agreement for further details.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
entity rx_ciccomp_tb is
constant FIR_INPUT_FILE_c : string := "rx_ciccomp_input.txt";
constant FIR_OUTPUT_FILE_c : string := "rx_ciccomp_output.txt";
constant PHYSCHANIN_c : natural := 1;
constant PHYSCHANOUT_c : natural := 1;
constant INWIDTH_c : natural := 32;
constant OUTWIDTH_c : natural := 46;
constant BANKINWIDTH_c : natural := 0;
constant BANKCOUNT_c : natural := 1;
constant DATA_WIDTH_c : natural := (INWIDTH_c+BANKINWIDTH_c) * PHYSCHANIN_c;
constant OUT_WIDTH_c : natural := OUTWIDTH_c * PHYSCHANOUT_c;
constant NUM_OF_CHANNELS_c : natural := 1;
constant CHANSPERPHYIN_c : natural := 1;
constant CHANSPERPHYOUT_c : natural := 1;
constant LOG2_CHANSPERPHYOUT_c : natural := 0;
constant TDM_FACTOR_c : natural := 1340;
constant INVERSE_TDM_FACTOR_c : natural := 1;
constant INVALID_CYCLES_c : natural := 1339;
constant INTERP_FACTOR_c : natural := 1;
constant TOTAL_INCHANS_ALLOWED : natural := PHYSCHANIN_c * CHANSPERPHYIN_c;
constant TOTAL_OUTCHANS_ALLOWED : natural := PHYSCHANOUT_c * CHANSPERPHYOUT_c;
constant NUM_OF_TAPS_c : natural := 64;
constant TOTAL_EFF_COEF_c : natural := 64;
constant COEFF_BIT_WIDTH_c : natural := 8;
constant COEFF_BUS_DATA_WIDTH_c : natural := 16;
constant COEFF_BUS_ADDR_WIDTH : natural := 6;
end entity rx_ciccomp_tb;
architecture rtl of rx_ciccomp_tb is
signal ast_sink_data : std_logic_vector (DATA_WIDTH_c-1 downto 0) := (others => '0');
signal ast_source_data : std_logic_vector (OUT_WIDTH_c-1 downto 0);
signal ast_sink_error : std_logic_vector (1 downto 0) := (others => '0');
signal ast_source_error : std_logic_vector (1 downto 0);
signal ast_sink_valid : std_logic := '0';
signal ast_source_valid : std_logic;
signal ast_source_ready : std_logic := '0';
signal clk : std_logic := '0';
signal reset_testbench : std_logic := '1';
signal reset_design : std_logic;
signal eof : std_logic;
signal sink_completed : std_logic := '0';
signal ast_sink_ready : std_logic;
----coef reload ports
signal cnt : natural range 0 to CHANSPERPHYIN_c;
signal push_counter : natural range 0 to CHANSPERPHYIN_c :=0;
constant tclk : time := 10 ns;
constant time_lapse_max : time := 60 us;
signal time_lapse : time;
signal valid_cycles : std_logic := '1';
function div_ceil(a : natural; b : natural) return natural is
variable res : natural := a/b;
begin
if res*b /= a then
res := res +1;
end if;
return res;
end div_ceil;
function to_hex (value : in signed) return string is
constant ne : integer := (value'length+3)/4;
constant NUS : string(2 downto 1) := (others => ' ');
variable pad : std_logic_vector(0 to (ne*4 - value'length) - 1);
variable ivalue : std_logic_vector(0 to ne*4 - 1);
variable result : string(1 to ne);
variable quad : std_logic_vector(0 to 3);
begin
if value'length < 1 then
return NUS;
else
if value (value'left) = 'Z' then
pad := (others => 'Z');
else
pad := (others => value(value'high));
end if;
ivalue := pad & std_logic_vector (value);
for i in 0 to ne-1 loop
quad := To_X01Z(ivalue(4*i to 4*i+3));
case quad is
when x"0" => result(i+1) := '0';
when x"1" => result(i+1) := '1';
when x"2" => result(i+1) := '2';
when x"3" => result(i+1) := '3';
when x"4" => result(i+1) := '4';
when x"5" => result(i+1) := '5';
when x"6" => result(i+1) := '6';
when x"7" => result(i+1) := '7';
when x"8" => result(i+1) := '8';
when x"9" => result(i+1) := '9';
when x"A" => result(i+1) := 'A';
when x"B" => result(i+1) := 'B';
when x"C" => result(i+1) := 'C';
when x"D" => result(i+1) := 'D';
when x"E" => result(i+1) := 'E';
when x"F" => result(i+1) := 'F';
when "ZZZZ" => result(i+1) := 'Z';
when others => result(i+1) := 'X';
end case;
end loop;
return result;
end if;
end function to_hex;
begin
DUT : entity work.rx_ciccomp
port map (
clk => clk,
reset_n => reset_design,
ast_sink_data => ast_sink_data,
ast_source_data => ast_source_data,
ast_sink_valid => ast_sink_valid,
ast_source_valid => ast_source_valid,
ast_sink_error => ast_sink_error,
ast_source_error => ast_source_error
);
-- for example purposes, the ready signal is always asserted.
ast_source_ready <= '1';
ast_sink_ready <= '1';
-- no input error
ast_sink_error <= (others => '0');
-----------------------------------------------------------------------------------------------
-- Read input data from file
-----------------------------------------------------------------------------------------------
source_model : process(clk) is
file in_file : text open read_mode is FIR_INPUT_FILE_c;
variable data_in : integer;
variable bank_in : integer;
variable indata : line;
variable read_data_completed: integer;
variable q, j, j_temp : integer := 0 ;
variable realInChansCount : integer ;
variable totalInChansCount : integer ;
variable idle_cyles : integer := 0 ;
type In_2D is array (PHYSCHANIN_c-1 downto 0, CHANSPERPHYIN_c-1 downto 0) of integer;
variable arrayIn : In_2D;
variable arrayBank : In_2D;
--Debug
variable my_line : line;
begin
if rising_edge(clk) then
if(reset_testbench = '0') then
ast_sink_data <= std_logic_vector(to_signed(0, DATA_WIDTH_c)) after tclk/4;
ast_sink_valid <= '0' after tclk/4;
eof <= '0';
realInChansCount := NUM_OF_CHANNELS_c * INVERSE_TDM_FACTOR_c;
totalInChansCount := TOTAL_INCHANS_ALLOWED;
else
if (sink_completed='0' or eof='0') then
eof <= '0';
if( valid_cycles = '1' and ast_sink_ready = '1') then
if not endfile(in_file) then
if (push_counter=0) then
q := 0;
for k in 0 to PHYSCHANIN_c-1 loop
-- Super-Sample Rate
if (k /= 0) then
j := j + INVERSE_TDM_FACTOR_c;
if (j > PHYSCHANIN_c - 1) then
j_temp := j_temp + 1;
j := j_temp;
end if;
else
j := k;
end if;
for i in 0 to CHANSPERPHYIN_c-1 loop
totalInChansCount := totalInChansCount - 1;
if (realInChansCount > 0) then
realInChansCount := realInChansCount - 1;
readline(in_file, indata);
read(indata, data_in);
arrayIn(j,i) := data_in;
if (BANKINWIDTH_c > 0) then
read(indata, bank_in);
arrayBank(j,i) := bank_in;
end if;
ast_sink_valid <= '1' after tclk/4;
--Debug
--write(my_line, string'(" j = "));
--write(my_line, j);
--write(my_line, string'(" i = "));
--write(my_line, i);
--write(my_line, string'(" Array content = "));
--write(my_line, arrayIn(j,i));
--writeline(output, my_line);
end if;
end loop;
if (totalInChansCount = 0) then
realInChansCount := NUM_OF_CHANNELS_c * INVERSE_TDM_FACTOR_c;
totalInChansCount := TOTAL_INCHANS_ALLOWED;
end if;
end loop;
j_temp := 0;
sink_completed <= '0';
read_data_completed := 1;
end if;
else
eof <='1';
end if;
-- Reorder the input format
-- Expected input format by FIR Compiler II
-- ..., <C2>, <C1>, <C0>, -->
-- ..., <C5>, <C4>, <C3>, -->
-- ..., <C8>, <C7>, <C6>, -->
if (read_data_completed = 1) then
for p in 0 to PHYSCHANIN_c-1 loop
--Debug
--write(my_line, string'(" Push input = "));
--write(my_line,arrayIn(p,q));
--writeline(output, my_line); -- write to display
ast_sink_data(p*(INWIDTH_c+BANKINWIDTH_c)+INWIDTH_c-1 downto (INWIDTH_c+BANKINWIDTH_c)*p) <= std_logic_vector(to_signed(arrayIn(p,q), INWIDTH_c)) after tclk/4;
if (BANKINWIDTH_c > 0) then
ast_sink_data(p*(INWIDTH_c+BANKINWIDTH_c)+(INWIDTH_c+BANKINWIDTH_c)-1 downto (INWIDTH_c+BANKINWIDTH_c)*p+INWIDTH_c) <= std_logic_vector(to_signed(arrayBank(p,q), BANKINWIDTH_c)) after tclk/4;
end if;
end loop;
if ( q < CHANSPERPHYIN_c ) then
q := q + 1;
else
q := 0;
end if;
if ( push_counter < CHANSPERPHYIN_c-1 ) then
push_counter <= push_counter + 1;
else
push_counter <= 0;
read_data_completed := 0;
sink_completed <= '1';
--start invalid cycles if needed
if ( idle_cyles < INVALID_CYCLES_c ) then
valid_cycles <= '0' ;
end if;
end if;
end if;
-- End Reordering and sinking data
else
if ( idle_cyles < INVALID_CYCLES_c ) then
ast_sink_valid <= '0' after tclk/4;
idle_cyles := idle_cyles + 1;
if ( idle_cyles = INVALID_CYCLES_c ) then
valid_cycles <= '1' ;
idle_cyles := 0;
end if;
end if;
ast_sink_data <= ast_sink_data after tclk/4;
end if;
else
eof <= '1';
ast_sink_valid <= '0' after tclk/4;
ast_sink_data <= std_logic_vector(to_signed(0, DATA_WIDTH_c)) after tclk/4;
end if;
end if;
end if;
end process source_model;
---------------------------------------------------------------------------------------------
-- Write FIR output to file
---------------------------------------------------------------------------------------------
sink_model : process(clk) is
file ro_file : text open write_mode is FIR_OUTPUT_FILE_c;
variable rdata : line;
variable y,z,z_temp : integer :=0;
variable realOutChansCount : natural := NUM_OF_CHANNELS_c * INVERSE_TDM_FACTOR_c;
variable totalOutChansCount : natural := TOTAL_OUTCHANS_ALLOWED;
type Out_2D is array (CHANSPERPHYOUT_c-1 downto 0, PHYSCHANOUT_c-1 downto 0) of string(div_ceil(OUTWIDTH_c,4) downto 1);
variable arrayOut : Out_2D;
begin
if rising_edge(clk) then
if(ast_source_valid = '1' and ast_source_ready = '1') then
-- Expected output format from FIR Compiler II
--> <C0>, <C1>, <C2>, ...
--> <C3>, <C4>, <C5>, ...
--> <C6>, <C7>, <C8>, ...
for x in 0 to PHYSCHANOUT_c-1 loop
-- Super-Sample Rate or Interpolation with TDM = 1
-- only interpolation factor is needed for super-sample rate test
if ( PHYSCHANOUT_c > NUM_OF_CHANNELS_c ) then
if (x /= 0) then
z := z + INVERSE_TDM_FACTOR_c * div_ceil(INTERP_FACTOR_c,TDM_FACTOR_c);
if (z > PHYSCHANOUT_c-1) then
z_temp := z_temp + 1;
z := z_temp;
end if;
end if;
else
z := x;
end if;
-- report as hex representation of integer.
arrayOut(y,x) := to_hex(signed(ast_source_data(z*OUTWIDTH_c+OUTWIDTH_c-1 downto OUTWIDTH_c*z)));
end loop;
if (y < CHANSPERPHYOUT_c - 1) then
y := y + 1;
else
y := 0;
z := 0;
z_temp := 0;
for n in 0 to PHYSCHANOUT_c-1 loop
for m in 0 to CHANSPERPHYOUT_c-1 loop
totalOutChansCount := totalOutChansCount - 1;
if (realOutChansCount > 0) then
if (NUM_OF_CHANNELS_c > PHYSCHANOUT_c) then
realOutChansCount := realOutChansCount - 1;
end if;
write(rdata, arrayOut(m,n));
writeline(ro_file, rdata);
end if;
end loop;
end loop;
end if;
if (totalOutChansCount = 0) then
realOutChansCount := NUM_OF_CHANNELS_c * INVERSE_TDM_FACTOR_c;
totalOutChansCount := TOTAL_OUTCHANS_ALLOWED;
end if;
end if;
end if;
end process sink_model;
-------------------------------------------------------------------------------
-- clock generator
-------------------------------------------------------------------------------
clkgen : process
begin -- process clkgen
if eof = '1' and sink_completed = '1' and ast_source_valid = '0' and time_lapse >= time_lapse_max then
clk <= '0';
assert FALSE
report "NOTE: Stimuli ended" severity note;
wait;
elsif time_lapse >= time_lapse_max then
clk <= '0';
assert FALSE
report "ERROR: Reached time_lapse_max without activity, probably simulation is stuck!" severity Error;
wait;
else
clk <= '0';
wait for tclk/2;
clk <= '1';
wait for tclk/2;
end if;
end process clkgen;
monitor_toggling_activity : process(clk, reset_testbench,
ast_source_data, ast_source_valid)
begin
if reset_testbench = '0' then
time_lapse <= 0 ns;
elsif ast_source_data'event or ast_source_valid'event then
time_lapse <= 0 ns;
elsif rising_edge(clk) then
if time_lapse < time_lapse_max then
time_lapse <= time_lapse + tclk;
end if;
end if;
end process monitor_toggling_activity;
-------------------------------------------------------------------------------
-- reset generator
-------------------------------------------------------------------------------
reset_testbench_gen : process
begin -- process resetgen
reset_testbench <= '1';
wait for tclk/4;
reset_testbench <= '0';
wait for tclk*2;
reset_testbench <= '1';
wait;
end process reset_testbench_gen;
reset_design_gen : process
begin -- process resetgen
reset_design <= '1';
wait for tclk/4;
reset_design <= '0';
wait for tclk*2;
reset_design <= '1';
wait for tclk*80;
reset_design <= '1';
wait for tclk*64*2;
reset_design <= '1';
wait;
end process reset_design_gen;
end architecture rtl;