Design patterns for FPGA timing constraints - Page 1
Forum section: electronics / general

author: tggzzz
author_rank: Super Contributor
timestamp: January 07, 2015, 04:22:03 pm
content: I'll shortly be starting a new project using Vivado to design a Zynq FPGA.I'm looking for tutorials about what is necessary and sufficient in the form of specifying timing constraints for reliable routing and operation. I'm not interested in all the bells and whistles thatcouldbe specified, just in simple, reliable and easy to understand specification strategies. In other words, I'd like to see some practical "design patterns", not all the arcane possibilities described in the reference manuals!The logic design patterns will be based aroundblocks containing FSMs in the form of one VHDL process for the combinatorial logic plus another VHDL process for the registerstwo (or more!) clock domains, some with period X, some period 8X (i.e. a nice simple integer relationship)re-synchronisation across those domain boundaries, using predefined standard Xilinx FPGA primitivesexternal i/o timing is, perhaps surprisingly, "don't care"; I'll resynchronise inputs myself, and will accept whatever the outputs provideand I'm presuming that the PL<->PS interface will be "dealt with" by Vivado without my interventionI'm not interested in which FPGA primitives to use: there's plenty of literature describing design patterns for those. In comparison, the design patterns for timing constraints can best be described as under-documented!

author: nctnico
author_rank: Super Contributor
timestamp: January 07, 2015, 04:54:31 pm
content: In my experience you have to make sure all paths are constraint. Inputs to flipflops, the clock domains, the worst case allowable delay between unrelated clock domains in order for asynchronous clock domain crossing to work, the flipflops to the outputs.Usually generated constraints only constrain the clock (and derived clocks) domains. The rest is up to you. I often use the input and output constraints to force the place & route to put the flipflops for certain input or output signals inside an I/O buffer primitive to meet timing of external devices.

author: tggzzz
author_rank: Super Contributor
timestamp: January 07, 2015, 06:17:27 pm
content: Quote from: nctnico on January 07, 2015, 04:54:31 pmCan you point to any worked examples, please.QuoteI will have to manually place the i/o blocks, and probably the next level after that too.

author: nctnico
author_rank: Super Contributor
timestamp: January 07, 2015, 08:25:29 pm
content: Worked examples would mean posting something like this:TIMEGRP all_ff = FFS;TIMEGRP debug_pads = PADS("debug*");TIMESPEC TS_DEBUG_OUT = FROM "all_ff" TO "debug_pads" 40 ns;It basically tells the place & route to don't care about timing on the debug outputs. Edit: I used this for a Spartan 6 device.Doing manual placement may seem cool but it's better to leave it to the optimizer (just like having a C compiler deal with optimisation). Up to now I only had one design where I had to lock a couple of blockrams in order to steer the place&route in the right direction. The best way is to use constraints to achieve timing goals.

author: hamster_nz
author_rank: Super Contributor
timestamp: January 07, 2015, 08:29:40 pm
content: Documentation on timing constraints is pretty sparse and not very helpful unless you already know what is going on. I am no expert at this, and have decided to take the low road for all my projects. This is my low road:1. Set period constraints on all your clocks.2. Always ensure that any off-FPGA clock forwarding is implemented using a DDR register.Code:sdram_clk_forward : ODDR2generic map(DDR_ALIGNMENT => "NONE", INIT => '0', SRTYPE => "SYNC")port map (Q => sdram_clk, C0 => clk, C1 => not clk, CE => '1', R => '0', S => '0', D0 => '0', D1 => '1');3. Ensure that all critical output signals are registered in an IOB4. Ensure that all critical input signals are registered in an IOB.I haven't attempted this in Vivado yet, but in ISE I use the following VHDL:Code:signal iob_command : std_logic_vector( 3 downto 0) := CMD_NOP;signal iob_address : std_logic_vector(12 downto 0) := (others => '0');signal iob_data : std_logic_vector(15 downto 0) := (others => '0');signal iob_dqm : std_logic_vector( 1 downto 0) := (others => '0');signal iob_cke : std_logic := '0';signal iob_bank : std_logic_vector( 1 downto 0) := (others => '0');attribute IOB: string;attribute IOB of iob_command: signal is "true";attribute IOB of iob_address: signal is "true";attribute IOB of iob_dqm : signal is "true";attribute IOB of iob_cke : signal is "true";attribute IOB of iob_bank : signal is "true";attribute IOB of iob_data : signal is "true";This is able to ensurea. I can ignore any on-chip routing delays, which change from build to build.b. The output signals have minimal skew relative to each other.c. The input signals are sampled at pretty much the same time.d. The phase of any clock going off chip is pretty consistent with other control signals (and it is easy to get a signal that is 180 degrees out of phase)e. I don't have to add timing constraints on every signalf. I don't need to play around with IDELAY/ODELAY settings.The downside is that there is additional cycle or two of latency when talking off chip (one cycle to register the output, and/or another cycle when the input signals are registered).

