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

Signal Tap example from Intel training course always fails timing

hcom
New Contributor II
1,451 Views

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-1641560065234.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
12 Replies
ShengN_Intel
Employee
1,428 Views

Hi hcom,

 

Kindly refer to this link.

JTAG signal constraints template in Recent TimeQuest Cookbook  (Page 18) probably can help.

 

Best regards,
Sheng

p/s: If any answer from the community or Intel support are helpful, please feel free to give Kudos.

 

 

 

0 Kudos
hcom
New Contributor II
1,416 Views

@ShengN_Intel That is almost exactly the same as the template I pasted above. Is there any reason to believe this old version uploaded to a forum would work better than the official template included with Quartus?

0 Kudos
ShengN_Intel
Employee
1,396 Views

Hi hcom,

 

Intel training course did mention the template in Timing Analyzer Cookbook as well, linked here.

I believe the JTAG signal constraints template in Cookbook can be used and function well. Just the method is different which used fitter-specific constraints.

Most likely the timing failure is because of the ports {altera_reserved_tdo}. Timing fails there.

 

I also found something here (page 25) regarding SDC command:

set_max_delay - To relax timing analysis for the setup/ hold checks to not fail.

set_false_path - Identifies specific timing paths as being false. This constraint removes timing requirements on these false paths so that they are not considered during the timing analysis.

 

I think you can add the second suggestion in top post into text editor template or use this one:

--- Quote Start ---

set jtag_33Mhz_t_period 30

create_clock -name {altera_reserved_tck} -period $jtag_33Mhz_t_period [get_ports {altera_reserved_tck}]

set_clock_groups -asynchronous -group {altera_reserved_tck}

set_max_delay -to [get_ports { altera_reserved_tdo } ] 0

--- Quote End ---  

Both methods should work properly as well. The periods 10Mhz or 33Mhz should be both okay depend on which one you choose.

 

Hope it helps.

Best regards,
Sheng

p/s: If any answer from the community or Intel support are helpful, please feel free to give Kudos.

0 Kudos
ShengN_Intel
Employee
1,348 Views

Hi hcom,

Any update on this thread?

Have your problem being resolved?

Best regards,
Sheng


0 Kudos
hcom
New Contributor II
1,340 Views

@ShengN_Intel No, there is no solution yet. It still fails timing.

0 Kudos
ShengN_Intel
Employee
1,326 Views

Hi hcom,

 

I found something from Cyclone 10 GX datasheet about jtag timing parameters below.

https://www.marutsu.co.jp/contents/shop/marutsu/ds/c10gx-51002.pdf 

ShengN_Intel_1-1643194337966.pngShengN_Intel_2-1643194404829.png

 

May be you can try the SDC constraints with these parameters:

create_clock -name altera_reserved_tck -period 30 [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 [get_ports altera_reserved_tdi] -min 5 #(hold constraints)
set_input_delay -clock altera_reserved_tck [get_ports altera_reserved_tms] -min 5 #(hold constraints)
set_output_delay -clock altera_reserved_tck -clock_fall [get_ports altera_reserved_tdo] -min 11 #(constraints tjpco at falling edge)

# I/O max delays
set_input_delay -clock altera_reserved_tck [get_ports altera_reserved_tdi] -max 28 #(setup constraints: tck - tdi)
set_input_delay -clock altera_reserved_tck [get_ports altera_reserved_tms] -max 27 #(setup constraints: tck - tms)
set_output_delay -clock altera_reserved_tck -clock_fall [get_ports altera_reserved_tdo] -max 30

 

Best regards,
Sheng

0 Kudos
ShengN_Intel
Employee
1,289 Views

Hi hcom,

 

Any further update? Have you pass the timing constraints with the SDC constraints provided?

 

Best regards,
Sheng


0 Kudos
hcom
New Contributor II
1,266 Views

@ShengN_Intel No, there is no solution yet. It still fails timing.

 

I still need a solution, but nothing I have tried has worked.

 

 

0 Kudos
ShengN_Intel
Employee
1,256 Views

Hi @hcom ,

 

I think you can straight set false path from those two fail timing nodes. Try to modify a bit the original Quartus SDC template like below.

proc set_s10_false_path_constraint { } { if {$::TimeQuestInfo(family) == "Cyclone 10 GX"}

                                                                        { set_false_path -from "the node"

                                                                          set_false_path -from "the node" } }

 

Best regards,
Sheng


0 Kudos
ShengN_Intel
Employee
1,235 Views

Hi @hcom ,

 

Any further update?

--- Quote Start ---

proc set_s10_false_path_constraint { } { if {$::TimeQuestInfo(family) == "Cyclone 10 GX"}

                                                                        { set_false_path -from "the node"

                                                                          set_false_path -from "the node" } }

--- Quote End ---  

Does the alternative provided above help?

 

Thanks.

Best regards,
Sheng

0 Kudos
hcom
New Contributor II
1,214 Views

@ShengN_Intel I must admit, I am shocked by your suggestion. Of course, I could set timing ignores everywhere in my design and then I would never see any timing errors. But then I also wouldn't be constraining anything, so (without specific justification) this would be an incredibly bad thing to do.

0 Kudos
ShengN_Intel
Employee
1,211 Views

Hi @hcom ,

 

Due to this thread is opened for too long time and no response from you for quite some time, so I had closed pending this thread. 

You may open a new thread on this topic and I will pick up the new one when it comes in.

I will reflect this to internal engineering and come back to you in new thread if there is any feedback from them.

 

Thanks,
Best regards,
Sheng

0 Kudos
Reply