Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21462 Discussions

CycloneIV-E external ADC parallel interface timings

eugenio1
Beginner
2,239 Views

Hi all.

 

I'm interfacing a CycloneIV-E to a AD9266 ADC and I'm struggling trying to close timings.

FPGA design has one 100MHz pll clock; the adc is clocked with a divide-by-two register (=50MHz); data from adc is 8bit wide, double data rate: it outputs even bits at one 100MHz clock cycle, and odd bits at the next 100MHz clock cycle.

eugenio1_1-1707993271574.png

This is the rtl view that generates the 50MHz clock (adc_clk) and latches the data (data[7:0]) to two registers with odd and even data. To avoid muxes (is this a wise choice?) the two latch registers are filled with odd and even bits at the odd and even positions and then or-ed together:

eugenio1_0-1707993060770.png

These are the .sdc constraints:

# Clock definition

create_generated_clock -name {ad9266_clk_reg} -source [get_pins {bk39_common_inst|pll_inst|altpll_component|auto_generated|pll1|clk[0]}] -divide_by 2 [get_registers {rf_in:rf_in_inst|ad9266:adc_inst|adc_clk_reg}]
create_generated_clock -name {ad9266_clk} -source [get_registers {rf_in:rf_in_inst|ad9266:adc_inst|adc_clk_reg}] [get_ports {rf_in_adc_clk}]

 

#delays (from datasheets and pcb design)

set ad9266_dco_tpd_rising_clk_max 4.04
set ad9266_dco_tpd_rising_clk_min 1.86
set ad9266_data_tpd_rising_clk_max 3.9
set ad9266_data_tpd_rising_clk_min 1.84
set ad9266_clk_tpd_delay_max 1.5
set ad9266_clk_tpd_delay_min 0.5
set ad9266_clk_trace_delay_max 0.15
set ad9266_clk_trace_delay_min 0.05
set ad9266_data_trace_delay_max 0.15
set ad9266_data_trace_delay_min 0.05
set ad9266_dco_delay_max [expr $ad9266_data_trace_delay_max + $ad9266_dco_tpd_rising_clk_max - $ad9266_clk_trace_delay_min - $ad9266_clk_tpd_delay_min]
set ad9266_dco_delay_min [expr $ad9266_data_trace_delay_min - $ad9266_dco_tpd_rising_clk_min - $ad9266_clk_trace_delay_max - $ad9266_clk_tpd_delay_max]
set ad9266_data_delay_max [expr $ad9266_data_trace_delay_max + $ad9266_data_tpd_rising_clk_max - $ad9266_clk_trace_delay_min - $ad9266_clk_tpd_delay_min]
set ad9266_data_delay_min [expr $ad9266_data_trace_delay_min - $ad9266_data_tpd_rising_clk_min - $ad9266_clk_trace_delay_max - $ad9266_clk_tpd_delay_max]

#input delay constraints (ddr)

set_input_delay -clock { ad9266_clk } -max $ad9266_dco_delay_max [get_ports {rf_in_adc_dco}]
set_input_delay -clock { ad9266_clk } -min $ad9266_dco_delay_min [get_ports {rf_in_adc_dco}]
set_input_delay -clock { ad9266_clk } -clock_fall -max $ad9266_dco_delay_max [get_ports {rf_in_adc_dco}] -add_delay
set_input_delay -clock { ad9266_clk } -clock_fall -min $ad9266_dco_delay_min [get_ports {rf_in_adc_dco}] -add_delay
set_input_delay -clock { ad9266_clk } -max $ad9266_data_delay_max [get_ports {rf_in_adc_data[*]}]
set_input_delay -clock { ad9266_clk } -min $ad9266_data_delay_min [get_ports {rf_in_adc_data[*]}]
set_input_delay -clock { ad9266_clk } -clock_fall -max $ad9266_data_delay_max [get_ports {rf_in_adc_data[*]}] -add_delay
set_input_delay -clock { ad9266_clk } -clock_fall -min $ad9266_data_delay_min [get_ports {rf_in_adc_data[*]}] -add_delay

 

Timequest reports all paths failing setup, with ~3.5ns of negative slack:

00_no_pipeline_no_fastio.png

 

Tried "Fast input" and "Fast output" assignments:

