aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Makefile10
-rw-r--r--build/xilinx.opt4
-rw-r--r--rtl/alpha_clkmgr.v182
-rw-r--r--rtl/alpha_fmc_top.v272
-rw-r--r--rtl/alpha_regs.v2
-rw-r--r--rtl/bench/tb_clkmgr.v38
-rw-r--r--rtl/clkmgr_mmcm.v241
-rw-r--r--rtl/clkmgr_mmcm_ctrl.v117
-rw-r--r--rtl/clkmgr_reset_gen.v69
-rw-r--r--ucf/alpha_fmc.ucf66
-rw-r--r--xdc/alpha_fmc_clocks.xdc1
-rw-r--r--xdc/alpha_fmc_pinout.xdc100
-rw-r--r--xdc/alpha_fmc_timing.xdc1
13 files changed, 712 insertions, 391 deletions
diff --git a/build/Makefile b/build/Makefile
index 2fc9fe0..789ab87 100644
--- a/build/Makefile
+++ b/build/Makefile
@@ -20,7 +20,10 @@ ucf ?= ../ucf/$(project).ucf
# Verilog include directories, if needed
-vlgincdir = $(CORE_TREE)/lib/lowlevel $(CORE_TREE)/math/ecdsalib/rtl/microcode
+vlgincdir = \
+ $(CORE_TREE)/lib/lowlevel \
+ $(CORE_TREE)/math/ecdsalib/rtl/microcode \
+ $(CORE_TREE)/lib/util
all: $(project).bit
@@ -36,7 +39,7 @@ core_selector.v core_vfiles.mk:
# Build some different configurations
-bare trng hash mkmif rsa hsm hsm-super keywrap:
+bare trng hash mkmif rsa hsm hsm-super hsm_ng hsm_ng_keywrap:
$(CONFIG_GEN) -p $@
$(MAKE) project=$(project)_$@ ucf=$(ucf)
@@ -47,7 +50,10 @@ vfiles = \
$(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)/platform/alpha/rtl/clkmgr_mmcm_ctrl.v \
./core_selector.v \
+ $(CORE_TREE)/platform/alpha/rtl/clkmgr_reset_gen.v \
+ $(CORE_TREE)/platform/common/extra/reset_replicator.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 \
diff --git a/build/xilinx.opt b/build/xilinx.opt
index 1ac8957..536725d 100644
--- a/build/xilinx.opt
+++ b/build/xilinx.opt
@@ -28,7 +28,7 @@
-shreg_extract YES
-shreg_min_size 2
-auto_bram_packing NO
--resource_sharing YES
+-resource_sharing NO
-async_to_sync NO
-use_dsp48 auto
-iobuf YES
@@ -43,5 +43,5 @@
-use_sync_set Auto
-use_sync_reset Auto
-iob auto
--equivalent_register_removal YES
+-equivalent_register_removal NO
-slice_utilization_ratio_maxmargin 5
diff --git a/rtl/alpha_clkmgr.v b/rtl/alpha_clkmgr.v
index 5c4099e..0f5f912 100644
--- a/rtl/alpha_clkmgr.v
+++ b/rtl/alpha_clkmgr.v
@@ -7,7 +7,7 @@
//
//
// Author: Pavel Shatov
-// Copyright (c) 2016, 2018 NORDUnet A/S All rights reserved.
+// Copyright (c) 2016, 2018-2019 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
@@ -38,101 +38,101 @@
//======================================================================
module alpha_clkmgr
- (
- input wire fmc_clk, // signal from clock pin
-
- output wire sys_clk, // buffered system clock output
- output wire sys_rst_n // system reset output (async set, sync clear, active-low)
- );
-
-
- //
- // Settings
- //
-
- /*
- * fmc_clk is 90 MHz, sys_clk is also 90 MHz routed through an MMCM.
- *
- * VCO frequency is 1080 MHz.
- *
- */
- localparam CLK_OUT_MUL = 12.0;
- localparam CLK_OUT_DIV = 12.0;
- localparam CLK_OUT_PHI = 45.0;
+(
+ input wire fmc_clk, // signal from clock pin
+ output wire io_clk, // buffered i/o clock
+ output wire sys_clk, // buffered system clock output
+ output wire sys_rst_n, // system reset output (async set, sync clear, active-low)
+ output wire core_clk // buffered high speed core clock
+);
- //
- // Wrapper for Xilinx-specific MMCM (Mixed Mode Clock Manager) primitive.
- //
-
- wire gclk_int; // buffered input clock
- wire mmcm_reset; // reset input
- wire mmcm_locked; // output clock valid
- wire gclk_missing; // input clock stopped
-
- clkmgr_mmcm #
- (
- .CLK_OUT_MUL (CLK_OUT_MUL), // 2..64
- .CLK_OUT_DIV (CLK_OUT_DIV), // 1..128
- .CLK_OUT_PHI (CLK_OUT_PHI) // 0.0..360.0
- )
- mmcm
- (
- .gclk_in (fmc_clk),
- .reset_in (mmcm_reset),
-
- .gclk_out (gclk_int),
- .gclk_missing_out (gclk_missing),
-
- .clk_out (sys_clk),
- .clk_valid_out (mmcm_locked)
- );
-
-
-
- //
- // MMCM Reset Logic
- //
-
- /* MMCM should be reset on power-up and when the input clock is stopped.
- * Note that MMCM requires active-high reset, so the shift register is
- * preloaded with 1's and then gradually filled with 0's.
- */
-
- reg [15: 0] mmcm_rst_shreg = {16{1'b1}}; // 16-bit shift register
-
- always @(posedge gclk_int or posedge gclk_missing)
- //
- if (gclk_missing == 1'b1)
- mmcm_rst_shreg <= {16{1'b1}};
- else
- mmcm_rst_shreg <= {mmcm_rst_shreg[14:0], 1'b0};
-
- assign mmcm_reset = mmcm_rst_shreg[15];
-
-
- //
- // System Reset Logic
- //
-
- /* System reset is asserted for 16 cycles whenever MMCM 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 posedge gclk_missing or negedge mmcm_locked)
- //
- if ((gclk_missing == 1'b1) || (mmcm_locked == 1'b0))
- sys_rst_shreg <= {16{1'b0}};
- else if (mmcm_locked == 1'b1)
- sys_rst_shreg <= {sys_rst_shreg[14:0], 1'b1};
-
- assign sys_rst_n = sys_rst_shreg[15];
+
+ //
+ // Parameters
+ //
+ parameter integer CLK_CORE_MULT = 4;
+
+
+ //
+ // STARTUPE2
+ //
+ wire cfg_mclk; // 65 MHz (+/- 50%) internal oscillator
+ wire cfg_eos; // end-of-startup flag
+
+ STARTUPE2 #
+ (
+ .SIM_CCLK_FREQ (0.0), // config clock frequency for simulation
+ .PROG_USR ("FALSE") // only used with encrypted bitstreams
+ )
+ STARTUPE2_inst
+ (
+ .CLK (1'b0), // no external clock
+ .CFGCLK (), // config clock (unused)
+ .CFGMCLK (cfg_mclk), // config clock
+ .EOS (cfg_eos), // end-of-startup flag
+
+ .USRCCLKO (1'b0), // custom clock for configuration memory access (unused)
+ .USRCCLKTS (1'b0), // UG470 recommends this to be held low
+ .USRDONEO (1'b1), // custom value to drive onto DONE pin (unused)
+ .USRDONETS (1'b1), // tri-state DONE pin (unused)
+
+ .GSR (1'b0), // UG470 recommends hardwiring this low
+ .GTS (1'b0), // UG470 recommends this to be tied low
+
+ .PREQ (), // unused when PROG_USR is disabled
+ .PACK (1'b0), // only used when PROG_USR is enabled
+
+ .KEYCLEARB (1'b1) // unused
+ );
+
+
+ //
+ // Wrapper for Xilinx-specific MMCM (Mixed Mode Clock Manager) primitive.
+ //
+ wire mmcm_reset; // reset input
+ wire mmcm_locked; // output clock valid
+
+ clkmgr_mmcm #
+ (
+ .CLK_CORE_MULT(CLK_CORE_MULT)
+ )
+ mmcm_inst
+ (
+ .fmc_clk_in (fmc_clk),
+ .rst_in (mmcm_reset),
+
+ .io_clk_out (io_clk),
+ .sys_clk_out (sys_clk),
+ .core_clk_out (core_clk),
+ .locked_out (mmcm_locked)
+ );
+
+ //
+ // MMCM Controller
+ //
+ clkmgr_mmcm_ctrl mmcm_ctrl_inst
+ (
+ .clk_in (cfg_mclk),
+ .reset_n_in (cfg_eos),
+ .locked_in (mmcm_locked),
+ .reset_out (mmcm_reset)
+ );
+
+
+ //
+ // System Reset Logic
+ //
+ clkmgr_reset_gen #(.SHREG_WIDTH(16)) reset_gen_inst
+ (
+ .clk_in (sys_clk),
+ .locked_in (mmcm_locked),
+ .reset_n_out (sys_rst_n)
+ );
endmodule
+
//======================================================================
// EOF alpha_clkmgr.v
diff --git a/rtl/alpha_fmc_top.v b/rtl/alpha_fmc_top.v
index a07beee..2206a89 100644
--- a/rtl/alpha_fmc_top.v
+++ b/rtl/alpha_fmc_top.v
@@ -8,7 +8,7 @@
//
//
// Author: Pavel Shatov
-// Copyright (c) 2016, 2018 NORDUnet A/S All rights reserved.
+// Copyright (c) 2016, 2018-2019 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
@@ -38,147 +38,139 @@
//
//======================================================================
-`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 buffer FMC_CLK and implement reset logic.
- // ----------------------------------------------------------------
- wire sys_clk; // system clock (90 MHz)
- wire sys_rst_n; // active-low reset
-
- alpha_clkmgr clkmgr
- (
- .fmc_clk (fmc_clk),
-
- .sys_clk (sys_clk),
- .sys_rst_n (sys_rst_n)
- );
-
-
-
- //----------------------------------------------------------------
- // FMC Arbiter
- //
- // FMC arbiter handles FMC accesses.
- //----------------------------------------------------------------
-
- 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)
- wire [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_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])
- );
-
-
- //----------------------------------------------------------------
- // Core Selector
- //
- // This multiplexer is used to map different types of cores, such as
- // hashes, RNGs and ciphers to different regions (segments) of memory.
- //----------------------------------------------------------------
-
- // A note on byte-swapping:
- // STM32 is little-endian, while the register interface here is
- // big-endian. The software reads and writes 32-bit integer values,
- // which means transmitting the least significant byte first. Up to
- // now, we've been doing byte-swapping in software, which is
- // inefficient, especially for bulk data transfer. So now we're doing
- // the byte-swapping in hardware.
-
- wire [31:0] write_data;
- assign write_data = {sys_fmc_dout[7:0], sys_fmc_dout[15:8], sys_fmc_dout[23:16], sys_fmc_dout[31:24]};
-
- wire [31 : 0] read_data;
- assign sys_fmc_din = {read_data[7:0], read_data[15:8], read_data[23:16], read_data[31:24]};
-
- core_selector cores
- (
- .sys_clk(sys_clk),
- .sys_rst_n(sys_rst_n),
-
- .sys_fmc_addr(sys_fmc_addr),
- .sys_fmc_wr(sys_fmc_wren),
- .sys_fmc_rd(sys_fmc_rden),
- .sys_write_data(write_data),
- .sys_read_data(read_data),
-
- .noise(ct_noise),
-
- .mkm_sclk(mkm_sclk),
- .mkm_cs_n(mkm_cs_n),
- .mkm_do(mkm_do),
- .mkm_di(mkm_di)
- );
-
-
- //
- // Dummy assignment to bypass unconnected outpins pins check in BitGen
- //
+(
+// 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 buffer FMC_CLK and implement reset logic.
+ // ----------------------------------------------------------------
+ wire io_clk; // FMC I/O clock (45 MHz)
+ wire sys_clk; // system clock (90 MHz)
+ wire sys_rst_n; // active-low system reset
+ wire core_clk; // high-speed core clock (45*N MHz)
+
+ alpha_clkmgr #(.CLK_CORE_MULT(2)) clkmgr
+ (
+ .fmc_clk (fmc_clk),
+
+ .io_clk (io_clk),
+ .sys_clk (sys_clk),
+ .sys_rst_n (sys_rst_n),
+ .core_clk (core_clk)
+ );
+
+
+
+ //----------------------------------------------------------------
+ // FMC Arbiter
+ //
+ // FMC arbiter handles FMC accesses.
+ //----------------------------------------------------------------
+
+ 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)
+ wire [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_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),
+ .io_clk(io_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])
+ );
+
+
+ //----------------------------------------------------------------
+ // 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),
+ .core_clk(core_clk),
+
+ .sys_fmc_addr(sys_fmc_addr),
+ .sys_fmc_wr(sys_fmc_wren),
+ .sys_fmc_rd(sys_fmc_rden),
+ .sys_write_data(sys_fmc_dout),
+ .sys_read_data(sys_fmc_din),
+ .sys_error(),
+
+ .noise(ct_noise),
+
+ .mkm_sclk(mkm_sclk),
+ .mkm_cs_n(mkm_cs_n),
+ .mkm_do(mkm_do),
+ .mkm_di(mkm_di),
+
+ .debug()
+ );
+
- assign led_pins[3:1] = 3'b000;
+ //
+ // Dummy assignment to get past the unconnected outpins pins check in BitGen
+ //
+ assign led_pins[3:1] = 3'b000;
endmodule
diff --git a/rtl/alpha_regs.v b/rtl/alpha_regs.v
index ce17863..31cfbbf 100644
--- a/rtl/alpha_regs.v
+++ b/rtl/alpha_regs.v
@@ -68,7 +68,7 @@ module board_regs
// Core ID constants.
localparam CORE_NAME0 = 32'h414c5048; // "ALPH"
localparam CORE_NAME1 = 32'h41202020; // "A "
- localparam CORE_VERSION = 32'h302e3230; // "0.20"
+ localparam CORE_VERSION = 32'h302e3330; // "0.30"
diff --git a/rtl/bench/tb_clkmgr.v b/rtl/bench/tb_clkmgr.v
new file mode 100644
index 0000000..a987e1c
--- /dev/null
+++ b/rtl/bench/tb_clkmgr.v
@@ -0,0 +1,38 @@
+`timescale 1ns / 1ps
+
+module tb_clkmgr;
+
+ // Input
+ reg fmc_clk = 1'b0;
+
+ // Clock
+ always #11.111 fmc_clk = ~fmc_clk;
+
+ // Outputs
+ wire io_clk;
+ wire sys_clk;
+ wire sys_rst_n;
+ wire core_clk;
+
+ // Internals
+ reg fmc_clk_inhibit = 1'b0;
+
+ // UUT
+ alpha_clkmgr uut
+ (
+ .fmc_clk(fmc_clk & ~fmc_clk_inhibit),
+ .io_clk(io_clk),
+ .sys_clk(sys_clk),
+ .sys_rst_n(sys_rst_n),
+ .core_clk(core_clk)
+ );
+
+ // Script
+ initial begin
+ #399000;
+ fmc_clk_inhibit = 1'b1;
+ #1000;
+ fmc_clk_inhibit = 1'b0;
+ end
+
+endmodule
diff --git a/rtl/clkmgr_mmcm.v b/rtl/clkmgr_mmcm.v
index 03b0747..afb5716 100644
--- a/rtl/clkmgr_mmcm.v
+++ b/rtl/clkmgr_mmcm.v
@@ -1,12 +1,12 @@
//======================================================================
//
// clkmgr_mmcm.v
-// ---------------
+// -------------
// Xilinx MMCM primitive wrapper to avoid using Clocking Wizard IP core.
//
//
// Author: Pavel Shatov
-// Copyright (c) 2016, 2018, NORDUnet A/S All rights reserved.
+// Copyright (c) 2019, 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
@@ -37,144 +37,121 @@
//======================================================================
module clkmgr_mmcm
- (
- input wire gclk_in,
- input wire reset_in,
-
- output wire gclk_out,
- output wire gclk_missing_out,
+(
+ input fmc_clk_in,
+ input rst_in,
+
+ output io_clk_out,
+ output sys_clk_out,
+ output core_clk_out,
+ output locked_out
+);
- output wire clk_out,
- output wire clk_valid_out
- );
-
-
- //
- // Parameters
- //
- parameter CLK_OUT_MUL = 12.0; // multiply factor for output clock frequency (2..64)
- parameter CLK_OUT_DIV = 12.0; // divide factor for output clock frequency (1..128)
- parameter CLK_OUT_PHI = 45.0; // clock phase shift (0.0..360.0)
-
-
- //
- // IBUFG
- //
-
- (* BUFFER_TYPE="NONE" *)
- wire gclk_in_ibufg;
-
- IBUFG IBUFG_gclk
- (
- .I (gclk_in),
- .O (gclk_in_ibufg)
- );
-
-
- //
- // MMCME2_ADV
- //
- wire mmcm_clkout0;
- wire mmcm_locked;
- wire mmcm_clkfbout;
- wire mmcm_clkfbout_bufg;
-
- MMCME2_ADV #
- (
- .CLKIN1_PERIOD (11.111),
- .REF_JITTER1 (0.010),
-
- .STARTUP_WAIT ("FALSE"),
- .BANDWIDTH ("OPTIMIZED"),
- .COMPENSATION ("ZHOLD"),
-
- .DIVCLK_DIVIDE (1),
-
- .CLKFBOUT_MULT_F (CLK_OUT_MUL),
- .CLKFBOUT_PHASE (0.000),
- .CLKFBOUT_USE_FINE_PS ("FALSE"),
-
- .CLKOUT0_DIVIDE_F (CLK_OUT_DIV),
- .CLKOUT0_PHASE (CLK_OUT_PHI),
- .CLKOUT0_USE_FINE_PS ("FALSE"),
- .CLKOUT0_DUTY_CYCLE (0.500),
-
- .CLKOUT4_CASCADE ("FALSE")
- )
- MMCME2_ADV_inst
- (
- .CLKIN1 (gclk_in_ibufg),
- .CLKIN2 (1'b0),
- .CLKINSEL (1'b1),
+ parameter integer CLK_CORE_MULT = 4;
- .CLKFBIN (mmcm_clkfbout_bufg),
- .CLKFBOUT (mmcm_clkfbout),
- .CLKFBOUTB (),
-
- .CLKINSTOPPED (gclk_missing_out),
- .CLKFBSTOPPED (),
+ function integer lookup_vco_freq;
+ input integer core_mult;
+ case (core_mult)
+ 2: lookup_vco_freq = 990;
+ 3: lookup_vco_freq = 945;
+ 4: lookup_vco_freq = 1080;
+ 5: lookup_vco_freq = 900;
+ 6: lookup_vco_freq = 1080;
+ 7: lookup_vco_freq = 945;
+ 8: lookup_vco_freq = 1080;
+ endcase
+ endfunction
+
+ localparam real FMC_CLK_PERIOD_F = 22.222;
+ localparam real FB_PHASE_F = 45.0;
+ localparam real SYS_FREQ_F = 90.0;
+
+ localparam integer VCO_FREQ = lookup_vco_freq(CLK_CORE_MULT);
+ localparam integer IO_FREQ = 45;
+ localparam integer CORE_FREQ = CLK_CORE_MULT * IO_FREQ;
- .CLKOUT0 (mmcm_clkout0),
- .CLKOUT0B (),
-
- .CLKOUT1 (),
- .CLKOUT1B (),
-
- .CLKOUT2 (),
- .CLKOUT2B (),
-
- .CLKOUT3 (),
- .CLKOUT3B (),
-
- .CLKOUT4 (),
- .CLKOUT5 (),
- .CLKOUT6 (),
-
- .DCLK (1'b0),
- .DEN (1'b0),
- .DWE (1'b0),
- .DADDR (7'd0),
- .DI (16'h0000),
- .DO (),
- .DRDY (),
-
- .PSCLK (1'b0),
- .PSEN (1'b0),
- .PSINCDEC (1'b0),
- .PSDONE (),
-
- .LOCKED (mmcm_locked),
- .PWRDWN (1'b0),
- .RST (reset_in)
- );
+ localparam real VCO_FREQ_F = 1.0 * VCO_FREQ;
+ localparam real FMC_FREQ_F = 1.0 * IO_FREQ;
+
+ localparam real FB_MULT_F = VCO_FREQ_F / FMC_FREQ_F;
+ localparam real CLK0_DIV_F = VCO_FREQ_F / SYS_FREQ_F;
+
+ localparam integer CLK1_DIV = VCO_FREQ / IO_FREQ;
+ localparam integer CLK2_DIV = VCO_FREQ / CORE_FREQ;
+ wire fmc_clk_ibufg;
+ IBUFG IBUFG_fmc_clk
+ (
+ .I(fmc_clk_in),
+ .O(fmc_clk_ibufg)
+ );
- //
- // Mapping
- //
- assign gclk_out = gclk_in_ibufg;
- assign clk_valid_out = mmcm_locked;
-
-
- //
- // BUFGs
- //
- BUFG BUFG_gclk
- (
- .I (mmcm_clkout0),
- .O (clk_out)
+ wire mmcm_clkout0;
+ wire mmcm_clkout1;
+ wire mmcm_clkout2;
+ wire mmcm_clkfbin;
+ wire mmcm_clkfbout;
+ MMCME2_BASE #
+ (
+ .CLKIN1_PERIOD (FMC_CLK_PERIOD_F),
+ .CLKFBOUT_MULT_F (FB_MULT_F),
+ .CLKFBOUT_PHASE (FB_PHASE_F),
+ .CLKOUT0_DIVIDE_F (CLK0_DIV_F),
+ .CLKOUT1_DIVIDE (CLK1_DIV),
+ .CLKOUT2_DIVIDE (CLK2_DIV)
+ )
+ MMCME2_BASE_io_clk
+ (
+ .CLKIN1 (fmc_clk_ibufg),
+ .RST (rst_in),
+ .PWRDWN (1'b0),
+
+ .LOCKED (locked_out),
+
+
+ .CLKFBOUT (mmcm_clkfbout),
+ .CLKFBOUTB (),
+ .CLKFBIN (mmcm_clkfbin),
+
+ .CLKOUT0 (mmcm_clkout0),
+ .CLKOUT0B (),
+ .CLKOUT1 (mmcm_clkout1),
+ .CLKOUT1B (),
+ .CLKOUT2 (mmcm_clkout2),
+ .CLKOUT2B (),
+ .CLKOUT3 (),
+ .CLKOUT3B (),
+ .CLKOUT4 (),
+ .CLKOUT5 (),
+ .CLKOUT6 ()
);
-
- BUFG BUFG_feedback
- (
- .I (mmcm_clkfbout),
- .O (mmcm_clkfbout_bufg)
- );
-
-
+
+ BUFG BUFG_clkfb
+ (
+ .I(mmcm_clkfbout),
+ .O(mmcm_clkfbin)
+ );
+
+ BUFG BUFG_clk_io
+ (
+ .I(mmcm_clkout0),
+ .O(sys_clk_out)
+ );
+
+ BUFG BUFG_clk_sys
+ (
+ .I(mmcm_clkout1),
+ .O(io_clk_out)
+ );
+
+ BUFG BUFG_clk_core
+ (
+ .I(mmcm_clkout2),
+ .O(core_clk_out)
+ );
endmodule
//======================================================================
-// EOF clkmgr_mmcm.v
+// EOF clkmgr_mmcm_io.v
//======================================================================
diff --git a/rtl/clkmgr_mmcm_ctrl.v b/rtl/clkmgr_mmcm_ctrl.v
new file mode 100644
index 0000000..6d22291
--- /dev/null
+++ b/rtl/clkmgr_mmcm_ctrl.v
@@ -0,0 +1,117 @@
+//======================================================================
+//
+// clkmgr_mmcm_ctrl.v
+// ------------------
+// PLL reset generator and lock monitor.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2019, 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_mmcm_ctrl
+(
+ input clk_in,
+ input reset_n_in,
+ input locked_in,
+ output reset_out
+);
+
+ //
+ // Timer Settings
+ //
+ localparam [13:0] tmr_zero = {14{1'b0}};
+ localparam [13:0] tmr_last = {14{1'b1}};
+ reg [13:0] tmr = tmr_zero;
+ wire [13:0] tmr_next = tmr + 1'b1;
+ wire [ 9:0] tmr_msb = tmr[13:4];
+
+ wire tmr_about_to_wrap = tmr == tmr_last;
+ wire tmr_msb_is_zero = tmr_msb == 10'd0;
+
+ //
+ // Lock Counting and Monitoring
+ //
+ reg [1:0] pll_seen_locks = 2'd0;
+ wire [1:0] pll_seen_locks_next = (pll_seen_locks < 2'd3) ? pll_seen_locks + 1'b1 : pll_seen_locks;
+
+ (* SHREG_EXTRACT="NO" *)
+ (* EQUIVALENT_REGISTER_REMOVAL="NO" *)
+ reg [3:0] pll_stable_lock_shreg = 4'h0;
+ wire pll_stable_lock = pll_stable_lock_shreg[3];
+
+ wire pll_needs_reset = (pll_seen_locks != 2'd1) || !pll_stable_lock;
+
+ //
+ // Output Register
+ //
+ reg reset_out_r = 1'b1;
+ assign reset_out = reset_out_r;
+
+ //
+ // Timer Increment/Wrap Logic
+ //
+ always @(posedge clk_in or negedge reset_n_in)
+ //
+ if (!reset_n_in) tmr <= tmr_zero;
+ else begin
+ if (!tmr_about_to_wrap) tmr <= tmr_next;
+ else if (pll_needs_reset) tmr <= tmr_zero;
+ end
+
+ //
+ // Lock Counter
+ //
+ always @(posedge locked_in or posedge reset_out)
+ //
+ if (reset_out) pll_seen_locks <= 2'd0;
+ else pll_seen_locks <= pll_seen_locks_next;
+
+ //
+ // Lock Monitor
+ //
+ always @(posedge clk_in or negedge locked_in)
+ //
+ if (!locked_in) pll_stable_lock_shreg <= 4'h0;
+ else pll_stable_lock_shreg <= {pll_stable_lock_shreg[2:0], 1'b1};
+
+ //
+ // Reset Generator
+ //
+ always @(posedge clk_in or negedge reset_n_in)
+ //
+ if (!reset_n_in) reset_out_r <= 1'b1;
+ else reset_out_r <= tmr_msb_is_zero;
+
+endmodule
+
+//======================================================================
+// EOF clkmgr_mmcm_ctrl.v
+//======================================================================
diff --git a/rtl/clkmgr_reset_gen.v b/rtl/clkmgr_reset_gen.v
new file mode 100644
index 0000000..9cc4401
--- /dev/null
+++ b/rtl/clkmgr_reset_gen.v
@@ -0,0 +1,69 @@
+//======================================================================
+//
+// clkmgr_reset_gen.v
+// ------------------
+// System reset generator.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2019, 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_reset_gen
+(
+ input clk_in,
+ input locked_in,
+ output reset_n_out
+);
+
+ //
+ // Parameter
+ //
+ parameter integer SHREG_WIDTH = 16;
+
+ //
+ // Shift Register
+ //
+ (* SHREG_EXTRACT="NO" *)
+ (* EQUIVALENT_REGISTER_REMOVAL="NO" *)
+ reg [SHREG_WIDTH-1:0] sys_rst_shreg = {SHREG_WIDTH{1'b0}};
+
+ always @(posedge clk_in or negedge locked_in)
+ //
+ if (!locked_in) sys_rst_shreg <= {SHREG_WIDTH{1'b0}};
+ else sys_rst_shreg <= {sys_rst_shreg[SHREG_WIDTH-2:0], 1'b1};
+
+ assign reset_n_out = sys_rst_shreg[SHREG_WIDTH-1];
+
+endmodule
+
+//======================================================================
+// EOF clkmgr_reset_gen.v
+//======================================================================
diff --git a/ucf/alpha_fmc.ucf b/ucf/alpha_fmc.ucf
index 7926762..908f9fe 100644
--- a/ucf/alpha_fmc.ucf
+++ b/ucf/alpha_fmc.ucf
@@ -46,31 +46,28 @@
#-------------------------------------------------------------------------------
-# FMC_CLK Timing (can be up to 90 MHz)
+# FMC_CLK Timing
#-------------------------------------------------------------------------------
NET "fmc_clk" TNM_NET = TNM_fmc_clk;
-# 90 MHz
-#TIMESPEC TS_fmc_clk = PERIOD TNM_fmc_clk 11.111 ns HIGH 50%;
-
-# 60 MHz
-TIMESPEC TS_fmc_clk = PERIOD TNM_fmc_clk 16.667 ns HIGH 50%;
+# 45 MHz
+TIMESPEC TS_fmc_clk = PERIOD TNM_fmc_clk 22.222 ns HIGH 50%;
#-------------------------------------------------------------------------------
# FPGA Pinout
#-------------------------------------------------------------------------------
#
-NET "led_pins<0>" LOC = "U3";
-NET "led_pins<1>" LOC = "T1";
-NET "led_pins<2>" LOC = "W22";
-NET "led_pins<3>" LOC = "AA20";
+NET "led_pins<0>" LOC = "U3";
+NET "led_pins<1>" LOC = "T1";
+NET "led_pins<2>" LOC = "W22";
+NET "led_pins<3>" LOC = "AA20";
#
-NET "led_pins<*>" IOSTANDARD = "LVCMOS33";
-NET "led_pins<*>" SLEW = SLOW;
-NET "led_pins<*>" DRIVE = 8;
+NET "led_pins<*>" IOSTANDARD = "LVCMOS33";
+NET "led_pins<*>" SLEW = SLOW;
+NET "led_pins<*>" DRIVE = 8;
#
-NET "gclk_pin" LOC = "D17" | IOSTANDARD = "LVCMOS33" ;
+#NET "gclk_pin" LOC = "D17" | IOSTANDARD = "LVCMOS33" ;
#
NET "fmc_clk" LOC = "W11" | IOSTANDARD = "LVCMOS33" ;
NET "fmc_ne1" LOC = "V5" | IOSTANDARD = "LVCMOS33" ;
@@ -155,34 +152,57 @@ NET "mkm_do" LOC = "Y1" | IOSTANDARD = "LVCMOS33" ; # MKM_FPGA_MISO
# Control signals NE1, NL and NWE all have different timing values.
# Instead of writing individual constraints for every control signal, the most
# strict constraint is applied to all control signals. This should not cause
-# any P&R issues, since Spartan-6 (and Artix-7) can handle 90 MHz easily.
+# any P&R issues, since Spartan-6 (and Artix-7) can handle 45 MHz very easily.
#
# NOE signal is not constrained, since it drives "T" input of IOBUF primitive.
#
-# Data and Address buses also have different timings, with Data bus timing being
+# Data and Address buses also have different timings, with Address bus timing being
# more strict.
#
-# Oh, and the datasheet doesn't explicitly specify hold time for the data bus.
+# Oh, and the datasheet doesn't explicitly specify hold time for the data bus. But that
+# is not a problem, since it's apparently impossible to specify both OFFSET OUT BEFORE
+# and AFTER at the same time :)
#
+# "ideal" values
+#TIMEGRP "TNM_FMC_IN_DATA" OFFSET = IN 8.5 ns VALID 19.5 ns BEFORE "fmc_clk" RISING ;
+#TIMEGRP "TNM_FMC_IN_ADDR" OFFSET = IN 11.0 ns VALID 11.0 ns BEFORE "fmc_clk" RISING ;
+#TIMEGRP "TNM_FMC_IN_CONTROL" OFFSET = IN 10.5 ns VALID 15.5 ns BEFORE "fmc_clk" RISING ;
+
+# more realistic ("strict") values with 1 ns subtracted from both sides of the
+# valid window
+TIMEGRP "TNM_FMC_IN_DATA" OFFSET = IN 7.5 ns VALID 17.5 ns BEFORE "fmc_clk" RISING ;
+TIMEGRP "TNM_FMC_IN_ADDR" OFFSET = IN 10.0 ns VALID 9.0 ns BEFORE "fmc_clk" RISING ;
+TIMEGRP "TNM_FMC_IN_CONTROL" OFFSET = IN 9.5 ns VALID 13.5 ns BEFORE "fmc_clk" RISING ;
+
NET "fmc_d<*>" TNM = "TNM_FMC_IN_DATA" ;
NET "fmc_a<*>" TNM = "TNM_FMC_IN_ADDR" ;
-
+#
NET "fmc_ne1" TNM = "TNM_FMC_IN_CONTROL" ;
NET "fmc_nl" TNM = "TNM_FMC_IN_CONTROL" ;
NET "fmc_nwe" TNM = "TNM_FMC_IN_CONTROL" ;
-TIMEGRP "TNM_FMC_IN_DATA" OFFSET = IN 3.0 ns VALID 8.5 ns BEFORE "fmc_clk" RISING ;
-TIMEGRP "TNM_FMC_IN_ADDR" OFFSET = IN 5.5 ns VALID 5.5 ns BEFORE "fmc_clk" RISING ;
-TIMEGRP "TNM_FMC_IN_CONTROL" OFFSET = IN 5.0 ns VALID 10.0 ns BEFORE "fmc_clk" RISING ;
-
#-------------------------------------------------------------------------------
# FMC Output Timing
#-------------------------------------------------------------------------------
+TIMEGRP "TNM_FMC_OUT_DATA" OFFSET = OUT 6.0 ns BEFORE "fmc_clk" FALLING; #+1ns
+
NET "fmc_d<*>" TNM = "TNM_FMC_OUT_DATA" ;
-TIMEGRP "TNM_FMC_OUT_DATA" OFFSET = OUT 6.0 ns AFTER "fmc_clk" RISING;
+
+#-------------------------------------------------------------------------------
+# Core Selector Multi-Cycle Readback Mux
+#-------------------------------------------------------------------------------
+NET "cores/reg_read_data_*<*>" TNM_NET = TNM_CORE_SELECTOR_MUX_INPUT ;
+NET "cores/addr_core_num_dly2<*>" TNM_NET = TNM_CORE_SELECTOR_MUX_CONTROL ;
+NET "cores/pipe_read_data_*<*>" TNM_NET = TNM_CORE_SELECTOR_MUX_OUTPUT ;
+
+TIMEGRP "TNM_CORE_SELECTOR_MUX_SRC" = "TNM_CORE_SELECTOR_MUX_INPUT" "TNM_CORE_SELECTOR_MUX_CONTROL" ;
+TIMEGRP "TNM_CORE_SELECTOR_MUX_DST" = "TNM_CORE_SELECTOR_MUX_OUTPUT" ;
+
+TIMESPEC TS_core_selector = FROM TNM_CORE_SELECTOR_MUX_SRC TO TNM_CORE_SELECTOR_MUX_DST TS_clkmgr_mmcm_inst_mmcm_clkout0 * 2 ;
+
#======================================================================
diff --git a/xdc/alpha_fmc_clocks.xdc b/xdc/alpha_fmc_clocks.xdc
new file mode 100644
index 0000000..4184ff4
--- /dev/null
+++ b/xdc/alpha_fmc_clocks.xdc
@@ -0,0 +1 @@
+create_clock -period 22.222 -name clk_fmc -waveform {0.000 11.111} [get_ports fmc_clk]
diff --git a/xdc/alpha_fmc_pinout.xdc b/xdc/alpha_fmc_pinout.xdc
new file mode 100644
index 0000000..9f4e08a
--- /dev/null
+++ b/xdc/alpha_fmc_pinout.xdc
@@ -0,0 +1,100 @@
+set_property PACKAGE_PIN "U3" [get_ports {led_pins[0]}]
+set_property PACKAGE_PIN "T1" [get_ports {led_pins[1]}]
+set_property PACKAGE_PIN "W22" [get_ports {led_pins[2]}]
+set_property PACKAGE_PIN "AA20" [get_ports {led_pins[3]}]
+
+set_property PACKAGE_PIN "W11" [get_ports {fmc_clk }]
+set_property PACKAGE_PIN "V5" [get_ports {fmc_ne1 }]
+set_property PACKAGE_PIN "W16" [get_ports {fmc_noe }]
+set_property PACKAGE_PIN "AA6" [get_ports {fmc_nwe }]
+set_property PACKAGE_PIN "W17" [get_ports {fmc_nl }]
+set_property PACKAGE_PIN "Y6" [get_ports {fmc_nwait }]
+
+set_property PACKAGE_PIN "Y17" [get_ports {fmc_a[0]}]
+set_property PACKAGE_PIN "AB16" [get_ports {fmc_a[1]}]
+set_property PACKAGE_PIN "AA16" [get_ports {fmc_a[2]}]
+set_property PACKAGE_PIN "Y16" [get_ports {fmc_a[3]}]
+set_property PACKAGE_PIN "AB17" [get_ports {fmc_a[4]}]
+set_property PACKAGE_PIN "AA13" [get_ports {fmc_a[5]}]
+set_property PACKAGE_PIN "AB13" [get_ports {fmc_a[6]}]
+set_property PACKAGE_PIN "AA15" [get_ports {fmc_a[7]}]
+set_property PACKAGE_PIN "AB15" [get_ports {fmc_a[8]}]
+set_property PACKAGE_PIN "Y13" [get_ports {fmc_a[9]}]
+set_property PACKAGE_PIN "AA14" [get_ports {fmc_a[10]}]
+set_property PACKAGE_PIN "Y14" [get_ports {fmc_a[11]}]
+set_property PACKAGE_PIN "AB10" [get_ports {fmc_a[12]}]
+set_property PACKAGE_PIN "V2" [get_ports {fmc_a[13]}]
+set_property PACKAGE_PIN "AB12" [get_ports {fmc_a[14]}]
+set_property PACKAGE_PIN "AB8" [get_ports {fmc_a[15]}]
+set_property PACKAGE_PIN "AA9" [get_ports {fmc_a[16]}]
+set_property PACKAGE_PIN "AA8" [get_ports {fmc_a[17]}]
+set_property PACKAGE_PIN "Y7" [get_ports {fmc_a[18]}]
+set_property PACKAGE_PIN "AB21" [get_ports {fmc_a[19]}]
+set_property PACKAGE_PIN "AB22" [get_ports {fmc_a[20]}]
+set_property PACKAGE_PIN "AB20" [get_ports {fmc_a[21]}]
+set_property PACKAGE_PIN "Y21" [get_ports {fmc_a[22]}]
+set_property PACKAGE_PIN "Y22" [get_ports {fmc_a[23]}]
+#set_property PACKAGE_PIN "AB18" [get_ports {fmc_a[24]}]
+#set_property PACKAGE_PIN "AA19" [get_ports {fmc_a[25]}]
+
+set_property PACKAGE_PIN "AB7" [get_ports {fmc_d[0]}]
+set_property PACKAGE_PIN "AB6" [get_ports {fmc_d[1]}]
+set_property PACKAGE_PIN "U1" [get_ports {fmc_d[2]}]
+set_property PACKAGE_PIN "U2" [get_ports {fmc_d[3]}]
+set_property PACKAGE_PIN "AB11" [get_ports {fmc_d[4]}]
+set_property PACKAGE_PIN "AA11" [get_ports {fmc_d[5]}]
+set_property PACKAGE_PIN "Y11" [get_ports {fmc_d[6]}]
+set_property PACKAGE_PIN "Y12" [get_ports {fmc_d[7]}]
+set_property PACKAGE_PIN "Y18" [get_ports {fmc_d[8]}]
+set_property PACKAGE_PIN "AA21" [get_ports {fmc_d[9]}]
+set_property PACKAGE_PIN "W20" [get_ports {fmc_d[10]}]
+set_property PACKAGE_PIN "N15" [get_ports {fmc_d[11]}]
+set_property PACKAGE_PIN "U20" [get_ports {fmc_d[12]}]
+set_property PACKAGE_PIN "AA1" [get_ports {fmc_d[13]}]
+set_property PACKAGE_PIN "AB1" [get_ports {fmc_d[14]}]
+set_property PACKAGE_PIN "AB2" [get_ports {fmc_d[15]}]
+set_property PACKAGE_PIN "AB3" [get_ports {fmc_d[16]}]
+set_property PACKAGE_PIN "Y3" [get_ports {fmc_d[17]}]
+set_property PACKAGE_PIN "AA3" [get_ports {fmc_d[18]}]
+set_property PACKAGE_PIN "AA5" [get_ports {fmc_d[19]}]
+set_property PACKAGE_PIN "AB5" [get_ports {fmc_d[20]}]
+set_property PACKAGE_PIN "Y4" [get_ports {fmc_d[21]}]
+set_property PACKAGE_PIN "AA4" [get_ports {fmc_d[22]}]
+set_property PACKAGE_PIN "V4" [get_ports {fmc_d[23]}]
+set_property PACKAGE_PIN "W10" [get_ports {fmc_d[24]}]
+set_property PACKAGE_PIN "R4" [get_ports {fmc_d[25]}]
+set_property PACKAGE_PIN "W12" [get_ports {fmc_d[26]}]
+set_property PACKAGE_PIN "W14" [get_ports {fmc_d[27]}]
+set_property PACKAGE_PIN "V20" [get_ports {fmc_d[28]}]
+set_property PACKAGE_PIN "V18" [get_ports {fmc_d[29]}]
+set_property PACKAGE_PIN "R21" [get_ports {fmc_d[30]}]
+set_property PACKAGE_PIN "P21" [get_ports {fmc_d[31]}]
+
+set_property PACKAGE_PIN "W19" [get_ports {ct_noise}]
+
+set_property PACKAGE_PIN "V3" [get_ports {mkm_sclk}]
+set_property PACKAGE_PIN "W2" [get_ports {mkm_cs_n}]
+set_property PACKAGE_PIN "W1" [get_ports {mkm_di}]
+set_property PACKAGE_PIN "Y1" [get_ports {mkm_do}]
+
+
+set_property IOSTANDARD "LVCMOS33" [get_ports {led_*}]
+set_property IOSTANDARD "LVCMOS33" [get_ports {fmc_*}]
+set_property IOSTANDARD "LVCMOS33" [get_ports {ct_noise}]
+set_property IOSTANDARD "LVCMOS33" [get_ports {mkm_*}]
+
+
+set_property DRIVE 8 [get_ports {led_pins[*]}]
+set_property DRIVE 8 [get_ports {fmc_nwait}]
+set_property DRIVE 8 [get_ports {fmc_d[*]}]
+set_property DRIVE 8 [get_ports {mkm_sclk}]
+set_property DRIVE 8 [get_ports {mkm_cs_n}]
+set_property DRIVE 8 [get_ports {mkm_di}]
+
+
+set_property SLEW "SLOW" [get_ports {led_pins[*]}]
+set_property SLEW "FAST" [get_ports {fmc_nwait}]
+set_property SLEW "FAST" [get_ports {fmc_d[*]}]
+set_property SLEW "SLOW" [get_ports {mkm_sclk}]
+set_property SLEW "SLOW" [get_ports {mkm_cs_n}]
+set_property SLEW "SLOW" [get_ports {mkm_di}]
diff --git a/xdc/alpha_fmc_timing.xdc b/xdc/alpha_fmc_timing.xdc
new file mode 100644
index 0000000..e311270
--- /dev/null
+++ b/xdc/alpha_fmc_timing.xdc
@@ -0,0 +1 @@
+create_clock -period 22.222 -name clk_fmc -waveform {0.000 11.111} [get_ports clk_fmc]