diff options
-rw-r--r-- | LICENSE | 28 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | build/.gitignore | 54 | ||||
-rw-r--r-- | build/Makefile | 86 | ||||
-rw-r--r-- | build/xilinx.mk | 176 | ||||
-rw-r--r-- | build/xilinx.opt | 42 | ||||
-rw-r--r-- | rtl/alpha_clkmgr.v | 132 | ||||
-rw-r--r-- | rtl/alpha_fmc_top.v | 247 | ||||
-rw-r--r-- | rtl/alpha_regs.v | 148 | ||||
-rw-r--r-- | rtl/clkmgr_dcm.v | 164 | ||||
-rw-r--r-- | rtl/lint-dummy.v | 128 | ||||
-rw-r--r-- | ucf/alpha_fmc.ucf | 198 |
12 files changed, 1408 insertions, 0 deletions
@@ -0,0 +1,28 @@ +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cfb7b9b --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +platform/alpha +============== + +Platform-specific files for the Cryptech Alpha board. + diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..2eb6775 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,54 @@ +*.xrpt +_xmsgs +default.xreport +netlist.lst +*.bgn +*.bit +*.bld +*.cfi +*.drc +*.lso +*.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 +par_usage_statistics.html +smartguide.ncd +smartpreview.twr +smartpreview.twr +usage_statistics_webtalk.html +webtalk.log +xlnx_auto* +xst +core_selector.v +core_vfiles.mk diff --git a/build/Makefile b/build/Makefile new file mode 100644 index 0000000..050789a --- /dev/null +++ b/build/Makefile @@ -0,0 +1,86 @@ +# 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 +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 + +# Build the default core_selector if it doesn't already exist. + +CONFIG = $(CORE_TREE)/platform/common/config +core_selector.v core_vfiles.mk: + $(CONFIG)/config.py -c $(CONFIG)/config.cfg + +# Build some different configurations + +bare: + $(CONFIG)/config.py -c $(CONFIG)/config.cfg -s bare + $(MAKE) project=$(project)_bare ucf=$(ucf) + +trng: + $(CONFIG)/config.py -c $(CONFIG)/config.cfg -s trng + $(MAKE) project=$(project)_trng ucf=$(ucf) + +hash: + $(CONFIG)/config.py -c $(CONFIG)/config.cfg -s hash + $(MAKE) project=$(project)_hash ucf=$(ucf) + +rsa: + $(CONFIG)/config.py -c $(CONFIG)/config.cfg -s rsa + $(MAKE) project=$(project)_rsa ucf=$(ucf) + +# Verilog files that always go with builds on this platform. + +vfiles = \ + $(CORE_TREE)/platform/alpha/fmc/rtl/alpha_fmc_top.v \ + $(CORE_TREE)/platform/alpha/common/rtl/alpha_regs.v \ + $(CORE_TREE)/platform/alpha/common/rtl/alpha_clkmgr.v \ + $(CORE_TREE)/platform/alpha/common/rtl/clkmgr_dcm.v \ + ./core_selector.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 + +# Verilog files selected by the core configuration script. + +-include ./core_vfiles.mk + +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 + rm core_selector.v core_vfiles.mk + +# Fun extras for running verilator as a linter. + +VERILATOR_FLAGS = --lint-only --top-module $(top_module) -Wall -Wno-fatal -Wno-DECLFILENAME + +lint: + verilator ${VERILATOR_FLAGS} $(vfiles) $(CORE_TREE)/platform/alpha/common/rtl/lint-dummy.v diff --git a/build/xilinx.mk b/build/xilinx.mk new file mode 100644 index 0000000..7a8d9d4 --- /dev/null +++ b/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/build/xilinx.opt b/build/xilinx.opt new file mode 100644 index 0000000..7fe9d8b --- /dev/null +++ b/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/rtl/alpha_clkmgr.v b/rtl/alpha_clkmgr.v new file mode 100644 index 0000000..1cc0337 --- /dev/null +++ b/rtl/alpha_clkmgr.v @@ -0,0 +1,132 @@ +//====================================================================== +// +// alpha_clkmgr.v +// --------------- +// Clock and reset implementation for the Cryptech Alpha +// FPGA framework. +// +// +// 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. +// +//====================================================================== + +module alpha_clkmgr + ( + input wire gclk_p, // signal from clock pins + input wire gclk_n, // + + input wire reset_mcu_b, // cpu reset (async, active-low) + + output wire sys_clk, // buffered system clock output + output wire sys_rst_n // system reset output (async set, sync clear, active-low) + ); + + + // + // Parameters + // + parameter CLK_OUT_MUL = 2; + parameter CLK_OUT_DIV = 2; + + // + // Wrapper for Xilinx-specific DCM (Digital Clock Manager) primitive. + // + + wire gclk; // buffered input clock + wire dcm_reset; // dcm reset + wire dcm_locked; // output clock valid + wire gclk_missing; // no input clock + + clkmgr_dcm # + ( + .CLK_OUT_MUL (CLK_OUT_MUL), + .CLK_OUT_DIV (CLK_OUT_DIV) + ) + dcm + ( + .clk_in_p (gclk_p), + .clk_in_n (gclk_n), + .reset_in (dcm_reset), + + .gclk_out (gclk), + .gclk_missing_out (gclk_missing), + + .clk_out (sys_clk), + .clk_valid_out (dcm_locked) + ); + + + // + // DCM Reset Logic + // + + /* DCM should be reset on power-up, when input clock is stopped or when the + * CPU gets reset. Note that DCM requires active-high reset, so the shift + * register is preloaded with 1's and gradually filled with 0's. + */ + + reg [15: 0] dcm_rst_shreg = {16{1'b1}}; // 16-bit shift register + + always @(posedge gclk or negedge reset_mcu_b or posedge gclk_missing) + // + if ((reset_mcu_b == 1'b0) || (gclk_missing == 1'b1)) + dcm_rst_shreg <= {16{1'b1}}; + else + dcm_rst_shreg <= {dcm_rst_shreg[14:0], 1'b0}; + + assign dcm_reset = dcm_rst_shreg[15]; + + + // + // System Reset Logic + // + + /* System reset is asserted for 16 cycles whenever DCM aquires lock. Note + * that system reset is active-low, so the shift register is preloaded with + * 0's and gradually filled with 1's. + */ + + reg [15: 0] sys_rst_shreg = {16{1'b0}}; // 16-bit shift register + + always @(posedge sys_clk or negedge reset_mcu_b or posedge gclk_missing or negedge dcm_locked) + // + if ((reset_mcu_b == 1'b0) || (gclk_missing == 1'b1) || (dcm_locked == 1'b0)) + sys_rst_shreg <= {16{1'b0}}; + else if (dcm_locked == 1'b1) + sys_rst_shreg <= {sys_rst_shreg[14:0], 1'b1}; + + assign sys_rst_n = sys_rst_shreg[15]; + + +endmodule + +//====================================================================== +// EOF alpha_clkmgr.v +//====================================================================== diff --git a/rtl/alpha_fmc_top.v b/rtl/alpha_fmc_top.v new file mode 100644 index 0000000..b5b85f6 --- /dev/null +++ b/rtl/alpha_fmc_top.v @@ -0,0 +1,247 @@ +//====================================================================== +// +// alpha_top.v +// ------------ +// Top module for the Cryptech Alpha 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 alpha_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_n; + + alpha_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_n (sys_rst_n) + ); + + + // + // 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 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_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_n(sys_rst_n), + + .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 + + + //---------------------------------------------------------------- + // Alpha Patch + // + // Patch logic to keep the Alpha 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/rtl/alpha_regs.v b/rtl/alpha_regs.v new file mode 100644 index 0000000..a53d2d3 --- /dev/null +++ b/rtl/alpha_regs.v @@ -0,0 +1,148 @@ +//====================================================================== +// +// alpha_regs.v +// ------------- +// Global registers for the Cryptech Alpha FPGA framework. +// +// +// 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 board_regs + ( + // Clock and reset. + input wire clk, + input wire reset_n, + + // Control. + input wire cs, + input wire we, + + // Data ports. + input wire [7 : 0] address, + input wire [31 : 0] write_data, + output wire [31 : 0] read_data, + output wire error + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + // API addresses. + localparam ADDR_CORE_NAME0 = 8'h00; + localparam ADDR_CORE_NAME1 = 8'h01; + localparam ADDR_CORE_VERSION = 8'h02; + localparam ADDR_DUMMY_REG = 8'hFF; // general-purpose register + + // Core ID constants. + localparam CORE_NAME0 = 32'h414c5048; // "ALPH" + localparam CORE_NAME1 = 32'h41202020; // "A " + localparam CORE_VERSION = 32'h302e3130; // "0.10" + + + + //---------------------------------------------------------------- + // Registers. + //---------------------------------------------------------------- + reg [31: 0] tmp_read_data; + reg write_error; + reg read_error; + + // dummy register to check that you can actually write something + reg [31: 0] reg_dummy; + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + wire [31 : 0] core_name0 = CORE_NAME0; + wire [31 : 0] core_name1 = CORE_NAME1; + wire [31 : 0] core_version = CORE_VERSION; + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign read_data = tmp_read_data; + assign error = write_error | read_error; + + //---------------------------------------------------------------- + // storage registers for mapping memory to core interface + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin + if (!reset_n) + begin + reg_dummy <= {32{1'b0}}; + end + else if (cs && we) + begin + write_error <= 0; + + // write operations + case (address) + ADDR_DUMMY_REG: + reg_dummy <= write_data; + default: + write_error <= 1; + endcase + end + end + + always @* + begin + tmp_read_data = 32'h00000000; + read_error = 0; + + if (cs && !we) + begin + // read operations + case (address) + ADDR_CORE_NAME0: + tmp_read_data = core_name0; + ADDR_CORE_NAME1: + tmp_read_data = core_name1; + ADDR_CORE_VERSION: + tmp_read_data = core_version; + ADDR_DUMMY_REG: + tmp_read_data = reg_dummy; + default: + read_error = 1; + endcase + end + end + +endmodule + +//====================================================================== +// EOF alpha_regs.v +//====================================================================== diff --git a/rtl/clkmgr_dcm.v b/rtl/clkmgr_dcm.v new file mode 100644 index 0000000..141863e --- /dev/null +++ b/rtl/clkmgr_dcm.v @@ -0,0 +1,164 @@ +//====================================================================== +// +// clkmgr_dcm.v +// --------------- +// Xilinx DCM_SP primitive wrapper to avoid using Clocking Wizard IP core. +// +// +// 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. +// +//====================================================================== + +module clkmgr_dcm + ( + input wire clk_in_p, + input wire clk_in_n, + input wire reset_in, + + output wire gclk_out, + output wire gclk_missing_out, + + output wire clk_out, + output wire clk_valid_out + ); + + + // + // Parameters + // + parameter CLK_OUT_MUL = 2; // multiply factor for output clock frequency (2..32) + parameter CLK_OUT_DIV = 2; // divide factor for output clock frequency (1..32) + + + // + // IBUFGDS + // + /* Xilinx-specific primitive to handle LVDS input signal. */ + (* BUFFER_TYPE="NONE" *) + wire clk_in; + + IBUFGDS IBUFGDS_gclk + ( + .I(clk_in_p), + .IB(clk_in_n), + .O(clk_in) + ); + + // + // DCM_SP + // + /* Xilinx-specific primitive. */ + wire dcm_clk_0; + wire dcm_clk_feedback; + wire dcm_clk_fx; + wire dcm_locked_int; + wire [ 7: 0] dcm_status_int; + + DCM_SP # + ( + .STARTUP_WAIT ("FALSE"), + .DESKEW_ADJUST ("SYSTEM_SYNCHRONOUS"), + .CLK_FEEDBACK ("1X"), + + .PHASE_SHIFT (0), + .CLKOUT_PHASE_SHIFT ("NONE"), + + .CLKIN_PERIOD (20.0), // 50 MHz => 20 ns + .CLKIN_DIVIDE_BY_2 ("FALSE"), + + .CLKDV_DIVIDE (5.000), + .CLKFX_MULTIPLY (CLK_OUT_MUL), + .CLKFX_DIVIDE (CLK_OUT_DIV) + ) + DCM_SP_inst + ( + .RST (reset_in), + + .CLKIN (clk_in), + .CLKFB (dcm_clk_feedback), + .CLKDV (), + + .CLK0 (dcm_clk_0), + .CLK90 (), + .CLK180 (), + .CLK270 (), + + .CLK2X (), + .CLK2X180 (), + + .CLKFX (dcm_clk_fx), + .CLKFX180 (), + + .PSCLK (1'b0), + .PSEN (1'b0), + .PSINCDEC (1'b0), + .PSDONE (), + + .LOCKED (dcm_locked_int), + .STATUS (dcm_status_int), + + .DSSEN (1'b0) + ); + + + // + // Mapping + // + assign gclk_out = clk_in; + assign gclk_missing_out= dcm_status_int[1]; + assign clk_valid_out = dcm_locked_int & ((dcm_status_int[2:1] == 2'b00) ? 1'b1 : 1'b0); + + + // + // Feedback + // + /* DCM_SP requires BUFG primitive in its feedback path. */ + BUFG BUFG_feedback + ( + .I (dcm_clk_0), + .O (dcm_clk_feedback) + ); + + // + // Output Buffer + // + /* Connect system clock to global clocking network. */ + BUFG BUFG_output + ( + .I (dcm_clk_fx), + .O (clk_out) + ); + + +endmodule + +//====================================================================== +// EOF clkmgr_dcm.v +//====================================================================== diff --git a/rtl/lint-dummy.v b/rtl/lint-dummy.v new file mode 100644 index 0000000..3e0424c --- /dev/null +++ b/rtl/lint-dummy.v @@ -0,0 +1,128 @@ +// dummy modules for Xilinx IP for verilator linting + +// The module definitions are ganked from +// /opt/Xilinx/14.7/ISE_DS/ISE/verilog/src/unisims. It would be easier +// to run verilator with -I for that directory, but verilator really +// doesn't like the Xilinx code. + +// Copyright (c) 1995/2004 Xilinx, Inc. +// All Right Reserved. + +/*verilator lint_off UNDRIVEN*/ +/*verilator lint_off UNUSED*/ + +module DCM_SP ( + CLK0, CLK180, CLK270, CLK2X, CLK2X180, CLK90, + CLKDV, CLKFX, CLKFX180, LOCKED, PSDONE, STATUS, + CLKFB, CLKIN, DSSEN, PSCLK, PSEN, PSINCDEC, RST); +parameter real CLKDV_DIVIDE = 2.0; +parameter integer CLKFX_DIVIDE = 1; +parameter integer CLKFX_MULTIPLY = 4; +parameter CLKIN_DIVIDE_BY_2 = "FALSE"; +parameter real CLKIN_PERIOD = 10.0; +parameter CLKOUT_PHASE_SHIFT = "NONE"; +parameter CLK_FEEDBACK = "1X"; +parameter DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS"; +parameter DFS_FREQUENCY_MODE = "LOW"; +parameter DLL_FREQUENCY_MODE = "LOW"; +parameter DSS_MODE = "NONE"; +parameter DUTY_CYCLE_CORRECTION = "TRUE"; +parameter FACTORY_JF = 16'hC080; +parameter integer PHASE_SHIFT = 0; +parameter STARTUP_WAIT = "FALSE"; +output CLK0, CLK180, CLK270, CLK2X, CLK2X180, CLK90; +output CLKDV, CLKFX, CLKFX180, LOCKED, PSDONE; +output [7:0] STATUS; +input CLKFB, CLKIN, DSSEN; +input PSCLK, PSEN, PSINCDEC, RST; +endmodule + +module BUFG (O, I); + output O; + input I; +endmodule + +module IBUFGDS (O, I, IB); + output O; + input I, IB; +endmodule + +module IOBUF (O, IO, I, T); + parameter CAPACITANCE = "DONT_CARE"; + parameter integer DRIVE = 12; + parameter IBUF_DELAY_VALUE = "0"; + parameter IBUF_LOW_PWR = "TRUE"; + parameter IFD_DELAY_VALUE = "AUTO"; + parameter IOSTANDARD = "DEFAULT"; + parameter SLEW = "SLOW"; + output O; + inout IO; + input I, T; +endmodule + +module FDCE (Q, C, CE, CLR, D); + parameter INIT = 1'b0; + output Q; + input C, CE, CLR, D; +endmodule + +module FD (Q, C, D); + parameter INIT = 1'b0; + output Q; + input C, D; +endmodule + +module DSP48A1 (BCOUT, CARRYOUT, CARRYOUTF, M, P, PCOUT, A, B, C, CARRYIN, CEA, CEB, CEC, CECARRYIN, CED, CEM, CEOPMODE, CEP, CLK, D, OPMODE, PCIN, RSTA, RSTB, RSTC, RSTCARRYIN, RSTD, RSTM, RSTOPMODE, RSTP); + parameter integer A0REG = 0; + parameter integer A1REG = 1; + parameter integer B0REG = 0; + parameter integer B1REG = 1; + parameter integer CARRYINREG = 1; + parameter integer CARRYOUTREG = 1; + parameter CARRYINSEL = "OPMODE5"; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter RSTTYPE = "SYNC"; + output [17:0] BCOUT; + output CARRYOUT; + output CARRYOUTF; + output [35:0] M; + output [47:0] P; + output [47:0] PCOUT; + input [17:0] A; + input [17:0] B; + input [47:0] C; + input CARRYIN; + input CEA; + input CEB; + input CEC; + input CECARRYIN; + input CED; + input CEM; + input CEOPMODE; + input CEP; + input CLK; + input [17:0] D; + input [7:0] OPMODE; + input [47:0] PCIN; + input RSTA; + input RSTB; + input RSTC; + input RSTCARRYIN; + input RSTD; + input RSTM; + input RSTOPMODE; + input RSTP; +endmodule + +module GND(G); + output G; +endmodule + +module VCC(P); + output P; +endmodule + diff --git a/ucf/alpha_fmc.ucf b/ucf/alpha_fmc.ucf new file mode 100644 index 0000000..b323104 --- /dev/null +++ b/ucf/alpha_fmc.ucf @@ -0,0 +1,198 @@ +#====================================================================== +# +# alpha_fmc.ucf +# ------------------- +# Constraint file for implementing the Cryptech Alpha base +# for the Xilinx Spartan6 LX45 on the Alpha. +# +# +# 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 alpha_fmc.ucf +#====================================================================== |