------------------------------------------------------------------------------- -- Title : Toplevel testbench -- Project : Prototype implementation of the GTU of the Alice TRD Experiment ------------------------------------------------------------------------------- -- File : toplevel_tb.vhd -- Author : Jan de Cuveland -- Company : -- Last update: 2003/07/07 -- Platform : ------------------------------------------------------------------------------- -- This is a prototype implementation of the Global Tracking Unit (GTU) -- of the Alice TRD detector. ------------------------------------------------------------------------------- -- Description: ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2003/05/13 1.0 cuveland Created ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use std.textio.all; use ieee.std_logic_textio.all; use work.gtu_types.all; use work.track_types.all; ------------------------------------------------------------------------------- entity toplevel_tb is generic ( in_file : string := "stim.data"; out_file : string := "out_file"; log_file : string := "log_file"; sector : integer := 10; -- 0..17 chamber : integer := 0); -- 0..4 end toplevel_tb; -- Format: "00 2 4 1 0x00432DBF 0x00000000 0x00000000" -- (sector) (chamber) (plane) (link) ((data)) ------------------------------------------------------------------------------- architecture default of toplevel_tb is type link_t is array (39 downto 0) of std_logic_vector(31 downto 0); type linklayer_t is array (1 downto 0) of link_t; type links_t is array (5 downto 0) of linklayer_t; constant clk_period_ext : time := 8 ns; -- 125 MHz constant clk_period_int : time := 25 ns; -- 40 MHz signal links : links_t; file stim : text open read_mode is in_file; file result : text open write_mode is out_file; file log : text open write_mode is log_file; signal chamber_i : unsigned(2 downto 0) := conv_unsigned(chamber, 3); signal clk_i : std_logic; signal rst_n_i : std_logic; signal pretrigger_i : std_logic; signal clk1_in_i : std_logic_vector(5 downto 0); signal clk0_in_i : std_logic_vector(5 downto 0); signal valid1_in_i : std_logic_vector(5 downto 0); signal valid0_in_i : std_logic_vector(5 downto 0); signal d1_in5_i : std_logic_vector(7 downto 0); signal d0_in5_i : std_logic_vector(7 downto 0); signal d1_in4_i : std_logic_vector(7 downto 0); signal d0_in4_i : std_logic_vector(7 downto 0); signal d1_in3_i : std_logic_vector(7 downto 0); signal d0_in3_i : std_logic_vector(7 downto 0); signal d1_in2_i : std_logic_vector(7 downto 0); signal d0_in2_i : std_logic_vector(7 downto 0); signal d1_in1_i : std_logic_vector(7 downto 0); signal d0_in1_i : std_logic_vector(7 downto 0); signal d1_in0_i : std_logic_vector(7 downto 0); signal d0_in0_i : std_logic_vector(7 downto 0); signal valid_out_i : std_logic; signal ready_out_i : std_logic; signal track_out_i : std_logic_vector(track_width-1 downto 0); signal pt_out_i : signed(pt_width-1 downto 0); signal pt : real; signal start_time : time; begin -- default DUT : entity work.toplevel port map ( chamber => chamber_i, clk => clk_i, rst_n => rst_n_i, pretrigger => pretrigger_i, clk1_in => clk1_in_i, clk0_in => clk0_in_i, valid1_in => valid1_in_i, valid0_in => valid0_in_i, d1_in5 => d1_in5_i, d0_in5 => d0_in5_i, d1_in4 => d1_in4_i, d0_in4 => d0_in4_i, d1_in3 => d1_in3_i, d0_in3 => d0_in3_i, d1_in2 => d1_in2_i, d0_in2 => d0_in2_i, d1_in1 => d1_in1_i, d0_in1 => d0_in1_i, d1_in0 => d1_in0_i, d0_in0 => d0_in0_i, valid_out => valid_out_i, ready_out => ready_out_i, track_out => track_out_i, pt_out => pt_out_i); pt <= real(conv_integer(pt_out_i)) / 128.0; -- generate internal clock process begin clk_i <= '1'; wait for clk_period_int / 2; clk_i <= '0'; wait for clk_period_int / 2; end process; -- generate reset process begin rst_n_i <= '0'; wait for 2.5 * clk_period_int; rst_n_i <= '1'; wait; end process; -- generate external clocks process begin clk0_in_i <= "111111"; clk1_in_i <= "111111"; wait for clk_period_ext / 2; clk0_in_i <= "000000"; clk1_in_i <= "000000"; wait for clk_period_ext / 2; end process; -- generate stimuli process begin valid0_in_i <= "000000"; valid1_in_i <= "000000"; pretrigger_i <= '0'; wait for 10 * clk_period_ext; pretrigger_i <= '1'; wait for 3 * clk_period_ext; pretrigger_i <= '0'; wait for 10 * clk_period_ext; wait for clk_period_ext * 1 / 4; valid0_in_i <= "111111"; valid1_in_i <= "111111"; for i in 0 to 39 loop d1_in5_i <= links(5)(1)(i)(7 downto 0); d0_in5_i <= links(5)(0)(i)(7 downto 0); d1_in4_i <= links(4)(1)(i)(7 downto 0); d0_in4_i <= links(4)(0)(i)(7 downto 0); d1_in3_i <= links(3)(1)(i)(7 downto 0); d0_in3_i <= links(3)(0)(i)(7 downto 0); d1_in2_i <= links(2)(1)(i)(7 downto 0); d0_in2_i <= links(2)(0)(i)(7 downto 0); d1_in1_i <= links(1)(1)(i)(7 downto 0); d0_in1_i <= links(1)(0)(i)(7 downto 0); d1_in0_i <= links(0)(1)(i)(7 downto 0); d0_in0_i <= links(0)(0)(i)(7 downto 0); wait for clk_period_ext / 2; d1_in5_i <= links(5)(1)(i)(15 downto 8); d0_in5_i <= links(5)(0)(i)(15 downto 8); d1_in4_i <= links(4)(1)(i)(15 downto 8); d0_in4_i <= links(4)(0)(i)(15 downto 8); d1_in3_i <= links(3)(1)(i)(15 downto 8); d0_in3_i <= links(3)(0)(i)(15 downto 8); d1_in2_i <= links(2)(1)(i)(15 downto 8); d0_in2_i <= links(2)(0)(i)(15 downto 8); d1_in1_i <= links(1)(1)(i)(15 downto 8); d0_in1_i <= links(1)(0)(i)(15 downto 8); d1_in0_i <= links(0)(1)(i)(15 downto 8); d0_in0_i <= links(0)(0)(i)(15 downto 8); wait for clk_period_ext / 2; d1_in5_i <= links(5)(1)(i)(23 downto 16); d0_in5_i <= links(5)(0)(i)(23 downto 16); d1_in4_i <= links(4)(1)(i)(23 downto 16); d0_in4_i <= links(4)(0)(i)(23 downto 16); d1_in3_i <= links(3)(1)(i)(23 downto 16); d0_in3_i <= links(3)(0)(i)(23 downto 16); d1_in2_i <= links(2)(1)(i)(23 downto 16); d0_in2_i <= links(2)(0)(i)(23 downto 16); d1_in1_i <= links(1)(1)(i)(23 downto 16); d0_in1_i <= links(1)(0)(i)(23 downto 16); d1_in0_i <= links(0)(1)(i)(23 downto 16); d0_in0_i <= links(0)(0)(i)(23 downto 16); wait for clk_period_ext / 2; d1_in5_i <= links(5)(1)(i)(31 downto 24); d0_in5_i <= links(5)(0)(i)(31 downto 24); d1_in4_i <= links(4)(1)(i)(31 downto 24); d0_in4_i <= links(4)(0)(i)(31 downto 24); d1_in3_i <= links(3)(1)(i)(31 downto 24); d0_in3_i <= links(3)(0)(i)(31 downto 24); d1_in2_i <= links(2)(1)(i)(31 downto 24); d0_in2_i <= links(2)(0)(i)(31 downto 24); d1_in1_i <= links(1)(1)(i)(31 downto 24); d0_in1_i <= links(1)(0)(i)(31 downto 24); d1_in0_i <= links(0)(1)(i)(31 downto 24); d0_in0_i <= links(0)(0)(i)(31 downto 24); wait for clk_period_ext / 2; end loop; valid0_in_i <= "000000"; valid1_in_i <= "000000"; wait; end process; -- load stimuli process variable l : line; variable i_sector, i_chamber : integer; variable i_plane, i_link : integer; variable data : std_logic_vector(31 downto 0); variable good : boolean; variable count : integer; variable char : character; begin while not endfile(stim) loop readline(stim, l); read(l, i_sector); read(l, i_chamber); read(l, i_plane); read(l, i_link); if i_sector = sector and i_chamber = chamber then count := 0; read(l, char, good); read(l, char, good); read(l, char, good); hread(l, data, good); while good loop links(i_plane)(i_link)(count) <= data; count := count + 1; read(l, char, good); read(l, char, good); read(l, char, good); hread(l, data, good); end loop; end if; end loop; wait; end process; -- save output tracks to file process (clk_i) variable l : line; begin if clk_i'event and clk_i = '1' then if valid_out_i = '1' then write(l, sector, right, 2); write(l, chamber, right, 2); write(l, conv_integer(unsigned(track_out_i(matchvec_high downto matchvec_low))), right, 3); for i in 5 downto 0 loop write(l, conv_integer(unsigned(track_out_i(addr0_high+i*6 downto addr0_low+i*6))), right, 2); end loop; write(l, conv_integer(pt_out_i), right, 6); write(l, string'(" ")); write(l, pt, right, 10); writeline(result, l); end if; end if; end process; -- log timing data to file process (valid0_in_i) begin if valid0_in_i(0)'event and valid0_in_i(0) = '1' then start_time <= now; end if; end process; process (ready_out_i) variable l : line; begin if ready_out_i'event and ready_out_i = '1' then write(l, sector, right, 2); write(l, chamber, right, 2); write(l, string'(" ")); write(l, now - start_time); write(l, string'(" ")); write(l, (now - start_time) / clk_period_int); writeline(log, l); end if; end process; end default; -------------------------------------------------------------------------------