------------------------------------------------------------------------------- -- Title : Matching Unit Memory -- Project : Prototype implementation of the GTU of the Alice TRD Experiment ------------------------------------------------------------------------------- -- File : matching_memory.vhd -- Author : Jan de Cuveland -- Company : -- Last update: 2003/06/04 -- Platform : ------------------------------------------------------------------------------- -- This is a prototype implementation of the Global Tracking Unit (GTU) -- of the Alice TRD detector. ------------------------------------------------------------------------------- -- Description: ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2003/03/25 1.0 cuveland Created -- 2006/06/22 1.1 angelov Memory instantiated ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use work.gtu_types.all; ------------------------------------------------------------------------------- entity matching_memory is port ( clk : in std_logic; rst_n : in std_logic; pretrigger : in std_logic; valid_in : in std_logic; y_in : in signed(proj_ypos_width-1 downto 0); a_in : in signed(deflang_width-1 downto 0); idx_in : in unsigned(idx_width-1 downto 0); addr_in : in unsigned(addr_width-1 downto 0); addr2_in : in unsigned(addr_width-1 downto 0); ab_select : in std_logic; inc : in unsigned(1 downto 0); idx_a : out unsigned(idx_width-1 downto 0); idx_b : out unsigned(idx_width-1 downto 0); y_a : out signed(proj_ypos_width-1 downto 0); y_b : out signed(proj_ypos_width-1 downto 0); a_a : out signed(deflang_width-1 downto 0); a_b : out signed(deflang_width-1 downto 0); addr_out : out unsigned(addr_width-1 downto 0); invalid : out std_logic; ready : out std_logic); end matching_memory; ------------------------------------------------------------------------------- architecture default of matching_memory is component dpram64xN is generic (Nd : Integer := 21); port( clk : in std_logic; we : in std_logic; wa : in unsigned( 5 downto 0); din : in std_logic_vector(Nd-1 downto 0); ra : in unsigned( 5 downto 0); dout : out std_logic_vector(Nd-1 downto 0) ); end component; component dpram64x26 port ( addra : IN std_logic_VECTOR(5 downto 0); addrb : IN std_logic_VECTOR(5 downto 0); clka : IN std_logic; clkb : IN std_logic; dina : IN std_logic_VECTOR(25 downto 0); doutb : OUT std_logic_VECTOR(25 downto 0); wea : IN std_logic); end component; -- Internal Signals signal reg_last : unsigned(5 downto 0); signal reg_a : unsigned(5 downto 0); signal reg_b : unsigned(5 downto 0); signal reg_a_in : std_logic_vector(5 downto 0); signal reg_b_in : std_logic_vector(5 downto 0); signal next_a : unsigned(5 downto 0); signal next_b : unsigned(5 downto 0); signal next_a_inc0 : unsigned(5 downto 0); signal next_b_inc0 : unsigned(5 downto 0); signal next_a_inc1 : unsigned(5 downto 0); signal next_b_inc1 : unsigned(5 downto 0); signal next_a_inc2 : unsigned(5 downto 0); signal next_b_inc2 : unsigned(5 downto 0); signal b_is_end : std_logic; signal a_plus_2 : unsigned(5 downto 0); signal b_plus_2 : unsigned(5 downto 0); constant a_low : integer := 0; constant a_high : integer := a_low + deflang_width - 1; -- 0 + 7 - 1 constant y_low : integer := a_high + 1; -- 7 constant y_high : integer := y_low + proj_ypos_width - 1; -- 7 + 10 - 1 constant idx_low : integer := y_high + 1; -- 17 constant idx_high : integer := idx_low + idx_width - 1; -- 17 + 3 - 1 constant addr_low : integer := idx_high + 1; -- 20 constant addr_high : integer := addr_low + addr_width - 1; -- 20 + 6 - 1 constant ram_size : integer := addr_high + 1; -- 20 + 6 signal invalid_i, invalid_reg : std_logic; signal ram_in : std_logic_vector(ram_size-1 downto 0); signal ram_a_out, ram_b_out : std_logic_vector(ram_size-1 downto 0); -- memory blocks --type mem is array (0 to 63) of std_logic_vector(ram_size-1 downto 0); --signal ram_block_a, ram_block_b : mem; begin ram_in <= std_logic_vector(addr_in) & std_logic_vector(idx_in) & std_logic_vector(y_in) & std_logic_vector(a_in); -- ram blocks --process (clk) --begin -- if clk'event and clk = '1' then -- if valid_in = '1' then -- ram_block_a(conv_integer(addr2_in)) <= ram_in; -- ram_block_b(conv_integer(addr2_in)) <= ram_in; -- end if; -- end if; --end process; -- --ram_a_out <= ram_block_a(conv_integer(reg_a)); --ram_b_out <= ram_block_b(conv_integer(reg_b)); -- Here can be used memory with 1 write and 2 read ports -- The read port can be made syncrhonous by feeding the next value of -- the reg_a/b to the read address port --rama: dpram64xN -- generic map(Nd => ram_in'length) -- port map( -- clk => clk, -- we => valid_in, -- wa => addr2_in, -- din => ram_in, ---- ra => reg_a, -- ra => reg_a_in, -- dout => ram_a_out -- ); -- --ramb: dpram64xN -- generic map(Nd => ram_in'length) -- port map( -- clk => clk, -- we => valid_in, -- wa => addr2_in, -- din => ram_in, ---- ra => reg_b, -- ra => reg_b_in, -- dout => ram_b_out -- ); -- generated with the core generator. Synchronous reading, therefore the read -- address must be known one clock before rama: dpram64x26 port map( addra => std_logic_vector(addr2_in), addrb => reg_a_in, clka => clk, clkb => clk, dina => ram_in, doutb => ram_a_out, wea => valid_in); ramb: dpram64x26 port map( addra => std_logic_vector(addr2_in), addrb => reg_b_in, clka => clk, clkb => clk, dina => ram_in, doutb => ram_b_out, wea => valid_in); reg_a_in <= "111111" when rst_n='0' or pretrigger='1' else std_logic_vector(next_a); reg_b_in <= "111111" when rst_n='0' or pretrigger='1' else std_logic_vector(next_b); -- registers process (clk, rst_n) begin if rst_n = '0' then reg_last <= "111111"; reg_a <= "111111"; reg_b <= "111111"; elsif clk'event and clk = '1' then reg_a <= unsigned(reg_a_in); reg_b <= unsigned(reg_b_in); if pretrigger = '1' then reg_last <= "111111"; reg_a <= "111111"; reg_b <= "111111"; else if valid_in = '1' then reg_last <= addr2_in; end if; -- reg_a <= next_a; -- reg_b <= next_b; end if; end if; end process; b_is_end <= '1' when ram_b_out(idx_high downto idx_low) = "111" else '0'; -- adders a_plus_2 <= reg_a + 2; b_plus_2 <= reg_b + 2; -- incrementation logic process (reg_last, reg_a, reg_b, b_is_end, a_plus_2, b_plus_2) begin next_a_inc0 <= reg_a; next_b_inc0 <= reg_b; next_a_inc1 <= reg_a; next_b_inc1 <= reg_b; next_a_inc2 <= reg_a; next_b_inc2 <= reg_b; invalid_i <= '0'; if reg_last = unsigned(conv_signed(-1, addr_width)) then next_a_inc0 <= "111111"; next_b_inc0 <= "111111"; next_a_inc1 <= "111111"; next_b_inc1 <= "111111"; next_a_inc2 <= "111111"; next_b_inc2 <= "111111"; invalid_i <= '1'; elsif reg_last = conv_unsigned(0, addr_width) then next_a_inc0 <= "000000"; next_b_inc0 <= "000000"; next_a_inc1 <= "000000"; next_b_inc1 <= "000000"; next_a_inc2 <= "000000"; next_b_inc2 <= "000000"; elsif reg_last = conv_unsigned(1, addr_width) and reg_b = conv_unsigned(0, addr_width) then next_a_inc0 <= "000000"; next_b_inc0 <= "000001"; next_a_inc1 <= "000000"; next_b_inc1 <= "000001"; next_a_inc2 <= "000000"; next_b_inc2 <= "000001"; elsif b_is_end = '1' then next_a_inc1 <= reg_b; next_a_inc2 <= reg_b; elsif reg_b /= reg_last then next_b_inc1 <= a_plus_2; next_a_inc1 <= reg_b; if a_plus_2 = reg_last then next_b_inc2 <= a_plus_2; next_a_inc2 <= reg_b; else next_a_inc2 <= a_plus_2; next_b_inc2 <= b_plus_2; end if; end if; end process; -- inc->next_[ab] multiplexer process (inc, next_a_inc0, next_b_inc0, next_a_inc1, next_b_inc1, next_a_inc2, next_b_inc2) begin if inc(1) = '1' then next_a <= next_a_inc2; next_b <= next_b_inc2; elsif inc(0) = '1' then next_a <= next_a_inc1; next_b <= next_b_inc1; else next_a <= next_a_inc0; next_b <= next_b_inc0; end if; end process; invalid <= invalid_reg; process (clk) begin if clk'event and clk = '1' then invalid_reg <= invalid_i; end if; end process; -- multiplexers addr_out <= unsigned(ram_a_out(addr_high downto addr_low)) when ab_select = '0' else unsigned(ram_b_out(addr_high downto addr_low)); -- output signals idx_a <= unsigned(ram_a_out(idx_high downto idx_low)) when invalid_reg = '0' else "000"; idx_b <= unsigned(ram_b_out(idx_high downto idx_low)) when invalid_reg = '0' else "000"; y_a <= signed(ram_a_out(y_high downto y_low)); y_b <= signed(ram_b_out(y_high downto y_low)); a_a <= signed(ram_a_out(a_high downto a_low)); a_b <= signed(ram_b_out(a_high downto a_low)); ready <= b_is_end; end default;