]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
preliminary version of new data width adjustment for slow serdes clocks. Not best...
authorTobias Weber <toweber86@gmail.com>
Fri, 20 Jul 2018 13:56:24 +0000 (15:56 +0200)
committerTobias Weber <toweber86@gmail.com>
Fri, 20 Jul 2018 13:56:47 +0000 (15:56 +0200)
mupix/Mupix8/sources/DataWidthConversion.vhd [new file with mode: 0644]
mupix/Mupix8/sources/Datapath/DataMux.vhd
mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd
mupix/Mupix8/tb/MupixTRBReadoutTest.vhd

diff --git a/mupix/Mupix8/sources/DataWidthConversion.vhd b/mupix/Mupix8/sources/DataWidthConversion.vhd
new file mode 100644 (file)
index 0000000..26d4533
--- /dev/null
@@ -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;
index f4255e2791f9a3515828ba0b1306e7b2398c2930..7921ecf1bcff7b46e6031e1b57316d01545f6255 100644 (file)
@@ -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;
index d2421738ce4978cf73500d5601898cabfc47875f..ac8087a6c6ceaf9921c35dfd9a97cdabe97abfe3 100644 (file)
@@ -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(
index 2da3c20aac569b232f06f9284996c3ca79c5907a..04b77bc0d92ba360f265ff3439f605997fd85250 100644 (file)
@@ -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");