set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "rf_in:rf_in_inst|ad9266:adc_inst|adc_clk_reg"
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to "rf_in:rf_in_inst|ad9266:adc_inst|adc_clk_reg"
set_instance_assignment -name FAST_INPUT_REGISTER ON -to "rf_in:rf_in_inst|ad9266:adc_inst|dco_adc_data_odd"
set_instance_assignment -name FAST_INPUT_REGISTER ON -to "rf_in:rf_in_inst|ad9266:adc_inst|dco_adc_data_even"

But no big improvement:

01_no_pipeline_fastio.png  

I've tried to insert a pipeline for data(in) and clock(out):

eugenio1_0-1708000956719.png

Updated .sdc constraints:

create_generated_clock -name {ad9266_clk_reg} -source [get_pins {bk39_common_inst|pll_inst|altpll_component|auto_generated|pll1|clk[0]}] -divide_by 2 [get_registers {rf_in:rf_in_inst|ad9266:adc_inst|adc_clk_pipeline}]
create_generated_clock -name {ad9266_clk} -source [get_registers {rf_in:rf_in_inst|ad9266:adc_inst|adc_clk_pipeline}] [get_ports {rf_in_adc_clk}]

Updated fast i/o assignments:

set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "rf_in:rf_in_inst|ad9266:adc_inst|adc_clk_pipeline"
set_instance_assignment -name FAST_INPUT_REGISTER ON -to "rf_in:rf_in_inst|ad9266:adc_inst|adc_pipeline"

 

Bit of improvement, but still not a game changer:

02_pipeline_fastio.png

 

Timequest is measuring a beefy delay from I/O pin and the first register:

11.529 3.284 data path
8.245 0.000 FF IC 1 IOIBUF_X0_Y11_N8 rf_in_adc_dco~input|i
9.087 0.842 FF CELL 1 IOIBUF_X0_Y11_N8 rf_in_adc_dco~input|o
11.281 2.194 FF IC 1 FF_X0_Y11_N10 rf_in_inst|adc_inst|adc_pipeline[8]|d
11.529 0.248 FF CELL 1 FF_X0_Y11_N10 rf_in:rf_in_inst|ad9266:adc_inst|adc_pipeline[8]

The contribution of .sdc delay is 3.64ns, about a third of the net delay from IOIBUF_X0_Y11_N8  to FF_X0_Y11_N10.

pipeline register are placed close to I/O, so I quite don't get where this delay is coming from: 

eugenio1_2-1708001703558.png

pipeline register is then routed to the actual data register, with a "long" path shown in chip planner:

eugenio1_3-1708001882565.png

Albeit long in chip planner, the delay is quite short: 

report_path -from rf_in:rf_in_inst|ad9266:adc_inst|adc_pipeline[8] -npaths 100 -panel_name {Report Path} -multi_corner
Report Path: Found 16 paths. Longest delay is 2.956

 

I'm having really a bad times trying to make sense from this data.

Am I missing something? Hints for timings closure?

 

Thank you!!!

Labels (1)
0 Kudos
5 Replies
RichardTanSY_Altera
2,121 Views

I noticed that the clock skew and data delay are quite large in the failing timing.

Also, why is most of the logic placed in the center in the Chip Planner? It seems congested.

Could there be a location assignment set that might cause this?

If so, try disabling it, as this might limit the fitter's capability to place and route the design in order to meet timing.


Regards,

Richard Tan


0 Kudos
eugenio1
Beginner
2,064 Views

All ports location are pcb driven, no chance to modify them.

Other than these, I didn't find other relevant assignments that could upset the fitter:

