-- Derived from: coregen/cg_io_deser_dly.vhd -- (c) Copyright 2009 - 2011 Xilinx, Inc. All rights reserved. -- -- -- Matt Warren 2014 ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; use ieee.std_logic_misc.all; use ieee.numeric_std.all; library unisim; use unisim.vcomponents.all; entity iserdes2_4b is generic ( -- width of the data for the system --sys_w : integer := 1; -- width of the data for the device dev_w : integer := 2); port ( -- From the system into the device --DATA_IN_FROM_PINS_P : in std_logic_vector(sys_w-1 downto 0); --DATA_IN_FROM_PINS_N : in std_logic_vector(sys_w-1 downto 0); serdata_i : in std_logic; --DATA_IN_TO_DEVICE : out std_logic_vector(dev_w-1 downto 0); pardata_o : out std_logic_vector(dev_w-1 downto 0); serdata_delayed_o : out std_logic; -- Input, Output delay control signals DELAY_BUSY : out std_logic; DELAY_CLK : in std_logic; delay_rst_i : in std_logic; DELAY_DATA_CAL : in std_logic; DELAY_DATA_CE : in std_logic; -- Enable signal for delay DELAY_DATA_INC : in std_logic; -- Delay increment (high), decrement (low) signal BITSLIP : in std_logic; -- Clock and reset signals --CLK_IN : in std_logic; -- Single ended Fast clock from IOB clk_io_i : in std_logic; iserdes_strb_i : in std_logic; clk_fabric_i : in std_logic; --CLK_DIV_OUT : out std_logic; -- Slow clock output IO_RESET : in std_logic -- Reset signal for IO circuit ); end iserdes2_4b; architecture rtl of iserdes2_4b is -- attribute CORE_GENERATION_INFO : string; -- attribute CORE_GENERATION_INFO of xilinx : -- architecture is "cg_io_deser_dly, selectio_wiz_v4_1, -- { -- component_name = cg_io_deser_dly, -- bus_dir = INPUTS, -- bus_sig_type = DIFF, -- bus_io_std = LVDS_25, -- use_serialization = true, -- use_phase_detector = false, -- serialization_factor = 8, -- enable_bitslip = true, -- enable_train = false, -- system_data_width = 1, -- bus_in_delay = VARIABLE, -- bus_out_delay = NONE, -- clk_sig_type = SINGLE, -- clk_io_std = LVCMOS12, -- clk_buf = BUFIO2, -- active_edge = RISING, -- clk_delay = FIXED, -- v6_bus_in_delay = NONE, -- v6_bus_out_delay = NONE, -- v6_clk_buf = BUFIO, -- v6_active_edge = NOT_APP, -- v6_ddr_alignment = SAME_EDGE_PIPELINED, -- v6_oddr_alignment = SAME_EDGE, ddr_alignment = C0, -- v6_interface_type = NETWORKING, -- interface_type = RETIMED, -- v6_bus_in_tap = 0, v6_bus_out_tap = 0, -- v6_clk_io_std = LVCMOS18, -- v6_clk_sig_type = DIFF -- }"; constant clock_enable : std_logic := '1'; signal unused : std_logic; -- signal clk_in_int : std_logic; signal clk_div : std_logic; signal clk_div_int : std_logic; signal clk_in_int_buf : std_logic; -- signal clk_in_int_delay : std_logic; -- After the buffer signal data_in_from_pins_int : std_logic; --_vector(sys_w-1 downto 0); -- Between the delay and serdes signal data_in_from_pins_delay : std_logic; --_vector(sys_w-1 downto 0); signal delay_data_busy : std_logic; --_vector(sys_w-1 downto 0); constant num_serial_bits : integer := dev_w; --/sys_w; --type serdarr is array (0 to 7) of std_logic_vector(sys_w-1 downto 0); -- Array to use intermediately from the serdes to the internal -- devices. bus "0" is the leftmost bus -- * fills in starting with 0 signal iserdes_q : std_logic_vector(7 downto 0) := (others => '0'); --serdarr := (( others => (others => '0'))); signal serdesstrobe : std_logic; signal icascade : std_logic; --_vector(sys_w-1 downto 0); signal slave_shiftout : std_logic; --_vector(sys_w-1 downto 0); begin DELAY_BUSY <= delay_data_busy; --or_reduce(delay_data_busy); -- -- Create the clock logic -- ibufg_clk_inst : IBUFG -- generic map ( -- IOSTANDARD => "LVCMOS12") -- port map ( -- I => CLK_IN, -- O => clk_in_int); -- -- delay the input clock -- iodelay2_clk : IODELAY2 -- generic map ( -- DATA_RATE => "SDR", -- IDELAY_VALUE => 0, -- IDELAY_TYPE => "FIXED", -- COUNTER_WRAPAROUND => "STAY_AT_LIMIT", -- DELAY_SRC => "IDATAIN", -- SERDES_MODE => "NONE", -- SIM_TAPDELAY_VALUE => 75) -- port map ( -- -- required datapath -- IDATAIN => clk_in_int, -- DATAOUT => clk_in_int_delay, -- T => '1', -- -- inactive data connections -- DATAOUT2 => open, -- DOUT => open, -- ODATAIN => '0', -- TOUT => open, -- -- tie off the clocks -- IOCLK0 => '0', -- No calibration needed -- IOCLK1 => '0', -- No calibration needed -- -- Tie of the variable delay programming -- CLK => '0', -- CAL => '0', -- INC => '0', -- CE => '0', -- BUSY => open, -- RST => '0'); -- -- Set up the clock for use in the serdes -- bufio2_inst : BUFIO2 -- generic map ( -- DIVIDE_BYPASS => false, -- I_INVERT => false, -- USE_DOUBLER => false, -- DIVIDE => 8) -- port map ( -- DIVCLK => clk_div, -- IOCLK => clk_in_int_buf, -- SERDESSTROBE => serdesstrobe, -- I => clk_in_int_delay); serdesstrobe <= iserdes_strb_i; clk_in_int_buf <= clk_io_i; -- -- Buffer up the divided clock -- clkdiv_buf_inst : BUFG -- port map ( -- O => clk_div_int, -- I => clk_div); -- CLK_DIV_OUT <= clk_div_int; clk_div_int <= clk_fabric_i; -- We have multiple bits- step over every bit, instantiating the required elements --pins : for pin_count in 0 to sys_w-1 generate --begin -- Instantiate the buffers ---------------------------------- -- Instantiate a buffer for every bit of the data bus -- ibufds_inst : IBUFDS -- generic map ( -- DIFF_TERM => false, -- Differential termination -- IOSTANDARD => "LVDS_25") -- port map ( -- I => DATA_IN_FROM_PINS_P (pin_count), -- IB => DATA_IN_FROM_PINS_N (pin_count), -- O => data_in_from_pins_int(pin_count)); data_in_from_pins_int <= serdata_i; -- Instantiate the delay primitive ----------------------------------- iodelay2_bus : IODELAY2 generic map ( DATA_RATE => "SDR", IDELAY_VALUE => 0, IDELAY_TYPE => "VARIABLE_FROM_ZERO", COUNTER_WRAPAROUND => "STAY_AT_LIMIT", DELAY_SRC => "IDATAIN", SERDES_MODE => "NONE", SIM_TAPDELAY_VALUE => 75 ) port map ( -- required datapath IDATAIN => data_in_from_pins_int, -- (pin_count), DATAOUT => data_in_from_pins_delay, --(pin_count), T => '1', -- inactive data connections DATAOUT2 => serdata_delayed_o, DOUT => open, ODATAIN => '0', TOUT => open, -- connect up the clocks IOCLK0 => clk_in_int_buf, -- High speed clock for calibration for SDR/DDR IOCLK1 => '0', -- High speed clock for calibration for DDR CLK => DELAY_CLK, CAL => DELAY_DATA_CAL, INC => DELAY_DATA_INC, CE => DELAY_DATA_CE, BUSY => delay_data_busy, --(pin_count), RST => delay_rst_i); -- Instantiate the serdes primitive ---------------------------------- -- declare the iserdes iserdes2_master : ISERDES2 generic map ( BITSLIP_ENABLE => true, DATA_RATE => "SDR", DATA_WIDTH => 4, INTERFACE_TYPE => "RETIMED", SERDES_MODE => "NONE") port map ( Q1 => iserdes_q(3), --(pin_count), Q2 => iserdes_q(2), --(pin_count), Q3 => iserdes_q(1), --(pin_count), Q4 => iserdes_q(0), --(pin_count), SHIFTOUT => open, INCDEC => open, VALID => open, BITSLIP => '0', -- 1-bit Invoke Bitslip. This can be used with any DATA_WIDTH, cascaded or not. -- The amount of bitslip is fixed by the DATA_WIDTH selection. CE0 => clock_enable, -- 1-bit Clock enable input CLK0 => clk_in_int_buf, -- 1-bit IO Clock network input. Optionally Invertible. This is the primary clock -- input used when the clock doubler circuit is not engaged (see DATA_RATE -- attribute). CLK1 => '0', CLKDIV => clk_div_int, -- 1-bit Global clock network input. This is the clock for the fabric domain. D => data_in_from_pins_delay, --(pin_count), -- 1-bit Input signal from IOB. IOCE => serdesstrobe, -- 1-bit Data strobe signal derived from BUFIO CE. Strobes data capture for -- NETWORKING and NETWORKING_PIPELINES alignment modes. RST => IO_RESET, -- 1-bit Asynchronous reset only. SHIFTIN => '0', --(pin_count), -- unused connections FABRICOUT => open, CFB0 => open, CFB1 => open, DFB => open); -- Concatenate the serdes outputs together. Keep the timesliced -- bits together, and placing the earliest bits on the right -- ie, if data comes in 0, 1, 2, 3, 4, 5, 6, 7, ... -- the output will be 3210, 7654, ... ------------------------------------------------------------- in_slices : for slice_count in 0 to num_serial_bits-1 generate begin -- This places the first data in time on the right --DATA_IN_TO_DEVICE(slice_count) <= --iserdes_q(num_serial_bits-slice_count-1)(0); -- To place the first data in time on the left, use the -- following code, instead --DATA_IN_TO_DEVICE(slice_count) <= iserdes_q(slice_count); pardata_o(slice_count) <= iserdes_q(slice_count); end generate in_slices; --end generate pins; end rtl;