]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
data multiplexer with conversion from 40 to 32 bit
authorTobias Weber <toweber86@gmail.com>
Fri, 22 Jun 2018 09:12:55 +0000 (11:12 +0200)
committerTobias Weber <toweber86@gmail.com>
Fri, 22 Jun 2018 09:12:55 +0000 (11:12 +0200)
mupix/Mupix8/sources/DataMuxWithConversion.vhd [new file with mode: 0644]

diff --git a/mupix/Mupix8/sources/DataMuxWithConversion.vhd b/mupix/Mupix8/sources/DataMuxWithConversion.vhd
new file mode 100644 (file)
index 0000000..93cfe04
--- /dev/null
@@ -0,0 +1,221 @@
+--------------------------------------------------------------------------------
+-- FIFO Data Multiplexer for n input channels to 1 output channels
+-- This module also 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
+-- TODO: make width conversion more flexible
+-- T. Weber, Ruhr University Bochum
+-------------------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.StdTypes.all;
+use work.Constants.all;
+
+entity FiFoDataMux is
+  generic(
+    g_datawidthfifo : integer := 40;    -- data width of input fifos
+    g_datawidthtrb  : integer := 32;    -- data width of trb data bus
+    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_datawidthfifo - 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_datawidthtrb - 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;
+
+  --data width converter signals
+  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 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 conversioncounter : integer range 0 to 6          := 0;
+  signal empty_delay       : std_logic_vector(1 downto 0)  := (others => '0');
+
+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;
+        fifo_rden    <= (others => '0');
+        dataout      <= (others => '0');
+        buff_wren    <= '0';
+        mux_fsm      <= idle;
+      else
+        empty_delay <= empty_delay(0) & fifo_empty(fifo_sel_reg);
+        case mux_fsm is
+          when idle =>
+            fifo_rden         <= (others => '0');
+            conversioncounter <= 0;
+            fifo_sel_reg      <= 0;
+            mux_fsm           <= idle;
+            dataout           <= (others => '0');
+            buff_wren         <= '0';
+            if fifo_sel_i /= -1 then
+              fifo_sel_reg          <= fifo_sel_i;
+              mux_fsm               <= wait_fifo;
+              fifo_rden(fifo_sel_i) <= '1';
+            end if;
+          when wait_fifo =>
+            fifo_rden(fifo_sel_reg) <= '1';
+            mux_fsm                 <= write;
+          when write =>
+            mux_fsm                        <= write;
+            fifo_rden(fifo_sel_reg)        <= '1';
+            increase_counter(fifo_sel_reg) <= '1';
+            -- width conversion
+            conversioncounter              <= conversioncounter + 1;
+            data_shift(1)                  <= data_shift(0);
+            data_shift(0)                  <= fifo_datain((fifo_sel_reg + 1)*g_datawidthfifo - 1 downto g_datawidthfifo*fifo_sel_reg);
+            if empty_delay = "11" then
+              mux_fsm <= idle;
+            end if;
+            case conversioncounter is   -- also controls fifo readout
+              when 0 =>
+                buff_wren <= '0';
+                dataout   <= (others => '0');
+              when 1 =>
+                buff_wren <= '1';
+                dataout   <= data_shift(0)(c_mupixhitsize - 1 downto 8);
+              when 2 =>
+                buff_wren <= '1';
+                if empty_delay = "11" then
+                  dataout <= data_shift(1)(7 downto 0) & padding_0;
+                else
+                  dataout <= data_shift(1)(7 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 16);
+                end if;
+                fifo_rden(fifo_sel_reg) <= '0';
+              when 3 =>
+                buff_wren <= '1';
+                if empty_delay = "11" then
+                  dataout <= data_shift(1)(15 downto 0) & padding_1;
+                else
+                  dataout <= data_shift(1)(15 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 24);
+                end if;
+                fifo_rden(fifo_sel_reg) <= '0';
+              when 4 =>
+                buff_wren <= '1';
+                if empty_delay = "11" then
+                  dataout <= data_shift(1)(23 downto 0) & padding_2;
+                else
+                  dataout <= data_shift(1)(23 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 32);
+                end if;
+                fifo_rden(fifo_sel_reg) <= '0';
+              when 5 =>
+                buff_wren               <= '1';
+                dataout                 <= data_shift(1)(31 downto 0);
+                fifo_rden(fifo_sel_reg) <= '0';
+              when 6 =>
+                fifo_rden(fifo_sel_reg) <= '1';
+                conversioncounter       <= 0;
+                buff_wren               <= '0';
+                dataout                 <= (others => '0');
+                mux_fsm                 <= wait_fifo;
+            end case;
+        end case;
+      end if;
+    end if;
+  end process mux_proc;
+
+
+  fifo_full_o <= fifo_full_i;
+
+end architecture RTL;