set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name SIMULATION_MODE FUNCTIONAL
set_global_assignment -name POWER_USE_TA_VALUE 50
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC OFF
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED
set_global_assignment -name TIMING_ANALYZER_DO_REPORT_TIMING ON
set_global_assignment -name TIMING_ANALYZER_DO_CCPP_REMOVAL OFF
set_global_assignment -name SYNCHRONIZER_IDENTIFICATION "FORCED IF ASYNCHRONOUS"
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON
set_global_assignment -name ROUTER_TIMING_OPTIMIZATION_LEVEL NORMAL
set_global_assignment -name QII_AUTO_PACKED_REGISTERS AUTO
set_global_assignment -name FITTER_EFFORT "AUTO FIT"
set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS OFF
set_global_assignment -name FLOW_ENABLE_RTL_VIEWER ON
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL
set_global_assignment -name TIMING_ANALYZER_REPORT_SCRIPT_INCLUDE_DEFAULT_ANALYSIS OFF
set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON
set_global_assignment -name POST_FLOW_SCRIPT_FILE "quartus_sh:post_build.tcl"
set_global_assignment -name OPTIMIZATION_MODE BALANCED
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON
set_global_assignment -name OPTIMIZE_POWER_DURING_SYNTHESIS "NORMAL COMPILATION"
set_global_assignment -name HDL_MESSAGE_LEVEL LEVEL3
set_global_assignment -name FITTER_AGGRESSIVE_ROUTABILITY_OPTIMIZATION AUTOMATICALLY
set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS ON
set_global_assignment -name MUX_RESTRUCTURE OFF
set_global_assignment -name STATE_MACHINE_PROCESSING AUTO
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER 1
set_global_assignment -name ENABLE_OCT_DONE OFF
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name SAFE_STATE_MACHINE ON
set_global_assignment -name SYNTH_PROTECT_SDC_CONSTRAINT ON
set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION OFF
set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON
set_global_assignment -name ALLOW_ANY_ROM_SIZE_FOR_RECOGNITION ON
set_global_assignment -name ALLOW_ANY_RAM_SIZE_FOR_RECOGNITION ON
set_global_assignment -name ALLOW_ANY_SHIFT_REGISTER_SIZE_FOR_RECOGNITION ON
set_global_assignment -name ALLOW_SHIFT_REGISTER_MERGING_ACROSS_HIERARCHIES ALWAYS
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA OFF
set_global_assignment -name PHYSICAL_SYNTHESIS_MAP_LOGIC_TO_MEMORY_FOR_AREA ON
set_global_assignment -name AUTO_RAM_RECOGNITION OFF
set_global_assignment -name OPTIMIZE_TIMING "NORMAL COMPILATION"
set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION NEVER

 I've relaxed the fitter effort and this result in ~100ps of slack improvement, not a big deal yet.

Chip planner still shows this scenario; the blocks in red contain the adc interface logic with failing paths:

eugenio1_0-1709294323735.png

 

The first of failing paths looks like this in technology map viewer:

eugenio1_1-1709294578110.png

Going down the rabbit hole in property editor I can see "Input pin to Input Register Delay" set to 5:

eugenio1_2-1709294665435.png

Does this ring a bell? The value is the same for all the failing paths, both for rising and falling clock edges (adc behaves like-ish a ddr device, odd bits can be lathed during rising edge of adc clk, even can be lathed during falling edge).

 

In assignment editor I specified that adc_clk should be a fast output register and adc_data a fast input register:

eugenio1_3-1709295153406.png

This result in actual DDIOOUTCELL usage for clock out, but a regular register for input:

eugenio1_4-1709295329715.png

No ignored assignment message in compilation report, but fitter decided not to accept the suggestion and use a regular register.

Could this be the issue?

 

 

This is how I (tried to) constrain the input timings, bearing the ddr-ish behavior:

#input delay constraints (ddr)

set_input_delay -clock { ad9266_clk } -max $ad9266_dco_delay_max [get_ports {rf_in_adc_dco}]
set_input_delay -clock { ad9266_clk } -min $ad9266_dco_delay_min [get_ports {rf_in_adc_dco}]
set_input_delay -clock { ad9266_clk } -clock_fall -max $ad9266_dco_delay_max [get_ports {rf_in_adc_dco}] -add_delay
set_input_delay -clock { ad9266_clk } -clock_fall -min $ad9266_dco_delay_min [get_ports {rf_in_adc_dco}] -add_delay
set_input_delay -clock { ad9266_clk } -max $ad9266_data_delay_max [get_ports {rf_in_adc_data[*]}]
set_input_delay -clock { ad9266_clk } -min $ad9266_data_delay_min [get_ports {rf_in_adc_data[*]}]
set_input_delay -clock { ad9266_clk } -clock_fall -max $ad9266_data_delay_max [get_ports {rf_in_adc_data[*]}] -add_delay
set_input_delay -clock { ad9266_clk } -clock_fall -min $ad9266_data_delay_min [get_ports {rf_in_adc_data[*]}] -add_delay

 

Is something wrong?

 

0 Kudos
SyafieqS
Employee
2,099 Views

Let me know if there is any update from previous reply.


0 Kudos
eugenio1
Beginner
2,001 Views

I've responded with more details and with the results of the suggested modifications, asking for further suggestions.

 

 

0 Kudos
SyafieqS
Employee
1,902 Views

From the timing report, seem this issue probably related to CDC. Have you tried to constraint the CDC between the 2 different clocks?

This might be the reason why you are having a large skew. Multicycle path or synchronizer is the way to handle this.


0 Kudos
Reply