Coding for Reuse Course - Module 4 Lesson 3
Timing Closure

Our project will now synthesize for the Xilinx Spartan 3A family and the Altera Cyclone IV E family with no changes. We now need to map and fit our code and make sure that it will meet our timing requirements.

In this lesson we will study how to achieve our timing requirements using both the Xilinx and Altera tool sets.

License Terms  

The source and/or object code (subsequently referred to as code) presented in this and subsequent lessons is the property of saxelec.com and owner who retains copyright protection. This code in whole or in part is licensed only for single copy per user, non-commercial use; except in the case of educational institutions, where a license of single copy per student, only as part of course curricula, is permitted.

Donald Gerard Polak (owner)

Preliminary  

Before we begin timing closure, there is one more issue that we need to address. The signal "trap" is used both as a clock, and in logic. Because there is only one register involved, it does meet the minimum requirements of rule 3.10. However, the Xilinx Spartan 6 family will not support this type of construct at all.

The timing of "trap" is not specified, so a sampling methodology is not guaranteed to work. The best way to address this issue is to add another I/O pad to "trap" to support the clock input. This "clk_trap" I/O pad is then connected externally to the "trap" I/O pad. That leaves us with the following HDL source code:

Project Source File with a Separate "clk_trap" Input.

The Xilinx constraints editor requires a fully placed and routed design. In the Xilinx directory that you created, replace the current source code with the new code we just developed and launch ISE. In the lower portion of the left hand window, double click "Implement Design" and let it run to completion.

Although we still have no synthesis warnings, we do have warnings from the translate, map, and place and route processes. Let us examine them and remove as many as possible.

When we look at the translate warnings:

ISE Translate Process Warnings

we can see that they originate from signals that we always force to zero. We can easily remove the upper 8 bits of "multiplicand", since the source mux will automatically force those bits to zero. The carry in for the divider and adder, the LSb of "daaval" and three of the interrupt vector bits re a different story. Obviously, the interrupt vector bits and "daaval" could be addressed in the source mux and the least significant nibble of the adder changed to eliminate this warning. But that comes at the cost of added complexity in our design, making it more difficult to debug and support. Instead, we will use the one's complement of rst_in_n to drive these bits.

The map warnings:

ISE Map Process Warnings

are a bit more difficult to address. Some of them can be removed by eliminating the "keep hierarchy" option and allowing optimization across hierarchal boundaries. This means, however, subsequent warnings will be more difficult to track down. The issue involving "clk_x1" is more problematic. Although many FPGA architectures support inverted clocks directly in their logic, some, including the Spartan 3A series, do not. In the Spartan 3A series, clock invert is a function of the digital clock manager (DCM).

Rather than creating a special case for a single vendor's particular device family, we devised a conditional compile, whereby we attach an extra I/O pad to the clk_x1 input to support logic, in this case a simple inverter. This new I/O pad MUST be connected externally to the clk_x1 input. The output of this inverter feeds "x2_pad". For best results, do not use internal pullups for either "x1" or "clk_x1" so you can adjust your Pierce oscillator with external component values.

The issue with "restart_7_5" was actually an error. The "SIM" instruction should report pending interrupts, which, in the case of restart 7.5 should be the latched state (r7_5_latched), rather than the state of the input pin.

Many of our other warnings may be eliminated by correcting these errors and changing our synthesis options. However, there is another alteration we need to make. Many modern FPGAs feature block RAM, and even those that don't can emulate block RAM with just a four logic element delay (with a properly constructed mux tree). The problem lies with the synthesis software being able to detect constructs that should be placed into block RAM. ISE does not detect a block ROM that can be placed into a block entity if it is too small. This could cause sub-optimal timing and many logic delays. To avoid this issue, we filled in our "fmask" table with all possible instruction values. That leaves us with the following source code:

Project Source File with ISE Translate, Map, Place, and Route Corrections

Of course, we need to alter our definitions file to take advantage of our "clk_x1" correction:

Definitions File to Take Advantage of clk_x1 Correction

We go into our synthesis process properties and set "-keep_hierarchy" to "No". We also open the Xilinx specific options and check both "-register_duplication" and "-equivalent_register_removal". Under the Map Process Properties, check "-ignore_keep_hierarchy". I also set "-ol" to "High" and "-cm" to "Speed".

Now when we rerun "Implement Design" we see that all warnings have been eliminated.

Applying ISE Constraints  

There are several ways to apply constraints to your project when using the Xilinx "ISE" tool. The first method, called "XST", allows you to apply certain Xilinx constraints directly to your HDL code or in an external "XCF" file. These are primarily synthesis options and location constraints. These constraints are applied to your HDL source code by the inclusion of specially formatted notes, macros, or metas. Using these constraints violates rule 3.8 and are not reusable. Using an external XCF file is permissible, but we don't necessarily need it.

