Skip to content
Snippets Groups Projects
Commit 2d8f2387 authored by Job van Wee's avatar Job van Wee
Browse files

Ready for review.

parent df73305c
Branches
No related tags found
1 merge request!233Resolve L2SDP-697
Pipeline #28032 failed
Showing
with 138 additions and 798 deletions
...@@ -13,10 +13,6 @@ synth_files = ...@@ -13,10 +13,6 @@ synth_files =
src/vhdl/ddrctrl.vhd src/vhdl/ddrctrl.vhd
test_bench_files = test_bench_files =
tb/vhdl/tb_ddrctrl_input_address_counter.vhd
tb/vhdl/tb_ddrctrl_input_pack.vhd
tb/vhdl/tb_ddrctrl_input_repack.vhd
tb/vhdl/tb_ddrctrl_input.vhd
tb/vhdl/tb_ddrctrl.vhd tb/vhdl/tb_ddrctrl.vhd
regression_test_vhdl = regression_test_vhdl =
......
...@@ -95,6 +95,7 @@ ARCHITECTURE str OF ddrctrl IS ...@@ -95,6 +95,7 @@ ARCHITECTURE str OF ddrctrl IS
SIGNAL dvr_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; SIGNAL dvr_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst;
SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL rd_siso : t_dp_siso := c_dp_siso_rst; SIGNAL rd_siso : t_dp_siso := c_dp_siso_rst;
SIGNAL stop : STD_LOGIC;
BEGIN BEGIN
...@@ -112,6 +113,7 @@ BEGIN ...@@ -112,6 +113,7 @@ BEGIN
clk => clk, clk => clk,
rst => rst, rst => rst,
in_sosi_arr => in_sosi_arr, in_sosi_arr => in_sosi_arr,
in_stop => stop,
out_of => out_of, out_of => out_of,
out_sosi => out_sosi, out_sosi => out_sosi,
out_adr => out_adr out_adr => out_adr
...@@ -209,7 +211,8 @@ BEGIN ...@@ -209,7 +211,8 @@ BEGIN
wr_sosi => wr_sosi, wr_sosi => wr_sosi,
rd_siso => rd_siso, rd_siso => rd_siso,
stop_in => stop_in stop_in => stop_in,
stop_out => stop
); );
END str; END str;
...@@ -56,7 +56,8 @@ ENTITY ddrctrl_controller IS ...@@ -56,7 +56,8 @@ ENTITY ddrctrl_controller IS
rd_siso : OUT t_dp_siso; rd_siso : OUT t_dp_siso;
-- ddrctrl -- ddrctrl
stop_in : IN STD_LOGIC stop_in : IN STD_LOGIC;
stop_out : OUT STD_LOGIC
); );
END ddrctrl_controller; END ddrctrl_controller;
...@@ -193,5 +194,6 @@ BEGIN ...@@ -193,5 +194,6 @@ BEGIN
dvr_mosi <= q_reg.dvr_mosi; dvr_mosi <= q_reg.dvr_mosi;
wr_sosi <= q_reg.wr_sosi; wr_sosi <= q_reg.wr_sosi;
rd_siso <= q_reg.rd_siso; rd_siso <= q_reg.rd_siso;
stop_out <= q_reg.stopped;
END rtl; END rtl;
...@@ -53,11 +53,13 @@ ENTITY ddrctrl_input IS ...@@ -53,11 +53,13 @@ ENTITY ddrctrl_input IS
clk : IN STD_LOGIC := '0'; clk : IN STD_LOGIC := '0';
rst : IN STD_LOGIC; rst : IN STD_LOGIC;
in_sosi_arr : IN t_dp_sosi_arr; -- input data in_sosi_arr : IN t_dp_sosi_arr; -- input data
in_stop : IN STD_LOGIC;
out_of : OUT NATURAL; -- amount of internal overflow this output out_of : OUT NATURAL; -- amount of internal overflow this output
out_sosi : OUT t_dp_sosi; -- output data out_sosi : OUT t_dp_sosi; -- output data
out_adr : OUT NATURAL; out_adr : OUT NATURAL;
out_bsn_ds : OUT NATURAL; out_bsn_ds : OUT NATURAL;
out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
out_bsn_adr : OUT NATURAL
); );
END ddrctrl_input; END ddrctrl_input;
...@@ -73,7 +75,8 @@ ARCHITECTURE str OF ddrctrl_input IS ...@@ -73,7 +75,8 @@ ARCHITECTURE str OF ddrctrl_input IS
SIGNAL sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL a_of : NATURAL := 0; SIGNAL a_of : NATURAL := 0;
SIGNAL bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); SIGNAL bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
SIGNAL adr : NATURAL := 0; SIGNAL adr : NATURAL := 0;
SIGNAL out_bsn_wr : STD_LOGIC := '0';
BEGIN BEGIN
...@@ -102,11 +105,13 @@ BEGIN ...@@ -102,11 +105,13 @@ BEGIN
rst => rst, rst => rst,
in_data => data, -- input data in_data => data, -- input data
in_bsn => bsn, in_bsn => bsn,
in_stop => in_stop,
adr => adr, adr => adr,
out_of => a_of, -- amount of internal overflow out_of => a_of, -- amount of internal overflow
out_sosi => sosi, -- output data out_sosi => sosi, -- output data
out_bsn_ds => out_bsn_ds, -- amount of bits between adr [0] and sosi_arr[0][0] where bsn is assigned to out_bsn_ds => out_bsn_ds, -- amount of bits between adr [0] and sosi_arr[0][0] where bsn is assigned to
out_bsn => out_bsn out_bsn => out_bsn,
out_bsn_wr => out_bsn_wr
); );
-- creates address by counting input valids -- creates address by counting input valids
...@@ -120,9 +125,11 @@ BEGIN ...@@ -120,9 +125,11 @@ BEGIN
rst => rst, rst => rst,
in_sosi => sosi, -- input data in_sosi => sosi, -- input data
in_of => a_of, in_of => a_of,
in_bsn_wr => out_bsn_wr,
out_sosi => out_sosi, -- output data out_sosi => out_sosi, -- output data
out_of => out_of, out_of => out_of,
out_adr => adr out_adr => adr,
out_bsn_adr => out_bsn_adr
); );
END str; END str;
...@@ -49,9 +49,11 @@ ENTITY ddrctrl_input_address_counter IS ...@@ -49,9 +49,11 @@ ENTITY ddrctrl_input_address_counter IS
rst : IN STD_LOGIC; rst : IN STD_LOGIC;
in_sosi : IN t_dp_sosi; -- input data in_sosi : IN t_dp_sosi; -- input data
in_of : IN NATURAL; in_of : IN NATURAL;
in_bsn_wr : IN STD_LOGIC;
out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data
out_of : OUT NATURAL; out_of : OUT NATURAL;
out_adr : OUT NATURAL out_adr : OUT NATURAL;
out_bsn_adr : OUT NATURAL
); );
END ddrctrl_input_address_counter; END ddrctrl_input_address_counter;
...@@ -71,12 +73,14 @@ ARCHITECTURE rtl OF ddrctrl_input_address_counter IS ...@@ -71,12 +73,14 @@ ARCHITECTURE rtl OF ddrctrl_input_address_counter IS
state : t_state; state : t_state;
out_sosi : t_dp_sosi; out_sosi : t_dp_sosi;
out_of : NATURAL; out_of : NATURAL;
out_bsn_adr : NATURAL;
s_in_sosi : t_dp_sosi; s_in_sosi : t_dp_sosi;
s_in_of : NATURAL; s_in_of : NATURAL;
s_adr : NATURAL; s_adr : NATURAL;
s_bsn_wr : STD_LOGIC;
END RECORD; END RECORD;
CONSTANT c_t_reg_init : t_reg := (RESET, c_dp_sosi_init, 0, c_dp_sosi_init, 0, 0); CONSTANT c_t_reg_init : t_reg := (RESET, c_dp_sosi_init, 0, 0, c_dp_sosi_init, 0, 0, '0');
-- signals for readability -- signals for readability
...@@ -99,18 +103,39 @@ BEGIN ...@@ -99,18 +103,39 @@ BEGIN
v.out_of := q_reg.s_in_of; v.out_of := q_reg.s_in_of;
v.s_in_sosi := in_sosi; v.s_in_sosi := in_sosi;
v.s_in_of := in_of; v.s_in_of := in_of;
IF in_bsn_wr = '1' THEN
v.s_bsn_wr := '1';
END IF;
CASE q_reg.state IS CASE q_reg.state IS
WHEN RESET => WHEN RESET =>
v.s_adr := c_max_adr-1; -- when there is a reset the fifo in io_ddr always needs the first out_sosi.valid to stop flushing the data so the first data word always gets lost. if s_adr is set to 0 after a restart the word from s_adr 1 will be put at address 0 in memory. v.s_adr := c_max_adr-1; -- when there is a reset the fifo in io_ddr always needs the first out_sosi.valid to stop flushing the data so the first data word always gets lost. if s_adr is set to 0 after a restart the word from s_adr 1 will be put at address 0 in memory.
IF q_reg.s_bsn_wr = '1' THEN
v.out_bsn_adr := v.s_adr;
v.s_bsn_wr := '0';
END IF;
WHEN COUNTING => WHEN COUNTING =>
v.s_adr := q_reg.s_adr+1; v.s_adr := q_reg.s_adr+1;
IF q_reg.s_bsn_wr = '1' THEN
v.out_bsn_adr := v.s_adr;
v.s_bsn_wr := '0';
END IF;
WHEN MAX => WHEN MAX =>
v.s_adr := 0; v.s_adr := 0;
IF q_reg.s_bsn_wr = '1' THEN
v.out_bsn_adr := v.s_adr;
v.s_bsn_wr := '0';
END IF;
WHEN IDLE => WHEN IDLE =>
END CASE; END CASE;
...@@ -129,8 +154,9 @@ BEGIN ...@@ -129,8 +154,9 @@ BEGIN
END PROCESS; END PROCESS;
-- fill outputs -- fill outputs
out_sosi <= q_reg.out_sosi; out_sosi <= q_reg.out_sosi;
out_of <= q_reg.out_of; out_of <= q_reg.out_of;
out_adr <= q_reg.s_adr; out_adr <= q_reg.s_adr;
out_bsn_adr <= q_reg.out_bsn_adr;
END rtl; END rtl;
...@@ -44,11 +44,13 @@ ENTITY ddrctrl_input_repack IS ...@@ -44,11 +44,13 @@ ENTITY ddrctrl_input_repack IS
rst : IN STD_LOGIC; rst : IN STD_LOGIC;
in_data : IN STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0); -- input data in_data : IN STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0); -- input data
in_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- input bsn in_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- input bsn
in_stop : IN STD_LOGIC := '0';
adr : IN NATURAL; adr : IN NATURAL;
out_of : OUT NATURAL := 0; -- amount of internal overflow this output out_of : OUT NATURAL := 0; -- amount of internal overflow this output
out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data
out_bsn_ds : OUT NATURAL := 0; out_bsn_ds : OUT NATURAL := 0;
out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
out_bsn_wr : OUT STD_LOGIC := '0'
); );
END ddrctrl_input_repack; END ddrctrl_input_repack;
...@@ -60,7 +62,7 @@ ARCHITECTURE rtl OF ddrctrl_input_repack IS ...@@ -60,7 +62,7 @@ ARCHITECTURE rtl OF ddrctrl_input_repack IS
CONSTANT k_c_v_w : NATURAL := c_out_data_w*2; -- the c_v data with, 2*576=1152 CONSTANT k_c_v_w : NATURAL := c_out_data_w*2; -- the c_v data with, 2*576=1152
-- type for statemachine -- type for statemachine
TYPE t_state IS (BSN_INPUT, OVERFLOW_OUTPUT, FILL_VECTOR, FIRST_OUTPUT, RESET); TYPE t_state IS (OVERFLOW_OUTPUT, FILL_VECTOR, FIRST_OUTPUT, RESET, STOP);
-- record for readability -- record for readability
TYPE t_reg IS RECORD TYPE t_reg IS RECORD
...@@ -68,7 +70,7 @@ ARCHITECTURE rtl OF ddrctrl_input_repack IS ...@@ -68,7 +70,7 @@ ARCHITECTURE rtl OF ddrctrl_input_repack IS
c_v : STD_LOGIC_VECTOR(k_c_v_w-1 DOWNTO 0); -- the vector that stores the input data until the data is put into the output data vector c_v : STD_LOGIC_VECTOR(k_c_v_w-1 DOWNTO 0); -- the vector that stores the input data until the data is put into the output data vector
c_v_count : NATURAL; -- the amount of times the c_v vector received data from the input since the last time it was filled completely c_v_count : NATURAL; -- the amount of times the c_v vector received data from the input since the last time it was filled completely
out_data_count : NATURAL; -- the amount of times the output data vector has been filled since the last time c_v was filled completely out_data_count : NATURAL; -- the amount of times the output data vector has been filled since the last time c_v was filled completely
bsn_written : STD_LOGIC; out_bsn_written : STD_LOGIC;
out_of : NATURAL; out_of : NATURAL;
out_sosi : t_dp_sosi; out_sosi : t_dp_sosi;
out_bsn_ds : NATURAL; out_bsn_ds : NATURAL;
...@@ -101,15 +103,28 @@ BEGIN ...@@ -101,15 +103,28 @@ BEGIN
v.c_v_count := q_reg.c_v_count+1; -- increase the counter of c_v with 1 v.c_v_count := q_reg.c_v_count+1; -- increase the counter of c_v with 1
v.out_sosi.valid := '0'; -- out_sosi.valid 0 v.out_sosi.valid := '0'; -- out_sosi.valid 0
IF rst = '1' THEN -- BSN_INPUT
v.state := RESET; IF adr = 0 AND q_reg.out_bsn_written = '0' THEN
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN v.out_bsn := in_bsn;
v.state := FIRST_OUTPUT; IF g_in_data_w*q_reg.c_v_count+q_reg.out_of >= c_out_data_w THEN
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN v.out_bsn_ds := g_in_data_w*q_reg.c_v_count+q_reg.out_of-c_out_data_w;
v.state := OVERFLOW_OUTPUT; ELSE
ELSE v.out_bsn_ds := g_in_data_w*q_reg.c_v_count+q_reg.out_of;
v.state := FILL_VECTOR; END IF;
END IF; v.out_bsn_written := '1';
END IF;
IF rst = '1' THEN
v.state := RESET;
ELSIF in_stop = '1' THEN
v.state := STOP;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN
v.state := FIRST_OUTPUT;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN
v.state := OVERFLOW_OUTPUT;
ELSE
v.state := FILL_VECTOR;
END IF;
WHEN FIRST_OUTPUT => -- if the input data exceeds output data vector width but not the c_v width WHEN FIRST_OUTPUT => -- if the input data exceeds output data vector width but not the c_v width
...@@ -119,15 +134,25 @@ BEGIN ...@@ -119,15 +134,25 @@ BEGIN
v.out_sosi.valid := '1'; -- out_sosi.valid 1 v.out_sosi.valid := '1'; -- out_sosi.valid 1
v.out_data_count := q_reg.out_data_count+1; -- increase the counter of out_sosi.data with 1 v.out_data_count := q_reg.out_data_count+1; -- increase the counter of out_sosi.data with 1
IF rst = '1' THEN IF adr = 0 AND q_reg.out_bsn_written = '0' THEN
v.state := RESET; v.out_bsn := in_bsn;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN IF g_in_data_w*q_reg.c_v_count+q_reg.out_of >= c_out_data_w THEN
v.state := OVERFLOW_OUTPUT; v.out_bsn_ds := g_in_data_w*q_reg.c_v_count+q_reg.out_of-c_out_data_w;
ELSIF adr = 0 AND v.bsn_written = '0' THEN -- because of delays in address counter the bsn number will be written in ddr address 1 or 2 dependend on . ELSE
v.state := BSN_INPUT; v.out_bsn_ds := g_in_data_w*q_reg.c_v_count+q_reg.out_of;
ELSE END IF;
v.state := FILL_VECTOR; v.out_bsn_written := '1';
END IF; END IF;
IF rst = '1' THEN
v.state := RESET;
ELSIF in_stop = '1' THEN
v.state := STOP;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN
v.state := OVERFLOW_OUTPUT;
ELSE
v.state := FILL_VECTOR;
END IF;
WHEN OVERFLOW_OUTPUT => -- if the input data exceeds the output data vector width and the c_v width WHEN OVERFLOW_OUTPUT => -- if the input data exceeds the output data vector width and the c_v width
...@@ -139,55 +164,59 @@ BEGIN ...@@ -139,55 +164,59 @@ BEGIN
v.c_v_count := 0; -- reset counter v.c_v_count := 0; -- reset counter
v.out_data_count := 0; -- reset counter v.out_data_count := 0; -- reset counter
IF rst = '1' THEN
v.state := RESET;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN
v.state := FIRST_OUTPUT;
ELSIF adr = 0 AND v.bsn_written = '0' THEN -- because of delays in address counter the bsn number will be written in ddr address 1 or 2 dependend on .
v.state := BSN_INPUT;
ELSE
v.state := FILL_VECTOR;
END IF;
WHEN BSN_INPUT =>
-- BSN_INPUT -- BSN_INPUT
v.out_bsn := in_bsn; IF adr = 0 AND q_reg.out_bsn_written = '0' THEN
v.out_bsn_ds := g_in_data_w*q_reg.c_v_count+q_reg.out_of; v.out_bsn := in_bsn;
v.bsn_written := '1'; IF g_in_data_w*q_reg.c_v_count+q_reg.out_of >= c_out_data_w THEN
v.out_bsn_ds := g_in_data_w*q_reg.c_v_count+q_reg.out_of-c_out_data_w;
ELSE
v.out_bsn_ds := g_in_data_w*q_reg.c_v_count+q_reg.out_of;
END IF;
v.out_bsn_written := '1';
END IF;
IF rst = '1' THEN
v.state := RESET;
ELSIF in_stop = '1' THEN
v.state := STOP;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN
v.state := FIRST_OUTPUT;
ELSE
v.state := FILL_VECTOR;
END IF;
-- FILL_VECTOR WHEN RESET =>
v.c_v(g_in_data_w*(q_reg.c_v_count+1)+v.out_of-1 DOWNTO g_in_data_w*q_reg.c_v_count+v.out_of) := in_data(g_in_data_w-1 DOWNTO 0); -- fill c_v v := c_t_reg_init;
v.c_v_count := q_reg.c_v_count+1; -- increase the counter of c_v with 1
v.out_sosi.valid := '0'; -- out_sosi.valid 0
IF rst = '1' THEN IF rst = '1' THEN
v.state := RESET; v.state := RESET;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN ELSIF in_stop = '1' THEN
v.state := FIRST_OUTPUT; v.state := STOP;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN ELSE
v.state := OVERFLOW_OUTPUT; v.state := FILL_VECTOR;
ELSE END IF;
v.state := FILL_VECTOR;
END IF;
WHEN RESET => WHEN STOP =>
v := c_t_reg_init; IF rst = '1' THEN
v.state := RESET;
ELSIF in_stop = '1' THEN
v.state := STOP;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN
v.state := FIRST_OUTPUT;
ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN
v.state := OVERFLOW_OUTPUT;
ELSE
v.state := FILL_VECTOR;
END IF;
IF rst = '1' THEN
v.state := RESET;
ELSIF adr = 0 AND v.bsn_written = '0' THEN -- because of delays in address counter the bsn number will be written in ddr address 1 or 2 dependend on .
v.state := BSN_INPUT;
ELSE
v.state := FILL_VECTOR;
END IF;
END CASE; END CASE;
IF NOT (adr=0) THEN IF NOT (adr=0) THEN
v.bsn_written := '0'; v.out_bsn_written := '0';
END IF; END IF;
d_reg <= v; d_reg <= v;
...@@ -198,5 +227,6 @@ BEGIN ...@@ -198,5 +227,6 @@ BEGIN
out_sosi <= q_reg.out_sosi; out_sosi <= q_reg.out_sosi;
out_bsn_ds <= q_reg.out_bsn_ds; out_bsn_ds <= q_reg.out_bsn_ds;
out_bsn <= q_reg.out_bsn; out_bsn <= q_reg.out_bsn;
out_bsn_wr <= q_reg.out_bsn_written;
END rtl; END rtl;
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Author: Job van Wee
-- Purpose: Self checking and self-stopping tb for ddrctrl_input.vhd
-- Usage:
-- > run -a
LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.MATH_REAL.ALL;
USE technology_lib.technology_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_pkg.ALL;
ENTITY tb_ddrctrl_input IS
GENERIC (
g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory
g_nof_streams : POSITIVE := 12; -- number of input streams
g_data_w : NATURAL := 14; -- data with of input data vectors
g_sim_length : NATURAL := 52
);
END tb_ddrctrl_input;
ARCHITECTURE tb OF tb_ddrctrl_input IS
-- constants for testbench
CONSTANT c_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation
CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz
CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns
-- constants for readability
CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168
CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576
CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( g_tech_ddr ) ; -- address with in simulation
CONSTANT c_adr_size : NATURAL := 2**c_adr_w; -- address size in simulation
-- function for making total data vector
FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS
VARIABLE v_total_vector : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0);
BEGIN
FOR I IN 0 TO g_sim_length*g_nof_streams-1 LOOP
v_total_vector(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := TO_UVEC(I, g_data_w);
END LOOP;
RETURN v_total_vector;
END FUNCTION c_total_vector_init;
-- constant for running the test
CONSTANT c_total_vector : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector
-- input signals for ddrctrl_input.vhd
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '0';
SIGNAL q_rst : STD_LOGIC := '0';
SIGNAL q_q_rst : STD_LOGIC := '0';
SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input data signal for ddrctrl_pack.vhd
-- output singals from ddrctrl_input.vhd
SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is
SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- output signal from ddrctrl_pack.vhd
SIGNAL out_adr : NATURAL := 0;
-- testbench signal
SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off
-- signals for running test
SIGNAL in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd
SIGNAL q_in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 1 clockcycle
SIGNAL q_q_in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 2 clockcycles
SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started
SIGNAL q_test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started with a delay of 1 clockcycle
SIGNAL q_q_test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started with a delay of 2 clockcycles
SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest
SIGNAL q_lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest with a delay of 1 clockcycle
BEGIN
-- generating clock
clk <= NOT clk OR tb_end AFTER c_clk_period/2;
-- excecuting test
p_test : PROCESS
BEGIN
-- start the test
tb_end <= '0';
WAIT UNTIL rising_edge(clk); -- align to rising edge
WAIT FOR c_clk_period*4;
rst <= '1';
WAIT FOR c_clk_period*1;
rst <= '0';
test_running <= '1';
-- filling the input data vectors with the corresponding numbers
make_data : FOR J IN 0 TO g_sim_length-1 LOOP
in_data_cnt <= in_data_cnt+1;
fill_in_sosi_arr_rest : FOR I IN 0 TO g_nof_streams-1 LOOP
in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) <= c_total_vector(g_data_w*(I+1)+J*c_in_data_w-1 DOWNTO g_data_w*I+J*c_in_data_w);
END LOOP;
WAIT FOR c_clk_period*1;
END LOOP;
test_running <= '0';
-- testing reset
--FOR I IN 0 TO g_sim_length-1 LOOP
--rst <= '1';
--WAIT FOR c_clk_period*1;
--rst <= '0';
--WAIT FOR c_clk_period*((((c_out_data_w/c_in_data_w)+1)*c_adr_size)+4);
--END LOOP;
-- stopping the testbench
WAIT FOR c_clk_period*4;
tb_end <= '1';
ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE;
END PROCESS;
-- generating compare data for out_sosi
p_out_sosi : PROCESS
BEGIN
WAIT UNTIL rising_edge(clk);
if rising_edge(clk) THEN
q_q_rst <= q_rst;
q_lag_due_reset <= lag_due_reset;
q_rst <= rst;
END IF;
IF q_rst = '1' THEN
IF lag_due_reset+out_adr+2 >= c_adr_size THEN
lag_due_reset <= lag_due_reset+out_adr+2-c_adr_size;
ELSE
lag_due_reset <= lag_due_reset+out_adr+2;
END IF;
END IF;
END PROCESS;
-- verifying if the address is correct by keeping track of the address
p_verify_address : PROCESS
VARIABLE v_adr : NATURAL range 0 to c_adr_size-1 := c_adr_size-2;
BEGIN
WAIT UNTIL rst = '1';
WAIT UNTIL rst = '0';
FOR I IN 0 TO g_sim_length-1 LOOP
IF v_adr >= q_lag_due_reset THEN
ASSERT v_adr-q_lag_due_reset = out_adr REPORT "Wrong address, 1, v_adr = " & NATURAL'image(v_adr-q_lag_due_reset) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR;
ELSE
ASSERT (v_adr-q_lag_due_reset)+c_adr_size = out_adr REPORT "Wrong address, 2, v_adr = " & NATURAL'image((v_adr-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR;
END IF;
WAIT UNTIL out_sosi.valid = '1';
IF q_q_rst = '1' THEN
WAIT UNTIL out_sosi.valid = '1';
END IF;
IF v_adr = c_adr_size-1 THEN
v_adr := 0;
ELSE
v_adr := v_adr+1;
END IF;
END LOOP;
WAIT;
END PROCESS;
-- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected
p_verify : PROCESS
VARIABLE ctr_of : NATURAL := 0;
VARIABLE out_data_cnt : NATURAL := 0;
BEGIN
WAIT UNTIL rising_edge(clk);
IF q_q_test_running = '1' AND out_sosi.valid = '1' THEN
out_data_cnt := out_data_cnt+1;
IF out_data_cnt mod 2 = 0 THEN
ctr_of := c_in_data_w*(q_q_in_data_cnt)-c_out_data_w*out_data_cnt;
ASSERT ctr_of = out_of REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) & ", out_of = " & NATURAL'image(out_of) SEVERITY ERROR;
END IF;
ASSERT out_sosi.data(c_out_data_w-1 DOWNTO 0) = c_total_vector(c_out_data_w*out_data_cnt-1 DOWNTO c_out_data_w*(out_data_cnt-1)) REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt) SEVERITY ERROR;
END IF;
END PROCESS;
-- DUT
u_ddrctrl_input : ENTITY work.ddrctrl_input
GENERIC MAP (
g_tech_ddr => g_tech_ddr,
g_sim_model => c_sim_model,
g_nof_streams => g_nof_streams,
g_data_w => g_data_w
)
PORT MAP (
clk => clk,
rst => rst,
in_sosi_arr => in_sosi_arr,
out_of => out_of,
out_sosi => out_sosi,
out_adr => out_adr
);
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Author: Job van Wee
-- Purpose: Self checking and self-stopping tb for ddrctrl_input_address_counter.vhd
-- Usage:
-- > run -a
LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE technology_lib.technology_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_pkg.ALL;
ENTITY tb_ddrctrl_input_address_counter IS
GENERIC (
g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory
g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation
g_sim_length : NATURAL := 52 -- determens the length of the duration of the test
);
END tb_ddrctrl_input_address_counter;
ARCHITECTURE tb OF tb_ddrctrl_input_address_counter IS
-- constants for running the testbench
CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz
CONSTANT c_clk_period : TIME := (10**6/c_clk_freq)*1 ps; -- clock period, 5 ns
-- constants for running the test
CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- in and output data vector with, 576
CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( g_tech_ddr ); -- address with in simulation
CONSTANT c_adr_size : NATURAL := 2**c_adr_w; -- address size in simulation
-- input signals for ddrctrl_address_counter.vhd
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '0';
SIGNAL q_rst : STD_LOGIC := '0';
SIGNAL q_q_rst : STD_LOGIC := '0';
SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_init; -- signal which is the input for ddrctrl_address_counter.vhd
SIGNAL in_of : NATURAL := 0; -- signal which contains the amount of overflow
-- output signal from ddrctrl_address_counter.vhd
SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- signal which is the output from ddrctrl_address_counter.vhd
SIGNAL out_adr : NATURAL := 0;
SIGNAL out_of : NATURAL := 0; -- signal which is the output from ddrctrl_address_counter.vhd
-- testbench signals
SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off
SIGNAL in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- signal which contains the data that is set as input
SIGNAL q_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- signal which contains the data that is set as input with a delay of 1 clockcycle
SIGNAL q_q_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- signal which contains the data that is set as input with a delay of 2 clockcycles
SIGNAL in_data_enable : STD_LOGIC := '0'; -- signal to determen if in_data is ready for reading
SIGNAL q_in_data_enable : STD_LOGIC := '0'; -- signal to determen if in_data is ready for reading with a delay of 1 clockcycle
SIGNAL q_q_in_data_enable: STD_LOGIC := '0'; -- signal to determen if in_data is ready for reading with a delay of 2 clockcycles
SIGNAL q_in_of : NATURAL := 0; -- signal which contains the amount of overflow with a delay of 1 clockcycle
SIGNAL q_q_in_of : NATURAL := 0; -- signal which contains the amount of overflow with a delay of 2 clockcycles
SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a reset
SIGNAL q_lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a reset with a delay of 1 clockcycle
BEGIN
-- wiring the input signals to the inputs of the testbench
in_sosi.data(c_data_w-1 DOWNTO 0) <= in_data(c_data_w-1 DOWNTO 0);
in_sosi.valid <= in_data_enable;
-- generating clock
clk <= NOT clk OR tb_end AFTER c_clk_period/2;
-- excecuting the test
p_test : PROCESS
BEGIN
-- initialize inputs
tb_end <= '0';
in_data <= (OTHERS => '0');
in_data_enable <= '0';
WAIT UNTIL rising_edge(clk);
WAIT FOR c_clk_period*4;
rst <= '1';
WAIT FOR c_clk_period*1;
rst <= '0';
-- changing inputs to start the address counting
FOR I IN 0 TO g_sim_length-1 LOOP
in_data_enable <= '1';
in_data <= NOT in_data;
in_of <= in_of + 1;
WAIT FOR c_clk_period*1;
in_data_enable <= '0';
WAIT FOR c_clk_period*2;
END LOOP;
-- stopping the test
WAIT FOR c_clk_period*4;
tb_end <= '1';
ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE;
END PROCESS;
-- generating compare data for out_sosi
p_out_sosi : PROCESS
BEGIN
WAIT UNTIL rising_edge(clk);
if rising_edge(clk) THEN
q_q_in_data_enable <= q_in_data_enable;
q_q_in_data <= q_in_data;
q_q_in_of <= q_in_of;
q_q_rst <= q_rst;
q_in_data_enable <= in_data_enable;
q_in_data <= in_data;
q_in_of <= in_of;
q_lag_due_reset <= lag_due_reset;
q_rst <= rst;
END IF;
IF q_rst = '1' THEN
IF lag_due_reset + out_adr >= c_adr_size THEN
lag_due_reset <= lag_due_reset+out_adr-c_adr_size;
ELSE
lag_due_reset <= lag_due_reset+out_adr;
END IF;
END IF;
END PROCESS;
-- verifying if the data is correct and if valid is correct
p_verify_data_valid : PROCESS
BEGIN
WAIT UNTIL rising_edge(clk);
IF rising_edge(clk) THEN
ASSERT q_q_in_data(c_data_w-1 DOWNTO 0) = out_sosi.data(c_data_w-1 DOWNTO 0) REPORT "in_sosi.data does not match out_sosi.data" SEVERITY ERROR;
ASSERT q_q_in_data_enable = out_sosi.valid REPORT "in_sosi.valid does not match out_sosi.valid" SEVERITY ERROR;
ASSERT q_q_in_of = out_of REPORT "in_of does not match out_of" SEVERITY ERROR;
END IF;
END PROCESS;
-- excecuting the reset test
p_test_reset : PROCESS
BEGIN
rst <= '0';
WAIT FOR c_clk_period*((c_adr_size*4)+3);
rst <= '1';
WAIT FOR c_clk_period*1;
END PROCESS;
-- verifying if the address is correct by keeping track of the address
p_verify_address : PROCESS
VARIABLE v_adr : NATURAL range 0 to c_adr_size-1 := c_adr_size-1;
BEGIN
WAIT UNTIL rst = '1';
WAIT UNTIL rst = '0';
FOR I IN 0 TO g_sim_length-1 LOOP
IF v_adr >= q_lag_due_reset THEN
ASSERT v_adr-q_lag_due_reset = out_adr REPORT "Wrong address, 1, v_adr = " & NATURAL'image(v_adr-q_lag_due_reset) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR;
ELSE
ASSERT (v_adr-q_lag_due_reset)+c_adr_size = out_adr REPORT "Wrong address, 2, v_adr = " & NATURAL'image((v_adr-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR;
END IF;
WAIT UNTIL out_sosi.valid = '1';
IF q_q_rst = '1' THEN
WAIT UNTIL out_sosi.valid = '1';
END IF;
IF v_adr = c_adr_size-1 THEN
v_adr := 0;
ELSE
v_adr := v_adr+1;
END IF;
END LOOP;
END PROCESS;
-- DUT
u_ddrctrl_input_address_counter : ENTITY work.ddrctrl_input_address_counter
GENERIC MAP (
g_tech_ddr => g_tech_ddr,
g_sim_model => g_sim_model
)
PORT MAP (
clk => clk,
rst => rst,
in_sosi => in_sosi,
in_of => in_of,
out_sosi => out_sosi,
out_of => out_of,
out_adr => out_adr
);
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Author: Job van Wee
-- Purpose: Self checking and self-stopping tb for ddrctrl_input_pack.vhd
-- Usage:
-- > run -a
LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.MATH_REAL.ALL;
USE technology_lib.technology_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_pkg.ALL;
ENTITY tb_ddrctrl_input_pack IS
GENERIC (
g_nof_streams : POSITIVE := 12; -- number of input streams
g_data_w : NATURAL := 14; -- data with of input data vectors
g_sim_length : NATURAL := 52 -- determens the lengt of the duration of the test
);
END tb_ddrctrl_input_pack;
ARCHITECTURE tb OF tb_ddrctrl_input_pack IS
-- constants for running the testbench
CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz
CONSTANT c_clk_period : TIME := (10**6/c_clk_freq)*1 ps; -- clock priod, 5 ns
-- constant for readability
CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- output data with, 168
-- function for making test vector
FUNCTION c_testv_init RETURN STD_LOGIC_VECTOR IS
VARIABLE temp : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0);
BEGIN
FOR I IN 0 TO g_nof_streams-1 LOOP
temp(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := TO_UVEC(I, g_data_w);
END LOOP;
RETURN temp;
END FUNCTION c_testv_init;
-- constants for running the test
CONSTANT c_testv : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0) := c_testv_init; -- testvector which contains a number for each stream, so the data of stream 6 will look like ...00110
-- input signals for ddrctrl_pack.vhd
SIGNAL clk : STD_LOGIC := '1'; -- clock signal
SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input signal for ddrctrl_pack.vhd
-- output singal from ddrctrl_pack.vhd
SIGNAL out_data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); -- output signal from ddrctrl_pack.vhd
-- testbench signal
SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off
BEGIN
-- generating clock
clk <= NOT clk OR tb_end AFTER c_clk_period/2;
-- excecuting the test
p_test : PROCESS
BEGIN
-- starting the test
tb_end <= '0';
WAIT UNTIL rising_edge(clk);
WAIT FOR c_clk_period*2;
-- the input data vectors get filled with the corresponding number
fill_in_sosi_arr : FOR I IN 0 TO g_nof_streams-1 LOOP
in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0) <= c_testv(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I);
END LOOP;
-- the numbers get cycled trough the input vectors
change_in_sosi_arr : FOR J IN 0 TO g_sim_length-1 LOOP
WAIT FOR c_clk_period*1;
in_sosi_arr(0).data(g_data_w - 1 DOWNTO 0) <= in_sosi_arr(g_nof_streams-1).data(g_data_w - 1 DOWNTO 0);
loop_switch_data : FOR I IN 1 TO g_nof_streams-1 LOOP
in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0) <= in_sosi_arr(I-1).data(g_data_w - 1 DOWNTO 0);
END LOOP;
END LOOP;
-- stopping the testbench
WAIT FOR c_clk_period*4;
tb_end <= '1';
ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE;
END PROCESS;
-- verification by checking if the input vectors equel the corresponding index of the output vector
p_verify : PROCESS
BEGIN
WAIT UNTIL rising_edge(clk);
IF rising_edge(clk) THEN
check_data : FOR I IN 0 TO g_nof_streams - 1 LOOP
ASSERT out_data(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I) = in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) REPORT "Data does not match, I = " & NATURAL'image(I) SEVERITY ERROR;
END LOOP;
END IF;
END PROCESS;
-- DUT
u_ddrctrl_input_pack : ENTITY work.ddrctrl_input_pack
GENERIC MAP (
g_nof_streams => g_nof_streams,
g_data_w => g_data_w
)
PORT MAP (
in_sosi_arr => in_sosi_arr,
out_data => out_data
);
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Author: Job van Wee
-- Purpose: Self checking and self-stopping tb for ddrctrl_input_repack.vhd
-- Usage:
-- > run -a
LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.MATH_REAL.ALL;
USE technology_lib.technology_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_pkg.ALL;
ENTITY tb_ddrctrl_input_repack IS
GENERIC (
g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory
g_in_data_w : NATURAL := 168; -- input data vector with
g_sim_lengt : NATURAL := 52 -- amount of times there wil be input data for ddrctrl_repack in this testbench
);
END tb_ddrctrl_input_repack;
ARCHITECTURE tb OF tb_ddrctrl_input_repack IS
-- constants for running testbench
CONSTANT c_clk_freq : NATURAL := 200; -- clock freqency in MHz
CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock period, 5 ns
-- constant for readability
CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576
-- function for making total data vector
FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS
VARIABLE temp : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0);
BEGIN
FOR I IN 0 TO g_sim_lengt-1 LOOP
temp(g_in_data_w*(I+1)-1 DOWNTO g_in_data_w*I) := TO_UVEC(I, g_in_data_w);
END LOOP;
RETURN temp;
END FUNCTION c_total_vector_init;
-- constant for running the test
CONSTANT c_total_vector : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector
-- input signals for ddrctrl_repack.vhd
SIGNAL clk : STD_LOGIC := '1'; -- clock signal
SIGNAL rst : STD_LOGIC := '0'; -- reset signal
SIGNAL in_data : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- input data signal for ddrctrl_repack
-- output signals from ddrctrl_repack.vhd
SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is
SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- output data signal form ddrctrl_repack
-- testbench signal
SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off
-- singals for running the test
SIGNAL in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd
SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started
BEGIN
-- Generating clock
clk <= NOT clk OR tb_end AFTER c_clk_period/2;
-- Excecuting the test
p_test : PROCESS
BEGIN
-- start the test
tb_end <= '0';
WAIT UNTIL rising_edge(clk); -- align to rising edge
WAIT FOR c_clk_period*5;
rst <= '1';
WAIT FOR c_clk_period*1;
rst <= '0';
WAIT FOR c_clk_period*1;
test_running <= '1'; -- start of test
-- filling the input vector g_sim_lengt amount of times
make_in_data : FOR I IN 0 TO g_sim_lengt-1 LOOP
in_data(g_in_data_w-1 DOWNTO 0) <= TO_UVEC(I, g_in_data_w);
WAIT FOR c_clk_period*1;
in_data_cnt <= in_data_cnt + 1;
END LOOP;
test_running <= '0';
-- stopping the testbench
WAIT FOR c_clk_period*5;
tb_end <= '1';
ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE;
END PROCESS;
-- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected
p_verify : PROCESS
VARIABLE ctr_of : NATURAL := 0;
VARIABLE out_data_cnt : NATURAL := 0;
BEGIN
WAIT UNTIL rising_edge(clk);
IF test_running = '1' AND out_sosi.valid = '1' THEN
out_data_cnt := out_data_cnt+1;
IF out_data_cnt mod 2 = 0 THEN
ctr_of := g_in_data_w*in_data_cnt-c_out_data_w*out_data_cnt;
ASSERT ctr_of = out_of REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) & ", out_of = " & NATURAL'image(out_of) SEVERITY ERROR;
END IF;
ASSERT out_sosi.data(c_out_data_w-1 DOWNTO 0) = c_total_vector(c_out_data_w*out_data_cnt-1 DOWNTO c_out_data_w*(out_data_cnt-1)) REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt) SEVERITY ERROR;
END IF;
END PROCESS;
-- DUT
u_ddrctrl_input_repack : ENTITY work.ddrctrl_input_repack
GENERIC MAP (
g_tech_ddr => g_tech_ddr,
g_in_data_w => g_in_data_w
)
PORT MAP (
clk => clk,
rst => rst,
in_data => in_data,
out_of => out_of,
out_sosi => out_sosi
);
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment