Hi Casperites,
I've been trying to exercise the SelectIO resources on ROACH2 and have
run into a bit of a road-block.
I'm wondering if someone might have done something similar, but
successfully, and would be wiling to
share the code. Or if someone sees something silly that I'm missing
below...
The simplest configuration I have tried is as follows:
-----OSERDES----- ----ISERDES-------
Data --> D[6:1] OFB --> OFB D[6:1] --> test points
I have a common MMCM providing CLK and CLKDIV to both SERDES.
When transmitting in Single Data Rate (SDR) I get out what I put in,
after doing some
"bit-slips" to rotate the received data.
However, in Dual Data Rate (DDR) I have a really weird situation.
Even-numbered data bits affect
two outputs bits of the ISERDES on odd bits have no effect whatsoever.
I have tried using an
iodelaye1 to time-shift the data and I can reverse the effect, i.e., the
odd data input
bits each affect two output bits and the even ones don't affect any. I
halve the CLK frequency
when going from SDR to DDR and don't change CLKDIV, which seems correct.
There must be
something simple I'm missing, but I'm about out of things to try!
I have tried a similar configuration except with the OSERDES driving an
external cable
and with an iodelaye1 in front of the iserdes. The result is the same.
I have also viewed the high speed serial waveform, using the
"combinatorial output" of the iserdes,
on a scope and it matches what I expect for any given input data. Makes
me think that the
problem is in the iserdes.
I've attached the associated VHDL in case anyone wants to have a look.
Thanks in advance for any suggestions!
Rich
-------------------------------------------------------
library ieee;
USE ieee.numeric_std.all;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
Library UNISIM;
use UNISIM.vcomponents.all;
-------------------------------------------------------
-- This block and associated sub-blocks are used to test iserdes, oserdes and
iodelay
entity serdes_tst is
port(
c125: in std_logic; --system clock input
td_in: in std_logic_vector(7 downto 0); --static test data
for oserdes
iodly_val: in std_logic_vector(4 downto 0); --delay value for
iodelay
bit_slip: in std_logic; --rising edge
triggers bit slip in iserdes
iodlyin: in std_logic; --input to iodelaye1
from LVDS
oserdes_out: out std_logic; --output of oserdes,
to LVDS driver
iserdes_outp: out std_logic_vector(7 downto 0); --parallel output of
iserdes, to top level
iserdes_outc: out std_logic; --combinatorial
output of iserdes, from iodelaye1
serdes_tp: out std_logic_vector(7 downto 0) --test points
);
end serdes_tst;
architecture arch of serdes_tst is
signal mcmm_rdy_sig: std_logic := '0';
signal clk_hs_mmcm: std_logic := '0'; --mmcm high speed clock
signal clk_hsB_mmcm: std_logic := '1'; --mmcm high speed clock
BAR
signal clk_ls_mmcm: std_logic := '0'; --mmcm low speed clock
(not used)
signal clkfbout: std_logic := '0'; --from clock feedback
output port of immcm
signal clk_hs_serdes: std_logic := '0'; --buffered mmcm high
speed clock
signal clk_hsB_serdes: std_logic := '0'; --buffered mmcm high
speed clock
signal clk_ls_serdes: std_logic := '0'; --buffered low low speed
clock (not used)
signal oserdes_out_sig: std_logic; --data output of oserdes
signal iserdes_out_sig: std_logic; --combinatorial data
output of iserdes
signal mmcm_div_sig: std_logic_vector(3 downto 0) := "0000";
--counter to divide down high spped clock for monitoring
signal OQ: std_logic := '0'; --oserdes serial output
signal TFB: std_logic := '0'; --3-st control to
ioserdes, not really used
signal TQ: std_logic := '0'; --3-st control to IOB,
not really used
signal iserdes_Q: std_logic_vector(6 downto 1) := "000000";
--parallel output of iserdes
signal serdes_OFB: std_logic := '0'; --used for loopback, oserdes
to iserdes
signal bit_slip_Z1_sig: std_logic := '0'; --used to trigger bit slip
signal bit_slip_Z2_sig: std_logic := '0'; --used to trigger bit slip
signal bit_slip_cmd_sig: std_logic := '0'; --used to command bit slip
signal iodly_out_sig : std_logic := '0'; --iodelay output
signal iserdes_in_sig : std_logic := '0'; --iodelay output
signal td_out_sig: std_logic_vector(7 downto 0) := "00000000";
--parallel output of iserdes
signal serdes_reset_sig: std_logic := '0'; --serdes reset signal
signal serdes_rst_tp_sig: std_logic_vector(7 downto 0) := "00000000";
--to give test points a place to connect
signal mmcm_reset_sig : std_logic := '0';
signal mmcm_rst_tp_sig : std_logic_vector(7 downto 0) := "00000000";
--to give test points a place to connect
component mmcm_rst
port(
c125: in std_logic; --125 MHz system
clock
mmcm_reset: out std_logic; --data out to serdes
mmcm_rst_tp: out std_logic_vector(7 downto 0) --test points
);
end component mmcm_rst;
component serdes_rst
port(
c125: in std_logic; --125 MHz system clock
clkdiv: in std_logic; --lower speed serdes clock from mmcm
mmcm_rdy: in std_logic; --mcm rdy signal
mmcm_rst: in std_logic; --mmcm reset signal
serdes_reset: out std_logic; --data out to serdes
serdes_rst_tp:out std_logic_vector(7 downto 0) --test points
);
end component serdes_rst;
begin
--signal connections
serdes_tp(0) <= iserdes_out_sig;
serdes_tp(1) <= serdes_rst_tp_sig(0);
serdes_tp(2) <= mmcm_div_sig(3);
serdes_tp(3) <= '0';
oserdes_out <= oserdes_out_sig; --serial data out of oserdes
iserdes_outp <= td_out_sig; --parallel data out of iserdes
iserdes_outc <= '0'; --combinatorial (serial)data out of iserdes
iserdes_in_sig <= iodly_out_sig;
--do a bit slip in response to a command from the microprocessor
bit_slip_proc: process(clk_ls_serdes) is
begin
if rising_edge(clk_ls_serdes) then
bit_slip_Z1_sig <= bit_slip; --to avoid short pulses and
metastable behavior
bit_slip_Z2_sig <= bit_slip_Z1_sig;
if (bit_slip_Z1_sig = '1') AND (bit_slip_Z2_sig = '0') then
bit_slip_cmd_sig <= '1';
else
bit_slip_cmd_sig <= '0';
end if;
end if;
end process bit_slip_proc;
--mmcm test counter counter: to test high freq output of mmcm
mmcm_counter: process(clk_hs_serdes) is
begin
if rising_edge(clk_hs_serdes) then
mmcm_div_sig <= mmcm_div_sig + 1;
end if;
end process mmcm_counter;
------------------mmcm_rst instantiation:
--------------------------------------------------------
-----------holds mmcm reset for about 1 second to assure system stability
mmcm_rst0 : mmcm_rst
port map (
c125 => c125, --system 125 MHz clock
mmcm_reset => mmcm_reset_sig, --serdes reset signal
mmcm_rst_tp => mmcm_rst_tp_sig --test points
);
------------------serdes_rst instantiation:
--------------------------------------------------------
-----------produces a reset pulse for serdes about 2 msec after mmcm is
ready-------------
serdes_rst0 : serdes_rst
port map (
c125 => c125, --system 125 MHz clock
clkdiv => clk_ls_serdes, --serdes low speed clock
mmcm_rdy => mcmm_rdy_sig, --ready from mmcm
mmcm_rst => mmcm_reset_sig, --mmcm reset signal
serdes_reset => serdes_reset_sig, --serdes reset signal
serdes_rst_tp => serdes_rst_tp_sig --test points
);
--------------------clock
buffers------------------------------------------------------------------
serdes_mmcm_BUFG_inst_0 : BUFG
port map (
O => clk_hs_serdes, -- 1-bit output: buffered high speed clock from
serdes
I => clk_hs_mmcm -- 1-bit input: high speed clock from serdes
);
serdes_mmcm_BUFG_inst_1 : BUFG
port map (
O => clk_hsB_serdes, -- 1-bit output: buffered high speed clock from
serdes
I => clk_hsB_mmcm -- 1-bit input: high speed clock from serdes
);
serdes_BUFG_inst_2 : BUFG
port map (
O => clk_ls_serdes, -- 1-bit output: buffered low speed clock from
serdes
I => clk_ls_mmcm -- 1-bit input: low speed clock from serdes
);
-------------- MMCM_BASE: Base Mixed Mode Clock
Manager-------------------------------
-- Virtex-6
-- Xilinx HDL Libraries Guide, version 13.1
MMCM_serdes : MMCM_BASE
generic map (
BANDWIDTH => "OPTIMIZED", -- Jitter programming
("HIGH","LOW","OPTIMIZED")
CLKFBOUT_MULT_F => 6.0, -- Multiply value for all CLKOUT (5.0-64.0).
(750 to 125 MHz) 750 MHz
CLKFBOUT_PHASE => 0.0, -- Phase offset in degrees of CLKFB
(0.00-360.00).
CLKIN1_PERIOD => 8.0, -- Input clock period in ns to ps resolution
(i.e. 33.333 is 30 MHz).
CLKOUT0_DIVIDE_F => 4.0, -- Divide amount for CLKOUT0 750/4 = 187.5 MHz
-- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT
(0.01-0.99).
CLKOUT0_DUTY_CYCLE => 0.5,
CLKOUT1_DUTY_CYCLE => 0.5,
CLKOUT2_DUTY_CYCLE => 0.5,
CLKOUT3_DUTY_CYCLE => 0.5,
CLKOUT4_DUTY_CYCLE => 0.5,
CLKOUT5_DUTY_CYCLE => 0.5,
CLKOUT6_DUTY_CYCLE => 0.5,
-- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT
(-360.000-360.000).
CLKOUT0_PHASE => 0.0,
CLKOUT1_PHASE => 0.0,
CLKOUT2_PHASE => 0.0,
CLKOUT3_PHASE => 0.0,
CLKOUT4_PHASE => 0.0,
CLKOUT5_PHASE => 0.0,
CLKOUT6_PHASE => 0.0,
-- CLKOUT1_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT
(1-128)
CLKOUT1_DIVIDE => 12, --750/12 = 62.5 MHz
CLKOUT2_DIVIDE => 1,
CLKOUT3_DIVIDE => 1,
CLKOUT4_DIVIDE => 1,
CLKOUT5_DIVIDE => 1,
CLKOUT6_DIVIDE => 1,
CLKOUT4_CASCADE => FALSE, -- Cascase CLKOUT4 counter with CLKOUT6
(TRUE/FALSE)
CLOCK_HOLD => FALSE, -- Hold VCO Frequency (TRUE/FALSE)
DIVCLK_DIVIDE => 1, -- Master division value (1-80)
REF_JITTER1 => 0.05, -- Reference input jitter in UI (0.000-0.999).
STARTUP_WAIT => FALSE -- Not supported. Must be set to FALSE.
)
port map (
-- Clock Outputs: 1-bit (each) output: User configurable clock outputs
CLKOUT0 => clk_hs_mmcm, -- 1-bit output: CLKOUT0 output
CLKOUT0B => clk_hsB_mmcm,-- 1-bit output: Inverted CLKOUT0 output
CLKOUT1 => clk_ls_mmcm, -- 1-bit output: CLKOUT1 output (not used)
CLKOUT1B => open, -- 1-bit output: Inverted CLKOUT1 output
CLKOUT2 => open, -- 1-bit output: CLKOUT2 output
CLKOUT2B => open, -- 1-bit output: Inverted CLKOUT2 output
CLKOUT3 => open, -- 1-bit output: CLKOUT3 output
CLKOUT3B => open, -- 1-bit output: Inverted CLKOUT3 output
CLKOUT4 => open, -- 1-bit output: CLKOUT4 output
CLKOUT5 => open, -- 1-bit output: CLKOUT5 output
CLKOUT6 => open, -- 1-bit output: CLKOUT6 output
-- Feedback Clocks: 1-bit (each) output: Clock feedback ports
CLKFBOUT => clkfbout, -- 1-bit output: Feedback clock output
CLKFBOUTB => open, -- 1-bit output: Inverted CLKFBOUT output
-- Status Port: 1-bit (each) output: MMCM status ports
LOCKED => mcmm_rdy_sig, -- 1-bit output: LOCK output
-- Clock Input: 1-bit (each) input: Clock input
CLKIN1 => C125,
--
-- Control Ports: 1-bit (each) input: MMCM control ports
PWRDWN => '0', -- 1-bit input: Power-down input
RST => '0', -- 1-bit input: Reset input
-- Feedback Clocks: 1-bit (each) input: Clock feedback ports
CLKFBIN => clkfbout -- 1-bit input: Feedback clock input
);
-- End of MMCM_serdes instantiation
----------------- OSERDESE1: Output
SERial/DESerializer----------------------------------
-- Virtex-6
-- Xilinx HDL Libraries Guide, version 13.1
OSERDESE1_inst : OSERDESE1
generic map (
DATA_RATE_OQ => "DDR", -- "SDR" or "DDR"
DATA_RATE_TQ => "SDR", -- "BUF", "SDR" or "DDR"
DATA_WIDTH => 6, -- Parallel data width (1-8,10)
DDR3_DATA => 1, -- Must leave at 1 (MIG-only parameter)
INIT_OQ => '0', -- Initial value of OQ output (0/1)
INIT_TQ => '0', -- Initial value of TQ output (0/1)
INTERFACE_TYPE => "DEFAULT", -- Must leave at "DEFAULT" (MIG-only
parameter)
ODELAY_USED => 0, -- Must leave at 0 (MIG-only parameter)
SERDES_MODE => "MASTER", -- "MASTER" or "SLAVE"
SRVAL_OQ => '0', -- OQ output value when SR is used (0/1)
SRVAL_TQ => '0', -- TQ output value when SR is used (0/1)
TRISTATE_WIDTH => 1 -- Parallel to serial 3-state converter
width (1 or 4)
)
port map (
-- MIG-only Signals: 1-bit (each) output: Do not use unless generated
by MIG
OCBEXTEND => open, -- 1-bit output: Leave unconnected (MIG-only
connected signal)
-- Outputs: 1-bit (each) output: Serial output ports
OFB => serdes_OFB, -- 1-bit output: Data feedback output
to ISERDESE1
OQ => oserdes_out_sig, -- 1-bit output: Data output (connect
to I/O port)
TFB => TFB, -- 1-bit output: 3-state control output
TQ => TQ, -- 1-bit output: 3-state path output
-- SHIFTOUT1-SHIFTOUT2: 1-bit (each) output: Data width expansion
output ports
SHIFTOUT1 => open, -- 1-bit output: Connect to SHIFTIN1 of slave
or unconnected
SHIFTOUT2 => open, -- 1-bit output: Connect to SHIFTIN2 of slave
or unconnected
-- Clocks: 1-bit (each) input: OSERDESE1 clock input ports
CLK => clk_hs_serdes, -- 1-bit input: High-speed clock
input,from mmcm via bufg
CLKDIV => clk_ls_serdes, -- 1-bit input: Divided clock input,
from mmcm via bufg
-- Control Signals: 1-bit (each) input: Clock enable and reset input
ports
OCE => '1', -- 1-bit input: Active high clock data path enable
input
RST => serdes_reset_sig, -- 1-bit input: Active high reset
input
TCE => '1', -- 1-bit input: Active high clock
enable input for 3-state
-- D1 - D6: 1-bit (each) input: Parallel data inputs
D1 => td_in(0),
D2 => td_in(1),
D3 => td_in(2),
D4 => td_in(3),
D5 => td_in(4),
D6 => td_in(5),
-- MIG-only Signals: 1-bit (each) input: Do not use unless generated by
MIG
CLKPERF => '0', -- 1-bit input: Ground input (MIG-only
connected signal)
CLKPERFDELAY => '0', -- 1-bit input: Ground input (MIG-only connected
signal)
ODV => '0', -- 1-bit input: Ground input (MIG-only
connected signal)
WC => '0', -- 1-bit input: Ground input (MIG-only
connected signal)
-- SHIFTIN1-SHIFTIN2: 1-bit (each) input: Data width expansion input
ports
SHIFTIN1 => '0', -- 1-bit input: Connect to SHIFTOUT1 of
master or GND
SHIFTIN2 => '0', -- 1-bit input: Connect to SHIFTOUT2 of
master or GND
-- T1 - T4: 1-bit (each) input: Parallel 3-state inputs
T1 => '0',
T2 => '0',
T3 => '0',
T4 => '0'
);
---- End of OSERDESE1_inst instantiation
--------------------- ISERDESE1: Input
SERial/DESerializer---------------------------
---- Virtex-6
---- Xilinx HDL Libraries Guide, version 13.1
ISERDESE1_inst : ISERDESE1
generic map (
DATA_RATE => "DDR", -- "SDR" or "DDR"
DATA_WIDTH => 6, -- Parallel data width (2-8, 10)
DYN_CLKDIV_INV_EN => FALSE, -- Enable DYNCLKDIVINVSEL inversion
(TRUE/FALSE)
DYN_CLK_INV_EN => FALSE, -- Enable DYNCLKINVSEL inversion
(TRUE/FALSE)
-- INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
INIT_Q1 => '1',
INIT_Q2 => '0',
INIT_Q3 => '1',
INIT_Q4 => '0',
INTERFACE_TYPE => "NETWORKING", -- "MEMORY", "MEMORY_DDR3",
"MEMORY_QDR", "NETWORKING", or "OVERSAMPLE"
IOBDELAY => "BOTH", -- "NONE", "IBUF", "IFD", "BOTH"
NUM_CE => 1, -- Number of clock enables (1 or 2)
OFB_USED => TRUE, -- Select OFB path (TRUE/FALSE)
SERDES_MODE => "MASTER", -- "MASTER" or "SLAVE"
-- SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
SRVAL_Q1 => '0',
SRVAL_Q2 => '0',
SRVAL_Q3 => '0',
SRVAL_Q4 => '0'
)
port map (
O => iserdes_out_sig, -- 1-bit output: Combinatorial
output
-- Q1 - Q6: 1-bit (each) output: Registered data outputs
-- flip these over to make the data "right reading"
Q1 => td_out_sig(5),
Q2 => td_out_sig(4),
Q3 => td_out_sig(3),
Q4 => td_out_sig(2),
Q5 => td_out_sig(1),
Q6 => td_out_sig(0),
-- SHIFTOUT1-SHIFTOUT2: 1-bit (each) output: Data width expansion
output ports
SHIFTOUT1 => open,
SHIFTOUT2 => open,
BITSLIP => bit_slip_cmd_sig, -- 1-bit input: Bitslip enable
input
-- CE1, CE2: 1-bit (each) input: Data register clock enable inputs
CE1 => '1',
CE2 => '1',
-- Clocks: 1-bit (each) input: ISERDESE1 clock input ports
CLK => clk_hs_serdes, -- 1-bit input: High-speed clock
input
CLKB => clk_hsB_serdes, -- 1-bit input: High-speed
secondary clock input
CLKDIV => clk_ls_serdes, -- 1-bit input: Low-speed clock
input
OCLK => '0', -- 1-bit input: High speed output clock
input used when INTERFACE_TYPE="MEMORY"
-- Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock
inversion pins to switch clock polarity
DYNCLKDIVSEL => '0', -- 1-bit input: Dynamic CLKDIV inversion
input, memory applications only
DYNCLKSEL => '0', -- 1-bit input: Dynamic CLK/CLKB inversion
input, memory applications only
-- Input Data: 1-bit (each) input: ISERDESE1 data input ports
D => '0', -- 1-bit input: Data input
DDLY => '0', -- 1-bit input: Serial input data from
IODELAYE1
OFB => serdes_OFB, -- 1-bit input: Data feedback input
from OSERDESE1
RST => serdes_reset_sig, -- 1-bit input: Active high
asynchronous reset input
-- SHIFTIN1-SHIFTIN2: 1-bit (each) input: Data width expansion input
ports
SHIFTIN1 => '0',
SHIFTIN2 => '0'
);
-- End of ISERDESE1_inst instantiation
------------------- IODELAYE1: programmable delay---------------------------
--comment this entity out to test simpler link using the "OFB" path from
oserdes to iserdes
--IODELAYE1_serdes : IODELAYE1
-- generic map (
-- CINVCTRL_SEL => FALSE, -- Dynamically inverts the
Clock (C) polarity.
-- DELAY_SRC => "I", -- Specifies the source to
the IODELAY component. "I" means it will be
-- -- connected directly to an
input port or IBUF (input mode), "O" means
-- -- it will be connected to an
output port or OBUF (output mode), "IO"
-- -- means it will be connected
to a port, and "DATAIN" means it will not
-- -- be connected to any port
(internal mode).
-- HIGH_PERFORMANCE_MODE => TRUE, -- When TRUE, this attribute
reduces the output jitter.
-- IDELAY_TYPE => "VAR_LOADABLE", -- Specifies a fixed,
variable or default (eliminate hold time) input
-- -- delay.
-- IDELAY_VALUE => 0, -- Specifies the number of
taps of delay for the input path when in
-- -- fixed mode or the initial
delay tap value for variable mode.
-- ODELAY_TYPE => "FIXED",
-- ODELAY_VALUE => 0, -- Specifies the number of
taps of delay for the output path.
-- REFCLK_FREQUENCY => 200.0, -- When using an associated
IDELAYCTRL, specifies the input reference
-- -- frequency to the component.
-- SIGNAL_PATTERN => "DATA" -- Used by the delay
calculator to determine different propagation
-- -- delays through the IODELAY
block based on the setting. DATA will be
-- -- the addition of per tap
delay and per tap jitter. No jitter is
-- -- introduced for clock-like
signals.
-- )
-- port map (
-- CNTVALUEOUT => open, -- 5-bit Counter value going
to fabric for monitoring purpose
-- DATAOUT => iodly_out_sig, -- 1-bit Delayed data
output from idatain to entity output
-- C => clk_ls_serdes, -- 1-bit Clock input (Must
be connected for variable mode)
-- CE => '0', -- 1-bit Active high enable
increment/decrement function
-- CINVCTRL => '0', -- 1-bit Dynamically inverts
the Clock (C) polarity
-- CLKIN => '0', -- 1-bit Clock Access into
the IODELAY (from the IO CLKMUX)
-- CNTVALUEIN => iodly_val, -- 5-bit Counter value from
fabric for loadable counter application
-- DATAIN => '0', -- 1-bit Data input for the
internal datapath delay. When DATAIN is used,
-- -- IDATAIN and ODATAIN must
be tied to a logic zero (ground).
-- IDATAIN => iodlyin, -- 1-bit Data input from LVDS
data receiver for sum_data(1)
-- -- Buffer). When IDATAIN is
used, DATAIN must be tied to a logic zero
-- -- (ground).
-- INC => '0', -- 1-bit Increment /
Decrement tap delay
-- ODATAIN => '0', -- 1-bit Data input for the
output datapath from the device (connect to
-- -- output data source). When
ODATAIN is used, DATAIN must be tied to a logic
-- -- zero (ground).
-- RST => '1', -- 1-bit Active high,
synchronous reset, resets delay chain to IDELAY_VALUE/
-- -- ODELAY_VALUE tap. If no
value is specified, the default is 0.
-- T => '1' -- 1-bit 3-state input
control. Tie high for input-only or internal delay or
-- -- tie low for output only.
-- );
-- End of IODELAYE1 instantiation
end arch;