diff options
author | Paul Selkirk <paul@psgd.org> | 2017-09-21 09:20:21 -0400 |
---|---|---|
committer | Paul Selkirk <paul@psgd.org> | 2017-09-21 09:20:21 -0400 |
commit | a4e91b6221f75045dd1d97362e9d12c590ebc15a (patch) | |
tree | 04dc1fbaaca17585754aaa624db08e0dad491a38 | |
parent | 74415e8d386b5080aaf7270a2d5356ed4f533859 (diff) |
Separate FMC test from mainline top-level module.
-rw-r--r-- | build/Makefile | 8 | ||||
-rw-r--r-- | build/Makefile.test | 49 | ||||
-rw-r--r-- | rtl/alpha_fmc_test.v | 227 | ||||
-rw-r--r-- | rtl/alpha_fmc_top.v | 69 | ||||
-rw-r--r-- | ucf/alpha_fmc_test.ucf | 199 |
5 files changed, 481 insertions, 71 deletions
diff --git a/build/Makefile b/build/Makefile index 763ad5e..4e3a9bb 100644 --- a/build/Makefile +++ b/build/Makefile @@ -25,10 +25,10 @@ all: $(project).bit CONFIG = $(CORE_TREE)/platform/common/config CONFIG_BOARD = alpha CONFIG_PROJECT = hsm -CONFIG_GEN = $(CONFIG)/core_config.py -c $(CONFIG)/core.cfg -b $(CONFIG_BOARD) -p $(CONFIG_PROJECT) +CONFIG_GEN = $(CONFIG)/core_config.py -c $(CONFIG)/core.cfg -b $(CONFIG_BOARD) core_selector.v core_vfiles.mk: - $(CONFIG_GEN) + $(CONFIG_GEN) -p $(CONFIG_PROJECT) # Build some different configurations @@ -56,6 +56,10 @@ hsm: $(CONFIG_GEN) -p hsm $(MAKE) project=$(project)_hsm ucf=$(ucf) +hsm-super: + $(CONFIG_GEN) -p hsm-super + $(MAKE) project=$(project)_hsm-super ucf=$(ucf) + # Verilog files that always go with builds on this platform. vfiles = \ diff --git a/build/Makefile.test b/build/Makefile.test new file mode 100644 index 0000000..7243bd5 --- /dev/null +++ b/build/Makefile.test @@ -0,0 +1,49 @@ +# Localize all the relative path awfulness in one variable. + +CORE_TREE := $(abspath ../../..) + +# Figure out what the native word size is on the build host, because +# the XiLinx tools care for some reason. + +WORD_SIZE := $(shell python -c 'from struct import pack; print len(pack("L", 0)) * 8') + +# Parameters to xilinx.mk. + +project ?= alpha_fmc_test +vendor = xilinx +family = artix7 +part = xc7a200tfbg484-3 +top_module = alpha_fmc_top +isedir = /opt/Xilinx/14.7/ISE_DS +xil_env = . $(isedir)/settings$(WORD_SIZE).sh +ucf ?= ../ucf/$(project).ucf + +all: $(project).bit + +# Verilog files that always go with builds on this platform. + +vfiles = \ + $(CORE_TREE)/platform/alpha/rtl/alpha_fmc_test.v \ + $(CORE_TREE)/platform/alpha/rtl/alpha_regs.v \ + $(CORE_TREE)/platform/alpha/rtl/alpha_clkmgr.v \ + $(CORE_TREE)/platform/alpha/rtl/clkmgr_mmcm.v \ + $(CORE_TREE)/comm/fmc/src/rtl/cdc_bus_pulse.v \ + $(CORE_TREE)/comm/fmc/src/rtl/fmc_arbiter_cdc.v \ + $(CORE_TREE)/comm/fmc/src/rtl/fmc_arbiter.v \ + $(CORE_TREE)/comm/fmc/src/rtl/fmc_d_phy.v \ + $(CORE_TREE)/comm/fmc/src/rtl/fmc_indicator.v \ + $(CORE_TREE)/comm/fmc/src/rtl/fmc_regs.v + +include xilinx.mk + +# 'clean' target collects files by project name, and we just broke that +# by adding configurations + +junk += *.bgn *.bit *.bld *.cfi *.drc *.lso *.map *.mcs *.mrp *.ncd *.ngc \ + *.ngd *.ngm *.pcf *.post_map.twr *.post_map.twx *.prj *.prm *.psr \ + *.scr *.srp *.twr *.twx *_bd.bmm *_bitgen.xwb *_bitgen.xwbt \ + *_err.twr *_err.twx *_par.grf *_par.ncd *_par.pad *_par.par \ + *_par.ptwx *_par.unroutes *_par.xpi *_par_pad.csv *_par_pad.txt \ + *_summary.xml *_usage.xml + +distclean: clean diff --git a/rtl/alpha_fmc_test.v b/rtl/alpha_fmc_test.v new file mode 100644 index 0000000..182911e --- /dev/null +++ b/rtl/alpha_fmc_test.v @@ -0,0 +1,227 @@ +//====================================================================== +// +// alpha_test.v +// ------------ +// Top module for the Cryptech Alpha FPGA framework. This design +// allow us to run the FMC interface at one clock and cores including +// core selector with the always present global clock. +// +// +// Author: Pavel Shatov +// Copyright (c) 2016, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// - Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +`timescale 1ns / 1ps + +module alpha_fmc_top + ( + input wire gclk_pin, // 50 MHz + + input wire ct_noise, // cryptech avalanche noise circuit + + input wire fmc_clk, // clock + input wire [23: 0] fmc_a, // address + inout wire [31: 0] fmc_d, // data + input wire fmc_ne1, // chip select + input wire fmc_noe, // output enable + input wire fmc_nwe, // write enable + input wire fmc_nl, // latch enable + output wire fmc_nwait,// wait + + output wire mkm_sclk, + output wire mkm_cs_n, + input wire mkm_do, + output wire mkm_di, + + output wire [3: 0] led_pins // {red, yellow, green, blue} + ); + + + //---------------------------------------------------------------- + // Clock Manager + // + // Clock manager is used to generate SYS_CLK from GCLK + // and implement the reset logic. + // ---------------------------------------------------------------- + wire sys_clk; + wire sys_rst_n; + + alpha_clkmgr # + ( + .CLK_OUT_MUL (20.0), // 2..64 + .CLK_OUT_DIV (20.0) // 1..128 + ) + clkmgr + ( + .gclk (gclk_pin), + + .sys_clk (sys_clk), + .sys_rst_n (sys_rst_n) + ); + + + //---------------------------------------------------------------- + // BUFG + // + // FMC clock must be routed through the global clocking backbone. + // ---------------------------------------------------------------- + wire fmc_clk_bug; + + BUFG BUFG_fmc_clk + ( + .I (fmc_clk), + .O (fmc_clk_bufg) + ); + + + + //---------------------------------------------------------------- + // FMC Arbiter + // + // FMC arbiter handles FMC access and transfers it into + // `sys_clk' clock domain. + //---------------------------------------------------------------- + + wire [23: 0] sys_fmc_addr; // address + wire sys_fmc_wren; // write enable + wire sys_fmc_rden; // read enable + wire [31: 0] sys_fmc_dout; // data output (from STM32 to FPGA) + reg [31: 0] sys_fmc_din; // data input (from FPGA to STM32) + + fmc_arbiter # + ( + .NUM_ADDR_BITS(24) // change to 26 when Alpha is alive! + ) + fmc + ( + .fmc_clk(fmc_clk_bufg), + .fmc_a(fmc_a), + .fmc_d(fmc_d), + .fmc_ne1(fmc_ne1), + .fmc_nl(fmc_nl), + .fmc_nwe(fmc_nwe), + .fmc_noe(fmc_noe), + .fmc_nwait(fmc_nwait), + + .sys_clk(sys_clk), + + .sys_addr(sys_fmc_addr), + .sys_wr_en(sys_fmc_wren), + .sys_rd_en(sys_fmc_rden), + .sys_data_out(sys_fmc_dout), + .sys_data_in(sys_fmc_din) + ); + + + //---------------------------------------------------------------- + // LED Driver + // + // A simple utility LED driver that turns on the Alpha + // board LED when the FMC interface is active. + //---------------------------------------------------------------- + fmc_indicator led + ( + .sys_clk(sys_clk), + .sys_rst_n(sys_rst_n), + .fmc_active(sys_fmc_wren | sys_fmc_rden), + .led_out(led_pins[0]) + ); + + + //---------------------------------------------------------------- + // Dummy Register + // + // General-purpose register to test FMC interface using STM32 + // demo program instead of core selector logic. + // + // This register is a bit tricky, but it allows testing of both + // data and address buses. Reading from FPGA will always return + // value, which is currently stored in the test register, + // regardless of read transaction address. Writing to FPGA has + // two variants: a) writing to address 0 will store output data + // data value in the test register, b) writing to any non-zero + // address will store _address_ of write transaction in the test + // register. + // + // To test data bus, write some different patterns to address 0, + // then readback from any address and compare. + // + // To test address bus, write anything to some different non-zero + // addresses, then readback from any address and compare returned + // value with previously written address. + // + //---------------------------------------------------------------- + reg [31: 0] test_reg; + + + + // + // Noise Capture Register + // + reg [31: 0] noise_reg; + + always @(posedge sys_clk) + // + noise_reg <= {noise_reg[30:0], ct_noise}; + + + + always @(posedge sys_clk) + // + if (sys_fmc_wren) begin + // + // when writing to address 0, store input data value + // + // when writing to non-zero address, store _address_ + // (padded with zeroes) instead of data + // + test_reg <= (sys_fmc_addr == {24{1'b0}}) ? sys_fmc_dout : {{8{1'b0}}, sys_fmc_addr}; + // + end else if (sys_fmc_rden) begin + // + // always return current value, ignore address + // + sys_fmc_din <= (sys_fmc_addr == {24{1'b1}}) ? noise_reg : test_reg; + + // when reading from address 0, return the current value + // when reading from other addresses, return the address + //sys_fmc_din <= (sys_fmc_addr == {22{1'b0}}) ? test_reg : {{10{1'b0}}, sys_fmc_addr}; + // + end + + + // + // Dummy assignments to bypass unconnected outpins pins check in BitGen + // + + assign led_pins[3:1] = 3'b000; + + +endmodule diff --git a/rtl/alpha_fmc_top.v b/rtl/alpha_fmc_top.v index 79bfba8..03c2802 100644 --- a/rtl/alpha_fmc_top.v +++ b/rtl/alpha_fmc_top.v @@ -108,17 +108,12 @@ module alpha_fmc_top // FMC arbiter handles FMC access and transfers it into // `sys_clk' clock domain. //---------------------------------------------------------------- - //`define test wire [23: 0] sys_fmc_addr; // address wire sys_fmc_wren; // write enable wire sys_fmc_rden; // read enable wire [31: 0] sys_fmc_dout; // data output (from STM32 to FPGA) -`ifdef test - reg [31: 0] sys_fmc_din; // data input (from FPGA to STM32) -`else wire [31: 0] sys_fmc_din; // data input (from FPGA to STM32) -`endif fmc_arbiter # ( @@ -160,69 +155,6 @@ module alpha_fmc_top ); -`ifdef test - //---------------------------------------------------------------- - // Dummy Register - // - // General-purpose register to test FMC interface using STM32 - // demo program instead of core selector logic. - // - // This register is a bit tricky, but it allows testing of both - // data and address buses. Reading from FPGA will always return - // value, which is currently stored in the test register, - // regardless of read transaction address. Writing to FPGA has - // two variants: a) writing to address 0 will store output data - // data value in the test register, b) writing to any non-zero - // address will store _address_ of write transaction in the test - // register. - // - // To test data bus, write some different patterns to address 0, - // then readback from any address and compare. - // - // To test address bus, write anything to some different non-zero - // addresses, then readback from any address and compare returned - // value with previously written address. - // - //---------------------------------------------------------------- - reg [31: 0] test_reg; - - - - // - // Noise Capture Register - // - reg [31: 0] noise_reg; - - always @(posedge sys_clk) - // - noise_reg <= {noise_reg[30:0], ct_noise}; - - - - always @(posedge sys_clk) - // - if (sys_fmc_wren) begin - // - // when writing to address 0, store input data value - // - // when writing to non-zero address, store _address_ - // (padded with zeroes) instead of data - // - test_reg <= (sys_fmc_addr == {24{1'b0}}) ? sys_fmc_dout : {{8{1'b0}}, sys_fmc_addr}; - // - end else if (sys_fmc_rden) begin - // - // always return current value, ignore address - // - sys_fmc_din <= (sys_fmc_addr == {24{1'b1}}) ? noise_reg : test_reg; - - // when reading from address 0, return the current value - // when reading from other addresses, return the address - //sys_fmc_din <= (sys_fmc_addr == {22{1'b0}}) ? test_reg : {{10{1'b0}}, sys_fmc_addr}; - // - end - -`else // !`ifdef test //---------------------------------------------------------------- // Core Selector // @@ -248,7 +180,6 @@ module alpha_fmc_top .mkm_do(mkm_do), .mkm_di(mkm_di) ); -`endif // diff --git a/ucf/alpha_fmc_test.ucf b/ucf/alpha_fmc_test.ucf new file mode 100644 index 0000000..34b2072 --- /dev/null +++ b/ucf/alpha_fmc_test.ucf @@ -0,0 +1,199 @@ +#====================================================================== +# +# alpha_fmc.ucf +# ------------------- +# Constraint file for implementing the Cryptech Alpha base +# for the Xilinx Artix-7 200T on the Alpha. +# +# +# Author: Pavel Shatov +# Copyright (c) 2016, NORDUnet A/S All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of the NORDUnet nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#====================================================================== + + +#-------------------------------------------------------------------------------- +# GCLK Timing (fixed at 50 MHz) +#-------------------------------------------------------------------------------- +NET "gclk_pin" TNM_NET = TNM_gclk; +TIMESPEC TS_gclk = PERIOD TNM_gclk 20 ns HIGH 50%; + + +#------------------------------------------------------------------------------- +# FMC_CLK Timing (can be up to 90 MHz) +#------------------------------------------------------------------------------- +NET "fmc_clk" TNM_NET = TNM_fmc_clk; +TIMESPEC TS_fmc_clk = PERIOD TNM_fmc_clk 90 MHz 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<*>" IOSTANDARD = "LVCMOS33"; +NET "led_pins<*>" SLEW = SLOW; +NET "led_pins<*>" DRIVE = 8; +# +NET "gclk_pin" LOC = "D17" | IOSTANDARD = "LVCMOS33" ; +# +NET "fmc_clk" LOC = "W11" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_ne1" LOC = "V5" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_noe" LOC = "W16" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_nwe" LOC = "AA6" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_nl" LOC = "W17" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_nwait" LOC = "Y6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +# +NET "fmc_a<0>" LOC = "Y17" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<1>" LOC = "AB16" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<2>" LOC = "AA16" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<3>" LOC = "Y16" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<4>" LOC = "AB17" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<5>" LOC = "AA13" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<6>" LOC = "AB13" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<7>" LOC = "AA15" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<8>" LOC = "AB15" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<9>" LOC = "Y13" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<10>" LOC = "AA14" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<11>" LOC = "Y14" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<12>" LOC = "AB10" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<13>" LOC = "V2" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<14>" LOC = "AB12" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<15>" LOC = "AB8" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<16>" LOC = "AA9" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<17>" LOC = "AA8" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<18>" LOC = "Y7" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<19>" LOC = "AB21" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<20>" LOC = "AB22" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<21>" LOC = "AB20" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<22>" LOC = "Y21" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<23>" LOC = "Y22" | IOSTANDARD = "LVCMOS33" ; +#NET "fmc_a<24>" LOC = "AB18" | IOSTANDARD = "LVCMOS33" ; +#NET "fmc_a<25>" LOC = "AA19" | IOSTANDARD = "LVCMOS33" ; +# +NET "fmc_d<0>" LOC = "AB7" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<1>" LOC = "AB6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<2>" LOC = "U1" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<3>" LOC = "U2" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<4>" LOC = "AB11" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<5>" LOC = "AA11" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<6>" LOC = "Y11" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<7>" LOC = "Y12" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<8>" LOC = "Y18" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<9>" LOC = "AA21" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<10>" LOC = "W20" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<11>" LOC = "N15" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<12>" LOC = "U20" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<13>" LOC = "AA1" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<14>" LOC = "AB1" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<15>" LOC = "AB2" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<16>" LOC = "AB3" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<17>" LOC = "Y3" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<18>" LOC = "AA3" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<19>" LOC = "AA5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<20>" LOC = "AB5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<21>" LOC = "Y4" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<22>" LOC = "AA4" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<23>" LOC = "V4" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<24>" LOC = "W10" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<25>" LOC = "R4" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<26>" LOC = "W12" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<27>" LOC = "W14" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<28>" LOC = "V20" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<29>" LOC = "V18" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<30>" LOC = "R21" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<31>" LOC = "P21" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; + +NET "ct_noise" LOC = "W19" | IOSTANDARD = "LVCMOS33" ; + +#------------------------------------------------------------------------------- +# FMC Input Timing +#------------------------------------------------------------------------------- +# +# The following timing values were derived from pages 173-175 of the STM32F429 +# datasheet. 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. +# +# 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 +# more strict. The same approach is used here, i.e. timing for Data bus is +# applied to Address bus too. +# +# Oh, and stupid datasheet doesn't explicitly specify hold time for the data bus! +# + +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 6.0 ns BEFORE "fmc_clk" RISING ; +TIMEGRP "TNM_FMC_IN_ADDR" OFFSET = IN 3.0 ns VALID 6.0 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 +#------------------------------------------------------------------------------- +# +# NWAIT signal is not constrained, since it is polled by STM32. +# + +NET "fmc_d<*>" TNM = "TNM_FMC_OUT_DATA" ; + +TIMEGRP "TNM_FMC_OUT_DATA" OFFSET = OUT 16.7 ns AFTER "fmc_clk" FALLING; + + +#------------------------------------------------------------------------------- +# CDC Paths +#------------------------------------------------------------------------------- +INST "fmc/fmc_cdc/cdc_fmc_sys/src_ff" TNM = "TNM_from_fmc_clk"; +INST "fmc/fmc_cdc/cdc_fmc_sys/src_latch*" TNM = "TNM_from_fmc_clk"; +INST "fmc/fmc_cdc/cdc_fmc_sys/ff_sync*" TNM = "TNM_to_sys_clk"; +INST "fmc/fmc_cdc/cdc_fmc_sys/dst_latch*" TNM = "TNM_to_sys_clk"; + +INST "fmc/fmc_cdc/cdc_sys_fmc/src_ff" TNM = "TNM_from_sys_clk"; +INST "fmc/fmc_cdc/cdc_sys_fmc/src_latch*" TNM = "TNM_from_sys_clk"; +INST "fmc/fmc_cdc/cdc_sys_fmc/ff_sync*" TNM = "TNM_to_fmc_clk"; +INST "fmc/fmc_cdc/cdc_sys_fmc/dst_latch*" TNM = "TNM_to_fmc_clk"; + +TIMESPEC "TS_fmc_clk_2_sys_clk" = FROM "TNM_from_fmc_clk" TO "TNM_to_sys_clk" TIG; +TIMESPEC "TS_sys_clk_2_fmc_clk" = FROM "TNM_from_sys_clk" TO "TNM_to_fmc_clk" TIG; + +#====================================================================== +# EOF alpha_fmc.ucf +#====================================================================== |