We will be using the constraints editor to develop a user constraints file (UCF) to include in our project. Initially we just want to set a period for our three clock domains.

The constraints editor is launched by selecting "Constraints Editor" under the "Tools" pull down menu. You will be asked if you want to create and add a user constraints file to your project:

ISE Add UCF Warning

Allow the editor to allow the constraints file to your project and set the name to "s8085d_r.ucf". The editor will open to "Timing Constraints" with "Clock Domains" open:

ISE Clock Domain Constraints

We click in the blank row below the "Clock Net *" column title and get a down arrow. Click on the down arrow to get the clock net name pull down list. Select "clk_x1" from the list. We now set the clock period. To meet our requirements, the minimum period specification is 31.25 ns. I generally go much higher to ensure that we have plenty of margin. I click in the "Period" column and get another pull down menu that defaults to nanoseconds, and a period specification that defaults to 0.0. I set this specification to 25 nanoseconds (40 MHz) for our initial attempt. We now MUST set a timespec name. This name MUST meet certain guidelines. We will use "TS_clk_x1" for the timespec name in order to meet these requirements.

ISE requires that you validate constraints after each entry. Before we proceed, we click on the "Validate Constraints" button. This will fill in the status, duty cycle, and edge fields and remove clk_x1 from the unconstrained clocks list.

ISE clk_x1 Constraints

It is not really necessary to constrain clk_trap or restart_7_5, however, we will do it anyway to avoid any warnings. I will set the period on these clocks to 10ns. When we are complete, we select "Save" under the "File" pull down menu.

We close the constraints window and rerun "Implement Design". There are no warnings reported, so we check the "Timing Constraints" report:

ISE Timing Constraints Report

We see that our design meets our timing requirements for a 40MHz clk_x1. This is more than our initial requirements, so this is considered a good design for ISE.

Meeting Timing with Quartus  

Before we begin setting constraints in Quartus, we want to perform a full compile with our latest source code. Copy the latest source code into your Quartus directory and launch Quartus. Then open your project.

After a successful synthesis has been run, Quartus will not automatically rerun synthesis, even if the source code has changed. Before you can compile the design, you must rerun the synthesis process and stop it before completion. Right click on "Analysis and Synthesis" and select "Start Again" from the pull down menu. You will get a warning window explaining that synthesis was already successfully run. Click the "Yes" button and allow the process to start. Then click the "Stop" icon on the top tool bar.

Now we can do the full compile. Double click the arrow next to "Compile Design" and let the process run to completion. The only warnings we get will come from the "Timequest Timing Analyzer". This is because we have not set our clock constraints, and they defaulted to 100 MHz.

Setting Quartus Constraints  

Quartus expects its constraints in a specially formatted file, usually created by the Synopsis "Symplify" tool. This constraints file, in "sdc" format, may also be created by any text editor. At first we only wish to constrain clk_x1, as this is the only signal where we have a firm specification. Therefore, we develop the following file:

Quartus "sdc" file

Before we compile, we have one more correction to do. We cannot ensure the timing of interrupts in relation to "clk_x1". "restart_7_5" and "clk_trap" in particular violate Rule 2.7. Therefore, we need to resynchronize all interrupts to "clk_x1" before using them:

Project source file with Interrupt Resynchronization.

We now need to add our constraints file to our project. Under the "Project" pull down menu, select "Add/Remove Files In Project". When the "add files" window:

Quartus Add Files Dialog

appears, click on the "..." button next to the "File Name" entry block to bring up the file browser. Select "Text Files" from the pull down list in the file browser. Then locate and select your SDC file and click the "Open" button. When the file browser window closes, click on "Add" and the "OK". The constraints file is now part of your project.

Compile and Check Your "Quartus" Project  

We now compile our project with the constraints added. When the compile is complete, we see the "TimeQuest Timing" folder highlighted in red. When we open the folder, we see that the only report highlighted in red is the "Unconstrained Paths". This indicates that we are meeting timing. We can look under the "Slow 100 mV 85C" folder at "FMAX" and see that we are good out to about 43 MHz.

Of course, we still have to check our new source code with ISE, because our interrupt synchronization changes. When we don that, we see that our project meets timing requirements in both the Xilinx Spartan 3A family and the Altera Cyclone IV E family devices. So we now have a 20 MHz, enhanced, re-targetable 8085A microprocessor intellectual property that will fit into FPGAs, but is still a little too large to fit into Altera CPLDs.

Exercise  
  1. Retarget your device for a Xilinx Spartan 6 device. Did you get any errors? Did your project meet timing? What kind of warnings did you get?

  2. Why do we need to resynchronize interrupts?

  3. What did we do to the "trap" input? Why?

  4. Why don't we use XST constraints?

  5. How do we add clock constraints for Xilinx? For Altera?

  6. Can you use both clock edges in any FPGA architecture? If not, how can we get around this?