author: zapta
author_rank: Super Contributor
timestamp: January 07, 2015, 08:41:47 pm
content: Why two clocks? Isn't it easier and safer to use a single clock and an enable signal that is active every 8th clock?

author: hamster_nz
author_rank: Super Contributor
timestamp: January 07, 2015, 09:10:36 pm
content: Quote from: zapta on January 07, 2015, 08:41:47 pmMaybe. But then the whole design will need to be constrained to the 8x clock speed, and you have a single high fan-out net for the enable single. Place + route then becomes a nightmare, timing gets poor and builds fail. And power usage will be higher as the whole clocking network is being driven at a fast speed.For example, if the 8x domain is 240MHz, all your logic has to be simple enough to run at 240MHz. If you use a second 30 MHz domain, your slow domain can use logic that is eight times more complex and still meet timing.You can get around this somewhat by pipelining the logic in what would be the slow domain, but it has a real P.I.T.A.Mike

author: tggzzz
author_rank: Super Contributor
timestamp: January 07, 2015, 09:13:49 pm
content: Quote from: zapta on January 07, 2015, 08:41:47 pmPotentially, yes, but that will only emerge during detailed design.My concern is that in order to meet timing constraints, it may be beneficial to physically partition the clock domains across the FPGA fabric. There will be a natural logical partitioning as well, potentially with FIFOs between domains.

author: nctnico
author_rank: Super Contributor
timestamp: January 07, 2015, 09:15:57 pm
content: Quote from: zapta on January 07, 2015, 08:41:47 pmNo. You'd have to add extra constraints to allow for more time between the clocks on a signal for which the clock is enabled every Nth clock. It is possible but a nuisance. Every FPGA design I've worked on has 2 clocks or more. A slow clock for housekeeping (say 10MHz), a medium clock (say 50MHz) for logic and a fast clock which is used for high speed stuff like getting data from an ADC. You can't run everything in an FPGA from a >100MHz clock because there is a limited amount of fast routing resources. Using a slow clock allows to use the otherwise wasted resources in an FPGA.Usually these clocks are derived from the same input clock using internal (D)PLLs (or whatever they are called) so their timing relation is fixed. The place & route uses the timing constraints from the master clock to determine the timing constraints for the derived clocks and their relation to eachother.

author: tggzzz
author_rank: Super Contributor
timestamp: January 07, 2015, 09:19:27 pm
content: Quote from: hamster_nz on January 07, 2015, 09:10:36 pmJust so.I'm going to be sucking ISERDES inputs as hard as I can (and then some), then processing at /8 or /16 or /32 speeds as feels right. The parallel processing of what remains essentially a serial data stream will be, um, interesting.But I'm not interested in the logic, since I know I can figure that out. It is judicious application if timing constraints that is my current concern, and any pointers to idiots intros would be appreciated.

author: tggzzz
author_rank: Super Contributor
timestamp: January 07, 2015, 09:22:01 pm
content: Quote from: nctnico on January 07, 2015, 09:15:57 pmPrecisely what I expect to happen. Any pointers to example timing constraints - in terms of what I willand won'thave to specify - would be welcomed.

author: hamster_nz
author_rank: Super Contributor
timestamp: January 07, 2015, 10:09:59 pm
content: Quote from: tggzzz on January 07, 2015, 09:19:27 pmI've got a few projects on my Wiki that might be of interest to you - they are for Spartan 6 but might give you some insight:Getting the SERDES clocking working at all is a real pain - this might help.http://hamsterworks.co.nz/mediawiki/index.php/OSERDES2_clockingHere's generating output signals with a OSERDES - the only timing constraint needed is the system clock for the onboard XTALhttp://hamsterworks.co.nz/mediawiki/index.php/DVI-D_SerdesSERDES input at around 750Mb/s - the only timing constraint needed is on the HDMI clock signal, to constrain the design to 75MHz - from that the 2x SERDES data clock and 10x IO clock is generated.http://hamsterworks.co.nz/mediawiki/index.php/HDMI_InputIf you were using the ISERDES2, your fabric front-end will run at 1/4th the serial interface's bit rate, and if you are on a dev board (and not a custom designed high-speed PCB) you might get 500Mb/s through the connectors. I can almost squeak 750MB/s though standard 2.54mm headers.

