]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
simple multiplexer for data fifos.
authorTobias Weber <toweber86@gmail.com>
Mon, 27 Nov 2017 10:37:00 +0000 (11:37 +0100)
committerTobias Weber <toweber86@gmail.com>
Mon, 27 Nov 2017 10:37:00 +0000 (11:37 +0100)
mupix/Mupix8/sources/DataMux.vhd [new file with mode: 0644]
mupix/Mupix8/tb/DataMuxTest.vhd [new file with mode: 0644]

diff --git a/mupix/Mupix8/sources/DataMux.vhd b/mupix/Mupix8/sources/DataMux.vhd
new file mode 100644 (file)
index 0000000..f7fe6a1
--- /dev/null
@@ -0,0 +1,141 @@
+------------------------------------------------------------------
+--FIFO Data Multiplexer for n input channels to 1 output channels
+--T. Weber, Ruhr Universität Bochum
+------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+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
+       );
+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;
+       
+       type t_mux_state is (idle, wait_fifo, write);
+       signal mux_fsm : t_mux_state := idle;
+       
+begin
+       
+       fifo_select_proc : process(fifo_empty, fifo_mask) is
+               variable sel : integer range -1 to g_inputs - 1;
+       begin
+               sel        := -1;
+               for i in 0 to g_inputs - 1 loop
+                       if fifo_empty(i) = '0' and fifo_mask(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;
+       
+end architecture RTL;
diff --git a/mupix/Mupix8/tb/DataMuxTest.vhd b/mupix/Mupix8/tb/DataMuxTest.vhd
new file mode 100644 (file)
index 0000000..b0f5f3a
--- /dev/null
@@ -0,0 +1,158 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.StdTypes.all;
+
+entity DataMuxTest is
+end entity DataMuxTest;
+architecture sim of DataMuxTest is
+       
+       component FiFoDataMux
+               generic(
+                       g_datawidth  : integer := 32;
+                       g_inputs     : integer := 4;
+                       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_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_datawidth - 1 downto 0);
+                       wordin_freq : out std_logic_vector(32*g_inputs - 1 downto 0);
+                       fifo_full_o : out std_logic
+               );
+       end component FiFoDataMux;
+       
+       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);
+                       Empty   : out std_logic;
+                       Full    : out std_logic
+               );
+       end component STD_FIFO;
+       
+       constant c_datawidth : integer := 8;
+       constant c_inputs : integer := 2;
+       constant c_clockspeed : integer := 1e3;
+       constant c_fifo_depth : integer := 16;
+       
+       constant c_clk_period : time  := 10 ns;
+       
+       signal clk         : std_logic;
+       signal rst         : std_logic                                           := '0';
+       signal WriteEn     : std_logic_vector(c_inputs - 1 downto 0)             := (others => '0');
+       signal DataIn      : std_logic_vector(c_inputs*c_datawidth - 1 downto 0) := (others => '0');
+       signal ReadEn      : std_logic_vector(c_inputs - 1 downto 0);
+       signal DataOut     : std_logic_vector(c_inputs*c_datawidth - 1 downto 0);
+       signal Empty       : std_logic_vector(c_inputs - 1 downto 0);
+       signal Full        : std_logic_vector(c_inputs - 1 downto 0);
+       signal fifo_mask   : std_logic_vector(c_inputs - 1 downto 0)             := (others => '0');
+       signal buff_wren   : std_logic;
+       signal wordin_freq : std_logic_vector(32*c_inputs - 1 downto 0);
+       signal fifo_full_o : std_logic;
+       signal dataout_buf : std_logic_vector(c_datawidth - 1 downto 0);
+       
+begin
+       
+       generate_fifo : for i in 0 to c_inputs - 1 generate
+               fifo :component STD_FIFO
+                       generic map(
+                               DATA_WIDTH => c_datawidth,
+                               FIFO_DEPTH => c_fifo_depth
+                       )
+                       port map(
+                               CLK     => clk,
+                               RST     => rst,
+                               WriteEn => WriteEn(i),
+                               DataIn  => DataIn((i + 1)*c_datawidth - 1 downto i*c_datawidth),
+                               ReadEn  => ReadEn(i),
+                               DataOut => DataOut((i + 1)*c_datawidth - 1 downto i*c_datawidth),
+                               Empty   => Empty(i),
+                               Full    => Full(i)
+                       );
+       end generate generate_fifo;
+       
+       dut : component FiFoDataMux
+               generic map(
+                       g_datawidth  => c_datawidth,
+                       g_inputs     => c_inputs,
+                       g_clockspeed => c_clockspeed
+               )
+               port map(
+                       clk         => clk,
+                       rst         => rst,
+                       fifo_empty  => Empty,
+                       fifo_full   => Full,
+                       fifo_datain => dataout,
+                       fifo_mask   => fifo_mask,
+                       fifo_rden   => ReadEn,
+                       buff_wren   => buff_wren,
+                       dataout     => dataout_buf,
+                       wordin_freq => wordin_freq,
+                       fifo_full_o => fifo_full_o
+               );
+               
+               clk_gen : process is
+               begin
+                       clk <= '0';
+                       wait for c_clk_period/2;
+                       clk <= '1';
+                       wait for c_clk_period/2;
+               end process clk_gen;
+               
+               stimulus : process is
+       begin
+               wait for 100 ns;
+               fifo_mask                                    <= "11";
+               --write to single fifo
+               for i in 0 to 10 loop
+                       WriteEn(1)                                   <= '1';
+                       DataIn(2*c_datawidth - 1 downto c_datawidth) <= x"A" & std_logic_vector(to_unsigned(i, 4));
+                       wait for c_clk_period;
+               end loop;
+               WriteEn(1)                                   <= '0';
+               DataIn(2*c_datawidth - 1 downto c_datawidth) <= (others => '0');
+               wait for 100 ns;
+               --write to both fifos at same time, reading should start at last fifo
+               for i in 0 to 10 loop
+                       WriteEn <= "11";
+                       DataIn  <= x"A" & std_logic_vector(to_unsigned(i, 4)) & x"B" & std_logic_vector(to_unsigned(i, 4));
+                       wait for c_clk_period;
+               end loop;
+               WriteEn                                      <= (others => '0');
+               DataIn                                       <= (others => '0');
+               wait for 200 ns;
+               --start writing into first fifo then in second fifo, state machine should finish reading fifo 1 and then start reading other fifo
+               for i in 0 to 10 loop
+                       if i < 5 then
+                               WriteEn(0)                                   <= '1';
+                               DataIn(c_datawidth - 1 downto 0) <= x"B" & std_logic_vector(to_unsigned(i, 4));
+                       else
+                               WriteEn <= "11";
+                               DataIn  <= x"A" & std_logic_vector(to_unsigned(i, 4)) & x"B" & std_logic_vector(to_unsigned(i, 4));
+                       end if;
+                       wait for c_clk_period;
+               end loop;
+               WriteEn                                      <= (others => '0');
+               DataIn                                       <= (others => '0');
+               wait;
+       end process stimulus;
+               
+       
+end architecture sim;