------------------------------------------------------------------------------- -- Title : Merger for tracks from different seed planes -- Project : Prototype implementation of the GTU of the Alice TRD Experiment ------------------------------------------------------------------------------- -- File : seed_merger.vhd -- Author : Jan de Cuveland -- Company : -- Last update: 2003/07/08 -- Platform : ------------------------------------------------------------------------------- -- This is a prototype implementation of the Global Tracking Unit (GTU) -- of the Alice TRD detector. ------------------------------------------------------------------------------- -- Description: ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2003/06/16 1.0 cuveland Created ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use work.gtu_types.all; use work.track_types.all; ------------------------------------------------------------------------------- entity seed_merger is port ( clk : in std_logic; rst_n : in std_logic; pretrigger : in std_logic; valid_in : in std_logic_vector(2 downto 0); ready_in : in std_logic_vector(2 downto 0); track2_in : in std_logic_vector(track_with_idx_width-1 downto 0); track1_in : in std_logic_vector(track_with_idx_width-1 downto 0); track0_in : in std_logic_vector(track_with_idx_width-1 downto 0); valid_out : out std_logic; ready_out : out std_logic; track_out : out std_logic_vector(track_with_idx_width-1 downto 0)); end; ------------------------------------------------------------------------------- architecture default of seed_merger is constant mem_addr_width : integer := 3; -- FIFO depth is 8 words -- input signals type track_with_idx_t3 is array (2 downto 0) of track_with_idx_t; signal track_in : track_with_idx_t3; -- internal signals signal ready_in_reg : std_logic_vector(2 downto 0); type mem_t is array (0 to 2**mem_addr_width-1) of std_logic_vector(track_with_idx_width-1 downto 0); type mem_t3 is array (2 downto 0) of mem_t; signal mem : mem_t3; type idx_t3 is array (2 downto 0) of unsigned(idx_width-1 downto 0); type y_t3 is array (2 downto 0) of signed(approx_ypos_width-1 downto 0); signal mem_out : track_with_idx_t3; signal mem_out_idx : idx_t3; signal mem_out_y : y_t3; type mem_addr_t3 is array (2 downto 0) of unsigned(mem_addr_width-1 downto 0); signal wr_addr_reg : mem_addr_t3; signal wr_addr_last : mem_addr_t3; signal rd_addr_reg : mem_addr_t3; signal not_empty : std_logic_vector(2 downto 0); signal lower_than_next : std_logic_vector(2 downto 0); signal pop : std_logic_vector(2 downto 0); begin gen_s : for s in 2 downto 0 generate -- mem write address register process (clk, rst_n) begin if rst_n = '0' then wr_addr_reg(s) <= (mem_addr_width-1 downto 0 => '0'); elsif clk'event and clk = '1' then if pretrigger = '1' then wr_addr_reg(s) <= (mem_addr_width-1 downto 0 => '0'); elsif valid_in(s) = '1' then wr_addr_reg(s) <= wr_addr_reg(s) + 1; end if; end if; end process; -- registers process (clk, rst_n) begin if rst_n = '0' then wr_addr_last(s) <= (mem_addr_width-1 downto 0 => '0'); ready_in_reg(s) <= '0'; elsif clk'event and clk = '1' then if pretrigger = '1' then wr_addr_last(s) <= (mem_addr_width-1 downto 0 => '0'); --### -- else wr_addr_last(s) <= wr_addr_reg(s); end if; ready_in_reg(s) <= ready_in(s); end if; end process; -- memory process (clk) begin if clk'event and clk = '1' then if valid_in(s) = '1' then mem(s)(conv_integer(wr_addr_reg(s))) <= track_in(s); end if; end if; end process; -- mem read address register process (clk, rst_n) begin if rst_n = '0' then rd_addr_reg(s) <= (mem_addr_width-1 downto 0 => '0'); elsif clk'event and clk = '1' then if pretrigger = '1' then rd_addr_reg(s) <= (mem_addr_width-1 downto 0 => '0'); elsif pop(s) = '1' then rd_addr_reg(s) <= rd_addr_reg(s) + 1; end if; end if; end process; mem_out(s) <= mem(s)(conv_integer(rd_addr_reg(s))); mem_out_idx(s) <= unsigned(mem_out(s)(idx_high downto idx_low)); mem_out_y(s) <= signed(mem_out(s)(y_high downto y_low)); -- convenience signals not_empty(s) <= '1' when wr_addr_last(s) /= rd_addr_reg(s) else '0'; lower_than_next(s) <= '1' when mem_out_idx(s) < mem_out_idx((s+1) mod 3) or (mem_out_idx(s) = mem_out_idx((s+1) mod 3) and mem_out_y(s) < mem_out_y((s+1) mod 3)) else '0'; end generate; process (not_empty, lower_than_next, ready_in_reg) begin pop <= "000"; if (not_empty(2) = '1' or ready_in_reg(2) = '1') and (not_empty(1) = '1' or ready_in_reg(1) = '1') and (not_empty(0) = '1' or ready_in_reg(0) = '1') then case not_empty is when "000" => null; when "001" => pop(0) <= '1'; when "010" => pop(1) <= '1'; when "011" => if lower_than_next(0) = '1' then pop(0) <= '1'; else pop(1) <= '1'; end if; when "100" => pop(2) <= '1'; when "101" => if lower_than_next(2) = '1' then pop(2) <= '1'; else pop(0) <= '1'; end if; when "110" => if lower_than_next(1) = '1' then pop(1) <= '1'; else pop(2) <= '1'; end if; when "111" => if lower_than_next(0) = '1' then if lower_than_next(2) = '1' then pop(2) <= '1'; else pop(0) <= '1'; end if; else if lower_than_next(1) = '1' then pop(1) <= '1'; else pop(2) <= '1'; end if; end if; when others => null; end case; end if; end process; valid_out <= '1' when pop /= "000" else '0'; ready_out <= '1' when not_empty = "000" and ready_in_reg = "111" else '0'; process (pop, mem_out) begin if pop(2) = '1' then track_out <= mem_out(2); elsif pop(1) = '1' then track_out <= mem_out(1); else track_out <= mem_out(0); end if; end process; -- connect input signals track_in(2) <= track2_in; track_in(1) <= track1_in; track_in(0) <= track0_in; end;