--============================================================================== -- CERN (BE-CO-HT) -- Testbench for CONV-BURST_CTRL design --============================================================================== -- -- author: Denia Bouhired (denia.bouhired@cern.ch) -- -- date of creation: 20-09-2016 -- -- version: 1.0 -- -- description: -- Simulation testbench for the new burst mode module to run in as part of the -- CONV-TTL-BLO common gateware. -- -- -- dependencies: -- None. -- --============================================================================== -- GNU LESSER GENERAL PUBLIC LICENSE --============================================================================== -- This source file is free software; you can redistribute it and/or modify it -- under the terms of the GNU Lesser General Public License as published by the -- Free Software Foundation; either version 2.1 of the License, or (at your -- option) any later version. This source 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 Lesser General Public License for more details. You should have -- received a copy of the GNU Lesser General Public License along with this -- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html --============================================================================== -- last changes: -- 20-09-2016 Denia Bouhired File created --============================================================================== -- TODO: - --============================================================================== library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; use std.textio.all; use work.gencores_pkg.all; --use work.wishbone_pkg.all; use work.conv_common_gw_pkg.all; entity testbench is end entity testbench; architecture behav of testbench is -- Clock periods constant c_clk_20_per : time := 50 ns; constant random_intervals : boolean := false; constant c_pgen_pwidth: natural := 5; constant c_pgen_duty_cycle_div : natural := 2; constant pwidth_sel : std_logic := '0'; constant gf_en_n :std_logic:= '0'; constant test_pgen : boolean:=false; -- constant g_temp_decre_step_in: t_temp_decre_step := (0,0,0,0,0,0,0,0,2500,731,220,250,40,85,50,125); constant g_temp_decre_step_in: t_temp_decre_step := (0, 0, 769, 31, 104, 14, 82, 0 ,0, 0, 0, 0, 0, 0, 0, 0); -- constant g_1_pulse_temp_rise_in :unsigned (19 downto 0) := x"17700"; constant g_1_pulse_temp_rise_in :unsigned (19 downto 0) :=x"01388"; type t_time_array is array (2 downto 0) of integer; component conv_pulse_gen is generic ( -- This generic enables elaboration of the fixed pulse width logic g_with_fixed_pwidth : boolean; -- Pulse width, in number of clk_i cycles -- Default pulse width (20 MHz clock): 1.2 us -- Minimum allowable pulse width (20 MHz clock): 1 us -- Maximum allowable pulse width (20 MHz clock): 2 us g_pwidth : natural range 2 to 40 := 24; -- Duty cycle divider: D = 1/g_duty_cycle_div g_duty_cycle_div : natural := 5 ); port ( -- Clock and active-low reset inputs clk_i : in std_logic; rst_n_i : in std_logic; -- Glitch filter enable input -- '1' - Glitch filter disabled (glitch-sensitive, no output jitter) -- '0' - Glitch filter enabled (glitch-insensitive, with output jitter) gf_en_n_i : in std_logic; -- Enable input, pulse generation is enabled when '1' en_i : in std_logic; -- Trigger input, has to be '1' to assure pulse output with delay no greater -- than internal gate delays. trig_a_i : in std_logic; trig_r_edge_p_i : in std_logic; --synced 1 cycle-long r edge output trig_f_edge_p_i : in std_logic; --synced 1 cycle-long f edge output -- Pulse error output, pulses high for one clock cycle when a pulse arrives -- within a pulse period pulse_err_p_o : out std_logic; -- Pulse output, active-high -- latency: -- glitch filter disabled: none -- glitch filter enabled: glitch filter length + 5 clk_i cycles pulse_o : out std_logic; pulse_r_edge_p_o : out std_logic; --synced 1 cycle-long r edge output pulse_f_edge_p_o : out std_logic ); end component conv_pulse_gen; component conv_dyn_burst_ctrl is generic ( g_pwidth : natural range 2 to 40 := 5; g_temp_decre_step : t_temp_decre_step := (0, 0, 769, 31, 104, 14, 82, 0 ,0, 0, 0, 0, 0, 0, 0,0); g_1_pulse_temp_rise :in unsigned (19 downto 0); g_max_temp :in unsigned (39 downto 0) ); port ( -- Clock and active-low reset inputs clk_i : in std_logic; rst_n_i : in std_logic; -- Enable input, pulse generation is enabled when '1' en_i : in std_logic; pulse_burst_i : in std_logic; pulse_r_edge_p_i : in std_logic; pulse_f_edge_p_i : in std_logic; temp_rise_o :out unsigned (39 downto 0); pulse_burst_o : out std_logic; -- Burst error output, pulses high for one clock cycle when a pulse arrives -- within a burst rejection phase burst_err_p_o : out std_logic ); end component conv_dyn_burst_ctrl; -- Signal declarations signal clk_20 : std_logic; signal rst_n : std_logic; signal en : std_logic; signal burst_train_d0 : std_logic; signal burst_train_d1 : std_logic; -- signal burst_train_d2 : std_logic; signal burst_train : std_logic; signal burst_train_f_edge : std_logic; signal burst_train_r_edge : std_logic; signal burst_train_redge_in : std_logic; signal burst_train_fedge_in : std_logic; signal burst_train_regulated_dyn : std_logic; signal rand_num : integer := 0; signal pulse_outp_err_p :std_logic; signal burst_outp_err_p :std_logic; signal pulse_outp :std_logic; signal pgen_pwidth : integer; signal pgen_duty_cycle_div : integer; signal temp_rise : unsigned (39 downto 0); signal pnumber : integer; signal period_array_lg : t_time_array; signal period_array_sh : t_time_array; signal pwidth_array_lg : t_time_array; signal pwidth_array_sh : t_time_array; signal t_start : TIME := NOW; signal t_sim1 :TIME := 0 ns; signal t_sim2 :TIME := 0 ns; signal t_sim3 :TIME := 0 ns; --============================================================================== -- architecture begin --============================================================================== begin -- =========================================================================== --Instantiate the DUT: Burst controller averaged over 1000 pulses --============================================================================ -- burst_train_dyn <= burst_train; --============================================================================ -- Instantiate the DUT: Dynamic --============================================================================ cmp_pulse_gen_sh : conv_pulse_gen generic map ( g_with_fixed_pwidth => true, g_pwidth => c_pgen_pwidth, g_duty_cycle_div => c_pgen_duty_cycle_div ) port map ( clk_i => clk_20, rst_n_i => rst_n, gf_en_n_i => gf_en_n, en_i => '1', trig_a_i => burst_train_d1, trig_r_edge_p_i => burst_train_redge_in, trig_f_edge_p_i => burst_train_fedge_in, pulse_err_p_o => pulse_outp_err_p, pulse_o => pulse_outp, pulse_r_edge_p_o => burst_train_r_edge , pulse_f_edge_p_o => burst_train_f_edge ); cmp_dut : conv_dyn_burst_ctrl generic map ( g_pwidth => c_pgen_pwidth, -- g_temp_decre_step => g_temp_decre_step_in, g_1_pulse_temp_rise => g_1_pulse_temp_rise_in, g_max_temp => x"00000F4240" --10^6 -- g_max_temp => x"02540BE400" --10^10 ) port map( clk_i => clk_20, rst_n_i => rst_n, en_i => '1', pulse_burst_i => pulse_outp, pulse_r_edge_p_i => burst_train_r_edge, pulse_f_edge_p_i => burst_train_f_edge, temp_rise_o => temp_rise, pulse_burst_o => burst_train_regulated_dyn, burst_err_p_o => burst_outp_err_p ); cmp_sync_ffs : gc_sync_ffs port map ( clk_i => clk_20, rst_n_i => rst_n, data_i => burst_train_d1, ppulse_o => burst_train_redge_in, npulse_o => burst_train_fedge_in ); --============================================================================ -- Generate clock signals --============================================================================ p_clk_20 : process begin clk_20 <= '1'; wait for c_clk_20_per/2; clk_20 <= '0'; wait for c_clk_20_per/2; end process p_clk_20; --============================================================================ -- Random number generator --============================================================================ p_ran_gen : process variable seed1, seed2: positive := 1; -- seed values for random generator variable rand: real; -- random real-number value in range 0 to 1.0 variable range_of_rand : real := 1000.0; -- the range of random values created will be 0 to +10000. begin uniform(seed1, seed2, rand); -- generate random number rand_num <= integer(rand*range_of_rand); -- rescale to 0..1000, convert integer part wait for 1000 ns; end process p_ran_gen; process begin rst_n <= '1'; wait for 2500 ns; rst_n <= '0'; wait for 2000 ns; rst_n <= '1'; wait; end process; process begin en <= '0'; wait for 5000 ns; en <= '1'; wait; end process; --============================================================================ -- Pulse stimuli --============================================================================ -- cmp_sync_input : gc_sync_ffs -- generic map -- ( -- g_sync_edge => "positive" -- ) -- port map -- ( -- clk_i => clk_20, -- rst_n_i => rst_n, -- data_i => burst_train, -- npulse_o => burst_train_f_edge, -- ppulse_o => burst_train_r_edge -- ); period_array_lg <= (8000 , 9600 , 20000 ); pwidth_array_lg <= (2000 , 500 , 1200 ); period_array_sh <= (450 , 500 , 1000 ); pwidth_array_sh <= (400 , 100 , 250 ); -- p_sel_params : process -- variable interval : time; -- begin -- -- if rst_n = '1' and en = '1' then -- --for gf_en_n in -- if pwidth_sel = '1' then -- for pwidth_index in 2 downto 0 loop -- for period_index in 2 downto 0 loop -- pnumber <= 0; -- while pnumber < 9 loop -- -- if random_intervals then -- -- interval := rand_num * 1 ns; -- -- if interval < 250 ns then -- -- interval := 250 ns; -- -- end if; -- -- else -- interval := (period_array_lg(period_index) - pwidth_array_lg(pwidth_index))*1ns; -- -- end if; -- burst_train <= '0'; -- wait for interval; -- burst_train <= '1'; -- wait for pwidth_array_lg(pwidth_index)*1ns;-- changes pulse width -- burst_train <= '0'; -- pnumber <= pnumber + 1; -- end loop; -- wait for 0.1 ms; -- end loop; -- wait for 0.2 ms; -- end loop; -- wait for 0.5 ms; -- else -- for pwidth_index in 2 downto 0 loop -- for period_index in 2 downto 0 loop -- pnumber<=0; -- while pnumber < 9 loop -- -- if random_intervals then -- -- interval := rand_num * 1 ns; -- -- if interval < 250 ns then -- -- interval := 250 ns; -- -- end if; -- -- else -- interval := (period_array_sh(period_index) - pwidth_array_sh(pwidth_index))*1ns; -- -- end if; -- burst_train <= '0'; -- wait for interval; -- burst_train <= '1'; -- wait for pwidth_array_sh(pwidth_index)*1ns;-- changes pulse width -- burst_train <= '0'; -- pnumber <= pnumber+1; -- end loop; -- wait for 0.01 ms; -- end loop; -- wait for 0.02 ms; -- end loop; -- wait for 0.05 ms; -- -- end if; -- end if; -- end process p_sel_params; p_delay : process (clk_20) begin if rising_edge(clk_20) then if (rst_n = '0') then burst_train_d0 <= '0'; burst_train_d1 <= '0'; else burst_train_d0 <= burst_train; burst_train_d1 <= burst_train_d0; end if; end if; end process p_delay; p_stim_burst1 : process variable interval : time;-- := 1000 ns; variable period1 : time := 250 ns;--changes pulse frequency variable period2 : time := 2000 ns;--changes pulse frequency variable period3 : time := 450 ns;--changes pulse frequency variable pwidth : time := 100 ns; begin while t_sim1 < 10000 us loop t_sim1 <= NOW - t_start; if random_intervals then interval := rand_num * 1 ns; if interval < 250 ns then interval := 250 ns; end if; else interval := period1 - pwidth; end if; burst_train <= '0'; wait for interval; burst_train <= '1'; wait for pwidth;-- changes pulse width burst_train <= '0'; end loop; while t_sim2 < 10000 us loop t_sim2 <= NOW - t_sim1; if random_intervals then interval := rand_num * 1 ns; else interval := period2 - pwidth; end if; burst_train <= '0'; wait for interval; burst_train <= '1'; wait for pwidth; burst_train <= '0'; end loop; burst_train <= '0'; wait for 5 ms; while t_sim3 < 30000 us loop t_sim3 <= NOW - t_sim1; interval := period3 - pwidth; burst_train <= '0'; wait for interval; burst_train <= '1'; wait for pwidth;-- changes pulse width burst_train <= '0'; end loop; end process p_stim_burst1; -- p_write_output : process (temp_rise_counter) -- file F : text open write_mode is "C:\Users\debouhir\work\CONV-TTL-BLO\conv-ttl-blo\conv-ttl-blo-gw\sim\Release\temp_rise_counter.txt"; -- variable L : line; -- begin -- write (L, NOW, left, 30); -- write (L, to_integer((temp_rise_counter (19 downto 0))), left, 50); -- write (L, to_integer((temp_rise_counter (39 downto 20))), left, 50); -- writeline (F, L); -- end process p_write_output; end architecture behav; --============================================================================== -- architecture end --==============================================================================