From: Tobias Weber Date: Fri, 20 Jul 2018 13:56:24 +0000 (+0200) Subject: preliminary version of new data width adjustment for slow serdes clocks. Not best... X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=e26b00a35c15390d7bb97e729d5b269cbb3af25c;p=trb3.git preliminary version of new data width adjustment for slow serdes clocks. Not best solution since it only works well for limited number of hits from mupix sensor. --- diff --git a/mupix/Mupix8/sources/DataWidthConversion.vhd b/mupix/Mupix8/sources/DataWidthConversion.vhd new file mode 100644 index 0000000..26d4533 --- /dev/null +++ b/mupix/Mupix8/sources/DataWidthConversion.vhd @@ -0,0 +1,151 @@ +------------------------------------------------------------------------------------------- +-- converts the 40 bit input data of the mupix into +-- 32 bit portions + padding of the last word for readout with the TRB +-- TODO: after adding the hit time sorter the data width conversion should be moved there +-- T. Weber +------------------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.Constants.all; + +entity DataWidthConversion is + generic ( + g_datawidthfifo : integer := 40; -- data width of input fifo + g_datawidthtrb : integer := 32); -- data width of trb data bus + port ( + clk : in std_logic; -- clock input + reset : in std_logic; -- reset input + fifo_empty : in std_logic; -- fifo empty signal + fifo_full : in std_logic; -- fifo full signal (unused) + fifo_datain : in std_logic_vector(g_datawidthfifo - 1 downto 0); -- input data + fifo_rden : out std_logic; -- fifo read enable + buff_wren : out std_logic; -- buffer write enable + dataout : out std_logic_vector(g_datawidthtrb - 1 downto 0)); -- data output +end entity DataWidthConversion; + +architecture rtl of DataWidthConversion is + + type converter_fsm_type is (idle, wait_fifo, convert); + signal converter_fsm_state : converter_fsm_type := idle; + + type convert_mem_type is array (0 to 1) of std_logic_vector(c_mupixhitsize - 1 downto 0); + signal data_shift : convert_mem_type := (others => (others => '0')); + + signal conversion_cnt_i : integer range 0 to 6 := 0; + signal empty_delay : std_logic_vector(1 downto 0) := (others => '0'); + signal empty_start : std_logic_vector(9 downto 0) := (others => '0'); + constant padding_0 : std_logic_vector(23 downto 0) := (others => '0'); + constant padding_1 : std_logic_vector(15 downto 0) := (others => '0'); + constant padding_2 : std_logic_vector(7 downto 0) := (others => '0'); + + signal buff_wren_i : std_logic := '0'; + signal dataout_i : std_logic_vector(g_datawidthtrb - 1 downto 0) := (others => '0'); + +begin -- architecture rtl + + conversion : process (clk) is + begin -- process conversion + if rising_edge(clk) then -- rising clock edge + if reset = '1' then -- synchronous reset (active high) + data_shift <= (others => (others => '0')); + buff_wren_i <= '0'; + dataout_i <= (others => '0'); + converter_fsm_state <= idle; + fifo_rden <= '0'; + empty_delay <= (others => '0'); + else + dataout_i <= (others => '0'); + buff_wren_i <= '0'; + empty_delay <= empty_delay(0) & fifo_empty; + empty_start <= empty_start(8 downto 0) & fifo_empty; + fifo_rden <= '0'; + case converter_fsm_state is + when idle => + data_shift <= (others => (others => '0')); + conversion_cnt_i <= 0; + -- this avoids unnecessary padding in case of serdes fifos are + -- writen by clock slower than TRB clock + if empty_start = "0000000000" then + fifo_rden <= '1'; + converter_fsm_state <= wait_fifo; + end if; + when wait_fifo => + fifo_rden <= '1'; + converter_fsm_state <= convert; + when convert => + fifo_rden <= '1'; + data_shift(1) <= data_shift(0); + data_shift(0) <= fifo_datain; + case conversion_cnt_i is -- also controls fifo readout + when 0 => + conversion_cnt_i <= conversion_cnt_i + 1; + buff_wren_i <= '0'; + dataout_i <= (others => '0'); + when 1 => + conversion_cnt_i <= conversion_cnt_i + 1; + buff_wren_i <= '1'; + dataout_i <= data_shift(0)(c_mupixhitsize - 1 downto 8); + when 2 => + conversion_cnt_i <= conversion_cnt_i + 1; + buff_wren_i <= '1'; + if empty_delay = "11" then + dataout_i <= data_shift(1)(7 downto 0) & padding_0; + else + dataout_i <= data_shift(1)(7 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 16); + end if; + fifo_rden <= '0'; + when 3 => + conversion_cnt_i <= conversion_cnt_i + 1; + buff_wren_i <= '1'; + if empty_delay = "11" then + dataout_i <= data_shift(1)(15 downto 0) & padding_1; + else + dataout_i <= data_shift(1)(15 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 24); + end if; + fifo_rden <= '0'; + when 4 => + conversion_cnt_i <= conversion_cnt_i + 1; + buff_wren_i <= '1'; + if empty_delay = "11" then + dataout_i <= data_shift(1)(23 downto 0) & padding_2; + else + dataout_i <= data_shift(1)(23 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 32); + end if; + fifo_rden <= '0'; + when 5 => + conversion_cnt_i <= conversion_cnt_i + 1; + buff_wren_i <= '1'; + dataout_i <= data_shift(1)(31 downto 0); + fifo_rden <= '0'; + when 6 => + fifo_rden <= '1'; + conversion_cnt_i <= 0; + buff_wren_i <= '0'; + dataout_i <= (others => '0'); + converter_fsm_state <= wait_fifo; + end case; + if empty_delay = "11" then + converter_fsm_state <= idle; + end if; + end case; + end if; + end if; + end process conversion; + + -- purpose: register outputs + output : process (clk) is + begin -- process output + if rising_edge(clk) then -- rising clock edge + if reset = '1' then -- synchronous reset (active high) + buff_wren <= '0'; + dataout <= (others => '0'); + else + buff_wren <= buff_wren_i; + dataout <= dataout_i; + end if; + end if; + end process output; + +end architecture rtl; diff --git a/mupix/Mupix8/sources/Datapath/DataMux.vhd b/mupix/Mupix8/sources/Datapath/DataMux.vhd index f4255e2..7921ecf 100644 --- a/mupix/Mupix8/sources/Datapath/DataMux.vhd +++ b/mupix/Mupix8/sources/Datapath/DataMux.vhd @@ -9,157 +9,182 @@ use ieee.numeric_std.all; use work.StdTypes.all; entity FiFoDataMux is - generic( - g_datawidth : integer := 32; -- data width - g_inputs : integer := 4; -- number of inputs to multiplexer - g_clockspeed : integer := 1e8 -- fpga clock speed - ); - port( - clk : in std_logic; -- clock input - rst : in std_logic; -- reset input - fifo_empty : in std_logic_vector(g_inputs - 1 downto 0); -- input FIFO empty flags - fifo_full : in std_logic_vector(g_inputs - 1 downto 0); -- input FIFO full flags - fifo_datain : in std_logic_vector(g_inputs*g_datawidth - 1 downto 0); -- input data from FIFOs - fifo_mask : in std_logic_vector(g_inputs - 1 downto 0); -- enable mask for FIFO inputs - fifo_rden : out std_logic_vector(g_inputs - 1 downto 0); -- read enable to FIFOs - buff_wren : out std_logic; -- write enable to output buffer - dataout : out std_logic_vector(g_datawidth - 1 downto 0); -- data output - wordin_freq : out std_logic_vector(32*g_inputs - 1 downto 0); -- number of input words from FIFOs - fifo_full_o : out std_logic -- or over input fifo full flags - ); + generic( + g_datawidth : integer := 32; -- data width + g_inputs : integer := 4; -- number of inputs to multiplexer + g_clockspeed : integer := 1e8 -- fpga clock speed + ); + port( + clk : in std_logic; -- clock input + rst : in std_logic; -- reset input + fifo_empty : in std_logic_vector(g_inputs - 1 downto 0); -- input FIFO empty flags + fifo_full : in std_logic_vector(g_inputs - 1 downto 0); -- input FIFO full flags + fifo_datain : in std_logic_vector(g_inputs*g_datawidth - 1 downto 0); -- input data from FIFOs + fifo_mask : in std_logic_vector(g_inputs - 1 downto 0); -- enable mask for FIFO inputs + fifo_rden : out std_logic_vector(g_inputs - 1 downto 0); -- read enable to FIFOs + buff_wren : out std_logic; -- write enable to output buffer + dataout : out std_logic_vector(g_datawidth - 1 downto 0); -- data output + wordin_freq : out std_logic_vector(32*g_inputs - 1 downto 0); -- number of input words from FIFOs + fifo_full_o : out std_logic -- or over input fifo full flags + ); end entity FiFoDataMux; architecture RTL of FiFoDataMux is - - signal ticks_counter : unsigned(f_log2(g_clockspeed) - 1 downto 0) := (others => '0'); - signal inword_counter : t_counter_array(0 to g_inputs - 1) := (others => (others => '0')); - signal increase_counter : std_logic_vector(g_inputs - 1 downto 0) := (others => '0'); - - signal fifo_full_i : std_logic; - - signal fifo_sel_i : integer range -1 to g_inputs - 1 := -1; - signal fifo_sel_reg : integer range 0 to g_inputs - 1 := 0; - - signal request_i : std_logic_vector(g_inputs - 1 downto 0); - signal grant_i : std_logic_vector(g_inputs - 1 downto 0); - - type t_mux_state is (idle, wait_fifo, write); - signal mux_fsm : t_mux_state := idle; - - component RoundRobinArbiter - generic(g_num_channels : integer := 4); - port( - clk : in std_logic; - requests : in std_logic_vector(g_num_channels - 1 downto 0); - grant : out std_logic_vector(g_num_channels - 1 downto 0) - ); - end component RoundRobinArbiter; - + + signal ticks_counter : unsigned(f_log2(g_clockspeed) - 1 downto 0) := (others => '0'); + signal inword_counter : t_counter32_array(0 to g_inputs - 1) := (others => (others => '0')); + signal increase_counter : std_logic_vector(g_inputs - 1 downto 0) := (others => '0'); + + signal fifo_full_i : std_logic; + + signal fifo_sel_i : integer range -1 to g_inputs - 1 := -1; + signal fifo_sel_reg : integer range 0 to g_inputs - 1 := 0; + + signal request_i : std_logic_vector(g_inputs - 1 downto 0); + signal grant_i : std_logic_vector(g_inputs - 1 downto 0); + + type t_mux_state is (idle, wait_fifo, writedata, pause); + signal mux_fsm : t_mux_state := idle; + signal pause_cnt_i : integer range 0 to 7 := 0; + + signal buff_wren_i : std_logic := '0'; + signal dataout_i : std_logic_vector(g_datawidth - 1 downto 0) := (others => '0'); + + component RoundRobinArbiter + generic(g_num_channels : integer := 4); + port( + clk : in std_logic; + requests : in std_logic_vector(g_num_channels - 1 downto 0); + grant : out std_logic_vector(g_num_channels - 1 downto 0) + ); + end component RoundRobinArbiter; + begin - - request_i <= not fifo_empty and fifo_mask; - - arbiter_1 : component RoundRobinArbiter - generic map( - g_num_channels => g_inputs - ) - port map( - clk => clk, - requests => request_i, - grant => grant_i - ); - - fifo_select_proc : process(grant_i) is - variable sel : integer range -1 to g_inputs - 1; - begin - sel := -1; - for i in 0 to g_inputs - 1 loop - if grant_i(i) = '1' then - sel := i; - end if; - end loop; - fifo_sel_i <= sel; - end process fifo_select_proc; - - full_flag_proc : process(fifo_full) is - variable full : std_logic := '0'; - begin - full := '0'; - for i in 0 to fifo_full'length - 1 loop - full := full or fifo_full(i); - end loop; - fifo_full_i <= full; - end process full_flag_proc; - - input_freq : process (clk) is - begin - if rising_edge(clk) then - if rst = '1' then - ticks_counter <= (others => '0'); - inword_counter <= (others => (others => '0')); - else - if increase_counter(fifo_sel_reg) = '1' then - inword_counter(fifo_sel_reg) <= inword_counter(fifo_sel_reg) + 1; - else - inword_counter(fifo_sel_reg) <= inword_counter(fifo_sel_reg); - end if; - if ticks_counter = g_clockspeed - 1 then - inword_counter <= (others => (others => '0')); - ticks_counter <= (others => '0'); - wordin_freq <= counter_array_to_stdvec(inword_counter); - else - ticks_counter <= ticks_counter + 1; - end if; - end if; - end if; - end process input_freq; - - - mux_proc : process(clk) is - begin - if rising_edge(clk) then - if rst = '1' then - fifo_sel_reg <= 0; - buff_wren <= '0'; - dataout <= (others => '0'); - fifo_rden <= (others => '0'); - else - case mux_fsm is - when idle => - fifo_rden <= (others => '0'); - buff_wren <= '0'; - dataout <= (others => '0'); - if fifo_sel_i /= -1 then - fifo_sel_reg <= fifo_sel_i; - fifo_rden(fifo_sel_i) <= '1'; - mux_fsm <= wait_fifo; - else - fifo_sel_reg <= 0; - mux_fsm <= idle; - end if; - when wait_fifo => - fifo_rden(fifo_sel_i) <= '1'; - mux_fsm <= write; - when write => - dataout <= fifo_datain((fifo_sel_reg + 1)*g_datawidth - 1 downto g_datawidth*fifo_sel_reg); - if fifo_empty(fifo_sel_reg) = '0' then - mux_fsm <= write; - fifo_rden(fifo_sel_reg) <= '1'; - buff_wren <= '1'; - increase_counter(fifo_sel_reg) <= '1'; - else - mux_fsm <= idle; - fifo_rden(fifo_sel_reg) <= '0'; - buff_wren <= '1'; - increase_counter <= (others => '0'); - end if; - end case; - end if; - end if; - end process mux_proc; - - - fifo_full_o <= fifo_full_i; - + + request_i <= not fifo_empty and fifo_mask; + + arbiter_1 : component RoundRobinArbiter + generic map( + g_num_channels => g_inputs + ) + port map( + clk => clk, + requests => request_i, + grant => grant_i + ); + + fifo_select_proc : process(grant_i) is + variable sel : integer range -1 to g_inputs - 1; + begin + sel := -1; + for i in 0 to g_inputs - 1 loop + if grant_i(i) = '1' then + sel := i; + end if; + end loop; + fifo_sel_i <= sel; + end process fifo_select_proc; + + full_flag_proc : process(fifo_full) is + variable full : std_logic := '0'; + begin + full := '0'; + for i in 0 to fifo_full'length - 1 loop + full := full or fifo_full(i); + end loop; + fifo_full_i <= full; + end process full_flag_proc; + + input_freq : process (clk) is + begin + if rising_edge(clk) then + if rst = '1' then + ticks_counter <= (others => '0'); + inword_counter <= (others => (others => '0')); + else + if increase_counter(fifo_sel_reg) = '1' then + inword_counter(fifo_sel_reg) <= inword_counter(fifo_sel_reg) + 1; + else + inword_counter(fifo_sel_reg) <= inword_counter(fifo_sel_reg); + end if; + if ticks_counter = g_clockspeed - 1 then + inword_counter <= (others => (others => '0')); + ticks_counter <= (others => '0'); + wordin_freq <= counter_array_to_stdvec(inword_counter); + else + ticks_counter <= ticks_counter + 1; + end if; + end if; + end if; + end process input_freq; + + + mux_proc : process(clk) is + begin + if rising_edge(clk) then + if rst = '1' then + fifo_sel_reg <= 0; + buff_wren_i <= '0'; + dataout_i <= (others => '0'); + fifo_rden <= (others => '0'); + else + buff_wren_i <= '0'; + dataout_i <= (others => '0'); + fifo_rden <= (others => '0'); + case mux_fsm is + when idle => + if fifo_sel_i /= -1 then + fifo_sel_reg <= fifo_sel_i; + fifo_rden(fifo_sel_i) <= '1'; + mux_fsm <= wait_fifo; + else + fifo_sel_reg <= 0; + mux_fsm <= idle; + end if; + when wait_fifo => + fifo_rden(fifo_sel_reg) <= '1'; + mux_fsm <= writedata; + when writedata => + pause_cnt_i <= 0; + dataout_i <= fifo_datain((fifo_sel_reg + 1)*g_datawidth - 1 downto g_datawidth*fifo_sel_reg); + increase_counter(fifo_sel_reg) <= '1'; + fifo_rden(fifo_sel_reg) <= '1'; + buff_wren_i <= '1'; + if fifo_empty(fifo_sel_reg) = '0' then + mux_fsm <= writedata; + else + mux_fsm <= pause; + end if; + when pause => -- wait in case filling clock is slower than reading + -- clock + increase_counter <= (others => '0'); + pause_cnt_i <= pause_cnt_i + 1; + mux_fsm <= pause; + if pause_cnt_i = 6 then + mux_fsm <= idle; + elsif fifo_empty(fifo_sel_reg) = '0' then + fifo_rden(fifo_sel_reg) <= '1'; + mux_fsm <= wait_fifo; + end if; + end case; + end if; + end if; + end process mux_proc; + + output_pipe : process (clk) is + begin -- process output_pipe + if rising_edge(clk) then + if rst = '1' then + dataout <= (others => '0'); + buff_wren <= '0'; + else + dataout <= dataout_i; + buff_wren <= buff_wren_i; + end if; + end if; + end process output_pipe; + + fifo_full_o <= fifo_full_i; + end architecture RTL; diff --git a/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd b/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd index d242173..ac8087a 100644 --- a/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd +++ b/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd @@ -68,27 +68,51 @@ architecture rtl of MupixTRBReadout is ); end component CircularMemory; - component FiFoDataMuxWithConversion - generic( - g_datawidthfifo : integer := 40; - g_datawidthtrb : integer := 32; + component FiFoDataMux is + generic ( + g_datawidth : integer := 32; g_inputs : integer := 4; - g_clockspeed : integer := 1e8 - ); - port( + g_clockspeed : integer := 1e8); + port ( clk : in std_logic; rst : in std_logic; fifo_empty : in std_logic_vector(g_inputs - 1 downto 0); fifo_full : in std_logic_vector(g_inputs - 1 downto 0); - fifo_datain : in std_logic_vector(g_inputs*g_datawidthfifo - 1 downto 0); + fifo_datain : in std_logic_vector(g_inputs*g_datawidth - 1 downto 0); fifo_mask : in std_logic_vector(g_inputs - 1 downto 0); fifo_rden : out std_logic_vector(g_inputs - 1 downto 0); buff_wren : out std_logic; - dataout : out std_logic_vector(g_datawidthtrb - 1 downto 0); + dataout : out std_logic_vector(g_datawidth - 1 downto 0); wordin_freq : out std_logic_vector(32*g_inputs - 1 downto 0); - fifo_full_o : out std_logic - ); - end component FiFoDataMuxWithConversion; + fifo_full_o : out std_logic); + end component FiFoDataMux; + + component FIFO_40_512 is + port ( + Data : in std_logic_vector(39 downto 0); + Clock : in std_logic; + WrEn : in std_logic; + RdEn : in std_logic; + Reset : in std_logic; + Q : out std_logic_vector(39 downto 0); + Empty : out std_logic; + Full : out std_logic); + end component FIFO_40_512; + + component DataWidthConversion is + generic ( + g_datawidthfifo : integer := 40; + g_datawidthtrb : integer := 32); + port ( + clk : in std_logic; + reset : in std_logic; + fifo_empty : in std_logic; + fifo_full : in std_logic; + fifo_datain : in std_logic_vector(g_datawidthfifo - 1 downto 0); + fifo_rden : out std_logic; + buff_wren : out std_logic; + dataout : out std_logic_vector(g_datawidthtrb - 1 downto 0)); + end component DataWidthConversion; component ReadoutController generic( @@ -133,6 +157,11 @@ architecture rtl of MupixTRBReadout is signal fifo_mux_wren : std_logic; signal fifo_mux_data_out : std_logic_vector(g_datawidthtrb - 1 downto 0); + signal fifo_data_width_empty_i, fifo_data_width_full_i : std_logic; + signal fifo_data_width_dataout_i : std_logic_vector(g_datawidthfifo - 1 downto 0); + signal fifo_data_width_datain_i : std_logic_vector(g_datawidthfifo - 1 downto 0); + signal fifo_data_width_rd_i, fifo_data_width_wr_i : std_logic; + signal start_readout_slow_to_buffer : std_logic := '0'; signal start_readout : std_logic := '0'; signal readout_controller_data_in : std_logic_vector(g_datawidthtrb - 1 downto 0); @@ -153,14 +182,12 @@ begin start_readout <= start_readout_slow_to_buffer or trb_trigger; - data_mux_1 : entity work.FiFoDataMuxWithConversion - generic map( - g_datawidthfifo => g_datawidthfifo, - g_datawidthtrb => g_datawidthtrb, + FiFoDataMux_1: entity work.FiFoDataMux + generic map ( + g_datawidth => g_datawidthfifo, g_inputs => g_mupix_links, - g_clockspeed => 1e8 - ) - port map( + g_clockspeed => 1e8) + port map ( clk => clk, rst => rst, fifo_empty => fifo_empty, @@ -168,11 +195,35 @@ begin fifo_datain => fifo_datain, fifo_mask => multiplexer_mask, fifo_rden => fifo_rden, - buff_wren => fifo_mux_wren, - dataout => fifo_mux_data_out, + buff_wren => fifo_data_width_wr_i, + dataout => fifo_data_width_datain_i, wordin_freq => wordin_freq, - fifo_full_o => fifo_full_o - ); + fifo_full_o => fifo_full_o); + + FIFO_40_512_1: entity work.FIFO_40_512 + port map ( + Data => fifo_data_width_datain_i, + Clock => clk, + WrEn => fifo_data_width_wr_i, + RdEn => fifo_data_width_rd_i, + Reset => rst, + Q => fifo_data_width_dataout_i, + Empty => fifo_data_width_empty_i, + Full => fifo_data_width_full_i); + + DataWidthConversion_1: entity work.DataWidthConversion + generic map ( + g_datawidthfifo => g_datawidthfifo, + g_datawidthtrb => g_datawidthtrb) + port map ( + clk => clk, + reset => rst, + fifo_empty => fifo_data_width_empty_i, + fifo_full => fifo_data_width_full_i, + fifo_datain => fifo_data_width_dataout_i, + fifo_rden => fifo_data_width_rd_i, + buff_wren => fifo_mux_wren, + dataout => fifo_mux_data_out); cycl_buffer_1 : entity work.CircularMemory generic map( diff --git a/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd b/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd index 2da3c20..04b77bc 100644 --- a/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd +++ b/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd @@ -38,24 +38,23 @@ architecture sim of MupixTRBReadoutTest is ); end component MupixTRBReadout; - component STD_FIFO - generic( - DATA_WIDTH : positive := 8; - FIFO_DEPTH : positive := 256 - ); - port( - CLK : in std_logic; - RST : in std_logic; - WriteEn : in std_logic; - DataIn : in std_logic_vector(DATA_WIDTH - 1 downto 0); - ReadEn : in std_logic; - DataOut : out std_logic_vector(DATA_WIDTH - 1 downto 0); + component serdes_fifo is + port ( + Data : in std_logic_vector(39 downto 0); + WrClock : in std_logic; + RdClock : in std_logic; + WrEn : in std_logic; + RdEn : in std_logic; + Reset : in std_logic; + RPReset : in std_logic; + Q : out std_logic_vector(39 downto 0); + RCNT : out std_logic_vector(10 downto 0); Empty : out std_logic; - Full : out std_logic - ); - end component STD_FIFO; + Full : out std_logic); + end component serdes_fifo; constant c_clk_period : time := 10 ns; + constant c_wrclk_period : time := 25 ns; constant c_mupix_links : integer := 4; constant c_cyc_mem_address_width : integer := 12; constant c_datawidthfifo : integer := 40; @@ -64,26 +63,26 @@ architecture sim of MupixTRBReadoutTest is type channel_type is array (0 to 3) of std_logic_vector(15 downto 0); constant c_channel_id : channel_type := (x"C01C", x"C02C", x"C03C", x"C04C"); - signal clk : std_logic; - signal rst : std_logic := '0'; - signal fifo_empty : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '1'); - signal fifo_full : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '0'); + signal clk, wrclk : std_logic; + signal rst : std_logic := '0'; + signal fifo_empty : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '1'); + signal fifo_full : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '0'); signal fifo_data_to_mux : std_logic_vector(c_mupix_links*c_datawidthfifo - 1 downto 0) := (others => '0'); - signal fifo_rden : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '0'); - signal trb_trigger : std_logic := '0'; + signal fifo_rden : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '0'); + signal trb_trigger : std_logic := '0'; signal dataout : std_logic_vector(c_datawidthtrb - 1 downto 0); signal data_valid : std_logic; signal busy : std_logic; - signal SLV_READ_IN : std_logic := '0'; - signal SLV_WRITE_IN : std_logic := '0'; + signal SLV_READ_IN : std_logic := '0'; + signal SLV_WRITE_IN : std_logic := '0'; signal SLV_DATA_OUT : std_logic_vector(31 downto 0); - signal SLV_DATA_IN : std_logic_vector(31 downto 0) := (others => '0'); - signal SLV_ADDR_IN : std_logic_vector(15 downto 0) := (others => '0'); + signal SLV_DATA_IN : std_logic_vector(31 downto 0) := (others => '0'); + signal SLV_ADDR_IN : std_logic_vector(15 downto 0) := (others => '0'); signal SLV_ACK_OUT : std_logic; signal SLV_NO_MORE_DATA_OUT : std_logic; signal SLV_UNKNOWN_ADDR_OUT : std_logic; - signal fifo_write_en : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '0'); + signal fifo_write_en : std_logic_vector(c_mupix_links - 1 downto 0) := (others => '0'); signal fifo_datain : std_logic_vector(c_mupix_links*c_datawidthfifo - 1 downto 0) := (others => '0'); begin @@ -118,21 +117,19 @@ begin ); gen_input_fifo : for i in 0 to 3 generate - input_fifo : entity work.STD_FIFO - generic map( - DATA_WIDTH => c_datawidthfifo, - FIFO_DEPTH => 16 - ) - port map( - CLK => CLK, - RST => RST, - WriteEn => fifo_write_en(i), - DataIn => fifo_datain((i + 1)*c_datawidthfifo - 1 downto i*c_datawidthfifo), - ReadEn => fifo_rden(i), - DataOut => fifo_data_to_mux((i + 1)*c_datawidthfifo - 1 downto i*c_datawidthfifo), + serdes_fifo : entity work.serdes_fifo + port map ( + Data => fifo_datain((i + 1)*c_datawidthfifo - 1 downto i*c_datawidthfifo), + WrClock => wrclk, + RdClock => clk, + WrEn => fifo_write_en(i), + RdEn => fifo_rden(i), + Reset => rst, + RPReset => rst, + Q => fifo_data_to_mux((i + 1)*c_datawidthfifo - 1 downto i*c_datawidthfifo), + RCNT => open, Empty => fifo_empty(i), - Full => fifo_full(i) - ); + Full => fifo_full(i)); end generate gen_input_fifo; @@ -144,8 +141,19 @@ begin wait for c_clk_period/2; end process clock_gen; + wrclock_gen : process is + begin -- process wrclock_gen + wrclk <= '1'; + wait for c_wrclk_period/2; + wrclk <= '0'; + wait for c_wrclk_period/2; + end process wrclock_gen; + stimulus : process is begin + rst <= '1'; + wait for 100 ns; + rst <= '0'; wait for 100 ns; TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"0000000A", x"0101"); TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"0000000B", x"0102"); @@ -153,15 +161,15 @@ begin TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"0000000F", x"0105"); TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000000", x"0106"); wait for 5*c_clk_period; - for i in 1 to 10 loop - fifo_write_en <= (others => '1'); + for i in 1 to 20 loop + fifo_write_en <= (others => '1'); fifo_datain(4*c_datawidthfifo - 1 downto 3*c_datawidthfifo) <= c_channel_id(0) & std_logic_vector(to_unsigned(i, 8)) & x"BEEB"; fifo_datain(3*c_datawidthfifo - 1 downto 2*c_datawidthfifo) <= c_channel_id(1) & std_logic_vector(to_unsigned(i, 8)) & x"BEEB"; fifo_datain(2*c_datawidthfifo - 1 downto 1*c_datawidthfifo) <= c_channel_id(2) & std_logic_vector(to_unsigned(i, 8)) & x"BEEB"; fifo_datain(1*c_datawidthfifo - 1 downto 0*c_datawidthfifo) <= c_channel_id(3) & std_logic_vector(to_unsigned(i, 8)) & x"BEEB"; - wait for c_clk_period; + wait for c_wrclk_period; end loop; - fifo_write_en <= (others => '0'); + fifo_write_en <= (others => '0'); fifo_datain(4*c_datawidthfifo - 1 downto 3*c_datawidthfifo) <= (others => '0'); wait for 500 ns; TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000000", x"0100");