]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
better working version of data width converter in simulation. However, hades38 is...
authorTobias Weber <toweber86@gmail.com>
Mon, 23 Jul 2018 13:39:51 +0000 (15:39 +0200)
committerTobias Weber <toweber86@gmail.com>
Mon, 23 Jul 2018 13:39:51 +0000 (15:39 +0200)
mupix/Mupix8/sources/DataWidthConversion.vhd [deleted file]
mupix/Mupix8/sources/Datapath/DataWidthConversion.vhd [new file with mode: 0644]
mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd
mupix/Mupix8/sources/MupixClocks.vhd [new file with mode: 0644]
mupix/Mupix8/tb/DataWidthConversionTest.vhd [new file with mode: 0644]
mupix/Mupix8/tb/MupixTRBReadoutTest.vhd
mupix/Mupix8/trb3_periph.prj

diff --git a/mupix/Mupix8/sources/DataWidthConversion.vhd b/mupix/Mupix8/sources/DataWidthConversion.vhd
deleted file mode 100644 (file)
index 26d4533..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
--------------------------------------------------------------------------------------------
--- 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/DataWidthConversion.vhd b/mupix/Mupix8/sources/Datapath/DataWidthConversion.vhd
new file mode 100644 (file)
index 0000000..0591b46
--- /dev/null
@@ -0,0 +1,223 @@
+-------------------------------------------------------------------------------------------
+-- 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_wrcnt  : in  std_logic_vector(9 downto 0);  -- fifo write counter
+    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
+
+  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');
+
+  type shiftreg_array_t is array (0 to 1) of std_logic_vector(4 * g_datawidthfifo - 1 downto 0);
+  signal shiftregs : shiftreg_array_t := (others => (others => '0'));
+
+  type writing_fsm_t is (idle, writing);
+  signal writing_fsm   : writing_fsm_t                                 := idle;
+  signal read_index    : integer range 0 to 1                          := 1;
+  signal shiftreg_read : std_logic_vector(4 * g_datawidthfifo - 1 downto 0);
+  signal wordssend     : integer range 0 to 4                          := 0;
+  signal buff_wren_i   : std_logic                                     := '0';
+  signal dataout_i     : std_logic_vector(g_datawidthtrb - 1 downto 0) := (others => '0');
+
+  type fifo_read_fsm_t is (idle, waitfifo, reading);
+  signal fifo_read_fsm                        : fifo_read_fsm_t              := idle;
+  signal start_sending, start_sending_accpted : std_logic                    := '0';
+  type counter_array is array (0 to 1) of integer range 0 to 4;
+  signal wordstosend                          : counter_array                := (0, 0);
+  signal fifo_wrcnt_reg                       : std_logic_vector(9 downto 0) := (others => '1');
+  signal pause_cnt_i                          : integer range 0 to 7         := 0;
+  signal readenable_cnt_i                     : integer range 0 to 4         := 0;
+  signal fill_index                           : integer range 0 to 1         := 0;
+  signal fill_cnt                             : integer range 0 to 4         := 0;
+
+begin  -- architecture rtl
+
+
+  fifo_reading : process (clk) is
+  begin  -- process fifo_reading
+    if rising_edge(clk) then            -- rising clock edge
+      if reset = '1' then               -- synchronous reset (active high)
+        start_sending  <= '0';
+        pause_cnt_i    <= 0;
+        fill_index     <= 0;
+        shiftregs      <= (others => (others => '0'));
+        fifo_wrcnt_reg <= (others => '1');
+      else
+        if start_sending = '1' and start_sending_accpted = '1' then
+          start_sending <= '0';
+        end if;
+        fifo_rden <= '0';
+        case fifo_read_fsm is
+          when idle =>
+            pause_cnt_i      <= pause_cnt_i + 1;
+            readenable_cnt_i <= 0;
+            fill_cnt         <= 0;
+            if to_integer(unsigned(fifo_wrcnt)) >= 4 then
+              fifo_read_fsm           <= waitfifo;
+              fifo_rden               <= '1';
+              readenable_cnt_i        <= 1;
+              wordstosend(fill_index) <= 4;
+              pause_cnt_i             <= 0;
+            elsif pause_cnt_i = 6 then
+              pause_cnt_i    <= 0;
+              fifo_wrcnt_reg <= fifo_wrcnt;
+              if fifo_wrcnt = fifo_wrcnt_reg and fifo_empty = '0' then
+                fifo_read_fsm           <= waitfifo;
+                fifo_rden               <= '1';
+                readenable_cnt_i        <= 1;
+                wordstosend(fill_index) <= to_integer(unsigned(fifo_wrcnt));
+              end if;
+            else
+              fifo_read_fsm           <= idle;
+              wordstosend(fill_index) <= 0;
+            end if;
+          when waitfifo =>
+            fifo_wrcnt_reg <= (others => '1');
+            fifo_read_fsm  <= reading;
+            if readenable_cnt_i < wordstosend(fill_index) then
+              readenable_cnt_i <= 2;
+              fifo_rden        <= '1';
+            end if;
+          when reading =>
+            if readenable_cnt_i < wordstosend(fill_index) then
+              readenable_cnt_i <= readenable_cnt_i + 1;
+              fifo_rden        <= '1';
+            end if;
+            shiftregs(fill_index) <= shiftregs(fill_index)(3 * g_datawidthfifo - 1 downto 0) & fifo_datain;
+            if fill_cnt < 3 then
+              fill_cnt <= fill_cnt + 1;
+            else
+              start_sending <= '1';
+              fifo_read_fsm <= idle;
+              if fill_index < 1 then
+                fill_index <= fill_index + 1;
+              else
+                fill_index <= 0;
+              end if;
+            end if;
+        end case;
+      end if;
+    end if;
+  end process fifo_reading;
+
+  shiftreg_read_mux : process (read_index, shiftregs) is
+  begin  -- process shiftreg_read_mux
+    case read_index is
+      when 0 =>
+        shiftreg_read <= shiftregs(0);
+      when 1 =>
+        shiftreg_read <= shiftregs(1);
+      when others =>
+        shiftreg_read <= (others => '0');
+    end case;
+  end process shiftreg_read_mux;
+
+  writing_proc : process (clk) is
+  begin  -- process writing
+    if rising_edge(clk) then            -- rising clock edge
+      if reset = '1' then               -- synchronous reset (active high)
+        buff_wren_i           <= '0';
+        dataout_i             <= (others => '0');
+        read_index            <= 1;
+        start_sending_accpted <= '0';
+      else
+        buff_wren_i           <= '0';
+        dataout_i             <= (others => '0');
+        start_sending_accpted <= '0';
+        case writing_fsm is
+          when idle =>
+            if start_sending = '1' then
+              start_sending_accpted <= '1';
+              writing_fsm           <= writing;
+              wordssend             <= 0;
+              if read_index = 1 then
+                read_index <= 0;
+              else
+                read_index <= read_index + 1;
+              end if;
+            end if;
+          when writing =>
+            case wordssend is
+              when 0 =>
+                wordssend   <= 1;
+                buff_wren_i <= '1';
+                dataout_i   <= shiftreg_read(159 downto 128);
+
+              when 1 =>
+                wordssend   <= 2;
+                buff_wren_i <= '1';
+                if wordstosend(read_index) = 1 then
+                  dataout_i   <= shiftreg_read(127 downto 120) & padding_0;
+                  writing_fsm <= idle;
+                else
+                  dataout_i <= shiftreg_read(127 downto 96);
+                end if;
+
+              when 2 =>
+                wordssend   <= 3;
+                buff_wren_i <= '1';
+                if wordstosend(read_index) = 2 then
+                  dataout_i   <= shiftreg_read(95 downto 80) & padding_1;
+                  writing_fsm <= idle;
+                else
+                  dataout_i <= shiftreg_read(95 downto 64);
+                end if;
+
+              when 3 =>
+                wordssend   <= 4;
+                buff_wren_i <= '1';
+                if wordstosend(read_index) = 3 then
+                  dataout_i   <= shiftreg_read(63 downto 40) & padding_2;
+                  writing_fsm <= idle;
+                else
+                  dataout_i <= shiftreg_read(63 downto 32);
+                end if;
+
+              when 4 =>
+                wordssend   <= 1;
+                writing_fsm <= idle;
+                buff_wren_i <= '1';
+                dataout_i   <= shiftreg_read(31 downto 0);
+            end case;
+        end case;
+      end if;
+    end if;
+  end process writing_proc;
+
+  output_pipe : process (clk) is
+  begin  -- process output_mux
+    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_pipe;
+
+end architecture rtl;
index ac8087a6c6ceaf9921c35dfd9a97cdabe97abfe3..b3df9485d48563e5d92dd5c3b809dfe705d8c454 100644 (file)
@@ -8,12 +8,12 @@ use ieee.std_logic_1164.all;
 use ieee.numeric_std.all;
 
 entity MupixTRBReadout is
