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

TimeQuest Constraints Automation

Altera_Forum
Honored Contributor II
3,548 Views

Hi all, 

 

Altera's site has the page "Simplify Design Reuse with Dynamic SDC Constraints" 

 

http://www.altera.com/support/examples/timequest/exm-tq-reusable-clock-sdc.html 

 

which intriguingly implies that SDC constraints files can be automated. 

 

How is this useful you ask? 

 

Consider the case of a Qsys component that has an associated set of top-level pin constraints, eg., external device setup/hold requirements and clock-to-output delays, or an asynchronous interface that needs timing paths cut. An automated SDC file would find every instance of the Qsys component in the design, map the ports on each component instance to top-level pins, and then setup constraints on those pins. The Qsys component _hw.tcl file can automatically add the SDC file to the project, and since that SDC script would automatically parse the design, the user does not have to do anything to setup the SDC constraints. 

 

This all sounds nice, but I'm having a hard time using the TimeQuest Tcl API to navigate the design hierarchy. 

 

Caveat/Warning: I searched through all of the .SDC files in the Quartus IP folder and none use the technique described by the Altera link above :( 

 

I did find that the DDR constraints scripts do perform some form of mapping, but they use Tcl API calls that do not appear to be documented (involving netlist atoms). 

 

I've attached a zip file with my current attempts at getting this to work. Rather than using a Qsys system, I created a simplified design containing a registered 2:1 multiplexer (mux_2to1.vhd), along with components that contain instances of that component, or generated instances of that component (because the path name to an instance created with a generate statement is different than a normal instance). 

 

success: quartus_map and the Tcl ::quartus::rtl package 

 

When I failed to get TimeQuest to do what I want, I decided I would try and figure out how the "RTL Netlist Viewer" was getting the information it displays on the GUI. The attached zip file contains Tcl procedures that implement the mapping from component instance ports to top-level pins. This at least proves the concept is feasible. Unfortunately these packages are not available in TimeQuest (quartus_sta), so pre-flow or post-flow scripts would be required to create an intermediate Tcl file containing the pin mapping. 

 

not quite success: TimeQuest (quartus_sta) and the ::quartus::sdc and sdc_ext packages (edit: success now due to the discussion below

 

The TimeQuest scripts in the zip can be used to find the mapping from the 2:1 multiplexer register clock, reset, and output ports, since those are a 1:1 mapping from the underlying low-level register. However, I cannot figure out how to map the sel, d[0], and d[1] combinatorial input ports on the component to pins in the design. There does not appear to be an API call that can be called with component/entity port names that then map to internal register/cell names. The examples show that you can find the combinatorial dataa, datab, datac, and datad ports on the low-level lookup table, but the connection from these inputs changes for each instance in the design! There is no static mapping ... argh! 

 

The zip file contains a top-level readme.txt file describing how to reproduce my tests. 

 

I look forward to any suggestions anyone has! 

 

Cheers, 

Dave
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
1,627 Views

Hi all, 

 

I've just repeated the tests in the zip under Quartus 12.1. I still haven't figured out how to get the path to input combinatorial signals from within TimeQuest. 

 

The ::quartus:rtl Tcl procedures that I found were broken under 11.1sp1 are still broken, so I'll file a service request with Altera on that. 

 

Rysc - if you happen to see this thread, would you mind taking a look at the attached zip and the readme.txt? (You have private messaging turned off, I tried to ping you directly). 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

Hi, 

 

Can you elaborate on why have you not been able to use the method described in the Altera example? I think it explains exactly how to do this. 

 

The only trick is that: 

 

1) You need to use registers as starting points for the get_fanins and get_fanouts functions 

2) You need to be able to figure out the proper wildcard to find these registers inside your QSys block, which does mean you do have to do some small number of hard-coding. Just use the RTL Viewer to see if you can figure out a patent in the form of "*myqsys*<some_input/output_register name>" 

 

I haven't looked at the ZIP as it looks larger that I can analyze, but I can say that your example is probably wrong. You may need to add input and output registers to your mux, so you can try to wildcard and find those registers in the [get_fanins] command. 

 

