Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

timing constraints for EHPI DSP to FPGA asynchronous interface

Hi, I am trying to write timing constraints for connecting a TI DSP, TMS320VC5510A, to a Cyclone IV FPGA. The bus used is EHPI in Multiplexed mode. It looks confusing because the interface is asynchronous, based on HDS / ADS {data and address strobes} which time the latching of data / addresses / control information to/from the DSP/FPGA. I am not sure yet how best to implement the SDC constraints. Does anybody have experience doing this ?

I have been using Rsycs excellent User Guide for TimeQuest, but it hasnt yet become clear how to optimally constrain such an asynchronous interface !

Many thanks, DrPositiveLogic

20 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Rysc,

    It was buried.....when i did a node search and changed the constraint to this:

    # Create Generated Clock for STROBE from PLL driving REG

    create_generated_clock -name HAD_STROBE_REG -source EHPI_PLL_inst|altpll_component|auto_generated|pll1|clk[0] [get_registers {bidir_interface:uut|hds_ni}]

    ....it now works....and i beleive i now have some working (at least syntactically !) constaints. If i run the report IO timing i get lots of failling paths ...well at least thats better than none before ...so progress ..:)

    Many many thanks for your help !
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Your well on your way. I spend a lot of time looking at the report_timing results. Note that report_timing -setup generally has only two numbers that come from your .sdc, the setup relationship and the external delay(oExt or iExt). The external delays are pulled directly from your -max/-min values. The setup relationship comes from your clock descriptions and multicycles. For now, ignore whether it meets timing or not, and just look at those two values and see if they're what you want. Same goes for hold. If your constraints are correct, THEN look at why it's failing. (And remember that you may have to re-compile once they're correct, as the place-and-route you're looking at is based on incorrect constraints). Good luck.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Rysc,

    I have a few other questions about constraing the EHP interface, which reference how to apply sensible constaints in TimeQuest.

    The thing that throws me is this: An FSM drives the following signals out

    to the DSP via a top level module ...the top level module instantiates

    the actual EHPI driver VHDL module, so this is a 2 tier hierarchy :

    1) hcs_ni : REG : directly drives output port : hcs_n

    2) has_n : REG : directly drives output port : has_n

    3) hds_ni : REG : directly drives output port : hds_n

    4) hrnw : REG : directly drives output port : hrnw

    5) had_oe : port is driven as follows: had_oe <= (ha_ena or ha_ena_d);

    where ha_ena and ha_ena_d are both REGS

    had_oe is the Tristate control for the Bidirectional data/addr/cotrol bus

    to the DSP.

    6) had_rddata : 16 bit input bus from top level, REGISTERED in EHPI module

    7) had_wrdata : 16 bit outputbus to top level and DSP HAD bus

    In the top level module which instantiates the EHPI driver module the

    top level BIDIR I/O HAD bus is driven as so:

    -- Read Data always reflects the INPUT BUS

    had_rddata <= had;

    -- write control for HAD bus

    had <= had_wrdata when had_oe_r = '0' else (others => 'Z');

    8) I also have a few feedback and handshaking signals from the DSP

    a) hrdy : DSP ready line

    b) h2dack_n : DSP acknowledge of a transfer complete...

    c) d2hreq : DSP request for service..

    These sre all used by logic interal to the EHPI driver....basically

    in parts of the FSM, but they are all REGISTERED before use.

    Now my questions are:

    1) For the actual interface signals:

    a) hcs_n (EHPI DSP chip select, active low) is asserted by the FSM

    a couple of clocks before any action takes place, ie before any read or

    writes start.

    b) has_n (address / control strobe, DSP latches HAD[1:0] on falling edge). This signal is asserted a clock after chip select and a clock before hds_n has been asserted.

    c) hds_n (data strobe, DSP latches data from the FPGA HAD[15:0] bus on the rising edge

    d) hrnw : Read not write : this signal is asserted two clocks before chip select by the FSM

    So as you can see in a way this interface is self timed,,,,because of the FSM control states which assert and de-assert each of the interface signals in a well defined sequence, with whole clock delays between state changes.

    The tristate control is another worrying part....because it has

    some OR logic after the pair of registers driving the actual Tristate contro port signal, had_oe. How is best to constrain this type if siganlling ...would i be best to add a REG like so:

    ADD CLOCKED REGISTER : had_oe_reg <= ha_ena or ha_ena_d);

    then async apply : had_oe <= had_oe_reg;

    But i still need to apply sensible constraints to all the EHPI to/from DSP signals so that TimeQuest can optimize the design and generate sensible reports.

    So Is my current approach sensible and best practice for this type of interface do you think ?

    Many many thanks for your help :)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Ugh. You've got a tough one. Let's step back for a second and look at what's occuring. When hcs_n is asserted, it probably has a min/max range that it needs to get out of the FPGA without causing a failure. For example, if hcs_n's delay is a cycle longer than has_n, then even though it is asserted a cycle before, it would go active after has_n.

    For all of the signals above, you might be better off with a "range" rather than using standard synchronous trasfers. For example, you could constrain them all with set_max_delay 12.5 and set_min_delay 0, which is very much like a Tco range of 0ns to 12.5ns. (The User Guide talks about some of the issues with using set_max/min_delay for I/O constraints, but I think it works for you here). The nice thing is that you can tweak the values, i.e. you could make it set_max_delay 14.5 and set_min_delay 2, which shifts everything over by 2ns. Basically you're constraining everything to occur within one period, but you don't care where that period is, because your logic sends them all out on different edges and hence "sequences them".

    I think you still then want to use has_n and hds_n as clocks for the address/control/data. Since they're latching on the falling edge, you might need to add -invert to the generated clock on these output ports, so the setup relationship will be shifted a half-cycle.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi there Rysc,,,,,brilliant answer ! I have been thinking along similar lines....ie using set min and max delays on each output....but was put off

    a bit by your User guide....which goes into quite some detail about the problems that these constraints can cause. But now you have confirmed its probably ok to use them in this case, i will try them.

    The clock inversion is a good tip....the has_n strobe is used to strobe in the HAD bus (used as address and control bus in conjunction with has_n). The hds_n strobe is +ve edge triggered and clock in the data from the same HAD bus.

    Here is my current HAS_N strobe clock def:

    create_generated_clock -name HAS_STROBE -source [get_pins {EHPI_PLL_inst|altpll_component|auto_generated|pll1|clk[0]}] [get_registers {bidir_interface:uut|has_n}]

    How do i invert this ?

    many thanks :)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Rysc:

    Does this sdc file look reasobale to you ? I am now using set_max_delay and set_min_delay and the HAS_STROBE is falling edge triggered ...i have

    set the HASOutputDelayMax to the clock periof (12.6 ns) for setup and

    the HASOutputDelayMin to 0 for hold.

    On the data path, HADOutputDelayMax is also set to 12.6ns and

    HADOutputDelayMin:) is set to 0 for hold.

    cheers :)

    # **********************************************************************************# Golden Constraints file for EHPI to DSP interface# **********************************************************************************# **********************************************************************************# Define all bas clock periods# **********************************************************************************# # Set period for EHPI base clock#

    set ehpi_base_period 25.201# set virtual DSP clock used to sample EHPI generated ctrl, strobes and data

    set dsp_clk_period [expr $ehpi_base_period/2]# DEFINE Timing constraints from TI Datasheet

    set DSP_Th 4

    set DSP_TcoMax 16# set max and min est DSP to FPGA delays

    set Max_fpga2dsp 2

    set Min_fpga2dsp 1# set max output delay for signals sampled by DSP from has_n strobe

    set HASOutputDelayMax $dsp_clk_period# set min Output delay for signals sampled by DSP from has_n strobe

    set HASOutputDelayMin 0# set max output delay for signals sampled by DSP from hds_n strobe

    set HADOutputDelayMax $dsp_clk_period# set min Output delay for signals sampled by DSP from has_n strobe

    set HADOutputDelayMin 0# set max INPUT delays for DSP to FPGA transfers based on EHPI MASTER CLOCK

    set InputDelayMax [expr $dsp_clk_period/2] # [expr $DSP_TcoMax + $Max_fpga2dsp]# set max INPUT delays for DSP to FPGA transfers based on EHPI MASTER CLOCK

    set InputDelayMin 0# [expr -1*$DSP_Th + $Min_fpga2dsp]# create constraint for input clock pin to PLL

    create_clock -name inclk0 -period $ehpi_base_period [get_ports inclk0]

    derive_pll_clocks

    derive_clock_uncertainty# Create Generated Clock for STROBE write output HAS

    create_generated_clock -invert -name HAS_STROBE -source [get_pins {EHPI_PLL_inst|altpll_component|auto_generated|pll1|clk[0]}] [get_registers {bidir_interface:uut|has_n}]# Create Generated Clock for STROBE to output pin

    create_generated_clock -name HAD_STROBE -source [get_registers {bidir_interface:uut|hds_ni}] [get_ports hds_n]

    set_clock_groups -asynchronous

    -group {inclk0

    EHPI_PLL_inst|altpll_component|auto_generated|pll1|clk[0]

    HAS_STROBE

    HAD_STROBE

    }

    # *************************************************************************************************************# Constrain EHPI to DSP CTRL strobed output paths# *************************************************************************************************************# Output MAX delay on HAS bus : using EHPI Virtual Address strobe# set_output_delay -clock HAS_STROBE -max $HASOutputDelayMax [get_ports {had[0] had[1] hrnw}]

    set_max_delay -to [get_ports {had[0] had[1] hrnw}] $HASOutputDelayMax # Output MIN delay on HAD bus : using EHPI Virtual Address strobe# set_output_delay -clock HAS_STROBE -min $HASOutputDelayMin [get_ports {had[0] had[1] hrnw}]

    set_min_delay -to [get_ports {had[0] had[1] hrnw}] $HASOutputDelayMin# *************************************************************************************************************# Constrain DSP to EHPI Input ports# *************************************************************************************************************# input MAX delay on HAD bus : using EHPI Virtual Data Strobe # set_input_delay -clock HAD_STROBE -max $InputDelayMax [get_ports {had

    [*]}]

    set_max_delay -from [get_ports {had

    [*]}] $InputDelayMax# input MIN delay on HAD bus : using EHPI Virtual Data Strobe # set_input_delay -clock HAD_STROBE -min $InputDelayMin [get_ports {had

    [*]}]

    set_min_delay -from [get_ports {had

    [*]}] $InputDelayMin# *************************************************************************************************************# Constrain DSP to EHPI Output ports# *************************************************************************************************************# Output MAX delay on HAD bus : using EHPI Virtual clock # set_output_delay -clock HAD_STROBE -max $OutputDelayMax [get_ports {had

    [*]}]

    set_max_delay -to [get_ports {had[2] had[3] had[4] had[5] had[6] had[7] had[8] had[9] had[10] had[11] had[12] had[13] had[14] had[15]}] $HADOutputDelayMax# Output MIN delay on HAD bus : using EHPI Virtual clock # set_output_delay -clock HAD_STROBE -min $OutputDelayMin [get_ports {had

    [*]}]

    set_min_delay -to [get_ports {had[2] had[3] had[4] had[5] had[6] had[7] had[8] had[9] had[10] had[11] had[12] had[13] had[14] had[15]}] $HADOutputDelayMin
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You can invert a generated clock with -invert.

    In reality, that's probably not correct, as it's not really inverted. You could also add -clock_fall to your set_output_delay and it would know it's latching on the falling edge. (The two solutions should give the same analysis in the end). Some other quick thoughts:

    - I was thinking of still using set_output_delay for the address/data outputs, since the strobes act a lot like a clock. In that case, you don't really have to constrain the strobes themselves, since the data will be constrained in relation to them. What you have now is more of a "I know the strobes will get out between a-b times, and so my data needs to get out between x-y times plus the clock cycle in my desgin..."

    Note that inverting the output clock doesn't matter if you don't use it(which you're not with set_max_delay), and that even if you did, set_max_delay would ignore that inversion since set_max_delay overrides the calculated setup relationship.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Rysc,

    Thanks for your further insights ! Currently i have the design constrained and passing timing....using the following constraints. So at the momemt i am using the set_min_delay / set_max_delay on all output signals to the DSP from the FPGA. I have a multicycle constraint on all of the input signals from the DSP to the FPGA, using the set_input_delay -min / max

    style.

    I am not 100% sure these constraints model my physical design however.

    The set_max_delay is saying : as long as you get out of the FPGA in less than a clock, then we are all happy. This is the external setup to the DSP. The min delay is set to 0 for the DSP hold constraint.

    Is this right ? I think this may be unrealistic, and the max output delay should really be ; clock period - [DSP setup + board delays]....

    Maybe it would be better then if i use your other suggestion to use set_output_delay:

    - then for the HAS_STROBE apply this as a -clock_fall to the ADDRESS / Control signals {had[0], had[1], rdnw}

    - for the HAD_STROBE {rising edge clocked) apply the set_output_delay to the had[15:0] data bus signals.

    Question: now i have a pair of constraints applied to the had[0] had[1] signals....will TimeQuest analyze i assume both paths and report these two signals setup/hold paths for both strobes ?

    Many thanks :)

    # *************************************************************************************************************# Set Multicycles on DSP to EHPI data output bus : 2 clocks# *************************************************************************************************************

    set_multicycle_path -from [get_ports {had

    [*]}] -to [get_registers {bidir_interface:uut|hdata

    [*]}] -setup -end 2

    set_multicycle_path -from [get_ports {had

    [*]}] -to [get_registers {bidir_interface:uut|hdata

    [*]}] -hold -end 1

    # *************************************************************************************************************# Constrain EHPI to DSP CTRL strobed output paths# *************************************************************************************************************# Output MAX delay on HAS bus : using EHPI Virtual Address strobe# set_output_delay -clock HAS_STROBE -max $HASOutputDelayMax [get_ports {had[0] had[1] hrnw}]

    set_max_delay -to [get_ports {had[0] had[1] hrnw}] $HASOutputDelayMax # Output MIN delay on HAD bus : using EHPI Virtual Address strobe# set_output_delay -clock HAS_STROBE -min $HASOutputDelayMin [get_ports {had[0] had[1] hrnw}]

    set_min_delay -to [get_ports {had[0] had[1] hrnw}] $HASOutputDelayMin

    # *************************************************************************************************************# Constrain DSP to EHPI Input ports# *************************************************************************************************************# input MAX delay on HAD bus : using EHPI Virtual Data Strobe

    set_input_delay -clock EHPI_PLL_inst|altpll_component|auto_generated|pll1|clk[0]} -max $InputDelayMax [get_ports {had

    [*]}]# set_max_delay -from [get_ports {had

    [*]}] $InputDelayMax# input MIN delay on HAD bus : using EHPI Virtual Data Strobe

    set_input_delay -clock EHPI_PLL_inst|altpll_component|auto_generated|pll1|clk[0] -min $InputDelayMin [get_ports {had

    [*]}]# set_min_delay -from [get_ports {had

    [*]}] $InputDelayMin

    # *************************************************************************************************************# Constrain DSP to EHPI Output ports# *************************************************************************************************************# Output MAX delay on HAD bus : using EHPI Virtual clock # set_output_delay -clock HAD_STROBE -max $OutputDelayMax [get_ports {had

    [*]}]

    set_max_delay -to [get_ports {had[2] had[3] had[4] had[5] had[6] had[7] had[8] had[9] had[10] had[11] had[12] had[13] had[14] had[15]}] $HADOutputDelayMax# Output MIN delay on HAD bus : using EHPI Virtual clock # set_output_delay -clock HAD_STROBE -min $OutputDelayMin [get_ports {had

    [*]}]

    set_min_delay -to [get_ports {had[2] had[3] had[4] had[5] had[6] had[7] had[8] had[9] had[10] had[11] had[12] had[13] had[14] had[15]}] $HADOutputDelayMin
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Note that set_input/output_delay and set_max_delay/set_min_delay work together. For example, if you do a set_output_delay assignment to an I/O, there will be three numbers from your .sdc, the launch edge, the latch edge, and the oExt delay. The launch and latch come from the clock relationships, while oExt comes directly from the -max and -min values. If you then apply a set_max_delay, the launch edge will become 0, the latch edge will become the -max value, but the oExt from your set_output_delay will be used. So you could use the set_output_delay to say what the Tsu of the external device is, and then use set_max_delay like you are now. (You could also just tighten your set_max_delay constraint by the Tsu amount and get the same results).

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    :) Hello Rysc,

    thanks for your reply....one insight that comes up with your analysis is that ...in my case of a strobed external interface.....the launch / latch clock relationships are:

    1) FPGA clock on the register which clocks in the data HAD_REG a clock before the strobe is generated

    2) Latch clock for HAD data bus is hds_n (rising edge) ....

    3) FPGA clock on the register which clocks in the data HCTRL_REG bits a clock before the strobe is generated

    4) Latch clock for HAD data bus is has_n (falling edge) ....

    There appears to be a multicycle constaint here...the HAD_REG and HCTRL_REG are both clocked in by the fSM a couple of clocks before either of the strobes is generated (again by the FSM).

    On the READ side (FPGA reads from DSP) the lauch clock is a DSP internal clock, which generates a DSP_READY flag to the FPGA...the latch clock is the hds_n signal, driven by the FPGA FSM after it detects the DSP_READY flag has gone high.

    So on the FPGA to DSP side i think these constraints should be OK:

    a) using DSP_TSu and FPGA_to_DSP_Delay_Max (estimated board delays) :

    set_output_delay -max [expr DSP_TSu + FPGA_to_DSP_Delay_Max]

    This is the FPGA to DSP setup requirement

    b) using DSP_Th and FPGA_to_DSP_Delay_Min (estimated board delays) :

    set_output_delay -min [expr DSP_TSu + FPGA_to_DSP_Delay_Min]

    This is the FPGA to DSP hold requirement

    For the DSP to FPGA path:

    c) set_input_delay -max = DSP_Tco_max + FPGA_to_DSP_Delay_Max

    d) set_input_delay -min = DSP_Tco_min + FPGA_to_DSP_Delay_Min

    BUT i dont see now how or why i would also need to use a set_max_delay or set_mn_delay constraint...as you implied here:

    If you then apply a set_max_delay, the launch edge will become 0, the latch edge will become the -max value, but the oExt from your set_output_delay will be used. So you could use the set_output_delay to say what the Tsu of the external device is, and then use set_max_delay like you are now. (You could also just tighten your set_max_delay constraint by the Tsu amount and get the same results).

    cheers