------------------------------------------------------------------------------- -- Title : Resorts tracks from different z channels -- Project : Prototype implementation of the GTU of the Alice TRD Experiment ------------------------------------------------------------------------------- -- File : zch_resorter.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 zch_resorter is port ( clk : in std_logic; rst_n : in std_logic; pretrigger : in std_logic; valid_in : in std_logic; ready_in : in std_logic; track_in : in std_logic_vector(track_with_zpos_width-1 downto 0); valid_out : out std_logic; ready_out : out std_logic; track_out : out std_logic_vector(track_width-1 downto 0)); end; ------------------------------------------------------------------------------- architecture default of zch_resorter is constant mem_addr_width : integer := 4; -- FIFO depth is 16 words -- input signals signal track_in_i : track_with_zhalf_t; signal z_lsb_in : std_logic; -- internal signals signal ready_in_reg : std_logic; signal valid_in_i : std_logic_vector(1 downto 0); type mem_t is array (0 to 2**mem_addr_width-1) of std_logic_vector(track_with_zhalf_width-1 downto 0); type mem_t2 is array (1 downto 0) of mem_t; signal mem : mem_t2; type track_with_zhalf_t2 is array (1 downto 0) of track_with_zhalf_t; type zhalf_t2 is array (1 downto 0) of unsigned(zhalf_width-1 downto 0); type y_t2 is array (1 downto 0) of signed(approx_ypos_width-1 downto 0); signal mem_out : track_with_zhalf_t2; signal mem_out_zhalf : zhalf_t2; signal mem_out_y : y_t2; type mem_addr_t2 is array (1 downto 0) of unsigned(mem_addr_width-1 downto 0); signal wr_addr_reg : mem_addr_t2; signal wr_addr_last : mem_addr_t2; signal rd_addr_reg : mem_addr_t2; signal not_empty : std_logic_vector(1 downto 0); signal pop : std_logic_vector(1 downto 0); begin -- connect input signals track_in_i <= track_in(track_with_zpos_width-1 downto zpos_low+1) & track_in(zpos_low-1 downto 0); z_lsb_in <= track_in(zpos_low); valid_in_i <= "01" when valid_in = '1' and z_lsb_in = '0' else "10" when valid_in = '1' and z_lsb_in = '1' else "00"; -- register process (clk, rst_n) begin if rst_n = '0' then ready_in_reg <= '0'; elsif clk'event and clk = '1' then ready_in_reg <= ready_in; end if; end process; gen_ch : for ch in 1 downto 0 generate -- mem write address register process (clk, rst_n) begin if rst_n = '0' then wr_addr_reg(ch) <= (mem_addr_width-1 downto 0 => '0'); elsif clk'event and clk = '1' then if pretrigger = '1' then wr_addr_reg(ch) <= (mem_addr_width-1 downto 0 => '0'); elsif valid_in_i(ch) = '1' then wr_addr_reg(ch) <= wr_addr_reg(ch) + 1; end if; end if; end process; -- register process (clk, rst_n) begin if rst_n = '0' then wr_addr_last(ch) <= (mem_addr_width-1 downto 0 => '0'); elsif clk'event and clk = '1' then if pretrigger = '1' then wr_addr_last(ch) <= (mem_addr_width-1 downto 0 => '0'); else wr_addr_last(ch) <= wr_addr_reg(ch); end if; end if; end process; -- memory process (clk) begin if clk'event and clk = '1' then if valid_in_i(ch) = '1' then mem(ch)(conv_integer(wr_addr_reg(ch))) <= track_in_i; end if; end if; end process; -- mem read address register process (clk, rst_n) begin if rst_n = '0' then rd_addr_reg(ch) <= (mem_addr_width-1 downto 0 => '0'); elsif clk'event and clk = '1' then if pretrigger = '1' then rd_addr_reg(ch) <= (mem_addr_width-1 downto 0 => '0'); elsif pop(ch) = '1' then rd_addr_reg(ch) <= rd_addr_reg(ch) + 1; end if; end if; end process; mem_out(ch) <= mem(ch)(conv_integer(rd_addr_reg(ch))); mem_out_zhalf(ch) <= unsigned(mem_out(ch)(zhalf_high downto zhalf_low)); mem_out_y(ch) <= signed(mem_out(ch)(y_high downto y_low)); -- convenience signals not_empty(ch) <= '1' when wr_addr_last(ch) /= rd_addr_reg(ch) else '0'; end generate; process (not_empty, ready_in_reg, mem_out_zhalf, mem_out_y) begin pop <= "00"; if not_empty = "11" or ready_in_reg = '1' then case not_empty is when "00" => null; when "01" => pop(0) <= '1'; when "10" => pop(1) <= '1'; when "11" => if mem_out_zhalf(0) < mem_out_zhalf(1) or (mem_out_zhalf(0) = mem_out_zhalf(1) and mem_out_y(0) < mem_out_y(1)) then pop(0) <= '1'; else pop(1) <= '1'; end if; when others => null; end case; end if; end process; valid_out <= '1' when pop /= "00" else '0'; ready_out <= '1' when not_empty = "00" and ready_in_reg = '1' else '0'; process (pop, mem_out) begin if pop(1) = '1' then track_out <= mem_out(1)(y_low-1 downto 0); else track_out <= mem_out(0)(y_low-1 downto 0); end if; end process; end;