Your SDC more or less do something like 

 

foreach name { *myqsys*a* *myqsys*b* } { 

foreach_in_collection fanin_id [get_fanin $name] {  

set top_level_input_name [get_node_info -name $fanin_id] 

 

Hope this helps
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

 

--- Quote Start ---  

 

Can you elaborate on why have you not been able to use the method described in the Altera example? I think it explains exactly how to do this. 

 

--- Quote End ---  

 

 

It explains how to find the higher-level connections to register ports, i.e., the input, output, clock, or reset pins. If you look in scripts/tmq_find_ports.tcl you'll see that I can find the mapping for these pins. 

 

The Altera example does not explain how to find the mapping between a combinatorial input and a top-level pin (and I'm not sure that it is possible). For example, here's some of the tests in the comments from scripts/tmq_find_ports.tcl 

 

# -------------------------------------------------------------------# Adding -through# ---------------# # The clock, reset, and output path can be identified by using# -through and get_pins to match the top-level signal to the pin# on the register in the cell, i.e., mux_reg|clk, |clrn, and |q.# # The inputs are trickier, as there are 3 signals (sel, d, and# d) feeding combinatorial logic prior to the |d port.# # Using get_pins -comp with a wildcard up to mux_reg showed that# the combinatorial inputs are mux_reg~0|dataa, datab, datac,# datad, and combout. Testing on the different instances shows# that sel d and d connect to different pins in different# instances! If the input mapping was static, eg.,# # mux_reg~0|dataa = sel# mux_reg~0|datab = d# mux_reg~0|datac = d# # Then the script could be automated. However, given that this# mapping is changing, a method of mapping the design inputs# to the cell combinatorial inputs is required.# # As an example, here's the input mappings# # tcl> tmq_find_combin dataa# # u1|mux_reg~0|dataa connects to pin_d# \g1:u2|mux_reg~0|dataa connects to pin_sel# u3|u1|mux_reg~0|dataa connects to pin_sel# u3|u2|mux_reg~0|dataa connects to pin_sel# u4|\g1:0:u1|mux_reg~0|dataa connects to pin_sel# u4|\g1:1:u1|mux_reg~0|dataa connects to pin_d# u4|\g1:2:u1|mux_reg~0|dataa connects to pin_sel# u4|\g1:3:u1|mux_reg~0|dataa connects to pin_sel# # tcl> tmq_find_combin datab# # \g1:u2|mux_reg~0|datab connects to pin_d# u3|u2|mux_reg~0|datab connects to pin_d# u4|\g1:0:u1|mux_reg~0|datab connects to pin_d# # tcl> tmq_find_combin datac# # u1|mux_reg~0|datac connects to pin_sel# \g1:u2|mux_reg~0|datac connects to pin_d# u3|u1|mux_reg~0|datac connects to pin_d# u4|\g1:0:u1|mux_reg~0|datac connects to pin_d# u4|\g1:1:u1|mux_reg~0|datac connects to pin_sel# u4|\g1:2:u1|mux_reg~0|datac connects to pin_d# u4|\g1:3:u1|mux_reg~0|datac connects to pin_d# # tcl> tmq_find_combin datad# # u1|mux_reg~0|datad connects to pin_d# u3|u1|mux_reg~0|datad connects to pin_d# u3|u2|mux_reg~0|datad connects to pin_d# u4|\g1:1:u1|mux_reg~0|datad connects to pin_d# u4|\g1:2:u1|mux_reg~0|datad connects to pin_d# u4|\g1:3:u1|mux_reg~0|datad connects to pin_d# # where mux_2to1 has three combinatorial inputs, the logic cells use# three of four combinatorial inputs, and the logic cell usage# changes for each instance, eg., note how the sel input does not# always map to dataa, and the four generated instances in u4 do not# even map identically.#  

 

 

--- Quote Start ---  

 

I haven't looked at the ZIP as it looks larger that I can analyze 

 

--- Quote End ---  

 

 

Sorry about the length, but I prefer to provide code so as to provide a specific example, either of the problem, or my misunderstanding :) 

 

 

--- Quote Start ---  

 

but I can say that your example is probably wrong. 

 

--- Quote End ---  

 

 

I'd prefer to call it "incomplete" :) 

 

 

--- Quote Start ---  

 

You may need to add input and output registers to your mux 

 

--- Quote End ---  

 

That is not possible. The 'real' component that I want to use this with interfaces with an external component, and adding input pipeline registers is not possible. 

 

 

--- Quote Start ---  

 

Hope this helps 

--- Quote End ---  

 

 

I appreciate you taking the time to respond, thanks! 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

 

--- Quote Start ---  

Hi all, 

 

Altera's site has the page "Simplify Design Reuse with Dynamic SDC Constraints" 

 

http://www.altera.com/support/examples/timequest/exm-tq-reusable-clock-sdc.html 

 

which intriguingly implies that SDC constraints files can be automated. 

 

How is this useful you ask? 

 

Consider the case of a Qsys component that has an associated set of top-level pin constraints, eg., external device setup/hold requirements and clock-to-output delays, or an asynchronous interface that needs timing paths cut. An automated SDC file would find every instance of the Qsys component in the design, map the ports on each component instance to top-level pins, and then setup constraints on those pins. The Qsys component _hw.tcl file can automatically add the SDC file to the project, and since that SDC script would automatically parse the design, the user does not have to do anything to setup the SDC constraints. 

 

--- Quote End ---  

 

 

Hi Dave, 

 

I've been using this method a couple of times already, as I too got tired of copy/pasting from/to .sdc files. And it works reasonably OK, the major issue is to find the internal pin name. I haven't done this for multiple instantiations, let alone nested instantiations, of the same module, but I guess it may well work with little changes.  

I attach an (annotated) example. 

The key will be to name the low-level instantiation adequately to avoid applying constraints to another module, e.g. in my example I have " *|*:reg|Q[*]|q " to match, this name may well occur in other modules, so I'll have to improve on that. 

 

 

--- Quote Start ---  

Caveat/Warning: I searched through all of the .SDC files in the Quartus IP folder and none use the technique described by the Altera link above 

--- Quote End ---  

 

The same applies for the somemegafunction_hw.tcl files, they're hidden in some java or whatever binary package. 

 

Regards, 

 

Josy
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

Thanks Josy, I'll check out your zip file :)

0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

In your example, you are able to search for pattern matches, eg., *|FlagB*|data* or *|SlWr|combout. This means your pin netlist has preserved those signal names, which I suspect are registers in your design. 

 

If I print the entire pins collection for the example design (see the code block below), you will see that it does not contain any of the original input combinatorial signals in the design, eg., the sel control of the multiplexer. You can see the combinatorial inputs to the cells (dataa, datab, etc.), but as I show above, the mapping to the component combinatorial signals changes for each instance (making it impossible to hard-code a path for use in the SDC file). 

 

I suspect that the TimeQuest netlist is just not the right place to look to create the mapping from instance ports to top-level signal ports. The RTL netlist is probably more appropriate, since it preserves the original signal names. Its not too much trouble to get Quartus to run a script that would automate the creation of a Tcl file containing the pin mapping (the pre-flow and post-flow scripts work quite well). 

 

I've filed an Altera Service Request with this zip file, when I get a response from them, I'll post an update. 

 

If you have any other suggestions for TimeQuest tests, let me know and I'll try them! 

 

Cheers, 

Dave 

 

 

tcl> set col _col0 tcl> get_collection_size $col 122 tcl> query_collection -report -all $col u1|mux_reg|clk pin_clk~inputclkctrl|outclk u1|mux_reg|clrn pin_rstN~inputclkctrl|outclk u1|mux_reg|d u1|mux_reg~0|combout pin_clk~inputclkctrl|inclk pin_clk~input|o pin_rstN~inputclkctrl|inclk pin_rstN~input|o u1|mux_reg~0|dataa pin_d~input|o u1|mux_reg~0|datac pin_sel~input|o u1|mux_reg~0|datad pin_d~input|o pin_clk~input|i pin_rstN~input|i pin_d~input|i pin_sel~input|i pin_d~input|i \g1:u2|mux_reg|clk \g1:u2|mux_reg|clrn \g1:u2|mux_reg|d \g1:u2|mux_reg~0|combout \g1:u2|mux_reg~0|dataa \g1:u2|mux_reg~0|datab pin_d~input|o \g1:u2|mux_reg~0|datac pin_d~input|o pin_d~input|i pin_d~input|i u3|u1|mux_reg|clk u3|u1|mux_reg|clrn u3|u1|mux_reg|d u3|u1|mux_reg~0|combout u3|u1|mux_reg~0|dataa u3|u1|mux_reg~0|datac pin_d~input|o u3|u1|mux_reg~0|datad pin_d~input|o pin_d~input|i pin_d~input|i u3|u2|mux_reg|clk u3|u2|mux_reg|clrn u3|u2|mux_reg|d u3|u2|mux_reg~0|combout u3|u2|mux_reg~0|dataa u3|u2|mux_reg~0|datab pin_d~input|o u3|u2|mux_reg~0|datad pin_d~input|o pin_d~input|i pin_d~input|i u4|\g1:0:u1|mux_reg|clk u4|\g1:0:u1|mux_reg|clrn u4|\g1:0:u1|mux_reg|d u4|\g1:0:u1|mux_reg~0|combout u4|\g1:0:u1|mux_reg~0|dataa u4|\g1:0:u1|mux_reg~0|datab pin_d~input|o u4|\g1:0:u1|mux_reg~0|datac pin_d~input|o pin_d~input|i pin_d~input|i u4|\g1:1:u1|mux_reg|clk u4|\g1:1:u1|mux_reg|clrn u4|\g1:1:u1|mux_reg|d u4|\g1:1:u1|mux_reg~0|combout u4|\g1:1:u1|mux_reg~0|dataa pin_d~input|o u4|\g1:1:u1|mux_reg~0|datac u4|\g1:1:u1|mux_reg~0|datad pin_d~input|o pin_d~input|i pin_d~input|i u4|\g1:2:u1|mux_reg|clk u4|\g1:2:u1|mux_reg|clrn u4|\g1:2:u1|mux_reg|d u4|\g1:2:u1|mux_reg~0|combout u4|\g1:2:u1|mux_reg~0|dataa u4|\g1:2:u1|mux_reg~0|datac pin_d~input|o u4|\g1:2:u1|mux_reg~0|datad pin_d~input|o pin_d~input|i pin_d~input|i u4|\g1:3:u1|mux_reg|clk u4|\g1:3:u1|mux_reg|clrn u4|\g1:3:u1|mux_reg|d u4|\g1:3:u1|mux_reg~0|combout u4|\g1:3:u1|mux_reg~0|dataa u4|\g1:3:u1|mux_reg~0|datac pin_d~input|o u4|\g1:3:u1|mux_reg~0|datad pin_d~input|o pin_d~input|i pin_d~input|i pin_q~output|o pin_q~output|i pin_q~output|o pin_q~output|i pin_q~output|o pin_q~output|i pin_q~output|o pin_q~output|i pin_q~output|o pin_q~output|i pin_q~output|o pin_q~output|i pin_q~output|o pin_q~output|i pin_q~output|o pin_q~output|i u1|mux_reg|q \g1:u2|mux_reg|q u3|u1|mux_reg|q u3|u2|mux_reg|q u4|\g1:0:u1|mux_reg|q u4|\g1:1:u1|mux_reg|q u4|\g1:2:u1|mux_reg|q u4|\g1:3:u1|mux_reg|q
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

 

--- Quote Start ---  

In your example, you are able to search for pattern matches, eg., *|FlagB*|data* or *|SlWr|combout. This means your pin netlist has preserved those signal names, which I suspect are registers in your design. 

 

If I print the entire pins collection for the example design (see the code block below), you will see that it does not contain any of the original input combinatorial signals in the design, eg., the sel control of the multiplexer. You can see the combinatorial inputs to the cells (dataa, datab, etc.), but as I show above, the mapping to the component combinatorial signals changes for each instance (making it impossible to hard-code a path for use in the SDC file). 

 

I suspect that the TimeQuest netlist is just not the right place to look to create the mapping from instance ports to top-level signal ports. The RTL netlist is probably more appropriate, since it preserves the original signal names. Its not too much trouble to get Quartus to run a script that would automate the creation of a Tcl file containing the pin mapping (the pre-flow and post-flow scripts work quite well). 

 

I've filed an Altera Service Request with this zip file, when I get a response from them, I'll post an update. 

 

If you have any other suggestions for TimeQuest tests, let me know and I'll try them! 

 

Cheers, 

Dave 

 

 

--- Quote End ---  

 

 

Hi Dave, 

 

FlagB feeds both into a register and into a combinatorial feeding SlWr 

I used a keep attribute to preserve the names: attribute keep: boolean; attribute keep of FlagB : signal is true; attribute keep of SlWr : signal is true; 

 

I played a bit around with your zip file in Quartus. I added an SDC file which lists all pins in the design and then searches for specific pins fed by external ports and feeding external ports. As you can see it finds all 'external' ports, but some multiple times. I had to stop here, first I need to do some proper (== eventually paid) work but secondly I don't do much Tcl (I kind of hate it, I always get caught my a missing $ or a mix-up of parenthesis, brackets and braces ... I wish we could use Python instead) 

I added a fifth instance, u5 : mux_4to1, defining a tree of basic multiplexers to be able to show a few pins not going to / coming from an external port. 

You can see that the reported pin-names are those left after fitting. E.g. if you add registers to the inputs of mux_2to1 you can see that some wil get optimized away by the fitter, although they will still be there in the RTL viewer so I looked in the Schematic Viewer 'post fitting' to find the names of interest. 

I attach a .qar (as I do everything in Quartus ...). 

 

Regards, 

 

Josy
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

Hi Josy, 

 

Thanks to your response I realized what I was missing! 

 

If I add a synthesis keep constraint inside the mux_2to1.vhd component to the combinatorial inputs, i.e., 

 

attribute keep : boolean; attribute keep of sel : signal is true; attribute keep of d : signal is true;  

 

Then the SDC netlist preserves these nodes, and get_pins will return matches to the sel, d[0], and d[1] combinatorial input signals, eg., 

 

tcl> set col * *d*}] tcl> query_collection -report -all $col u1|sel~buf0|combout u1|d~buf0|combout u1|d~buf0|combout u1|sel~buf0|datad pin_sel~input|o u1|d~buf0|datad pin_d~input|o u1|d~buf0|datac pin_d~input|o pin_sel~input|i pin_d~input|i pin_d~input|i \g1:u2|d~buf0|combout \g1:u2|d~buf0|combout \g1:u2|sel~buf0|combout \g1:u2|d~buf0|datac \g1:u2|d~buf0|datad \g1:u2|sel~buf0|datac u3|u1|d~buf0|combout u3|u1|d~buf0|combout u3|u1|sel~buf0|combout u3|u1|d~buf0|datad u3|u1|d~buf0|datad u3|u1|sel~buf0|datac u3|u2|sel~buf0|combout u3|u2|d~buf0|combout u3|u2|d~buf0|combout u3|u2|sel~buf0|datac u3|u2|d~buf0|datad u3|u2|d~buf0|datac u4|\g1:0:u1|sel~buf0|combout u4|\g1:0:u1|d~buf0|combout u4|\g1:0:u1|d~buf0|combout u4|\g1:0:u1|sel~buf0|datad u4|\g1:0:u1|d~buf0|datad u4|\g1:0:u1|d~buf0|datac u4|\g1:1:u1|sel~buf0|combout u4|\g1:1:u1|d~buf0|combout u4|\g1:1:u1|d~buf0|combout u4|\g1:1:u1|sel~buf0|datad u4|\g1:1:u1|d~buf0|datad u4|\g1:1:u1|d~buf0|datad u4|\g1:2:u1|d~buf0|combout u4|\g1:2:u1|d~buf0|combout u4|\g1:2:u1|sel~buf0|combout u4|\g1:2:u1|d~buf0|datad u4|\g1:2:u1|d~buf0|datad u4|\g1:2:u1|sel~buf0|datad u4|\g1:3:u1|sel~buf0|combout u4|\g1:3:u1|d~buf0|combout u4|\g1:3:u1|d~buf0|combout u4|\g1:3:u1|sel~buf0|datac u4|\g1:3:u1|d~buf0|datac u4|\g1:3:u1|d~buf0|datac  

 

