Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16556 Discussions

Signal Tap example from Intel training course always fails timing

hcom
New Contributor II
640 Views

I was told to re-post this question because it didn't get resolved after 2 months:

I am using Quartus Prime 21.1.0 Build 169 03/24/2021 SC Pro Edition to target a Cyclone 10 GX (10CX085) FPGA.

I followed this Intel training course to set up Signal Tap:

https://learning.intel.com/developer/learn/course/203

I followed Section 6.2 to create JTAG timing constraints using Quartus's SDC template (pasted below). However, this seems to always fail timing, no matter what else is in my design:

 

# Search "---customize here---" for the few decisions you need to make 
#
# By default, the most challenging timing spec is applied to work in 
# many JTAG chain setup situations

set_time_format -unit ns -decimal_places 3

# This is the main entry point called at the end of this SDC file.
proc set_jtag_timing_constraints { } {

    set num_tck_port [get_collection_size [get_ports -nowarn {altera_reserved_tck}]]
    
    if { $num_tck_port > 0 } {
        # Define a set of timing constraints that describe the JTAG paths 
        # to analyze. TimeQuest timing reports show whether the JTAG logic 
        # in the FPGA core will operate with this setup.
        set_jtag_timing_spec
        
        set_s10_false_path_constraint
    }
}

proc set_s10_false_path_constraint { } {
    if {$::TimeQuestInfo(family) == "Stratix 10"} {
        set_false_path -from "*|atom_inst|atom~soc_sdm/padsig_io1.reg"
        set_false_path -from "*|atom_inst|atom~soc_sdm/padsig_io1.reg__nff"
    }
}

proc set_jtag_timing_spec { } {
    derive_clock_uncertainty

    # There are few possible JTAG chain configurations:
    # a. This device is the only device in the JTAG chain
    # b. This device is the first one in the JTAG chain
    # c. This device is in the middle of the JTAG chain
    # d. This device is the last one in the JTAG chain
    
    # No matter where the device is in the chain. The tck and tms are driven
    # directly from JTAG hardware.
    set_tck_timing_spec
    set_tms_timing_spec

    # Depending on where the device is located along the chain, tdi can be 
    # either driven by blaster hw (a. b.) or driven by another device in the 
    # chain(c. d.)
    # ---customize here---
    set tdi_is_driven_by_blaster 1
    
    if { $tdi_is_driven_by_blaster } {
        set_tdi_timing_spec_when_driven_by_blaster
    } else {
        set_tdi_timing_spec_when_driven_by_device
    }
    
    # Depending on where the device is located along the chain, tdo can  
    # drive either blaster hw (a. d.) or another device in the chain (b. c.)
    # ---customize here---
    set tdo_drive_blaster 1
    
    if { $tdo_drive_blaster } {
        set_tdo_timing_spec_when_drive_blaster
    } else {
        set_tdo_timing_spec_when_drive_device
    }
    
    set_optional_ntrst_timing_spec
    
    # Cut a few timing paths that are not related to JTAG logic in 
    # the FPGA core, such as security mode.
    set_false_path -from [get_ports {altera_reserved_tdi}] -to [get_ports {altera_reserved_tdo}]
    if { [get_collection_size [get_registers -nowarn *~jtag_reg]] > 0 } {
        set_false_path -from [get_registers *~jtag_reg] -to [get_ports {altera_reserved_tdo}]
    }
    
}

proc set_tck_timing_spec { } {
    # USB Blaster 1 uses 6 MHz clock = 166.666 ns period
    set ub1_t_period 166.666
    # USB Blaster 2 uses 24 MHz clock = 41.666 ns period
    set ub2_default_t_period 41.666
    # USB Blaster 2 running at 16 MHz clock safe mode = 62.5 ns period
    set ub2_safe_t_period 62.5

    # ---customize here---
    set tck_t_period $ub2_default_t_period
    
    create_clock -name {altera_reserved_tck} -period $tck_t_period  [get_ports {altera_reserved_tck}]
    set_clock_groups -asynchronous -group {altera_reserved_tck}
}

proc get_tck_delay_max { } {
    set tck_blaster_tco_max 14.603
    set tck_cable_max 11.627
    
    # tck delay on the PCB depends on the trace length from JTAG 10-pin 
    # header to FPGA on board. In general on the PCB, the signal travels 
    # at the speed of ~160 ps/inch (1000 mils = 1 inch).
    # ---customize here---
    set tck_header_trace_max 0.5

    return [expr $tck_blaster_tco_max + $tck_cable_max + $tck_header_trace_max]
}

proc get_tck_delay_min { } {
    set tck_blaster_tco_min 14.603
    set tck_cable_min 10.00
    
    # tck delay on the PCB depends on the trace length from JTAG 10-pin 
    # header to FPGA on board. In general on the PCB, the signal travels 
    # at the speed of ~160 ps/inch (1000 mils = 1 inch).
    # ---customize here---
    set tck_header_trace_min 0.1

    return [expr $tck_blaster_tco_min + $tck_cable_min + $tck_header_trace_min]
}

