From dd056a2fe9b1548d2b211c3ea146d57ebcce198c Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Mon, 23 Jul 2018 15:39:51 +0200 Subject: [PATCH] better working version of data width converter in simulation. However, hades38 is down and a new firmware could not be compiled. --- mupix/Mupix8/sources/DataWidthConversion.vhd | 151 ------------ .../sources/Datapath/DataWidthConversion.vhd | 223 ++++++++++++++++++ .../sources/Datapath/MupixTRBReadout.vhd | 41 ++-- mupix/Mupix8/sources/MupixClocks.vhd | 56 +++++ mupix/Mupix8/tb/DataWidthConversionTest.vhd | 145 ++++++++++++ mupix/Mupix8/tb/MupixTRBReadoutTest.vhd | 2 +- mupix/Mupix8/trb3_periph.prj | 3 +- 7 files changed, 449 insertions(+), 172 deletions(-) delete mode 100644 mupix/Mupix8/sources/DataWidthConversion.vhd create mode 100644 mupix/Mupix8/sources/Datapath/DataWidthConversion.vhd create mode 100644 mupix/Mupix8/sources/MupixClocks.vhd create mode 100644 mupix/Mupix8/tb/DataWidthConversionTest.vhd diff --git a/mupix/Mupix8/sources/DataWidthConversion.vhd b/mupix/Mupix8/sources/DataWidthConversion.vhd deleted file mode 100644 index 26d4533..0000000 --- a/mupix/Mupix8/sources/DataWidthConversion.vhd +++ /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 index 0000000..0591b46 --- /dev/null +++ b/mupix/Mupix8/sources/Datapath/DataWidthConversion.vhd @@ -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; diff --git a/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd b/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd index ac8087a..b3df948 100644 --- a/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd +++ b/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd @@ -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 index 0000000..d5edeee --- /dev/null +++ b/mupix/Mupix8/sources/MupixClocks.vhd @@ -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 index 0000000..debb75a --- /dev/null +++ b/mupix/Mupix8/tb/DataWidthConversionTest.vhd @@ -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; diff --git a/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd b/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd index 04b77bc..199892b 100644 --- a/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd +++ b/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd @@ -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"; diff --git a/mupix/Mupix8/trb3_periph.prj b/mupix/Mupix8/trb3_periph.prj index 75402e2..24a9196 100644 --- a/mupix/Mupix8/trb3_periph.prj +++ b/mupix/Mupix8/trb3_periph.prj @@ -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" -- 2.43.0