and now a get_fanins call can be used on sel, d[0], or d[1] to find the input mapping, eg., 

 

tcl> tmq_find_comb_input sel u1|sel~buf0|combout connects to pin_sel u1|sel~buf0|datad connects to pin_sel \g1:u2|sel~buf0|combout connects to pin_sel \g1:u2|sel~buf0|datac connects to pin_sel u3|u1|sel~buf0|combout connects to pin_sel u3|u1|sel~buf0|datac connects to pin_sel u3|u2|sel~buf0|combout connects to pin_sel u3|u2|sel~buf0|datac connects to pin_sel u4|\g1:0:u1|sel~buf0|combout connects to pin_sel u4|\g1:0:u1|sel~buf0|datad connects to pin_sel u4|\g1:1:u1|sel~buf0|combout connects to pin_sel u4|\g1:1:u1|sel~buf0|datad connects to pin_sel u4|\g1:2:u1|sel~buf0|combout connects to pin_sel u4|\g1:2:u1|sel~buf0|datad connects to pin_sel u4|\g1:3:u1|sel~buf0|combout connects to pin_sel u4|\g1:3:u1|sel~buf0|datac connects to pin_sel tcl> tmq_find_comb_input d u1|d~buf0|combout connects to pin_d u1|d~buf0|datac connects to pin_d \g1:u2|d~buf0|combout connects to pin_d \g1:u2|d~buf0|datac connects to pin_d u3|u1|d~buf0|combout connects to pin_d u3|u1|d~buf0|datad connects to pin_d u3|u2|d~buf0|combout connects to pin_d u3|u2|d~buf0|datad connects to pin_d u4|\g1:0:u1|d~buf0|combout connects to pin_d u4|\g1:0:u1|d~buf0|datac connects to pin_d u4|\g1:1:u1|d~buf0|combout connects to pin_d u4|\g1:1:u1|d~buf0|datad connects to pin_d u4|\g1:2:u1|d~buf0|combout connects to pin_d u4|\g1:2:u1|d~buf0|datad connects to pin_d u4|\g1:3:u1|d~buf0|combout connects to pin_d u4|\g1:3:u1|d~buf0|datac connects to pin_d tcl> tmq_find_comb_input d u1|d~buf0|combout connects to pin_d u1|d~buf0|datad connects to pin_d \g1:u2|d~buf0|combout connects to pin_d \g1:u2|d~buf0|datad connects to pin_d u3|u1|d~buf0|combout connects to pin_d u3|u1|d~buf0|datad connects to pin_d u3|u2|d~buf0|combout connects to pin_d u3|u2|d~buf0|datac connects to pin_d u4|\g1:0:u1|d~buf0|combout connects to pin_d u4|\g1:0:u1|d~buf0|datad connects to pin_d u4|\g1:1:u1|d~buf0|combout connects to pin_d u4|\g1:1:u1|d~buf0|datad connects to pin_d u4|\g1:2:u1|d~buf0|combout connects to pin_d u4|\g1:2:u1|d~buf0|datad connects to pin_d u4|\g1:3:u1|d~buf0|combout connects to pin_d u4|\g1:3:u1|d~buf0|datac connects to pin_d  

 