proc set_tms_timing_spec { } {
    set tms_blaster_tco_max 9.468
    set tms_blaster_tco_min 9.468

    set tms_cable_max 11.627
    set tms_cable_min 10.0
    
    # tms delay on the PCB depends on the trace length from JTAG 10-pin 
    # header to FPGA on board. In general on the PCB, the signal travels 
    # at the speed of ~160 ps/inch (1000 mils = 1 inch).
    # ---customize here---
    set tms_header_trace_max 0.5
    set tms_header_trace_min 0.1
    
    set tms_in_max [expr $tms_cable_max + $tms_header_trace_max + $tms_blaster_tco_max - [get_tck_delay_min]]
    set tms_in_min [expr $tms_cable_min + $tms_header_trace_min + $tms_blaster_tco_min - [get_tck_delay_max]]
    
    set_input_delay -add_delay -clock_fall -clock altera_reserved_tck -max $tms_in_max [get_ports {altera_reserved_tms}]
    set_input_delay -add_delay -clock_fall -clock altera_reserved_tck -min $tms_in_min [get_ports {altera_reserved_tms}]
}

proc set_tdi_timing_spec_when_driven_by_blaster { } {
    set tdi_blaster_tco_max 8.551
    set tdi_blaster_tco_min 8.551
    
    set tdi_cable_max 11.627
    set tdi_cable_min 10.0
    
    # tms delay on the PCB depends on the trace length from JTAG 10-pin 
    # header to FPGA on board. In general on the PCB, the signal travels 
    # at the speed of ~160 ps/inch (1000 mils = 1 inch).
    # ---customize here---
    set tdi_header_trace_max 0.5
    set tdi_header_trace_min 0.1

    set tdi_in_max [expr $tdi_cable_max + $tdi_header_trace_max + $tdi_blaster_tco_max - [get_tck_delay_min]]
    set tdi_in_min [expr $tdi_cable_min + $tdi_header_trace_min + $tdi_blaster_tco_min - [get_tck_delay_max]]
    
    #TDI launches at the falling edge of TCK per standard
    set_input_delay -add_delay -clock_fall -clock altera_reserved_tck -max $tdi_in_max [get_ports {altera_reserved_tdi}]
    set_input_delay -add_delay -clock_fall -clock altera_reserved_tck -min $tdi_in_min [get_ports {altera_reserved_tdi}]
}

proc set_tdi_timing_spec_when_driven_by_device { } {
    # TCO timing spec of tdo on the device driving this tdi input
    # ---customize here---
    set previous_device_tdo_tco_max 10.0
    set previous_device_tdo_tco_min 10.0
    
    # tdi delay on the PCB depends on the trace length from JTAG 10-pin 
    # header to FPGA on board. In general on the PCB, the signal travels 
    # at the speed of ~160 ps/inch (1000 mils = 1 inch).
    # ---customize here---
    set tdi_trace_max 0.5
    set tdi_trace_min 0.1

    set tdi_in_max [expr $previous_device_tdo_tco_max + $tdi_trace_max - [get_tck_delay_min]]
    set tdi_in_min [expr $previous_device_tdo_tco_min + $tdi_trace_min - [get_tck_delay_max]]
    
    #TDI launches at the falling edge of TCK per standard
    set_input_delay -add_delay -clock_fall -clock altera_reserved_tck -max $tdi_in_max [get_ports {altera_reserved_tdi}]
    set_input_delay -add_delay -clock_fall -clock altera_reserved_tck -min $tdi_in_min [get_ports {altera_reserved_tdi}]
}

proc set_tdo_timing_spec_when_drive_blaster { } {
    set tdo_blaster_tsu 5.831
    set tdo_blaster_th -1.651
    
    set tdo_cable_max 11.627
    set tdo_cable_min 10.0
    
    # tdi delay on the PCB depends on the trace length from JTAG 10-pin 
    # header to FPGA on board. In general on the PCB, the signal travels 
    # at the speed of ~160 ps/inch (1000 mils = 1 inch).
    # ---customize here---
    set tdo_header_trace_max 0.5
    set tdo_header_trace_min 0.1

    set tdo_out_max [expr $tdo_cable_max + $tdo_header_trace_max + $tdo_blaster_tsu + [get_tck_delay_max]]
    set tdo_out_min [expr $tdo_cable_min + $tdo_header_trace_min - $tdo_blaster_th + [get_tck_delay_min]]
    
    #TDO does not latch inside the USB Blaster II at the rising edge of TCK, 
    # it actually is latched one half cycle later in packed mode 
    # (equivalent to 1 JTAG fall-to-fall cycles)
    set_output_delay -add_delay -clock_fall -clock altera_reserved_tck -max $tdo_out_max [get_ports {altera_reserved_tdo}]
    set_output_delay -add_delay -clock_fall -clock altera_reserved_tck -min $tdo_out_min [get_ports {altera_reserved_tdo}]
}