-  generic(g_mupix_links           : natural := 4;   -- number of input data channels from mupix
+  generic(g_mupix_links           : natural := 4;  -- number of input data channels from mupix
           -- memory depth of circularbuffer (should match value of RAM in Circ Buffer)
-          g_cyc_mem_address_width : integer := 12;  
+          g_cyc_mem_address_width : integer := 12;
           g_datawidthfifo         : integer := 40;  -- width of data words from fifos
           -- trb data width (should be 32 and match RAM in Circ Buffer)
-          g_datawidthtrb          : integer := 32   
+          g_datawidthtrb          : integer := 32
           );
   port(
     clk                  : in  std_logic;  -- clock input
@@ -95,10 +95,11 @@ architecture rtl of MupixTRBReadout is
       RdEn  : in  std_logic;
       Reset : in  std_logic;
       Q     : out std_logic_vector(39 downto 0);
+      WCNT  : out std_logic_vector(9 downto 0);
       Empty : out std_logic;
       Full  : out std_logic);
   end component FIFO_40_512;
-  
+
   component DataWidthConversion is
     generic (
       g_datawidthfifo : integer := 40;
@@ -107,7 +108,7 @@ architecture rtl of MupixTRBReadout is
       clk         : in  std_logic;
       reset       : in  std_logic;
       fifo_empty  : in  std_logic;
-      fifo_full   : in  std_logic;
+      fifo_wrcnt  : in  std_logic_vector(9 downto 0);
       fifo_datain : in  std_logic_vector(g_datawidthfifo - 1 downto 0);
       fifo_rden   : out std_logic;
       buff_wren   : out std_logic;
@@ -157,11 +158,12 @@ 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_empty_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 fifo_data_width_cnt_i : std_logic_vector(9 downto 0);
+
   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);
@@ -172,17 +174,17 @@ architecture rtl of MupixTRBReadout is
   signal readout_controller_data_valid : std_logic;
 
   type slow_readout_fsm_type is (idle, waitstate);
-  signal slow_readout_fsm : slow_readout_fsm_type                      := idle;
+  signal slow_readout_fsm : slow_readout_fsm_type                         := idle;
   signal slow_data        : std_logic_vector(g_datawidthtrb - 1 downto 0) := (others => '0');
-  signal start_slow_read  : std_logic                                  := '0';
-  signal slow_read_busy   : std_logic                                  := '0';
-  signal slow_read_done   : std_logic                                  := '0';
+  signal start_slow_read  : std_logic                                     := '0';
+  signal slow_read_busy   : std_logic                                     := '0';
+  signal slow_read_done   : std_logic                                     := '0';
 
 begin
 
   start_readout <= start_readout_slow_to_buffer or trb_trigger;
 
-  FiFoDataMux_1: entity work.FiFoDataMux
+  FiFoDataMux_1 : entity work.FiFoDataMux
     generic map (
       g_datawidth  => g_datawidthfifo,
       g_inputs     => g_mupix_links,
@@ -199,19 +201,20 @@ begin
       dataout     => fifo_data_width_datain_i,
       wordin_freq => wordin_freq,
       fifo_full_o => fifo_full_o);
-  
-  FIFO_40_512_1: entity work.FIFO_40_512
+
+  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,
+      WCNT  => fifo_data_width_cnt_i,
       Q     => fifo_data_width_dataout_i,
       Empty => fifo_data_width_empty_i,
-      Full  => fifo_data_width_full_i);
+      Full  => open);
 