where here I've called get_fanins on both of the nodes matched by get_pins, just to check that both paths map back to a common input, and to show that the dataa/datab/datac/datad mapping to each instance differs. 

 

Cheers, 

Dave 

 

NOTE: I updated the zip file above with the latest version.
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

 

--- Quote Start ---  

Hi Josy, 

 

Thanks to your response I realized what I was missing! 

 

If I add a synthesis keep constraint inside the mux_2to1.vhd component to the combinatorial inputs, i.e., 

 

attribute keep : boolean; attribute keep of sel : signal is true; attribute keep of d : signal is true;  

 

Then the SDC netlist preserves these nodes, and get_pins will return matches to the sel, d[0], and d[1] combinatorial input signals, eg., 

 

 

--- Quote End ---  

 

 

Quartus will add an LE for each instance of a 'kept' signal (after optimization). This extra LE in the input is not optimal especially if the margins are a bit tight. 

I renamed the top pins: pin_d to pin_A, pin_sel to pin_B and pin_q to pin_Y to avoid matching *sel* and the like directly. 

I also added a version of mux_2to1 with registered inputs for 'sel' and 'd' without the 'keep' attribute to see what goes on. Initially this also has an LE to feed the register, but this can be avoided by pushing the register into the IO-cell. 

 

In real life now most of the times external signals will go direct into a register, and only few will feed a combinatorial circuit. 

 

