diff options
author | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2020-01-23 11:16:12 +0300 |
---|---|---|
committer | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2020-01-23 11:16:12 +0300 |
commit | 35359243a63cac4a9e8cce6bd718f17756ce8a98 (patch) | |
tree | dd1a893c31667dfba35bb437071e12c252f49fd4 | |
parent | fbf287f57879678fe8cf4a74e07e72ca5c7b153b (diff) |
Changed FMC I/O frequency to 45 MHz in the UCF file to match hardware and also
updated offset constraint values accordingly.
Another important change is that the core selector is now multicycle. The I/O
logic runs at 45 MHz, while all the cores and the core selector run at 90 MHz.
The job of the core selector is to distribute the write data (STM32 -> FPGA) to
the particular core being addressed and to select the read data (FPGA -> STM32)
from the core being addressed.
Timing issues arising from the distribution of write commands are mitigated by
replication of data and control signals. Each core has its individual set of
chip select, address and write data registers, they can be placed somewhere
inbetween the core itself and the selector and thus the critical timing paths
become twice shorter.
Readback logic has a huge multiplexor that selects the read data from the core
being addressed and then forwards it into the FMC bus arbiter. Since the FMC
arbiter operates at 45 MHz (twice slower, than the readback multiplexor), it
makes sense to give the multiplexor two 90 MHz clock cycles to select the
value, since the arbiter waits one 45 MHz clock cycle before sampling the
readback data. This is achieved by applying FROM-TO constraint. Note the two
gotches here (took me some time to figure out):
1) you attach the TNM or TNM_NET... well, okay, there's the third potential
gotcha here, since only one of the two works with I/O pads, read the CDG for
more details, but luckily, it's not out case, phew. So, you attach a TNM_NET
to a net, and ISE will follow the net and attach the TNM to **the next
register being driven by this net**. This is somewhat non-obvious: say, you
have a flip-flop called 'something_dout<0>' and it's output net is naturally
also called 'something_dout<0>', attaching TNM_NET to this net doesn't
apply the TNM to the flip-flop, it instead follows the net and attaches the
TNM to all the load flip-flops on the net. For FROM-TO to work as expected
we have to apply TNM_NET to all the output "read data" nets of all the
cores, so that they could be traced into the multiplexor. Note, that for a
multicycle multiplexor you actually need two FROM-TO constraints: one for
the data and one for the control signal.
2) Applying FROM-TO affects both the setup and the hold check in ISE. This is
different from Vivado, when you have to individually specify the setup and
the hold checks.
-rw-r--r-- | ucf/alpha_fmc.ucf | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/ucf/alpha_fmc.ucf b/ucf/alpha_fmc.ucf index 7926762..908f9fe 100644 --- a/ucf/alpha_fmc.ucf +++ b/ucf/alpha_fmc.ucf @@ -46,31 +46,28 @@ #------------------------------------------------------------------------------- -# FMC_CLK Timing (can be up to 90 MHz) +# FMC_CLK Timing #------------------------------------------------------------------------------- NET "fmc_clk" TNM_NET = TNM_fmc_clk; -# 90 MHz -#TIMESPEC TS_fmc_clk = PERIOD TNM_fmc_clk 11.111 ns HIGH 50%; - -# 60 MHz -TIMESPEC TS_fmc_clk = PERIOD TNM_fmc_clk 16.667 ns HIGH 50%; +# 45 MHz +TIMESPEC TS_fmc_clk = PERIOD TNM_fmc_clk 22.222 ns HIGH 50%; #------------------------------------------------------------------------------- # FPGA Pinout #------------------------------------------------------------------------------- # -NET "led_pins<0>" LOC = "U3"; -NET "led_pins<1>" LOC = "T1"; -NET "led_pins<2>" LOC = "W22"; -NET "led_pins<3>" LOC = "AA20"; +NET "led_pins<0>" LOC = "U3"; +NET "led_pins<1>" LOC = "T1"; +NET "led_pins<2>" LOC = "W22"; +NET "led_pins<3>" LOC = "AA20"; # -NET "led_pins<*>" IOSTANDARD = "LVCMOS33"; -NET "led_pins<*>" SLEW = SLOW; -NET "led_pins<*>" DRIVE = 8; +NET "led_pins<*>" IOSTANDARD = "LVCMOS33"; +NET "led_pins<*>" SLEW = SLOW; +NET "led_pins<*>" DRIVE = 8; # -NET "gclk_pin" LOC = "D17" | IOSTANDARD = "LVCMOS33" ; +#NET "gclk_pin" LOC = "D17" | IOSTANDARD = "LVCMOS33" ; # NET "fmc_clk" LOC = "W11" | IOSTANDARD = "LVCMOS33" ; NET "fmc_ne1" LOC = "V5" | IOSTANDARD = "LVCMOS33" ; @@ -155,34 +152,57 @@ NET "mkm_do" LOC = "Y1" | IOSTANDARD = "LVCMOS33" ; # MKM_FPGA_MISO # Control signals NE1, NL and NWE all have different timing values. # Instead of writing individual constraints for every control signal, the most # strict constraint is applied to all control signals. This should not cause -# any P&R issues, since Spartan-6 (and Artix-7) can handle 90 MHz easily. +# any P&R issues, since Spartan-6 (and Artix-7) can handle 45 MHz very easily. # # NOE signal is not constrained, since it drives "T" input of IOBUF primitive. # -# Data and Address buses also have different timings, with Data bus timing being +# Data and Address buses also have different timings, with Address bus timing being # more strict. # -# Oh, and the datasheet doesn't explicitly specify hold time for the data bus. +# Oh, and the datasheet doesn't explicitly specify hold time for the data bus. But that +# is not a problem, since it's apparently impossible to specify both OFFSET OUT BEFORE +# and AFTER at the same time :) # +# "ideal" values +#TIMEGRP "TNM_FMC_IN_DATA" OFFSET = IN 8.5 ns VALID 19.5 ns BEFORE "fmc_clk" RISING ; +#TIMEGRP "TNM_FMC_IN_ADDR" OFFSET = IN 11.0 ns VALID 11.0 ns BEFORE "fmc_clk" RISING ; +#TIMEGRP "TNM_FMC_IN_CONTROL" OFFSET = IN 10.5 ns VALID 15.5 ns BEFORE "fmc_clk" RISING ; + +# more realistic ("strict") values with 1 ns subtracted from both sides of the +# valid window +TIMEGRP "TNM_FMC_IN_DATA" OFFSET = IN 7.5 ns VALID 17.5 ns BEFORE "fmc_clk" RISING ; +TIMEGRP "TNM_FMC_IN_ADDR" OFFSET = IN 10.0 ns VALID 9.0 ns BEFORE "fmc_clk" RISING ; +TIMEGRP "TNM_FMC_IN_CONTROL" OFFSET = IN 9.5 ns VALID 13.5 ns BEFORE "fmc_clk" RISING ; + NET "fmc_d<*>" TNM = "TNM_FMC_IN_DATA" ; NET "fmc_a<*>" TNM = "TNM_FMC_IN_ADDR" ; - +# NET "fmc_ne1" TNM = "TNM_FMC_IN_CONTROL" ; NET "fmc_nl" TNM = "TNM_FMC_IN_CONTROL" ; NET "fmc_nwe" TNM = "TNM_FMC_IN_CONTROL" ; -TIMEGRP "TNM_FMC_IN_DATA" OFFSET = IN 3.0 ns VALID 8.5 ns BEFORE "fmc_clk" RISING ; -TIMEGRP "TNM_FMC_IN_ADDR" OFFSET = IN 5.5 ns VALID 5.5 ns BEFORE "fmc_clk" RISING ; -TIMEGRP "TNM_FMC_IN_CONTROL" OFFSET = IN 5.0 ns VALID 10.0 ns BEFORE "fmc_clk" RISING ; - #------------------------------------------------------------------------------- # FMC Output Timing #------------------------------------------------------------------------------- +TIMEGRP "TNM_FMC_OUT_DATA" OFFSET = OUT 6.0 ns BEFORE "fmc_clk" FALLING; #+1ns + NET "fmc_d<*>" TNM = "TNM_FMC_OUT_DATA" ; -TIMEGRP "TNM_FMC_OUT_DATA" OFFSET = OUT 6.0 ns AFTER "fmc_clk" RISING; + +#------------------------------------------------------------------------------- +# Core Selector Multi-Cycle Readback Mux +#------------------------------------------------------------------------------- +NET "cores/reg_read_data_*<*>" TNM_NET = TNM_CORE_SELECTOR_MUX_INPUT ; +NET "cores/addr_core_num_dly2<*>" TNM_NET = TNM_CORE_SELECTOR_MUX_CONTROL ; +NET "cores/pipe_read_data_*<*>" TNM_NET = TNM_CORE_SELECTOR_MUX_OUTPUT ; + +TIMEGRP "TNM_CORE_SELECTOR_MUX_SRC" = "TNM_CORE_SELECTOR_MUX_INPUT" "TNM_CORE_SELECTOR_MUX_CONTROL" ; +TIMEGRP "TNM_CORE_SELECTOR_MUX_DST" = "TNM_CORE_SELECTOR_MUX_OUTPUT" ; + +TIMESPEC TS_core_selector = FROM TNM_CORE_SELECTOR_MUX_SRC TO TNM_CORE_SELECTOR_MUX_DST TS_clkmgr_mmcm_inst_mmcm_clkout0 * 2 ; + #====================================================================== |