diff options
-rw-r--r-- | fmc/build/.gitignore | 53 | ||||
-rw-r--r-- | fmc/build/Makefile | 70 | ||||
-rw-r--r-- | fmc/build/xilinx.mk | 176 | ||||
-rw-r--r-- | fmc/build/xilinx.opt | 42 | ||||
-rw-r--r-- | fmc/rtl/novena_fmc_top.v | 247 | ||||
-rw-r--r-- | fmc/ucf/novena_fmc.ucf | 198 |
6 files changed, 786 insertions, 0 deletions
diff --git a/fmc/build/.gitignore b/fmc/build/.gitignore new file mode 100644 index 0000000..865bda8 --- /dev/null +++ b/fmc/build/.gitignore @@ -0,0 +1,53 @@ +coregen-tmp +*.xrpt +novena_fmc.mcs +novena_fmc.cfi +novena_fmc.prm +novena_fmc.bgn +novena_fmc.bit +novena_fmc.drc +novena_fmc_bd.bmm +novena_fmc_par.ncd +novena_fmc_par.par +novena_fmc_par.pad +novena_fmc_par_pad.csv +novena_fmc_par_pad.txt +novena_fmc_par.grf +novena_fmc_par.ptwx +novena_fmc_par.unroutes +novena_fmc_par.xpi +novena_fmc.ncd +novena_fmc.pcf +novena_fmc.ngm +novena_fmc.mrp +novena_fmc.map +smartguide.ncd +novena_fmc.psr +novena_fmc_summary.xml +novena_fmc_usage.xml +novena_fmc.ngd +novena_fmc.bld +xlnx_auto* +novena_fmc_top.lso +novena_fmc.srp +netlist.lst +xst +novena_fmc.ngc +novena_fmc.prj +novena_fmc.scr +novena_fmc.post_map.twr +novena_fmc.post_map.twx +smartpreview.twr +novena_fmc.twr +novena_fmc.twx +smartpreview.twr +novena_fmc_err.twr +novena_fmc_err.twx +novena_fmc.lso +novena_fmc_bitgen.xwb +novena_fmc_bitgen.xwbt +usage_statistics_webtalk.html +par_usage_statistics.html +webtalk.log +_xmsgs +default.xreport diff --git a/fmc/build/Makefile b/fmc/build/Makefile new file mode 100644 index 0000000..7c73c89 --- /dev/null +++ b/fmc/build/Makefile @@ -0,0 +1,70 @@ +project = novena_fmc +vendor = xilinx +family = spartan6 +part = xc6slx45csg324-3 +top_module = novena_fmc_top +isedir = /opt/Xilinx/14.7/ISE_DS +xil_env = . $(isedir)/settings64.sh +ucf = ../ucf/$(project).ucf + +vfiles = \ + ../rtl/novena_fmc_top.v \ + ../../common/rtl/novena_regs.v \ + ../../common/rtl/novena_clkmgr.v \ + ../../common/rtl/clkmgr_dcm.v \ + ../../../common/core_selector/src/rtl/core_selector.v \ + ../../../common/core_selector/src/rtl/global_selector.v \ + ../../../common/core_selector/src/rtl/hash_selector.v \ + ../../../common/core_selector/src/rtl/rng_selector.v \ + ../../../common/core_selector/src/rtl/cipher_selector.v \ + ../../../common/core_selector/src/rtl/math_selector.v \ + ../../../../comm/fmc/src/rtl/cdc_bus_pulse.v \ + ../../../../comm/fmc/src/rtl/fmc_arbiter_cdc.v \ + ../../../../comm/fmc/src/rtl/fmc_arbiter.v \ + ../../../../comm/fmc/src/rtl/fmc_d_phy.v \ + ../../../../comm/fmc/src/rtl/fmc_indicator.v \ + ../../../../comm/fmc/src/rtl/fmc_regs.v \ + ../../../../hash/sha1/src/rtl/sha1.v \ + ../../../../hash/sha1/src/rtl/sha1_core.v \ + ../../../../hash/sha1/src/rtl/sha1_w_mem.v \ + ../../../../hash/sha256/src/rtl/sha256.v \ + ../../../../hash/sha256/src/rtl/sha256_core.v \ + ../../../../hash/sha256/src/rtl/sha256_k_constants.v \ + ../../../../hash/sha256/src/rtl/sha256_w_mem.v \ + ../../../../hash/sha512/src/rtl/sha512.v \ + ../../../../hash/sha512/src/rtl/sha512_core.v \ + ../../../../hash/sha512/src/rtl/sha512_h_constants.v \ + ../../../../hash/sha512/src/rtl/sha512_k_constants.v \ + ../../../../hash/sha512/src/rtl/sha512_w_mem.v \ + ../../../../rng/avalanche_entropy/src/rtl/avalanche_entropy.v \ + ../../../../rng/avalanche_entropy/src/rtl/avalanche_entropy_core.v \ + ../../../../rng/rosc_entropy/src/rtl/rosc.v \ + ../../../../rng/rosc_entropy/src/rtl/rosc_entropy.v \ + ../../../../rng/rosc_entropy/src/rtl/rosc_entropy_core.v \ + ../../../../rng/trng/src/rtl/trng.v \ + ../../../../rng/trng/src/rtl/trng_csprng.v \ + ../../../../rng/trng/src/rtl/trng_csprng_fifo.v \ + ../../../../rng/trng/src/rtl/trng_mixer.v \ + ../../../../cipher/aes/src/rtl/aes.v \ + ../../../../cipher/aes/src/rtl/aes_core.v \ + ../../../../cipher/aes/src/rtl/aes_decipher_block.v \ + ../../../../cipher/aes/src/rtl/aes_encipher_block.v \ + ../../../../cipher/aes/src/rtl/aes_inv_sbox.v \ + ../../../../cipher/aes/src/rtl/aes_key_mem.v \ + ../../../../cipher/aes/src/rtl/aes_sbox.v \ + ../../../../cipher/chacha/src/rtl/chacha.v \ + ../../../../cipher/chacha/src/rtl/chacha_core.v \ + ../../../../cipher/chacha/src/rtl/chacha_qr.v \ + ../../../../math/modexp/src/rtl/adder.v \ + ../../../../math/modexp/src/rtl/blockmem1r1w.v \ + ../../../../math/modexp/src/rtl/blockmem2r1wptr.v \ + ../../../../math/modexp/src/rtl/blockmem2r1w.v \ + ../../../../math/modexp/src/rtl/blockmem2rptr1w.v \ + ../../../../math/modexp/src/rtl/modexp.v \ + ../../../../math/modexp/src/rtl/modexp_core.v \ + ../../../../math/modexp/src/rtl/montprod.v \ + ../../../../math/modexp/src/rtl/residue.v \ + ../../../../math/modexp/src/rtl/shl.v \ + ../../../../math/modexp/src/rtl/shr.v + +include xilinx.mk diff --git a/fmc/build/xilinx.mk b/fmc/build/xilinx.mk new file mode 100644 index 0000000..7a8d9d4 --- /dev/null +++ b/fmc/build/xilinx.mk @@ -0,0 +1,176 @@ +# The top level module should define the variables below then include +# this file. The files listed should be in the same directory as the +# Makefile. +# +# variable description +# ---------- ------------- +# project project name (top level module should match this name) +# top_module top level module of the project +# libdir path to library directory +# libs library modules used +# vfiles all local .v files +# xilinx_cores all local .xco files +# vendor vendor of FPGA (xilinx, altera, etc.) +# family FPGA device family (spartan3e) +# part FPGA part name (xc4vfx12-10-sf363) +# flashsize size of flash for mcs file (16384) +# optfile (optional) xst extra opttions file to put in .scr +# map_opts (optional) options to give to map +# par_opts (optional) options to give to par +# intstyle (optional) intstyle option to all tools +# ucf constraint file, defaults to $(project).ucf +# +# Library modules should have a modules.mk in their root directory, +# namely $(libdir)/<libname>/module.mk, that simply adds to the vfiles +# and xilinx_cores variable. +# +# all the .xco files listed in xilinx_cores will be generated with core, with +# the resulting .v and .ngc files placed back in the same directory as +# the .xco file. +# +# TODO: .xco files are device dependant, should use a template based system + +coregen_work_dir ?= ./coregen-tmp +#map_opts ?= -timing -ol high -detail -pr b -register_duplication -w -xe n +# from https://github.com/fpga-logi/logi-hard/blob/master/build_lib/synth/xilinx.mk: +map_opts ?= -w -logic_opt off -ol high -t 1 -xt 0 -register_duplication off -r 4 -global_opt off -mt off -ir off -pr off -lc off -power off +par_opts ?= -ol high +isedir ?= /opt/Xilinx/13.3/ISE_DS +xil_env ?= . $(isedir)/settings32.sh +flashsize ?= 8192 +ucf ?= $(project).ucf + +libmks = $(patsubst %,$(libdir)/%/module.mk,$(libs)) +mkfiles = $(libmks) xilinx.mk +include $(libmks) + +corengcs = $(foreach core,$(xilinx_cores),$(core:.xco=.ngc)) +local_corengcs = $(foreach ngc,$(corengcs),$(notdir $(ngc))) +vfiles += $(foreach core,$(xilinx_cores),$(core:.xco=.v)) +junk += $(local_corengcs) + +.PHONY: default xilinx_cores clean twr etwr +default: $(project).bit $(project).mcs +xilinx_cores: $(corengcs) +twr: $(project).twr +etwr: $(project)_err.twr + +define cp_template +$(2): $(1) + cp $(1) $(2) +endef +$(foreach ngc,$(corengcs),$(eval $(call cp_template,$(ngc),$(notdir $(ngc))))) + +%.ngc %.v: %.xco + @echo "=== rebuilding $@" + if [ -d $(coregen_work_dir) ]; then \ + rm -rf $(coregen_work_dir)/*; \ + else \ + mkdir -p $(coregen_work_dir); \ + fi + cd $(coregen_work_dir); \ + $(xil_env); \ + coregen -b $$OLDPWD/$<; \ + cd - + xcodir=`dirname $<`; \ + basename=`basename $< .xco`; \ + if [ ! -r $(coregen_work_dir/$$basename.ngc) ]; then \ + echo "'$@' wasn't created."; \ + exit 1; \ + else \ + cp $(coregen_work_dir)/$$basename.v $(coregen_work_dir)/$$basename.ngc $$xcodir; \ + fi +junk += $(coregen_work_dir) + +date = $(shell date +%F-%H-%M) + +# some common junk +junk += *.xrpt + +programming_files: $(project).bit $(project).mcs + mkdir -p $@/$(date) + mkdir -p $@/latest + for x in .bit .mcs .cfi _bd.bmm; do cp $(project)$$x $@/$(date)/$(project)$$x; cp $(project)$$x $@/latest/$(project)$$x; done + $(xil_env); xst -help | head -1 | sed 's/^/#/' | cat - $(project).scr > $@/$(date)/$(project).scr + +$(project).mcs: $(project).bit + $(xil_env); \ + promgen -w -s $(flashsize) -p mcs -o $@ -u 0 $^ +junk += $(project).mcs $(project).cfi $(project).prm + +$(project).bit: $(project)_par.ncd + $(xil_env); \ + bitgen $(intstyle) -g UnusedPin:Pullnone -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit +junk += $(project).bgn $(project).bit $(project).drc $(project)_bd.bmm + + +$(project)_par.ncd: $(project).ncd + $(xil_env); \ + if par $(intstyle) $(par_opts) -w $(project).ncd $(project)_par.ncd; then \ + :; \ + else \ + $(MAKE) etwr; \ + fi +junk += $(project)_par.ncd $(project)_par.par $(project)_par.pad +junk += $(project)_par_pad.csv $(project)_par_pad.txt +junk += $(project)_par.grf $(project)_par.ptwx +junk += $(project)_par.unroutes $(project)_par.xpi + +$(project).ncd: $(project).ngd + if [ -r $(project)_par.ncd ]; then \ + cp $(project)_par.ncd smartguide.ncd; \ + smartguide="-smartguide smartguide.ncd"; \ + else \ + smartguide=""; \ + fi; \ + $(xil_env); \ + map $(intstyle) $(map_opts) $$smartguide $< +junk += $(project).ncd $(project).pcf $(project).ngm $(project).mrp $(project).map +junk += smartguide.ncd $(project).psr +junk += $(project)_summary.xml $(project)_usage.xml + +$(project).ngd: $(project).ngc $(ucf) + $(xil_env); ngdbuild $(intstyle) $(project).ngc -uc $(ucf) +junk += $(project).ngd $(project).bld + +$(project).ngc: $(vfiles) $(local_corengcs) $(project).scr $(project).prj + $(xil_env); xst $(intstyle) -ifn $(project).scr +junk += xlnx_auto* $(top_module).lso $(project).srp +junk += netlist.lst xst $(project).ngc + +$(project).prj: $(vfiles) $(mkfiles) + for src in $(vfiles); do echo "verilog work $$src" >> $(project).tmpprj; done + sort -u $(project).tmpprj > $(project).prj + rm -f $(project).tmpprj +junk += $(project).prj + +optfile += $(wildcard $(project).opt) +top_module ?= $(project) +$(project).scr: $(optfile) $(mkfiles) ./xilinx.opt + echo "run" > $@ + echo "-p $(part)" >> $@ + echo "-top $(top_module)" >> $@ + echo "-ifn $(project).prj" >> $@ + echo "-ofn $(project).ngc" >> $@ + cat ./xilinx.opt $(optfile) >> $@ +junk += $(project).scr + +$(project).post_map.twr: $(project).ncd + $(xil_env); trce -e 10 $< $(project).pcf -o $@ +junk += $(project).post_map.twr $(project).post_map.twx smartpreview.twr + +$(project).twr: $(project)_par.ncd + $(xil_env); trce $< $(project).pcf -o $(project).twr +junk += $(project).twr $(project).twx smartpreview.twr + +$(project)_err.twr: $(project)_par.ncd + $(xil_env); trce -e 10 $< $(project).pcf -o $(project)_err.twr +junk += $(project)_err.twr $(project)_err.twx +junk += $(project).lso $(project)_bitgen.xwb $(project)_bitgen.xwbt +junk += usage_statistics_webtalk.html par_usage_statistics.html webtalk.log _xmsgs default.xreport + +.gitignore: $(mkfiles) + echo programming_files $(junk) | sed 's, ,\n,g' > .gitignore + +clean:: + rm -rf $(junk) diff --git a/fmc/build/xilinx.opt b/fmc/build/xilinx.opt new file mode 100644 index 0000000..7fe9d8b --- /dev/null +++ b/fmc/build/xilinx.opt @@ -0,0 +1,42 @@ +-ifmt mixed +-ofmt NGC +-opt_mode speed +-opt_level 1 +-iuc NO +-keep_hierarchy no +-netlist_hierarchy as_optimized +-rtlview no +-glob_opt AllClockNets +-read_cores yes +-write_timing_constraints NO +-cross_clock_analysis NO +-hierarchy_separator / +-bus_delimiter <> +-case maintain +-slice_utilization_ratio 100 +-bram_utilization_ratio 100 +#-dsp_utilization_ratio 100 +-safe_implementation No +-fsm_extract YES +-fsm_encoding Auto +-fsm_style lut +-ram_extract Yes +-ram_style Auto +-rom_extract Yes +-rom_style Auto +-shreg_extract YES +-auto_bram_packing NO +-resource_sharing YES +-async_to_sync NO +#-use_dsp48 auto +-iobuf YES +-max_fanout 500 +-register_duplication YES +-register_balancing No +-optimize_primitives NO +-use_clock_enable Auto +-use_sync_set Auto +-use_sync_reset Auto +-iob auto +-equivalent_register_removal YES +-slice_utilization_ratio_maxmargin 5 diff --git a/fmc/rtl/novena_fmc_top.v b/fmc/rtl/novena_fmc_top.v new file mode 100644 index 0000000..75c6f6d --- /dev/null +++ b/fmc/rtl/novena_fmc_top.v @@ -0,0 +1,247 @@ +//====================================================================== +// +// novena_top.v +// ------------ +// Top module for the Cryptech Novena FPGA framework. This design +// allow us to run the EIM interface at one clock and cores including +// core selector with the always present global clock. +// +// +// Author: Pavel Shatov +// Copyright (c) 2015, 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 novena_fmc_top + ( + input wire gclk_p_pin, + input wire gclk_n_pin, + + input wire reset_mcu_b_pin, + + // Cryptech avalanche noise board input + input wire ct_noise, + + input wire fmc_clk, // clock + input wire [21: 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 apoptosis_pin, + output wire led_pin + ); + + + //---------------------------------------------------------------- + // Clock Manager + // + // Clock manager is used to generate SYS_CLK from GCLK + // and implement the reset logic. + // ---------------------------------------------------------------- + wire sys_clk; + wire sys_rst; + + novena_clkmgr # + ( + .CLK_OUT_MUL (2), // 2..32 + .CLK_OUT_DIV (2) // 1..32 + ) + clkmgr + ( + .gclk_p (gclk_p_pin), + .gclk_n (gclk_n_pin), + + .reset_mcu_b (reset_mcu_b_pin), + + .sys_clk (sys_clk), + .sys_rst (sys_rst) + ); + + + // + // BUFG + // + 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 [21: 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 # + ( + .NUM_ADDR_BITS(22) // change to 26 when + ) + 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 Novena + // board LED when the FMC interface is active. + //---------------------------------------------------------------- + fmc_indicator led + ( + .sys_clk(sys_clk), + .sys_rst(sys_rst), + .fmc_active(sys_fmc_wren | sys_fmc_rden), + .led_out(led_pin) + ); + + +`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; + + 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 == {22{1'b0}}) ? sys_fmc_dout : {{10{1'b0}}, sys_fmc_addr}; + // + end else if (sys_fmc_rden) begin + // + // always return current value, ignore address + // + sys_fmc_din <= 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 + // + // This multiplexer is used to map different types of cores, such as + // hashes, RNGs and ciphers to different regions (segments) of memory. + //---------------------------------------------------------------- + + core_selector cores + ( + .sys_clk(sys_clk), + .sys_rst(sys_rst), + + .sys_eim_addr(sys_fmc_addr[16:0]), // XXX parameterize + .sys_eim_wr(sys_fmc_wren), + .sys_eim_rd(sys_fmc_rden), + .sys_write_data(sys_fmc_dout), + .sys_read_data(sys_fmc_din), + + .noise(ct_noise) + ); +`endif + + + //---------------------------------------------------------------- + // Novena Patch + // + // Patch logic to keep the Novena board happy. + // The apoptosis_pin pin must be kept low or the whole board + // (more exactly the CPU) will be reset after the FPGA has + // been configured. + //---------------------------------------------------------------- + assign apoptosis_pin = 1'b0; + + +endmodule diff --git a/fmc/ucf/novena_fmc.ucf b/fmc/ucf/novena_fmc.ucf new file mode 100644 index 0000000..bbfd27b --- /dev/null +++ b/fmc/ucf/novena_fmc.ucf @@ -0,0 +1,198 @@ +#====================================================================== +# +# novena_fmc.ucf +# ------------------- +# Constraint file for implementing the Cryptech Novena base +# for the Xilinx Spartan6 LX45 on the Novena. +# +# +# Author: Pavel Shatov +# Copyright (c) 2014, 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. +# +#====================================================================== + +#------------------------------------------------------------------------------- +CONFIG VCCAUX = 3.3; +#------------------------------------------------------------------------------- + + +#-------------------------------------------------------------------------------- +# GCLK Timing (fixed at 50 MHz) +#-------------------------------------------------------------------------------- +NET "gclk_p_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_pin" LOC = "A16" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8; +NET "apoptosis_pin" LOC = "K1" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8; +NET "reset_mcu_b_pin" LOC = "F1" | IOSTANDARD = "LVCMOS33" | PULLUP; +# +NET "gclk_p_pin" LOC = "H2" | IOSTANDARD = "LVDS_25" | DIFF_TERM = "TRUE"; +NET "gclk_n_pin" LOC = "H1" | IOSTANDARD = "LVDS_25" | DIFF_TERM = "TRUE"; +# +NET "fmc_clk" LOC = "T8" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_ne1" LOC = "R7" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_noe" LOC = "R8" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_nwe" LOC = "V11" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_nl" LOC = "T7" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_nwait" LOC = "V8" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +# +NET "fmc_a<0>" LOC = "V7" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<1>" LOC = "M5" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<2>" LOC = "L4" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<3>" LOC = "M3" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<4>" LOC = "L3" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<5>" LOC = "P2" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<6>" LOC = "K3" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<7>" LOC = "K4" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<8>" LOC = "R3" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<9>" LOC = "T3" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<10>" LOC = "V4" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<11>" LOC = "T4" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<12>" LOC = "J3" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<13>" LOC = "J1" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<14>" LOC = "J6" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<15>" LOC = "U16" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<16>" LOC = "M1" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<17>" LOC = "F2" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<18>" LOC = "R11" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<19>" LOC = "V5" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<20>" LOC = "G1" | IOSTANDARD = "LVCMOS33" ; +NET "fmc_a<21>" LOC = "T2" | IOSTANDARD = "LVCMOS33" ; +#NET "fmc_a<22>" LOC = " " | IOSTANDARD = "LVCMOS33" ; +#NET "fmc_a<23>" LOC = " " | IOSTANDARD = "LVCMOS33" ; +#NET "fmc_a<24>" LOC = " " | IOSTANDARD = "LVCMOS33" ; +#NET "fmc_a<25>" LOC = " " | IOSTANDARD = "LVCMOS33" ; +# +NET "fmc_d<0>" LOC = "K2" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<1>" LOC = "V16" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<2>" LOC = "V9" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<3>" LOC = "T9" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<4>" LOC = "T5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<5>" LOC = "R5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<6>" LOC = "T10" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<7>" LOC = "R10" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<8>" LOC = "P6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<9>" LOC = "N5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<10>" LOC = "V10" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<11>" LOC = "U10" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<12>" LOC = "L5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<13>" LOC = "K6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<14>" LOC = "H4" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<15>" LOC = "H3" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<16>" LOC = "K5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<17>" LOC = "L2" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<18>" LOC = "L1" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<19>" LOC = "L7" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<20>" LOC = "T11" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<21>" LOC = "T14" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<22>" LOC = "V14" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<23>" LOC = "L6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<24>" LOC = "U13" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<25>" LOC = "V13" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<26>" LOC = "U11" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<27>" LOC = "U8" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<28>" LOC = "V6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<29>" LOC = "T6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<30>" LOC = "U5" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; +NET "fmc_d<31>" LOC = "U7" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 8; + +NET "ct_noise" LOC = "H7" | 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 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 11.5 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 novena_fmc.ucf +#====================================================================== |