[Cryptech-Commits] [core/comm/fmc] 01/01: Initial commit

git at cryptech.is git at cryptech.is
Sun Nov 1 03:58:43 UTC 2015


This is an automated email from the git hooks/post-receive script.

paul at psgd.org pushed a commit to branch master
in repository core/comm/fmc.

commit fb17b78136c9e3efe54ac55ab08086256b3a0944
Author: Paul Selkirk <paul at psgd.org>
Date:   Thu Oct 29 13:34:29 2015 -0400

    Initial commit
---
 LICENSE                   |  27 +++++
 README.md                 |   5 +
 src/rtl/cdc_bus_pulse.v   | 145 +++++++++++++++++++++++
 src/rtl/fmc_arbiter.v     | 295 ++++++++++++++++++++++++++++++++++++++++++++++
 src/rtl/fmc_arbiter_cdc.v | 145 +++++++++++++++++++++++
 src/rtl/fmc_d_phy.v       |  77 ++++++++++++
 src/rtl/fmc_indicator.v   |  69 +++++++++++
 src/rtl/fmc_regs.v        | 129 ++++++++++++++++++++
 8 files changed, 892 insertions(+)

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..fd7518e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..50443da
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+fmc
+===
+
+Verilog implementation of the Flexible Memory Controller interface used to
+connect FPGA cores to the STM32 MCU.
diff --git a/src/rtl/cdc_bus_pulse.v b/src/rtl/cdc_bus_pulse.v
new file mode 100644
index 0000000..cc2d8db
--- /dev/null
+++ b/src/rtl/cdc_bus_pulse.v
@@ -0,0 +1,145 @@
+//======================================================================
+//
+// cdc_bus_pulse.v
+// ---------------
+// Clock Domain Crossing handler for the Cryptech Novena
+// FPGA framework design.
+//
+// This module is based on design suggested on page 27 of the
+// paper 'Clock Domain Crossing (CDC) Design & Verification Techniques
+// Using SystemVerilog' by Clifford E. Cummings (Sunburst Design, Inc.)
+//
+//
+// 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 cdc_bus_pulse
+  #(parameter   DATA_WIDTH      = 32)     // width of data bus
+   (
+    input wire                   src_clk, // source domain clock
+    input wire [DATA_WIDTH-1:0]  src_din, // data from source clock domain
+    input wire                   src_req, // start transfer pulse from source clock domain
+
+    input wire                   dst_clk, // destination domain clock
+    output wire [DATA_WIDTH-1:0] dst_dout, // data to destination clock domain
+    output wire                  dst_pulse // transfer done pulse to destination clock domain
+    );
+
+   //
+   // Source Side Registers
+   //
+   reg                           src_ff         = 1'b0;                 // transfer request flag
+   reg [DATA_WIDTH-1:0]          src_latch      = {DATA_WIDTH{1'bX}};   // source data buffer
+
+
+   //
+   // Source Request Handler
+   //
+   always @(posedge src_clk)
+     //
+     if (src_req) begin                         // transfer request pulse?
+        src_ff          <= ~src_ff;             // toggle transfer request flag...
+        src_latch       <= src_din;             // ... and capture data in source buffer
+     end
+
+
+   //
+   // Source -> Destination Flag Sync Logic
+   //
+
+   /* ISE may decide to infer SRL here, so we explicitly instantiate slice registers. */
+
+   wire flag_sync_first;        // first FF output
+   wire flag_sync_second;       // second FF output
+   wire flag_sync_third;        // third FF output
+   wire flag_sync_pulse;        // flag toggle detector output
+
+   FDCE ff_sync_first
+     (
+      .C(dst_clk),
+      .D(src_ff),               // capture flag from another clock domain
+      .Q(flag_sync_first),      // metastability can occur here
+      .CLR(1'b0),
+      .CE(1'b1)
+      );
+   FDCE ff_sync_second
+     (
+      .C(dst_clk),
+      .D(flag_sync_first),      // synchronize captured flag to remove metastability
+      .Q(flag_sync_second),     // and pass it to another flip-flop
+      .CLR(1'b0),
+      .CE(1'b1)
+      );
+   FDCE ff_sync_third
+     (
+      .C(dst_clk),
+      .D(flag_sync_second),     // delay synchronized flag in another flip-flip, because we need
+      .Q(flag_sync_third),      // two synchronized flag values (current and delayed) to detect its change
+      .CLR(1'b0),
+      .CE(1'b1)
+      );
+
+   // when delayed flag value differs from its current value, it was changed
+   // by the source side, so there must have been a transfer request
+   assign flag_sync_pulse = flag_sync_second ^ flag_sync_third;
+
+
+   //
+   // Destination Side Registers
+   //
+   reg  dst_pulse_reg   = 1'b0;                         // transfer done flag
+   reg [DATA_WIDTH-1:0] dst_latch = {DATA_WIDTH{1'bX}}; // destination data buffer
+
+   assign dst_pulse     = dst_pulse_reg;
+   assign dst_dout      = dst_latch;
+
+   //
+   // Destination Request Handler
+   //
+   always @(posedge dst_clk) begin
+      //
+      dst_pulse_reg <= flag_sync_pulse; // generate pulse if flag change was detected
+      //
+      if (flag_sync_pulse)
+        dst_latch <= src_latch;
+      /* By the time destination side receives synchronized flag
+       * value, data should be stable, we can safely capture and store
+       * it in the destination buffer.
+       */
+
+   end
+
+
+endmodule
+
+//======================================================================
+// EOF cdc_bus_pulse.v
+//======================================================================
diff --git a/src/rtl/fmc_arbiter.v b/src/rtl/fmc_arbiter.v
new file mode 100644
index 0000000..d6fb950
--- /dev/null
+++ b/src/rtl/fmc_arbiter.v
@@ -0,0 +1,295 @@
+//======================================================================
+//
+// fmc_arbiter.v
+// -------------
+// Port arbiter for the FMC interface for the Cryptech
+// Novena FPGA + STM32 Bridge Board 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 fmc_arbiter
+  (
+   // fmc bus
+   fmc_clk,
+   fmc_a, fmc_d,
+   fmc_ne1, fmc_nl, fmc_nwe, fmc_noe, fmc_nwait,
+
+   // system clock
+   sys_clk,
+
+   // user bus
+   sys_addr,
+   sys_wr_en,
+   sys_data_out,
+   sys_rd_en,
+   sys_data_in
+   );
+
+
+   //
+   // Parameters
+   //
+   parameter NUM_ADDR_BITS = 22;
+
+
+   //
+   // Ports
+   //
+   input        wire                     fmc_clk;
+   input        wire [NUM_ADDR_BITS-1:0] fmc_a;
+   inout        wire [             31:0] fmc_d;
+   input        wire                     fmc_ne1;
+   input        wire                     fmc_nl;
+   input        wire                     fmc_nwe;
+   input        wire                     fmc_noe;
+   output       wire                     fmc_nwait;
+
+   input        wire                     sys_clk;
+
+   output       wire [NUM_ADDR_BITS-1:0] sys_addr;
+   output       wire                     sys_wr_en;
+   output       wire [             31:0] sys_data_out;
+   output       wire                     sys_rd_en;
+   input        wire [             31:0] sys_data_in;
+
+
+   //
+   // Data Bus PHY
+   //
+
+   /* PHY is needed to control bi-directional data bus. */
+
+   wire [31: 0]                          d_ro;   // value read from pins (receiver output)
+   reg [31: 0]                           d_di;   // value drives onto pins (driver input)
+
+   fmc_d_phy #
+     (
+      .BUS_WIDTH(32)
+      )
+   d_phy
+     (
+      .buf_io(fmc_d),          // <-- connect directly to top-level bi-dir port
+      .buf_di(d_di),
+      .buf_ro(d_ro),
+      .buf_t(fmc_noe)          // <-- bus direction is controlled by STM32
+      );
+
+
+   //
+   // FSM
+   //
+   localparam   FMC_FSM_STATE_INIT              = 5'b0_0_000; // arbiter is idle
+
+   localparam   FMC_FSM_STATE_WRITE_START       = 5'b1_1_000; // got address to write at
+   localparam   FMC_FSM_STATE_WRITE_LATENCY_1   = 5'b1_1_001; // dummy state to compensate STM32's latency
+   localparam   FMC_FSM_STATE_WRITE_LATENCY_2   = 5'b1_1_010; // dummy state to compensate STM32's latency
+   localparam   FMC_FSM_STATE_WRITE_LATENCY_3   = 5'b1_1_011; // dummy state to compensate STM32's latency
+   localparam   FMC_FSM_STATE_WRITE_DATABEAT    = 5'b1_1_100; // got data to write
+   localparam   FMC_FSM_STATE_WRITE_WAIT        = 5'b1_1_101; // request to user-side logic sent
+   localparam   FMC_FSM_STATE_WRITE_DONE        = 5'b1_1_111; // user-side logic acknowledged transaction
+
+   localparam   FMC_FSM_STATE_READ_START        = 5'b1_0_000; // got address to read from
+   localparam   FMC_FSM_STATE_READ_LATENCY_1    = 5'b1_0_001; // dummy state to compensate STM32's latency
+   localparam   FMC_FSM_STATE_READ_LATENCY_2    = 5'b1_0_010; // dummy state to compensate STM32's latency
+   localparam   FMC_FSM_STATE_READ_LATENCY_3    = 5'b1_0_011; // dummy state to compensate STM32's latency
+   localparam   FMC_FSM_STATE_READ_WAIT         = 5'b1_0_101; // request to user-side logic sent
+   localparam   FMC_FSM_STATE_READ_READY        = 5'b1_0_110; // got acknowledge from user logic
+   localparam   FMC_FSM_STATE_READ_DATABEAT     = 5'b1_0_100; // returned data to master
+   localparam   FMC_FSM_STATE_READ_DONE         = 5'b1_0_111; // transaction complete
+
+   reg [              4:0]               fmc_fsm_state  = FMC_FSM_STATE_INIT;                   // fsm state
+   reg [NUM_ADDR_BITS-1:0]               fmc_addr_latch = {NUM_ADDR_BITS{1'bX}};                // transaction address
+   reg [             31:0]               fmc_data_latch = {32{1'bX}};                                           // write data latch
+
+   /* These flags are used to wake up from INIT state. */
+   wire                                  fmc_write_start_flag = (fmc_ne1 == 1'b0) && (fmc_nwe == 1'b0) && (fmc_nl == 1'b0);
+   wire                                  fmc_read_start_flag  = (fmc_ne1 == 1'b0) && (fmc_nwe == 1'b1) && (fmc_nl == 1'b0);
+
+   /* These are transaction response flag and data from user-side logic. */
+   wire                                  fmc_user_ack;
+   wire [31: 0]                          fmc_user_data;
+
+   //
+   // FSM Transition Logic
+   //
+   always @(posedge fmc_clk)
+     //
+     case (fmc_fsm_state)
+       //
+       // INIT -> WRITE, INIT -> READ
+       //
+       FMC_FSM_STATE_INIT: begin
+          //
+          if (fmc_write_start_flag)     fmc_fsm_state   <= FMC_FSM_STATE_WRITE_START;
+          if (fmc_read_start_flag)      fmc_fsm_state   <= FMC_FSM_STATE_READ_START;
+          //
+       end
+       //
+       // WRITE
+       //
+       FMC_FSM_STATE_WRITE_START:       fmc_fsm_state <= FMC_FSM_STATE_WRITE_LATENCY_1;
+       FMC_FSM_STATE_WRITE_LATENCY_1:   fmc_fsm_state <= FMC_FSM_STATE_WRITE_LATENCY_2;
+       FMC_FSM_STATE_WRITE_LATENCY_2:   fmc_fsm_state <= FMC_FSM_STATE_WRITE_LATENCY_3;
+       FMC_FSM_STATE_WRITE_LATENCY_3:   fmc_fsm_state <= FMC_FSM_STATE_WRITE_DATABEAT;
+       FMC_FSM_STATE_WRITE_DATABEAT:    fmc_fsm_state <= FMC_FSM_STATE_WRITE_WAIT;
+       FMC_FSM_STATE_WRITE_WAIT:        if (fmc_user_ack) fmc_fsm_state <= FMC_FSM_STATE_WRITE_DONE;
+       FMC_FSM_STATE_WRITE_DONE:        fmc_fsm_state <= FMC_FSM_STATE_INIT;
+       //
+       // READ
+       //
+       FMC_FSM_STATE_READ_START:        fmc_fsm_state <= FMC_FSM_STATE_READ_LATENCY_1;
+       FMC_FSM_STATE_READ_LATENCY_1:    fmc_fsm_state <= FMC_FSM_STATE_READ_LATENCY_2;
+       FMC_FSM_STATE_READ_LATENCY_2:    fmc_fsm_state <= FMC_FSM_STATE_READ_LATENCY_3;
+       FMC_FSM_STATE_READ_LATENCY_3:    fmc_fsm_state <= FMC_FSM_STATE_READ_WAIT;
+       FMC_FSM_STATE_READ_WAIT:         if (fmc_user_ack) fmc_fsm_state <= FMC_FSM_STATE_READ_READY;
+       FMC_FSM_STATE_READ_READY:        fmc_fsm_state <= FMC_FSM_STATE_READ_DATABEAT;
+       FMC_FSM_STATE_READ_DATABEAT:     fmc_fsm_state <= FMC_FSM_STATE_READ_DONE;
+       FMC_FSM_STATE_READ_DONE:         fmc_fsm_state <= FMC_FSM_STATE_INIT;
+       //
+       default:                                                                                                                 fmc_fsm_state   <= FMC_FSM_STATE_INIT;
+       //
+     endcase
+
+
+   //
+   // Address Latch
+   //
+   always @(posedge fmc_clk)
+     //
+     if ((fmc_fsm_state == FMC_FSM_STATE_INIT) && (fmc_write_start_flag || fmc_read_start_flag))
+       //
+       fmc_addr_latch <= fmc_a;
+
+
+   //
+   // Additional Write Logic (Data Latch)
+   //
+   always @(posedge fmc_clk)
+     //
+     if (fmc_fsm_state == FMC_FSM_STATE_WRITE_LATENCY_3)
+       //
+       fmc_data_latch <= d_ro;
+
+
+   //
+   // Additional Read Logic (Read Latch)
+   //
+
+   /* Note that this register is updated on the falling edge of FMC_CLK, because
+    * STM32 samples bi-directional data bus on the rising edge.
+    */
+
+   always @(negedge fmc_clk)
+     //
+     if (fmc_fsm_state == FMC_FSM_STATE_READ_DATABEAT)
+       //
+       d_di <= fmc_user_data;
+
+
+
+   //
+   // Wait Logic
+   //
+   reg  fmc_wait_reg    = 1'b0;
+
+   always @(posedge fmc_clk)
+     //
+     begin
+        //
+        if ( (fmc_fsm_state == FMC_FSM_STATE_WRITE_START) ||
+             (fmc_fsm_state == FMC_FSM_STATE_READ_START) )
+          fmc_wait_reg  <= 1'b1;                // start waiting for read/write to complete
+        /*
+         if ( (fmc_fsm_state == FMC_FSM_STATE_WRITE_DONE) ||
+         (fmc_fsm_state == FMC_FSM_STATE_READ_READY) )
+         fmc_wait_reg  <= 1'b0;
+         */
+        if (fmc_fsm_state == FMC_FSM_STATE_INIT)
+          fmc_wait_reg  <= 1'b0;                // fsm is idle, no need to wait any more
+        //
+     end
+
+   assign fmc_nwait = ~fmc_wait_reg;
+
+
+   /* These flags are used to generate 1-cycle pulses to trigger CDC
+    * transaction.  Note that FSM goes from WRITE_DATABEAT to WRITE_WAIT and from
+    * READ_LATENCY_3 to READ_WAIT unconditionally, so these flags will always be
+    * active for 1 cycle only, which is exactly what we need.
+    */
+
+   wire arbiter_write_req_pulse = (fmc_fsm_state == FMC_FSM_STATE_WRITE_DATABEAT)  ? 1'b1 : 1'b0;
+   wire arbiter_read_req_pulse  = (fmc_fsm_state == FMC_FSM_STATE_READ_LATENCY_3)  ? 1'b1 : 1'b0;
+
+   //
+   // CDC Block
+   //
+
+   /* This block is used to transfer request data from FMC_CLK clock domain to
+    * SYS_CLK clock domain and then transfer acknowledge from SYS_CLK to FMC_CLK
+    * clock domain in return. Af first 1+1+22+32 = 56 bits are transfered,
+    * these are: write flag, read flag, address, write data. During read transaction
+    * some bogus write data is passed, which is not used later anyway.
+    * During read requests 32 bits of data are returned, during write requests
+    * 32 bits of bogus data are returned, that are never used later.
+    */
+
+   fmc_arbiter_cdc #
+     (
+      .NUM_ADDR_BITS(NUM_ADDR_BITS)
+      )
+   fmc_cdc
+     (
+      .fmc_clk(fmc_clk),
+
+      .fmc_req(arbiter_write_req_pulse | arbiter_read_req_pulse),
+      .fmc_ack(fmc_user_ack),
+
+      .fmc_din({arbiter_write_req_pulse, arbiter_read_req_pulse, fmc_addr_latch, fmc_data_latch}),
+      .fmc_dout(fmc_user_data),
+
+      .sys_clk(sys_clk),
+      .sys_addr(sys_addr),
+      .sys_wren(sys_wr_en),
+      .sys_data_out(sys_data_out),
+      .sys_rden(sys_rd_en),
+      .sys_data_in(sys_data_in)
+      );
+
+
+endmodule
+
+
+//======================================================================
+// EOF fmc_arbiter.v
+//======================================================================
diff --git a/src/rtl/fmc_arbiter_cdc.v b/src/rtl/fmc_arbiter_cdc.v
new file mode 100644
index 0000000..0eca0b1
--- /dev/null
+++ b/src/rtl/fmc_arbiter_cdc.v
@@ -0,0 +1,145 @@
+//======================================================================
+//
+// fmc_arbiter_cdc.v
+// -----------------
+// The actual clock domain crossing handler of the FMC arbiter
+// for the Cryptech Novena 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 fmc_arbiter_cdc #
+  (
+   parameter NUM_ADDR_BITS = 22
+   )
+   (
+    input wire                           fmc_clk, // fmc clock
+    input wire                           fmc_req, // fmc transaction request
+    output wire                          fmc_ack, // fmc transaction acknowledge
+    input wire [NUM_ADDR_BITS+32+2-1: 0] fmc_din, // data from cpu to fpga (write access)
+    output wire [31: 0]                  fmc_dout, // data from fpga to cpu (read access)
+
+    input wire                           sys_clk, // user internal clock
+    output wire [NUM_ADDR_BITS-1: 0]     sys_addr, // user access address
+    output wire                          sys_wren, // user write flag
+    output wire [31: 0]                  sys_data_out, // user write data
+    output wire                          sys_rden, // user read flag
+    input wire [31: 0]                   sys_data_in   // user read data
+    );
+
+
+   //
+   // FMC_CLK -> SYS_CLK Request
+   //
+   wire                                  sys_req;         // request pulse in sys_clk clock domain
+   wire [NUM_ADDR_BITS+32+2-1: 0]        sys_dout;        // transaction data in sys_clk clock domain
+
+   cdc_bus_pulse #
+     (
+      .DATA_WIDTH(NUM_ADDR_BITS+32+2)   // {write, read, addr, data}
+      )
+   cdc_fmc_sys
+     (
+      .src_clk(fmc_clk),
+      .src_din(fmc_din),
+      .src_req(fmc_req),
+
+      .dst_clk(sys_clk),
+      .dst_dout(sys_dout),
+      .dst_pulse(sys_req)
+      );
+
+
+   //
+   // Output Registers
+   //
+   reg                                   sys_wren_reg     = 1'b0;
+   reg                                   sys_rden_reg     = 1'b0;
+   reg [NUM_ADDR_BITS-1: 0]              sys_addr_reg     = {NUM_ADDR_BITS{1'bX}};
+   reg [31: 0]                           sys_data_out_reg = {32{1'bX}};
+
+   assign sys_wren      = sys_wren_reg;
+   assign sys_rden      = sys_rden_reg;
+   assign sys_addr      = sys_addr_reg;
+   assign sys_data_out  = sys_data_out_reg;
+
+
+   //
+   // System (User) Clock Access Handler
+   //
+   always @(posedge sys_clk)
+     //
+     if (sys_req)                               // request detected?
+       begin
+          sys_wren_reg     <= sys_dout[32+NUM_ADDR_BITS+1];     // set write flag if needed
+          sys_rden_reg     <= sys_dout[32+NUM_ADDR_BITS+0];     // set read flag if needed
+          sys_addr_reg     <= sys_dout[32+NUM_ADDR_BITS-1:32];  // set operation address
+          sys_data_out_reg <= sys_dout[31: 0];  // set data to write
+       end
+     else                                       // no request active
+       begin
+          sys_wren_reg  <=  1'b0;               // clear write flag
+          sys_rden_reg  <=  1'b0;               // clear read flag
+       end
+
+
+   //
+   // System Request 1-cycle delay to compensate registered mux delay in user-side logic
+   //
+   reg sys_req_dly = 1'b0;
+
+   always @(posedge sys_clk)
+     sys_req_dly <= sys_req;
+
+   //
+   // SYS_CLK -> FMC_CLK Acknowledge
+   //
+   cdc_bus_pulse #
+     (
+      .DATA_WIDTH(32)
+      )
+   cdc_sys_fmc
+     (
+      .src_clk(sys_clk),
+      .src_din(sys_data_in),
+      .src_req(sys_req_dly),
+
+      .dst_clk(fmc_clk),
+      .dst_dout(fmc_dout),
+      .dst_pulse(fmc_ack)
+      );
+
+endmodule
+
+//======================================================================
+// EOF fmc_arbiter_cdc.v
+//======================================================================
diff --git a/src/rtl/fmc_d_phy.v b/src/rtl/fmc_d_phy.v
new file mode 100644
index 0000000..ce643bb
--- /dev/null
+++ b/src/rtl/fmc_d_phy.v
@@ -0,0 +1,77 @@
+//======================================================================
+//
+// fmc_d_phy.v
+// ------------
+// IO buffer module for the FMC D port.
+//
+//
+// 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 fmc_d_phy
+  #(parameter BUS_WIDTH = 16)
+   (
+    inout wire [BUS_WIDTH-1:0]  buf_io, // connect directly to top-level pins
+    input wire [BUS_WIDTH-1:0]  buf_di, // drive input (value driven onto pins)
+    output wire [BUS_WIDTH-1:0] buf_ro, // receiver output (value read from pins)
+    input wire                  buf_t   // tristate control (driver is disabled during tristate)
+    );
+
+   //
+   // IOBUFs
+   //
+   genvar                       i;
+   generate
+      for (i = 0; i < BUS_WIDTH; i = i+1)
+        begin: fmc_d
+           //
+           IOBUF #
+               (
+                .IOSTANDARD("LVCMOS33"),
+                .DRIVE(8),
+                .SLEW("FAST")
+                )
+           IOBUF_inst
+               (
+                .IO(buf_io[i]),
+                .O(buf_ro[i]),
+                .I(buf_di[i]),
+                .T(buf_t)
+                );
+           //
+        end
+   endgenerate
+
+endmodule
+
+//======================================================================
+// EOF fmc_d_phy.v
+//======================================================================
diff --git a/src/rtl/fmc_indicator.v b/src/rtl/fmc_indicator.v
new file mode 100644
index 0000000..a802a59
--- /dev/null
+++ b/src/rtl/fmc_indicator.v
@@ -0,0 +1,69 @@
+//======================================================================
+//
+// fmc_indicator.v
+// ---------------
+// A simple LED indicator to show that the FMC is alive.
+//
+//
+// 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 fmc_indicator
+  (
+   input wire  sys_clk,
+   input wire  sys_rst,
+   input wire  fmc_active,
+   output wire led_out
+   );
+
+   //
+   // Parameters
+   //
+   localparam   CNT_BITS                = 24;   // led will be dim for 2**(24-1) = 8388608 ticks, which is ~100 ms @ 80 MHz.
+
+   //
+   // Counter
+   //
+   reg [CNT_BITS-1:0] cnt;
+
+   always @(posedge sys_clk)
+     //
+     if (sys_rst)                       cnt <= {CNT_BITS{1'b0}};
+     else if (cnt > {CNT_BITS{1'b0}})   cnt <= cnt - 1'b1;
+     else if (fmc_active)               cnt <= {CNT_BITS{1'b1}};
+
+   assign led_out = ~cnt[CNT_BITS-1];
+
+endmodule
+
+//======================================================================
+// EOF fmc_indicator.v
+//======================================================================
diff --git a/src/rtl/fmc_regs.v b/src/rtl/fmc_regs.v
new file mode 100644
index 0000000..8f740e3
--- /dev/null
+++ b/src/rtl/fmc_regs.v
@@ -0,0 +1,129 @@
+//======================================================================
+//
+// fmc.v
+// ------
+// Configuration registers for the fmc core.
+//
+//
+// Author: Joachim Strombergson
+// 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 comm_regs
+  (
+   // Clock and reset.
+   input wire           clk,
+   input wire           rst,
+
+   // 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;
+
+   // Core ID constants.
+   localparam CORE_NAME0   = 32'h666d6320;  // "fmc "
+   localparam CORE_NAME1   = 32'h20202020;  // "    "
+   localparam CORE_VERSION = 32'h302e3130;  // "0.10"
+
+
+   //----------------------------------------------------------------
+   // Wires.
+   //----------------------------------------------------------------
+   reg [31: 0]          tmp_read_data;
+   reg                  write_error;
+   reg                  read_error;
+
+
+   //----------------------------------------------------------------
+   // 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)
+     begin
+        write_error <= 0;
+
+        if (cs && we)
+          begin
+             // write operations
+             case (address)
+               // no writeable registers
+               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;
+               default:
+                 read_error = 1;
+             endcase
+          end
+     end
+
+endmodule
+
+//======================================================================
+// EOF fmc_regs.v
+//======================================================================



More information about the Commits mailing list