proc set_tdo_timing_spec_when_drive_device { } {
    # TCO timing spec of tdi on the device driven by this tdo output
    # ---customize here---
    set next_device_tdi_tco_max 10.0
    set next_device_tdi_tco_min 10.0
    
    # tdi delay on the PCB depends on the trace length from JTAG 10-pin 
    # header to FPGA on board. In general on the PCB, the signal travels 
    # at the speed of ~160 ps/inch (1000 mils = 1 inch).
    # ---customize here---
    set tdo_trace_max 0.5
    set tdo_trace_min 0.1

    set tdo_out_max [expr $next_device_tdi_tco_max + $tdo_trace_max + [get_tck_delay_max]]
    set tdo_out_min [expr $next_device_tdi_tco_min + $tdo_trace_min + [get_tck_delay_min]]

    #TDO latches at the rising edge of TCK per standard
    set_output_delay -add_delay -clock altera_reserved_tck -max $tdo_out_max [get_ports {altera_reserved_tdo}]
    set_output_delay -add_delay -clock altera_reserved_tck -min $tdo_out_min [get_ports {altera_reserved_tdo}]
}

proc set_optional_ntrst_timing_spec { } {
    # ntrst is an optional JTAG pin to asynchronously reset the device JTAG controller.
    # There is no path from this pin to any FPGA core fabric.
    if { [get_collection_size [get_ports -nowarn {altera_reserved_ntrst}]] > 0 } {
        set_false_path -from [get_ports {altera_reserved_ntrst}]
    }
}

set_jtag_timing_constraints

 

 Here are the timing failures reported by Timing Analyzer:

hcom_0-1646246661707.png

 

After much online searching, there seems to be universal confusion about how to properly constrain JTAG with Intel devices. For example, see here and here and here (and countless more).

Everywhere I look, I seem to see totally different recommendations. The most "official" solution I could find online was this old article from Intel, which suggests using:

 

create_clock -name altera_reserved_tck -period 10 [get_ports altera_reserved_tck]

#cut all paths to and from altera_reserved_tck
set_clock_groups -asynchronous -group [get_clocks altera_reserved_tck]

# I/O min delays
set_input_delay -clock altera_reserved_tck -clock_fall [get_ports altera_reserved_tdi] -min 2
set_input_delay -clock altera_reserved_tck -clock_fall [get_ports altera_reserved_tms] -min 2
set_output_delay -clock altera_reserved_tck [get_ports altera_reserved_tdo] -min 3

# I/O max delays
set_input_delay -clock altera_reserved_tck -clock_fall [get_ports altera_reserved_tdi] -max 3
set_input_delay -clock altera_reserved_tck -clock_fall [get_ports altera_reserved_tms] -max 3
set_output_delay -clock altera_reserved_tck [get_ports altera_reserved_tdo] -max 4

 

This one passes timing analysis, but I'm discouraged by the arbitrary values that are provided without any explanation, except:

Note that the values specified in the constraints above are arbitrary values. You should ensure that the values you specify match the destination hardware.

Another suggestion I found here (with no explanation) is to use this:

 

create_clock -period "10 MHz" -name altera_reserved_tck [get_ports altera_reserved_tck] 
set_false_path -from [get_ports {altera_reserved_tdi}] 
set_false_path -from [get_ports {altera_reserved_tms}] 
set_false_path -to [get_ports {altera_reserved_tdo}] 
# Specify the JTAG clock in a group 
set_clock_groups -asynchronous -group altera_reserved_tck  

 

It looks like the last set_false_path prevents the timing errors that I got with the SDC template... but it's not clear to me if I'm then just ignoring a genuine timing violation.

What is the correct way of doing this? This is quite baffling for someone who normally uses Xilinx devices, because in my ~10 years of experience, Xilinx's Chipscope generally just works. It's not clear to me why it is such a complicated and unpleasant experience with Quartus.

0 Kudos
1 Solution
Nurina
Employee
495 Views

Hi, 

 

Thanks for bringing this up. This SDC constraints problem was probably missed by the internal team. I'll report this problem to them so they may rectify it.

 

Regards,

Nurina

View solution in original post

0 Kudos
4 Replies
sstrell
Honored Contributor III
593 Views

I would just false path the JTAG interface.  It's fixed hardware and slow speed, so I've never understood why these paths show up as unconstrained and requiring constraints.

0 Kudos
hcom
New Contributor II
531 Views

@sstrell That's what I have done as a workaround... but it bothers me that this enormous constraints file is provided, and then it fails timing.

If Intel's "official" stance is that timing can be ignored on the JTAG interface, then the provided constraints file should reflect that (and as an added bonus, it would only need to be a couple of lines long).

0 Kudos
Nurina
Employee
496 Views

Hi, 

 

Thanks for bringing this up. This SDC constraints problem was probably missed by the internal team. I'll report this problem to them so they may rectify it.

 

Regards,

Nurina

0 Kudos
Nurina
Employee
468 Views

Hi,


We did not receive any response to the previous reply provided, thus I will put this case to close pending. Please post a response in the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support. The community users will be able to help you with your follow-up questions.

Regards,

Nurina


P/S: If you like my comment, feel free to give Kudos. If my comment solved your problem, feel free to accept my comment as solution.


0 Kudos
Reply