-  DataWidthConversion_1: entity work.DataWidthConversion
+  DataWidthConversion_1 : entity work.DataWidthConversion
     generic map (
       g_datawidthfifo => g_datawidthfifo,
       g_datawidthtrb  => g_datawidthtrb)
@@ -219,7 +222,7 @@ begin
       clk         => clk,
       reset       => rst,
       fifo_empty  => fifo_data_width_empty_i,
-      fifo_full   => fifo_data_width_full_i,
+      fifo_wrcnt  => fifo_data_width_cnt_i,
       fifo_datain => fifo_data_width_dataout_i,
       fifo_rden   => fifo_data_width_rd_i,
       buff_wren   => fifo_mux_wren,
diff --git a/mupix/Mupix8/sources/MupixClocks.vhd b/mupix/Mupix8/sources/MupixClocks.vhd
new file mode 100644 (file)
index 0000000..d5edeee
--- /dev/null
@@ -0,0 +1,56 @@
+--------------------------------------
+-- Generation of Mupix Data Clocks
+-- T. Weber, Ruhr Universitaet Bochum
+--------------------------------------
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library ecp3;
+use ecp3.components.all;
+
+
+entity MupixClocks is  
+  port (
+    input_clock : in  std_logic;        -- input clock to pll (200 Mhz)
+    clkext      : out std_logic;        -- external mupix clock
+    clkref      : out std_logic);       -- mupix reference clock
+end entity MupixClocks;
+
+architecture rtl of MupixClocks is
+
+  component pll_mupix_main
+    port (CLK   : in  std_logic;
+          CLKOP : out std_logic;
+          LOCK  : out std_logic);
+  end component;
+
+  signal mupix_clk_i : std_logic;
+  
+  attribute ODDRAPPS                 : string;
+  attribute ODDRAPPS of mupix_oddr_1 : label is "SCLK_ALIGNED";
+  attribute ODDRAPPS of mupix_oddr_2 : label is "SCLK_ALIGNED";
+  
+begin  -- architecture rtl
+
+   mupix_main_pll_1 : pll_mupix_main
+     port map (
+       CLK   => input_clock,
+       CLKOP => mupix_clk_i,
+       LOCK  => open);
+
+   mupix_oddr_1 : ODDRXD1
+     port map(
+       SCLK => mupix_clk_i,
+       DA   => '1',
+       DB   => '0',
+       Q    => clkext);
+
+   mupix_oddr_2 : ODDRXD1
+     port map(
+       SCLK => mupix_clk_i,
+       DA   => '1',
+       DB   => '0',
+       Q    => clkref);
+
+end architecture rtl;
diff --git a/mupix/Mupix8/tb/DataWidthConversionTest.vhd b/mupix/Mupix8/tb/DataWidthConversionTest.vhd
new file mode 100644 (file)
index 0000000..debb75a
--- /dev/null
@@ -0,0 +1,145 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity DataWidthConversionTest is
+end entity DataWidthConversionTest;
+
+architecture sim of DataWidthConversionTest is
+
+  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 serdes_fifo;
+
+  component DataWidthConversion is
+    generic (
+      g_datawidthfifo : integer;
+      g_datawidthtrb  : integer);
+    port (
+      clk         : in  std_logic;
+      reset       : in  std_logic;
+      fifo_empty  : in  std_logic;
+      fifo_wrcnt  : in  std_logic_vector(9 downto 0);
+      fifo_datain : in  std_logic_vector(39 downto 0);
+      fifo_rden   : out std_logic;
+      buff_wren   : out std_logic;
+      dataout     : out std_logic_vector(31 downto 0));
+  end component DataWidthConversion;
+
+  constant wrclock_period : time := 25 ns;
+  constant rdclock_period : time := 10 ns;
+
+  signal Data      : std_logic_vector(39 downto 0) := (others => '0');
+  signal WrClock   : std_logic                     := '0';
+  signal RdClock   : std_logic                     := '0';
+  signal WrEn      : std_logic                     := '0';
+  signal RdEn      : std_logic;
+  signal reset     : std_logic                     := '0';
+  signal Q         : std_logic_vector(39 downto 0);
+  signal Empty     : std_logic;
+  signal Full      : std_logic;
+  signal buff_wren : std_logic;
+  signal dataout   : std_logic_vector(31 downto 0);
+  signal rcnt      : std_logic_vector(10 downto 0);
+
+  signal send_buffer    : std_logic_vector(48*40 - 1 downto 0) := (others => '0');
+  signal receive_buffer : std_logic_vector(60*32 - 1 downto 0) := (others => '0');
+
+begin  -- architecture sim
+
+  serdes_fifo_1 : entity work.serdes_fifo
+    port map (
+      Data    => Data,
+      WrClock => WrClock,
+      RdClock => RdClock,
+      WrEn    => WrEn,
+      RdEn    => RdEn,
+      Reset   => reset,
+      RPReset => reset,
+      Q       => Q,
+      RCNT    => rcnt,
+      Empty   => Empty,
+      Full    => open);
+
+  DataWidthConversion_1 : entity work.DataWidthConversion
+    generic map (
+      g_datawidthfifo => 40,
+      g_datawidthtrb  => 32)
+    port map (
+      clk         => RdClock,
+      reset       => reset,
+      fifo_empty  => Empty,
+      fifo_wrcnt  => rcnt(9 downto 0),
+      fifo_datain => Q,
+      fifo_rden   => RdEn,
+      buff_wren   => buff_wren,
+      dataout     => dataout);
+
+  wrclock_gen : process is
+  begin  -- process wrclock_gen
+    WrClock <= '1';
+    wait for wrclock_period/2;
+    WrClock <= '0';
+    wait for wrclock_period/2;
+  end process wrclock_gen;
+
+  rdclock_gen : process is
+  begin  -- process rdclock_gen
+    RdClock <= '1';
+    wait for rdclock_period/2;
+    RdClock <= '0';
+    wait for rdclock_period/2;
+  end process rdclock_gen;
+
+  send : process (WrClock) is
+    variable cnt : integer range 0 to 47 := 47;
+  begin  -- process send
+    if rising_edge(WrClock) then        -- rising clock edge
+      if WrEn = '1' then
+        send_buffer((cnt + 1)*40 - 1 downto cnt*40) <= data;
+        cnt                                         := cnt - 1;
+      end if;
+    end if;
+  end process send;
+
+  receive : process (RdClock) is
+    variable cnt : integer range 0 to 59 := 59;
+  begin  -- process receive
+    if rising_edge(RdClock) then        -- rising clock edge
+      if buff_wren = '1' then
+        receive_buffer((cnt + 1)*32 - 1 downto cnt*32) <= dataout;
+        cnt                                            := cnt - 1;
+      end if;
+    end if;
+  end process receive;
+
+  fifo_fill : process is
+  begin  -- process fifo_fill
+    reset <= '1';
+    wait for 100 ns;
+    reset <= '0';
+    for i in 1 to 45 loop
+      WrEn <= '1';
+      data <= x"c01c" & std_logic_vector(to_unsigned(i, 8)) & x"BEEB";
+      wait for wrclock_period;
+    end loop;  -- i
+    WrEn <= '0';
+    data <= (others => '0');
+    wait for 1 us;
+    assert send_buffer = receive_buffer report "sending and receive buffer do not match" severity error;
+    assert send_buffer /= receive_buffer report "sending and receive buffer do  match" severity note;
+    wait;
+  end process fifo_fill;
+
+end architecture sim;
index 04b77bc0d92ba360f265ff3439f605997fd85250..199892b03b866676ec60ff1cce689a3186343914 100644 (file)
@@ -161,7 +161,7 @@ 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 20 loop
+    for i in 1 to 22 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";
index 75402e27cb1f76c8a65a73e2cc25a3b2f510fbde..24a919623060b97bcfb08c327cfc98ad9a60f88c 100644 (file)
@@ -182,7 +182,8 @@ add_file -vhdl -lib "work" "sources/Datapath/MupixTRBReadout.vhd"
 add_file -vhdl -lib "work" "sources/Datapath/MuPixDataLink_new.vhd"
 add_file -vhdl -lib "work" "sources/Datapath/TriggerHandler.vhd"
 add_file -vhdl -lib "work" "sources/Datapath/Arbiter.vhd"
-add_file -vhdl -lib "work" "sources/Datapath/DataMuxWithConversion.vhd"
+add_file -vhdl -lib "work" "sources/Datapath/DataMux.vhd"
+add_file -vhdl -lib "work" "sources/DataWidthConversion.vhd"
 add_file -vhdl -lib "work" "sources/Datapath/MuPixUnpacker.vhd"
 add_file -vhdl -lib "work" "sources/Datapath/LinkSynchronizer.vhd"