aboutsummaryrefslogtreecommitdiff
path: root/rtl
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2016-05-12 18:20:34 -0400
committerPaul Selkirk <paul@psgd.org>2016-05-12 18:26:49 -0400
commit9994e1276580164c6a09b66026c645a50367592d (patch)
treec35c1e2fb3fb9e05677f65489dccba55e4415189 /rtl
Initial commit, based on core/platform/novena[/fmc], probably doesn't work, but gives Pavel and Fredrik a place to put their stuff.
Diffstat (limited to 'rtl')
-rw-r--r--rtl/alpha_clkmgr.v132
-rw-r--r--rtl/alpha_fmc_top.v247
-rw-r--r--rtl/alpha_regs.v148
-rw-r--r--rtl/clkmgr_dcm.v164
-rw-r--r--rtl/lint-dummy.v128
5 files changed, 819 insertions, 0 deletions
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
+