library ieee;
use ieee.std_logic_1164.all;
library UNISIM;
use UNISIM.vcomponents.all;
library sychro1;
library utilities;
library comm;
library kakona;
use kakona.kakona_package.all;
entity xilly_toplevel is
port (
-- FMC & other ports:
-- local oscillator to be divided
IN_CLK_LO_N : IN std_logic;
IN_CLK_LO_P : IN std_logic;
-- divided clock
OUT_CLK_LO_DIVIDED_N : OUT std_logic;
OUT_CLK_LO_DIVIDED_P : OUT std_logic;
-- input data:
-- clock:
IN_CLK_FOR_DATA_P : IN std_logic;
IN_CLK_FOR_DATA_N : IN std_logic;
-- frame signal:
IN_FRAME_FOR_DATA_N : IN std_logic;
IN_FRAME_FOR_DATA_P : IN std_logic;
-- data from ADCs:
IN_DATA_ADC_P : IN std_logic_vector( C_NUM_INPUT_ADC_DATA_PORTS - 1 downto 0 );
IN_DATA_ADC_N : IN std_logic_vector( C_NUM_INPUT_ADC_DATA_PORTS - 1 downto 0 );
-- our LEDs:
GPIO_LED2 : OUT std_logic_vector(3 DOWNTO 0);
-- SPI communication block:
OUT_SPI_N_CE : OUT std_logic_vector( C_NUM_INPUT_ADC_MODULES-1 downto 0 );
OUT_SPI_DOUT : OUT std_logic;
OUT_SPI_CLK : OUT std_logic;
-- test:
--OUT_TEST1 : OUT std_logic;
-- dummy inputs due to incorrect soldering -- pins are hardconnected to ground.
IN_DUMMY : IN std_logic_vector( 1 downto 0 );
-- GPIO_DIP_SWITCH:
GPIO_DIP_SW : IN std_logic_vector( 7 downto 0 );
-- original xillybus-only ports:
PCIE_PERST_B_LS : IN std_logic;
PCIE_REFCLK_N : IN std_logic;
PCIE_REFCLK_P : IN std_logic;
PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0));
end xilly_toplevel;
architecture behavioral of xilly_toplevel is
component multiplexer_from_fifos
generic
( G_NUM_CHANNELS : natural := 2; -- number of channels
G_DATA_WIDTH : natural := 32 -- data width of individual packets
);
port (
clk : in std_logic;
rst : in std_logic;
-- input side
i_data : in std_logic_vector( G_DATA_WIDTH*G_NUM_CHANNELS - 1 downto 0 );
i_valid : in std_logic_vector( G_NUM_CHANNELS - 1 downto 0 );
o_rden : out std_logic_vector( G_NUM_CHANNELS - 1 downto 0 );
-- output side
o_data : out std_logic_vector( G_DATA_WIDTH - 1 downto 0 );
o_valid : out std_logic;
i_full : in std_logic
);
end component;
COMPONENT fifo_32x512_walmostfull
PORT (
clk : IN STD_LOGIC;
srst : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
full : OUT STD_LOGIC;
empty : OUT STD_LOGIC;
valid : OUT STD_LOGIC;
prog_full : OUT STD_LOGIC
);
END COMPONENT;
component bitslip_compensation
port (
clk : in std_logic;
rst : in std_logic;
i_data : in std_logic_vector( 15 downto 0 );
i_valid : in std_logic;
o_bitslip : out std_logic;
o_bitslip_done : out std_logic;
o_bitslip_drop_byte : out std_logic;
o_bitslip_failed : out std_logic
);
end component;
component iserdes_clock_generator
port
(
-- Clock and reset signals
CLK_IN_P : in std_logic; -- Differential fast clock from IOB
CLK_IN_N : in std_logic;
CLK_OUT : out std_logic; -- Fast clock output (synchronous to data)
CLK_DIV_OUT : out std_logic; -- Slow clock output
CLK_RESET : in std_logic); -- Reset signal for Clock circuit
end component;
component xillybus
port (
PCIE_PERST_B_LS : IN std_logic;
PCIE_REFCLK_N : IN std_logic;
PCIE_REFCLK_P : IN std_logic;
PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0);
bus_clk : OUT std_logic;
quiesce : OUT std_logic;
user_r_control_r_rden : OUT std_logic;
user_r_control_r_empty : IN std_logic := '0';
user_r_control_r_data : IN std_logic_vector(31 DOWNTO 0) := ( others => '0' );
user_r_control_r_eof : IN std_logic := '0';
user_r_control_r_open : OUT std_logic;
user_w_control_w_wren : OUT std_logic;
user_w_control_w_full : IN std_logic := '0';
user_w_control_w_data : OUT std_logic_vector(31 DOWNTO 0);
user_w_control_w_open : OUT std_logic;
user_r_data1_r_rden : OUT std_logic;
user_r_data1_r_empty : IN std_logic;
user_r_data1_r_data : IN std_logic_vector(31 DOWNTO 0);
user_r_data1_r_eof : IN std_logic;
user_r_data1_r_open : OUT std_logic;
user_w_data1_w_wren : OUT std_logic;
user_w_data1_w_full : IN std_logic;
user_w_data1_w_data : OUT std_logic_vector(31 DOWNTO 0);
user_w_data1_w_open : OUT std_logic;
user_r_data2_r_rden : OUT std_logic;
user_r_data2_r_empty : IN std_logic := '0';
user_r_data2_r_data : IN std_logic_vector(31 DOWNTO 0) := ( others => '0' );
user_r_data2_r_eof : IN std_logic := '0';
user_r_data2_r_open : OUT std_logic;
user_w_data2_w_wren : OUT std_logic;
user_w_data2_w_full : IN std_logic := '0';
user_w_data2_w_data : OUT std_logic_vector(31 DOWNTO 0);
user_w_data2_w_open : OUT std_logic);
end component;
component xilly_userlogiccmp_wrapper
port (
i_clk : in std_logic;
i_rst : in std_logic;
user_r_control_r_rden : in std_logic := '0';
user_r_control_r_empty : out std_logic := '1';
user_r_control_r_data : out std_logic_vector(31 DOWNTO 0);
user_w_control_w_wren : in std_logic := '0';
user_w_control_w_full : out std_logic := '0';
user_w_control_w_data : in std_logic_vector(31 DOWNTO 0) := ( others => '0' );
user_r_data1_r_rden : in std_logic := '0';
user_r_data1_r_empty : out std_logic := '1';
user_r_data1_r_data : out std_logic_vector(31 DOWNTO 0);
user_w_data1_w_wren : in std_logic := '0';
user_w_data1_w_full : out std_logic := '0';
user_w_data1_w_data : in std_logic_vector(31 DOWNTO 0) := ( others => '0' );
user_r_data2_r_rden : in std_logic := '0';
user_r_data2_r_empty : out std_logic := '1';
user_r_data2_r_data : out std_logic_vector(31 DOWNTO 0);
user_w_data2_w_wren : in std_logic := '0';
user_w_data2_w_full : out std_logic := '0';
user_w_data2_w_data : in std_logic_vector(31 DOWNTO 0) := ( others => '0' )
);
end component;
signal bus_clk : std_logic;
signal quiesce : std_logic;
signal user_r_control_r_rden : std_logic;
signal user_r_control_r_empty : std_logic;
signal user_r_control_r_data : std_logic_vector(31 DOWNTO 0);
--signal user_r_control_r_eof : std_logic;
signal user_r_control_r_open : std_logic;
signal user_w_control_w_wren : std_logic;
signal user_w_control_w_full : std_logic;
signal user_w_control_w_data : std_logic_vector(31 DOWNTO 0);
signal user_w_control_w_open : std_logic;
signal user_r_data1_r_rden : std_logic;
signal user_r_data1_r_empty : std_logic;
signal user_r_data1_r_data : std_logic_vector(31 DOWNTO 0);
--signal user_r_data1_r_eof : std_logic;
signal user_r_data1_r_open : std_logic;
signal user_w_data1_w_wren : std_logic;
signal user_w_data1_w_full : std_logic;
signal user_w_data1_w_data : std_logic_vector(31 DOWNTO 0);
signal user_w_data1_w_open : std_logic;
signal user_r_data2_r_rden : std_logic;
signal user_r_data2_r_empty : std_logic;
signal user_r_data2_r_data : std_logic_vector(31 DOWNTO 0);
--signal user_r_data2_r_eof : std_logic;
signal user_r_data2_r_open : std_logic;
signal user_w_data2_w_wren : std_logic;
signal user_w_data2_w_full : std_logic;
signal user_w_data2_w_data : std_logic_vector(31 DOWNTO 0);
signal user_w_data2_w_open : std_logic;
-- reset signal from xillybus. '1' when no device is open
signal s_reset : std_logic;
-- generated clock from ADC by iserdes_clock_generator:
signal s_iserdes_clk : std_logic;
signal s_iserdes_clk_div : std_logic;
-- Frame signal
signal s_data16_to_bitslip : std_logic_vector( 15 downto 0 );
signal s_data16_to_bitslip_valid : std_logic;
signal s_bitslip : std_logic;
signal s_bitslip_done : std_logic;
signal s_bitslip_drop_byte : std_logic;
signal s_bitslip_failed : std_logic;
signal s_bitslip_regged : std_logic;
signal s_bitslip_drop_byte_regged : std_logic;
-- from all ADC processing blocks:
signal s_from_processing_blocks_data : std_logic_vector( (C_NUM_INPUT_ADC_DATA_PORTS+1)*32 - 1 downto 0 ); -- +1 is space for output from frame
signal s_from_processing_blocks_valid : std_logic_vector( C_NUM_INPUT_ADC_DATA_PORTS+1 - 1 downto 0 );
signal s_from_processing_blocks_rden : std_logic_vector( C_NUM_INPUT_ADC_DATA_PORTS+1 - 1 downto 0 );
-- from multiplexer:
signal s_from_multiplexer_data : std_logic_vector( 31 downto 0 );
signal s_from_multiplexer_valid : std_logic;
signal s_from_multiplexer_full : std_logic;
-- SPI communication module:
signal s_spi_done : std_logic;
-- GPIO_DIP_SW register
signal s_gpio_dip_sw : std_logic_vector( 7 downto 0 );
signal s_valid_for_bitslip_processing : std_logic;
begin
-- Xillybus instantiation:
xillybus_ins : xillybus
port map (
-- Ports related to /dev/xillybus_control_r
-- FPGA to CPU signals:
user_r_control_r_rden => user_r_control_r_rden,
user_r_control_r_empty => user_r_control_r_empty,
user_r_control_r_data => user_r_control_r_data,
user_r_control_r_eof => '0',
user_r_control_r_open => user_r_control_r_open,
-- Ports related to /dev/xillybus_control_w
-- CPU to FPGA signals:
user_w_control_w_wren => user_w_control_w_wren,
user_w_control_w_full => user_w_control_w_full,
user_w_control_w_data => user_w_control_w_data,
user_w_control_w_open => user_w_control_w_open,
-- Ports related to /dev/xillybus_data1_r
-- FPGA to CPU signals:
user_r_data1_r_rden => user_r_data1_r_rden,
user_r_data1_r_empty => user_r_data1_r_empty,
user_r_data1_r_data => user_r_data1_r_data,
user_r_data1_r_eof => '0',
user_r_data1_r_open => user_r_data1_r_open,
-- Ports related to /dev/xillybus_data1_w
-- CPU to FPGA signals:
user_w_data1_w_wren => user_w_data1_w_wren,
user_w_data1_w_full => user_w_data1_w_full,
user_w_data1_w_data => user_w_data1_w_data,
user_w_data1_w_open => user_w_data1_w_open,
-- Ports related to /dev/xillybus_data2_r
-- FPGA to CPU signals:
user_r_data2_r_rden => user_r_data2_r_rden,
user_r_data2_r_empty => user_r_data2_r_empty,
user_r_data2_r_data => user_r_data2_r_data,
user_r_data2_r_eof => '0',
user_r_data2_r_open => user_r_data2_r_open,
-- Ports related to /dev/xillybus_data2_w
-- CPU to FPGA signals:
user_w_data2_w_wren => user_w_data2_w_wren,
user_w_data2_w_full => user_w_data2_w_full,
user_w_data2_w_data => user_w_data2_w_data,
user_w_data2_w_open => user_w_data2_w_open,
-- General signals
PCIE_PERST_B_LS => PCIE_PERST_B_LS,
PCIE_REFCLK_N => PCIE_REFCLK_N,
PCIE_REFCLK_P => PCIE_REFCLK_P,
PCIE_RX_N => PCIE_RX_N,
PCIE_RX_P => PCIE_RX_P,
GPIO_LED => GPIO_LED,
PCIE_TX_N => PCIE_TX_N,
PCIE_TX_P => PCIE_TX_P,
bus_clk => bus_clk,
quiesce => quiesce
);
s_reset <= '0' when user_r_control_r_open = '1' or
user_w_control_w_open = '1' or
user_r_data1_r_open = '1' or
user_w_data1_w_open = '1' or
user_r_data2_r_open = '1' or
user_w_data2_w_open = '1' or
s_gpio_dip_sw(0) = '0' else
'1';
-- register the gpio_dip_sw(0) with the 125MHz clock:
registers_for_gpio0 : process( bus_clk )
begin
if( rising_edge( bus_clk ) ) then
s_gpio_dip_sw(0) <= gpio_dip_sw(0);
s_gpio_dip_sw(2) <= gpio_dip_sw(2); -- used for SPI confifuration block that is clocked with bus_clk
end if;
end process;
-- register the gpio_dip_sw(1) with the clk_div clock:
registers_for_gpio1 : process( s_iserdes_clk_div )
begin
if( rising_edge( s_iserdes_clk_div ) ) then
s_gpio_dip_sw(1) <= gpio_dip_sw(1);
end if;
end process;
-- xilly_userlogiccmp_wrapper instantiation:
xilly_userlogiccmp_wrapper_inst : xilly_userlogiccmp_wrapper
port map (
i_clk => bus_clk,
i_rst => s_reset,
user_r_control_r_rden => user_r_control_r_rden,
user_r_control_r_empty => user_r_control_r_empty,
user_r_control_r_data => user_r_control_r_data,
user_w_control_w_wren => user_w_control_w_wren,
user_w_control_w_full => user_w_control_w_full,
user_w_control_w_data => user_w_control_w_data,
user_r_data1_r_rden => user_r_data1_r_rden,
user_r_data1_r_empty => user_r_data1_r_empty,
user_r_data1_r_data => user_r_data1_r_data,
user_w_data1_w_wren => user_w_data1_w_wren,
user_w_data1_w_full => user_w_data1_w_full,
user_w_data1_w_data => user_w_data1_w_data,
-- user_r_data2_r_rden => user_r_data2_r_rden,
-- user_r_data2_r_empty => user_r_data2_r_empty,
-- user_r_data2_r_data => user_r_data2_r_data,
-- user_w_data2_w_wren => user_w_data2_w_wren,
-- user_w_data2_w_full => user_w_data2_w_full,
-- user_w_data2_w_data => user_w_data2_w_data
user_r_data2_r_rden => open,
user_r_data2_r_empty => open,
user_r_data2_r_data => open,
user_w_data2_w_wren => open,
user_w_data2_w_full => open,
user_w_data2_w_data => open
);
-- tie outputs:
--OUT_TEST1 <= '0';
GPIO_LED2(0) <= s_bitslip_done;
GPIO_LED2(1) <= s_bitslip_failed;
GPIO_LED2(2) <= s_bitslip_drop_byte_regged;
GPIO_LED2(3) <= s_bitslip_regged;
ddd : process( s_iserdes_clk_div )
begin
if( rising_edge( s_iserdes_clk_div ) ) then
if( s_reset = '1' ) then
s_bitslip_regged <= '0';
s_bitslip_drop_byte_regged <= '0';
else
s_bitslip_regged <= s_bitslip_regged or s_bitslip;
s_bitslip_drop_byte_regged <= s_bitslip_drop_byte_regged or s_bitslip_drop_byte;
end if;
end if;
end process;
-----------------------------------------------------------------------------------------------
-- DATA PROCESSING:
-- Clock generator:
iserdes_clock_generator_inst : iserdes_clock_generator
port map (
CLK_IN_P => IN_CLK_FOR_DATA_P, CLK_IN_N => IN_CLK_FOR_DATA_N,
CLK_OUT => s_iserdes_clk, CLK_DIV_OUT => s_iserdes_clk_div, CLK_RESET => '0' );
-- FRAME signal processing block:
frame_processing_block_inst : entity work.processing_block
port map (
clk_iserdes_in => s_iserdes_clk, clk_iserdes_in_div => s_iserdes_clk_div, clk_global => bus_clk,
rst => s_reset,
bitslip => s_bitslip, bitslip_done => s_bitslip_done, bitslip_drop_byte => s_bitslip_drop_byte,
in_data_p => IN_FRAME_FOR_DATA_P, in_data_n => IN_FRAME_FOR_DATA_N,
in_data_swap_pn => C_FRAME_WIRES_SWAPPED_PN,
in_output_counting => s_gpio_dip_sw(1),
o_iserdes_output => s_data16_to_bitslip,
o_iserdes_output_valid => s_data16_to_bitslip_valid,
o_data => s_from_processing_blocks_data( 31 downto 0 ),
o_valid => s_from_processing_blocks_valid( 0 ),
i_rden => s_from_processing_blocks_rden( 0 )
);
-- bitslip processing:
s_valid_for_bitslip_processing <= s_data16_to_bitslip_valid and s_spi_done;
bitslip_compensation_inst : bitslip_compensation
port map (
clk => s_iserdes_clk_div, rst => s_reset,
i_data => s_data16_to_bitslip, i_valid => s_valid_for_bitslip_processing,
o_bitslip => s_bitslip, o_bitslip_done => s_bitslip_done, o_bitslip_drop_byte => s_bitslip_drop_byte, o_bitslip_failed => s_bitslip_failed );
-- ADCs signal processing blocks:
adc_proc_block_gen : for i in 0 to C_NUM_INPUT_ADC_DATA_PORTS - 1 generate
adc_processing_block_inst : entity work.processing_block
port map (
clk_iserdes_in => s_iserdes_clk, clk_iserdes_in_div => s_iserdes_clk_div, clk_global => bus_clk,
rst => s_reset,
bitslip => s_bitslip, bitslip_done => s_bitslip_done, bitslip_drop_byte => s_bitslip_drop_byte,
in_data_p => IN_DATA_ADC_P(i), in_data_n => IN_DATA_ADC_N(i),
in_data_swap_pn => C_DATA_WIRES_SWAPPED_PN(i),
in_output_counting => '0',
o_iserdes_output => open, o_iserdes_output_valid => open,
o_data => s_from_processing_blocks_data( 32*(i+1+1) - 1 downto 32*(i+1) ), -- i+1, because 31 downto 0 is used by the FRAME result
o_valid => s_from_processing_blocks_valid( i + 1 ),
i_rden => s_from_processing_blocks_rden( i + 1 )
);
end generate;
-- multiplexer:
multiplexer_from_fifos_inst : multiplexer_from_fifos
generic map (
G_NUM_CHANNELS => C_NUM_INPUT_ADC_DATA_PORTS + 1,
G_DATA_WIDTH => 32 )
port map (
clk => bus_clk, rst => s_reset,
i_data => s_from_processing_blocks_data, i_valid => s_from_processing_blocks_valid,
o_rden => s_from_processing_blocks_rden,
o_data => s_from_multiplexer_data, o_valid => s_from_multiplexer_valid, i_full => s_from_multiplexer_full
);
-- interface to xillybus:
-- FIFO_OUT instantiation:
data2_frame_fifo_out_inst : fifo_32x512_walmostfull
port map (
clk => bus_clk, srst => s_reset,
din => s_from_multiplexer_data, wr_en => s_from_multiplexer_valid, full => open, prog_full => s_from_multiplexer_full,
dout => user_r_data2_r_data, rd_en => user_r_data2_r_rden, empty => user_r_data2_r_empty, valid => open );
-----------------------------------------------------------------------------------------------
-- LO - Local Oscillator division module:
-- TODO: not tested: addition of the CE input. Will the ADCs configure themselves without CLOCK?
lo_divider_wrapper_inst : entity work.lo_divider_wrapper
generic map ( G_DIVISOR => 30 )
port map (
IN_CLK_LO_N => IN_CLK_LO_N, IN_CLK_LO_P => IN_CLK_LO_P, in_clk_enable => '1',
OUT_CLK_LO_DIVIDED_N => OUT_CLK_LO_DIVIDED_N, OUT_CLK_LO_DIVIDED_P => OUT_CLK_LO_DIVIDED_P );
-----------------------------------------------------------------------------------------------
-- SPI MASTER COMMUNICATION MODULE
spi_transmitter_wrapper_inst : entity work.spi_transmitter_wrapper
generic map(
G_DATA1 => C_SPI_ADC_DATA1,
G_DATA2 => C_SPI_ADC_DATA2,
G_NUM_BITS_PACKET => C_SPI_ADC_LENGTH,
G_NUM_PACKETS => C_SPI_ADC_PACKETS,
G_NUM_BITS_PAUSE => C_SPI_ADC_PAUSE )
port map(
i_clk125 => bus_clk, i_reset => s_reset, i_data_selector => s_gpio_dip_sw(2),
o_done => s_spi_done,
OUT_SPI_N_CE => OUT_SPI_N_CE, OUT_SPI_DOUT => OUT_SPI_DOUT, OUT_SPI_CLK => OUT_SPI_CLK );
end architecture;