One more observation: we have only dealt with a single clock for all instantiated modules. Things get a bit complicated when every instance is fed by a different clock source. This doesn't happen that often though, but I have connected multiple octal ADCs to one FPGA in the past. 

 

Regards, 

 

Josy
0 Kudos
Altera_Forum
Honored Contributor II
1,627 Views

Hi Josy, 

 

 

--- Quote Start ---  

Quartus will add an LE for each instance of a 'kept' signal (after optimization). This extra LE in the input is not optimal especially if the margins are a bit tight. 

 

--- Quote End ---  

 

Ah, that is a good thing to note. The example above is 'contrived', so I think its time to apply this to my real component :) 

 

 

--- Quote Start ---  

 

I renamed the top pins: pin_d to pin_A, pin_sel to pin_B and pin_q to pin_Y to avoid matching *sel* and the like directly. 

I also added a version of mux_2to1 with registered inputs for 'sel' and 'd' without the 'keep' attribute to see what goes on. Initially this also has an LE to feed the register, but this can be avoided by pushing the register into the IO-cell. 

 

--- Quote End ---  

 

As soon as an input goes directly to a register, you can search based on the reg|d input, so there is no need for a 'keep' attribute. 

 

 

--- Quote Start ---  

 

In real life now most of the times external signals will go direct into a register, and only few will feed a combinatorial circuit. 

 

--- Quote End ---  

 

 

My first application of this technique will be for constraining an FTDI FT232H USB-to-FIFO device. In asynchronous FIFO mode the inputs pass through synchronizers, so there is a register that I can use to 'find' the top-level pin. However, in synchronous FIFO mode, the timing requirements of the interface are such that the inputs must feed combinatorially into the FSM, so that the output can be registered (located in an IOE register). I'm writing a document and will post it to the AlteraWiki. 

 

 

 

--- Quote Start ---  

 

One more observation: we have only dealt with a single clock for all instantiated modules. Things get a bit complicated when every instance is fed by a different clock source. This doesn't happen that often though, but I have connected multiple octal ADCs to one FPGA in the past. 

 

--- Quote End ---  

 

I haven't tried it yet, but I don't see any complication. I think the script can be written to look for the clock, then check if there is a constraint. For example, in FT232H synchronous mode, the FT232H generates a 60MHz clock, hence the SDC constraints file should be able to check for such a constraint - the first time it checks a clock it will not find the constraint, so it can add it - the second check will find the constraint, so move on ...  

 

I'll see how these ideas work out in practice sometime this week :) 

 

Cheers, 

Dave
0 Kudos
Reply