aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2020-01-23 11:16:12 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2020-01-23 11:16:12 +0300
commit35359243a63cac4a9e8cce6bd718f17756ce8a98 (patch)
treedd1a893c31667dfba35bb437071e12c252f49fd4
parentfbf287f57879678fe8cf4a74e07e72ca5c7b153b (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.ucf66
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 ;
+
#======================================================================