From e577cc64a71648f3c0667748060310341ccdc0c4 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 27 Jun 2018 17:10:08 +0800 Subject: [PATCH] saving some unfinished work --- mupix/Mupix8/sources/GrayCounter2.vhd | 53 +++ mupix/Mupix8/sources/MuPixDataLink_new.vhd | 354 +++++++++++++++++++++ mupix/Mupix8/tb/GraycounterTest.vhd | 98 ++++++ 3 files changed, 505 insertions(+) create mode 100644 mupix/Mupix8/sources/GrayCounter2.vhd create mode 100644 mupix/Mupix8/sources/MuPixDataLink_new.vhd create mode 100644 mupix/Mupix8/tb/GraycounterTest.vhd diff --git a/mupix/Mupix8/sources/GrayCounter2.vhd b/mupix/Mupix8/sources/GrayCounter2.vhd new file mode 100644 index 0000000..a700293 --- /dev/null +++ b/mupix/Mupix8/sources/GrayCounter2.vhd @@ -0,0 +1,53 @@ +---------------------------------------------------- +-- Gray counter by converting binary number +-- Tobias Weber 27.06.2018 +-- Ruhr University Bochum +---------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity Graycounter is + generic ( + COUNTWIDTH : integer := 8 + ); + port ( + clk : in std_logic; -- clock + reset : in std_logic; -- reset + inc_en : in std_logic; -- increment counter enable + counter : out std_logic_vector(COUNTWIDTH - 1 downto 0) -- counter + ); +end Graycounter; + +architecture rtl of Graycounter is + + signal binary_counter : unsigned(COUNTWIDTH - 1 downto 0) := (others => '0'); + signal gray_counter : std_logic_vector(COUNTWIDTH - 1 downto 0) := (others => '0'); + +begin + + binary_cnt: process(clk) + begin + if rising_edge(clk) then + if (reset = '1') then + binary_counter <= (others => '0'); + counter <= (others => '0'); + else + if inc_en = '1' then + binary_counter <= binary_counter + 1; + end if; + counter <= gray_counter; + end if; + end if; + end process binary_cnt; + + graycode: process (binary_counter) is + begin -- process graycode + gray_counter <= std_logic_vector(binary_counter xor ('0' & binary_counter(COUNTWIDTH - 1 downto 1))); + end process graycode; + + +end rtl; diff --git a/mupix/Mupix8/sources/MuPixDataLink_new.vhd b/mupix/Mupix8/sources/MuPixDataLink_new.vhd new file mode 100644 index 0000000..b46066a --- /dev/null +++ b/mupix/Mupix8/sources/MuPixDataLink_new.vhd @@ -0,0 +1,354 @@ +------------------------------------------------------------------ +-- Mupix data 10b8b readout with internal FIFO +--T. Weber, Ruhr Universität Bochum +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.StdTypes.all; +use work.Constants.all; + +entity MupixDataLinkWithUnpacker is + generic ( + useRecoveredClock : integer range 0 to 1 := c_Yes); + port( + sysclk : in std_logic; --trb system clock (typically 100 MHz) + dataclk : in std_logic; --mupix link clock from FPGA PLL(50 - 150 MHz) + rst : in std_logic; --synchronous reset + clear : in std_logic; --asynchronous reset + --lattice serdes + mupix_data : in std_logic_vector(7 downto 0); --lvds pairs of 4 incoming data channels + --fifo signals + fifo_rden : in std_logic_vector(c_links - 1 downto 0); -- read enable to FIFOs + fifo_empty : out std_logic_vector(c_links - 1 downto 0); -- input FIFO empty flags + fifo_full : out std_logic_vector(c_links - 1 downto 0); -- input FIFO full flags + fifo_data : out std_logic_vector(c_links*c_mupixhitsize - 1 downto 0); -- input data from FIFOs + --misc + channel_status_led : out std_logic_vector(c_links - 1 downto 0); + --TRB slow control channel + SLV_READ_IN : in std_logic; + SLV_WRITE_IN : in std_logic; + SLV_DATA_OUT : out std_logic_vector(31 downto 0); + SLV_DATA_IN : in std_logic_vector(31 downto 0); + SLV_ADDR_IN : in std_logic_vector(15 downto 0); + SLV_ACK_OUT : out std_logic; + SLV_NO_MORE_DATA_OUT : out std_logic; + SLV_UNKNOWN_ADDR_OUT : out std_logic); +end entity MupixDataLinkWithUnpacker; + +architecture rtl of MupixDataLinkWithUnpacker is + + signal clkrx : std_logic_vector(3 downto 0); + + component InputSynchronizer + generic(depth : integer := 2; + width : integer := 1); + port( + clk : in std_logic; + rst : in std_logic; + input : in std_logic_vector(width - 1 downto 0); + sync_output : out std_logic_vector(width - 1 downto 0)); + end component InputSynchronizer; + + component serdes_fifo + 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 mupix_serdes_new + generic (USER_CONFIG_FILE : string := "mupix_serdes_new.txt"); + port ( +------------------ +-- CH0 -- + hdinp_ch0, hdinn_ch0 : in std_logic; -- input serial link from mupix + rxiclk_ch0 : in std_logic; -- rx clock for fifo bridge (should be sysclock or recovered clock?) + rx_full_clk_ch0 : out std_logic; -- full receive clock from serdes + rx_half_clk_ch0 : out std_logic; -- half receive clock from serdes + fpga_rxrefclk_ch0 : in std_logic; -- reference clock from fpga fabric + rxdata_ch0 : out std_logic_vector (7 downto 0); -- received data + rx_k_ch0 : out std_logic; -- control charactor indicator + rx_disp_err_ch0 : out std_logic; -- indicate disparity error + rx_cv_err_ch0 : out std_logic; -- error in data + word_align_en_ch0_c : in std_logic; -- enable word alignment (pulse high) + rx_pwrup_ch0_c : in std_logic; -- power up receive channel + rx_los_low_ch0_s : out std_logic; -- signal lost + rx_cdr_lol_ch0_s : out std_logic; -- clock recovery failure + rx_div2_mode_ch0_c : in std_logic; -- enable clock div mode +-- CH1 -- + hdinp_ch1, hdinn_ch1 : in std_logic; + rxiclk_ch1 : in std_logic; + rx_full_clk_ch1 : out std_logic; + rx_half_clk_ch1 : out std_logic; + fpga_rxrefclk_ch1 : in std_logic; + rxdata_ch1 : out std_logic_vector (7 downto 0); + rx_k_ch1 : out std_logic; + rx_disp_err_ch1 : out std_logic; + rx_cv_err_ch1 : out std_logic; + word_align_en_ch1_c : in std_logic; + rx_pwrup_ch1_c : in std_logic; + rx_los_low_ch1_s : out std_logic; + rx_cdr_lol_ch1_s : out std_logic; + rx_div2_mode_ch1_c : in std_logic; +-- CH2 -- + hdinp_ch2, hdinn_ch2 : in std_logic; + rxiclk_ch2 : in std_logic; + rx_full_clk_ch2 : out std_logic; + rx_half_clk_ch2 : out std_logic; + fpga_rxrefclk_ch2 : in std_logic; + rxdata_ch2 : out std_logic_vector (7 downto 0); + rx_k_ch2 : out std_logic; + rx_disp_err_ch2 : out std_logic; + rx_cv_err_ch2 : out std_logic; + word_align_en_ch2_c : in std_logic; + rx_pwrup_ch2_c : in std_logic; + rx_los_low_ch2_s : out std_logic; + rx_cdr_lol_ch2_s : out std_logic; + rx_div2_mode_ch2_c : in std_logic; +-- CH3 -- + hdinp_ch3, hdinn_ch3 : in std_logic; + rxiclk_ch3 : in std_logic; + rx_full_clk_ch3 : out std_logic; + rx_half_clk_ch3 : out std_logic; + fpga_rxrefclk_ch3 : in std_logic; + rxdata_ch3 : out std_logic_vector (7 downto 0); + rx_k_ch3 : out std_logic; + rx_disp_err_ch3 : out std_logic; + rx_cv_err_ch3 : out std_logic; + word_align_en_ch3_c : in std_logic; + rx_pwrup_ch3_c : in std_logic; + rx_los_low_ch3_s : out std_logic; + rx_cdr_lol_ch3_s : out std_logic; + rx_div2_mode_ch3_c : in std_logic; +---- Miscillaneous ports + fpga_txrefclk : in std_logic; -- tx reference clock + tx_sync_qd_c : in std_logic; -- serializer reset + refclk2fpga : out std_logic; -- reference clock to fpga core + rst_n : in std_logic; -- reset all + serdes_rst_qd_c : in std_logic); -- reset serdes, but nor pcs + end component mupix_serdes_new; + + component MupixUnpacker + generic( + g_hitsize : integer := 40; + g_countersize : integer := 32 + ); + port( + clk : in std_logic; + reset : in std_logic; + data_in : in std_logic_vector(7 downto 0); + komma : in std_logic; + valid : in std_logic; + hit_out : out std_logic_vector(g_hitsize - 1 downto 0); + hit_enable : out std_logic; + coarsecounter : out std_logic_vector(g_countersize - 1 downto 0); + counter_enable : out std_logic; + link_flag : out std_logic; + errorcounter : out std_logic_vector(31 downto 0)); + end component MupixUnpacker; + + component LinkSynchronizer + generic ( + clk_speed : integer := 8); + port ( + clk_in : in std_logic; + reset_in : in std_logic; + comma_in : in std_logic; + cverr_in : in std_logic; + link_sync_out : out std_logic; + link_sync_flag : out std_logic; + comma_counter_out : out std_logic_vector(15 downto 0)); + end component LinkSynchronizer; + + constant ch_powerup_i : std_logic_vector(3 downto 0) := "1111"; -- change to powerdown unused channels + constant ch_divmode_i : std_logic_vector(3 downto 0) := "0000"; -- use half rx clock speed + + -- serdes signals (declare for all channels possibly used) + signal rx_full_clock_i : std_logic_vector(3 downto 0); -- recovered receive clock + signal rx_data_i : std_logic_vector(4*8 - 1 downto 0); -- receive data + signal rx_komma_i : std_logic_vector(3 downto 0); -- komma words + signal rx_disp_err_i : std_logic_vector(3 downto 0); -- disparity error indicator + signal rx_dataerror_i : std_logic_vector(3 downto 0); -- error in rx data + signal align_en_i : std_logic_vector(3 downto 0); -- regain word alignment to rx data + signal rx_sig_lost_i : std_logic_vector(3 downto 0); -- rx signal lost + signal rx_cdr_i : std_logic_vector(3 downto 0); -- clock recovery failure + + -- synced signals + signal rx_cdr_sync : std_logic_vector(3 downto 0); + signal rx_sig_lost_sync : std_logic_vector(3 downto 0); + + -- fifo signals + signal fifo_data_oi : std_logic_vector(c_links*c_mupixhitsize - 1 downto 0); + signal fifo_data_ii : std_logic_vector(c_links*c_mupixhitsize - 1 downto 0); + signal fifo_empty_i : std_logic_vector(c_links - 1 downto 0) := (others => '0'); + signal fifo_full_i : std_logic_vector(c_links - 1 downto 0) := (others => '0'); + signal fifo_wren_i : std_logic_vector(c_links - 1 downto 0) := (others => '0'); + signal fifo_rden_i : std_logic_vector(c_links - 1 downto 0) := (others => '0'); + constant fifo_depth : integer := 10; -- fifo depth (change when regenerating FIFO IP core) + signal fifo_readcnt_i : std_logic_vector((c_links - 1)*fifo_depth - 1 downto 0); + + -- status and error counters + signal serdes_channel_select : integer range 0 to 3 := 0; + signal disp_error_counter : t_counter_array(0 to 3) := (others => (others => '0')); + signal data_error_counter : t_counter_array(0 to 3) := (others => (others => '0')); + signal unpacker_error_counter : t_counter_array(0 to 3) := (others => (others => '0')); + + -- link synchronizer signals + signal link_sync_out_i : std_logic_vector(c_links - 1 downto 0) := (others => '0'); + signal link_sync_flag_i : std_logic_vector(c_links - 1 downto 0) := (others => '0'); + signal komma_counter : t_counter_array(0 to 3) := (others => (others => '0')); + + -- unpacker signals + signal unpacker_valid_i : std_logic_vector(c_links - 1 downto 0) := (others => '0'); + +begin + + gen_receive_clock_rec : if useRecoveredClock = c_Yes generate + clkrx <= rx_full_clock_i; + end generate; + + gen_receive_clock_norec : if useRecoveredClock = c_No generate + clkrx <= sysclk & sysclk & sysclk & sysclk; + end generate; + + -- not sure about correct clock distribution + mupix_serdes_new : entity work.mupix_serdes_new + generic map ( + USER_CONFIG_FILE => "mupix_serdes_new.txt") + port map ( + hdinp_ch0 => mupix_data(0), + hdinn_ch0 => mupix_data(1), + rxiclk_ch0 => clkrx(0), + rx_full_clk_ch0 => rx_full_clock_i(0), + rx_half_clk_ch0 => open, + fpga_rxrefclk_ch0 => dataclk, + rxdata_ch0 => rx_data_i(1*8 - 1 downto 0*8), + rx_k_ch0 => rx_komma_i(0), + rx_disp_err_ch0 => rx_disp_err_i(0), + rx_cv_err_ch0 => rx_dataerror_i(0), + word_align_en_ch0_c => align_en_i(0), + rx_pwrup_ch0_c => ch_powerup_i(0), + rx_los_low_ch0_s => rx_sig_lost_i(0), + rx_cdr_lol_ch0_s => rx_cdr_i(0), + rx_div2_mode_ch0_c => ch_divmode_i(0), + hdinp_ch1 => mupix_data(2), + hdinn_ch1 => mupix_data(3), + rxiclk_ch1 => clkrx(1), + rx_full_clk_ch1 => rx_full_clock_i(1), + rx_half_clk_ch1 => open, + fpga_rxrefclk_ch1 => dataclk, + rxdata_ch1 => rx_data_i(2*8 - 1 downto 1*8), + rx_k_ch1 => rx_komma_i(1), + rx_disp_err_ch1 => rx_disp_err_i(1), + rx_cv_err_ch1 => rx_dataerror_i(1), + word_align_en_ch1_c => align_en_i(1), + rx_pwrup_ch1_c => ch_powerup_i(1), + rx_los_low_ch1_s => rx_sig_lost_i(1), + rx_cdr_lol_ch1_s => rx_cdr_i(1), + rx_div2_mode_ch1_c => ch_divmode_i(1), + hdinp_ch2 => mupix_data(4), + hdinn_ch2 => mupix_data(5), + rxiclk_ch2 => clkrx(2), + rx_full_clk_ch2 => rx_full_clock_i(2), + rx_half_clk_ch2 => open, + fpga_rxrefclk_ch2 => dataclk, + rxdata_ch2 => rx_data_i(3*8 - 1 downto 2*8), + rx_k_ch2 => rx_komma_i(2), + rx_disp_err_ch2 => rx_disp_err_i(2), + rx_cv_err_ch2 => rx_dataerror_i(2), + word_align_en_ch2_c => align_en_i(2), + rx_pwrup_ch2_c => ch_powerup_i(2), + rx_los_low_ch2_s => rx_sig_lost_i(2), + rx_cdr_lol_ch2_s => rx_cdr_i(2), + rx_div2_mode_ch2_c => ch_divmode_i(2), + hdinp_ch3 => mupix_data(6), + hdinn_ch3 => mupix_data(7), + rxiclk_ch3 => clkrx(3), + rx_full_clk_ch3 => rx_full_clock_i(3), + rx_half_clk_ch3 => open, + fpga_rxrefclk_ch3 => dataclk, + rxdata_ch3 => rx_data_i(4*8 - 1 downto 3*8), + rx_k_ch3 => rx_komma_i(3), + rx_disp_err_ch3 => rx_disp_err_i(3), + rx_cv_err_ch3 => rx_dataerror_i(3), + word_align_en_ch3_c => align_en_i(3), + rx_pwrup_ch3_c => ch_powerup_i(3), + rx_los_low_ch3_s => rx_sig_lost_i(3), + rx_cdr_lol_ch3_s => rx_cdr_i(3), + rx_div2_mode_ch3_c => ch_divmode_i(2), + fpga_txrefclk => dataclk, + tx_sync_qd_c => '0', + refclk2fpga => open, + rst_n => '1', + serdes_rst_qd_c => clear); + + generate_synchronizer : for j in 0 to c_links - 1 generate + entity work.LinkSynchronizer + generic map ( + clk_speed => 8) + port map ( + clk_in => clkrx, + reset_in => rst, + comma_in => rx_komma_i(j), + cverr_in => rx_dataerror_i(j), + link_sync_out => link_sync_out_i(j), + link_sync_flag => link_sync_flag_i(j), + comma_counter_out => komma_counter(j)); + end generate generate_synchronizer; + + unpacker_valid_i <= not rx_dataerror_i; + + generate_unpacker : for j in 0 to c_links - 1 generate + entity work.MupixUnpacker + generic map ( + g_hitsize => c_mupixhitsize, + g_countersize => 31) + port map ( + clk => clkrx, + reset => rst, + data_in => rx_data_i((j + 1)*8 - 1 downto j*8), + komma => rx_komma_i(j), + valid => unpacker_valid_i(j), + hit_out => fifo_data_ii((j + 1)*c_mupixhitsize downto j*c_mupixhitsize), + hit_enable => fifo_wren_i(j), + coarsecounter => open, + counter_enable => open, + link_flag => open, + errorcounter => unpacker_error_counter(j)); + end generate generate_fifo; + + generate_fifo : for j in 0 to c_links - 1 generate + entity work.serdes_fifo + port map ( + Data => fifo_data_ii((j + 1)*c_mupixhitsize downto j*c_mupixhitsize), + WrClock => clkrx(j), + RdClock => sysclk, + WrEn => fifo_wren_i(j), + RdEn => fifo_rden_i(j), + Reset => rst, + RPReset => rst, + Q => fifo_data_oi((j + 1)*c_mupixhitsize downto j*c_mupixhitsize), + RCNT => fifo_readcnt_i((j + 1)*fifo_depth - 1 downto j*fifo_depth), + Empty => fifo_empty_i(j), + Full => fifo_full_i(j)); + end generate generate_fifo; + + sync_los_low : InputSynchronizer + generic map(depth => 2, width => 4) + port map(clk => sysclk, rst => rst, input => rx_sig_lost_i, sync_output => rx_sig_lost_sync); + + sync_cdr_lol : InputSynchronizer + generic map(depth => 2, width => 4) + port map(clk => sysclk, rst => rst, input => rx_cdr_i, sync_output => rx_cdr_sync); + +end architecture; diff --git a/mupix/Mupix8/tb/GraycounterTest.vhd b/mupix/Mupix8/tb/GraycounterTest.vhd new file mode 100644 index 0000000..561a6d9 --- /dev/null +++ b/mupix/Mupix8/tb/GraycounterTest.vhd @@ -0,0 +1,98 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity GraycounterTest is +end entity GraycounterTest; + +architecture sim of GraycounterTest is + + constant clk_period : time := 10 ns; + constant COUNTWIDTH : integer := 3; + + signal clk : std_logic; + signal reset : std_logic := '0'; + signal inc_en : std_logic := '0'; + signal counter : std_logic_vector(COUNTWIDTH - 1 downto 0); + signal bypass : std_logic := '0'; + signal binary_out : std_logic_vector(COUNTWIDTH - 1 downto 0); + + component Graycounter is + generic ( + COUNTWIDTH : integer); + port ( + clk : in std_logic; + reset : in std_logic; + inc_en : in std_logic; + counter : out std_logic_vector(COUNTWIDTH-1 downto 0)); + end component Graycounter; + + component gray_to_binary is + generic ( + NBITS : integer); + port ( + clk : in std_logic; + reset : in std_logic; + bypass : in std_logic; + gray_in : in std_logic_vector (NBITS - 1 downto 0); + bin_out : out std_logic_vector (NBITS - 1 downto 0)); + end component gray_to_binary; + +begin -- architecture sim + + Graycounter_1 : entity work.Graycounter + generic map ( + COUNTWIDTH => COUNTWIDTH) + port map ( + clk => clk, + reset => reset, + inc_en => inc_en, + counter => counter); + + gray_to_binary_1: entity work.gray_to_binary + generic map ( + NBITS => COUNTWIDTH) + port map ( + clk => clk, + reset => reset, + bypass => bypass, + gray_in => counter, + bin_out => binary_out); + + clock_gen : process is + begin + clk <= '1'; + wait for clk_period/2; + clk <= '0'; + wait for clk_period/2; + end process clock_gen; + + sim : process is + begin -- process sim + wait for 100 ns; + inc_en <= '1'; + -- normal couting + wait for 4*clk_period; + inc_en <= '0'; + wait for 10*clk_period; + inc_en <= '1'; + wait for 6*clk_period; + inc_en <= '0'; + -- reacting to reset + wait for clk_period; + reset <= '1'; + wait for clk_period; + reset <= '0'; + wait for 2*clk_period; + inc_en <= '1'; + wait for 4*clk_period; + inc_en <= '0'; + wait for 5*clk_period; + inc_en <= '1'; + wait for 15*clk_period; + inc_en <= '0'; + wait; + end process sim; + + +end architecture sim; -- 2.43.0