author: tggzzz
author_rank: Super Contributor
timestamp: January 07, 2015, 10:25:46 pm
content: Quote from: hamster_nz on January 07, 2015, 10:09:59 pmThanks for the pointers, I'll follow them up.I'm using a MicroZed, which has reasonable connectors (including lots of grounds!) and claims to be 50 ohm on the microzed board itself. I'll be interested to see what I can shovel through them too

author: hamster_nz
author_rank: Super Contributor
timestamp: January 07, 2015, 10:36:30 pm
content: Just had a look at the I/O Resources guide....http://www.xilinx.com/support/documentation/user_guides/ug471_7Series_SelectIO.pdfYou'll be using the ISERDESE2, giving up to 8:1 deserialzation, and can be chained to get 16:1. I don't think you will be needed a separate fast domain - even at the top speed of 1,250 Mb/s you get a fabric clock rate of < 80 MHz. And given the issue with connectors bandwidth/signal integrity limits you won't be able to use anything near that. Oh, as you are using the MicroZed connectors maybe you will get pretty fast speeds.Pay special attention to "ISERDESE2 Clocking Methods" on page 150. It doesn't look as bad as the clocking needed for Spartan 6.

author: tggzzz
author_rank: Super Contributor
timestamp: January 07, 2015, 10:56:17 pm
content: I smiled when I saw the ISERDES2 specBut this is all too sexy. I'm after the timing constraints :{ Looks like the Vivado timing wizard does a, ahem, wizard job - but I don't like magic that I don't understand.

author: hamster_nz
author_rank: Super Contributor
timestamp: January 08, 2015, 08:37:53 am
content: The only way I've ever seen is first to define the clock:Code:create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]And then to set the delays on the on the data signals in question:Code:set_input_delay –clock sys_clk_pin –max 4 [get_ports DIN]set_input_delay –clock sys_clk_pin –min 1 [get_ports DIN]However, I still like the simplicity of forcing critical registers to be place in IOBs. I've just looked up how to do that in XDC format:Code:set_property IOB TRUE [get_cells Din_reg*]

author: tggzzz
author_rank: Super Contributor
timestamp: January 08, 2015, 10:58:32 am
content: Quote from: hamster_nz on January 08, 2015, 08:37:53 amThat's more than just simple; it is also reliable, transparent, correct, self-documenting, and electrically optimal

author: nctnico
author_rank: Super Contributor
timestamp: January 08, 2015, 04:21:21 pm
content: I'm not sure whether the place and route always listens to these settings. I'd use constraints because you'll get a failed timing constraint if the timing isn't met. Besides that constraints will give the place & route the freedom to use any option it wants as long as the design meets the timing goals. In FPGA design the only thing which counts is meeting the timing goals!

author: tggzzz
author_rank: Super Contributor
timestamp: January 08, 2015, 10:27:18 pm
content: Quote from: nctnico on January 08, 2015, 04:21:21 pmWhich settings do you mean? If it does not listen to IOB placement settings/constraints then the timing is irrelevant!

author: nctnico
author_rank: Super Contributor
timestamp: January 08, 2015, 10:34:41 pm
content: I mean the settings to force signals to use the flipflop in the IOB (IO block).

author: hamster_nz
author_rank: Super Contributor
timestamp: January 08, 2015, 11:03:07 pm
content: Nctnico is right - at least under ISE the IOB constraint was treated as a "nice to have" and would be dropped (with a warning) if it was not possible to implement it as requested.I until the edges of the design settled down I check the Pinout Report and verify that OFF or IFF is set appropriately in the "IO Register" column (as well as it showing as LOCATED). ISE had a habit of ignoring constraint files...

author: tggzzz
author_rank: Super Contributor
timestamp: January 08, 2015, 11:46:37 pm
content: Quote from: hamster_nz on January 08, 2015, 11:03:07 pmMultiple expletives deleted!Thank you both for the "heads up"!