From c03aa37d4f237f2eb90d9a958428011ca2bd455c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Wed, 11 May 2016 17:13:04 +0200 Subject: Adding all source files and testbenches for the mkmif core. Adding Makefile for building simulation and linting. Adding top level license file. --- src/rtl/mkmif_spi.v | 378 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 src/rtl/mkmif_spi.v (limited to 'src/rtl/mkmif_spi.v') diff --git a/src/rtl/mkmif_spi.v b/src/rtl/mkmif_spi.v new file mode 100644 index 0000000..fc80470 --- /dev/null +++ b/src/rtl/mkmif_spi.v @@ -0,0 +1,378 @@ +//====================================================================== +// +// mkmif_spi.v +// ----------- +// SPI interface for the master key memory. When enabled the +// interface waits for command to transmit and receive a given +// number of bytes. Data is transmitted onto the spi_di port +// from the MSB of the spi_data register. Simultaneously, +// data captured on the spi_do port is inserted at LSB in the +// spi_data register. The spi clock is generated when data is to be +// sent or recived. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2011, 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 mkmif_spi( + input wire clk, + input wire reset_n, + + output wire spi_sclk, + output wire spi_cs_n, + input wire spi_do, + output wire spi_di, + + input wire set, + input wire start, + input wire [2 : 0] length, + input wire [15 : 0] divisor, + output wire ready, + input wire [55 : 0] wr_data, + output wire [31 : 0] rd_data + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam CTRL_IDLE = 2'h0; + localparam CTRL_START = 2'h1; + localparam CTRL_WAIT = 2'h2; + localparam CTRL_DONE = 2'h3; + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg do_sample0_reg; + reg do_sample1_reg; + + reg cs_n_reg; + reg cs_n_new; + reg cs_n_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [55 : 0] data_reg; + reg [55 : 0] data_new; + reg data_set; + reg data_nxt; + reg data_we; + + reg sclk_reg; + reg sclk_new; + reg sclk_rst; + reg sclk_en; + reg sclk_we; + + reg [15 : 0] clk_ctr_reg; + reg [15 : 0] clk_ctr_new; + reg clk_ctr_we; + + reg [5 : 0] bit_ctr_reg; + reg [5 : 0] bit_ctr_new; + reg bit_ctr_rst; + reg bit_ctr_inc; + reg bit_ctr_done; + reg bit_ctr_we; + + reg [2 : 0] length_reg; + reg length_we; + + reg [15 : 0] divisor_reg; + reg divisor_we; + + reg [1 : 0] spi_ctrl_reg; + reg [1 : 0] spi_ctrl_new; + reg spi_ctrl_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign spi_sclk = sclk_reg; + assign spi_cs_n = cs_n_reg; + assign spi_di = data_reg[55]; + assign rd_data = data_reg[31 : 0]; + assign ready = ready_reg; + + + //---------------------------------------------------------------- + // reg_update + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin + if (!reset_n) + begin + do_sample0_reg <= 1'h0; + do_sample1_reg <= 1'h0; + cs_n_reg <= 1'h1; + ready_reg <= 1'h0; + length_reg <= 3'h0; + divisor_reg <= 16'h0; + data_reg <= 56'h0; + sclk_reg <= 1'h0; + clk_ctr_reg <= 16'h0; + bit_ctr_reg <= 6'h0; + spi_ctrl_reg <= CTRL_IDLE; + end + else + begin + do_sample0_reg <= spi_do; + do_sample1_reg <= do_sample0_reg; + + if (cs_n_we) + cs_n_reg <= cs_n_new; + + if (ready_we) + ready_reg <= ready_new; + + if (data_we) + data_reg <= data_new; + + if (length_we) + length_reg <= length; + + if (divisor_we) + divisor_reg <= divisor; + + if (sclk_we) + sclk_reg <= sclk_new; + + if (clk_ctr_we) + clk_ctr_reg <= clk_ctr_new; + + if (bit_ctr_we) + bit_ctr_reg <= bit_ctr_new; + + if (spi_ctrl_we) + spi_ctrl_reg <= spi_ctrl_new; + + end + end // reg_update + + + //---------------------------------------------------------------- + // data_gen + // + // Generate the data bitstream to be written out to the external + // SPI connected memory. Basically a shift register. + // Note that we also shift in data received from the external + // memory. + //---------------------------------------------------------------- + always @* + begin : data_gen + data_new = 56'h0; + data_we = 0; + + if (data_set) + begin + data_new = wr_data; + data_we = 1; + end + + if (data_nxt) + begin + data_new = {data_reg[54 : 0], do_sample1_reg}; + data_we = 1; + end + end // data_gen + + + //---------------------------------------------------------------- + // sclk_gen + // + // Generator of the spi_sclk clock. + //---------------------------------------------------------------- + always @* + begin : sclk_gen + sclk_new = 0; + sclk_we = 0; + clk_ctr_new = 0; + clk_ctr_we = 0; + data_nxt = 0; + bit_ctr_rst = 0; + bit_ctr_inc = 0; + + if (sclk_rst) + begin + clk_ctr_new = 0; + clk_ctr_we = 1; + bit_ctr_rst = 1; + sclk_new = 0; + sclk_we = 1; + end + + if (sclk_en) + begin + if (clk_ctr_reg == divisor_reg) + begin + clk_ctr_new = 0; + clk_ctr_we = 1'b1; + sclk_new = ~sclk_reg; + sclk_we = 1; + + if (sclk_reg) + begin + bit_ctr_inc = 1; + data_nxt = 1; + end + end + else + begin + clk_ctr_new = clk_ctr_reg + 1'b1; + clk_ctr_we = 1'b1; + end + end + end // sclk_gen + + + //---------------------------------------------------------------- + // bit_ctr + // + // Bit counter used by the FSM to keep track of the number bits + // being read from or written to the memory. + //---------------------------------------------------------------- + always @* + begin : bit_ctr + bit_ctr_new = 6'h0; + bit_ctr_we = 1'b0; + bit_ctr_done = 1'b0; + + if (bit_ctr_reg == {length_reg, 3'h0}) + bit_ctr_done = 1'b1; + + if (bit_ctr_rst) + begin + bit_ctr_new = 6'h0; + bit_ctr_we = 1'b1; + end + + if (bit_ctr_inc) + begin + bit_ctr_new = bit_ctr_reg + 1'b1; + bit_ctr_we = 1'b1; + end + end // bit_ctr + + + //---------------------------------------------------------------- + // spi_ctrl + // + // Control FSM for the SPI interface. + //---------------------------------------------------------------- + always @* + begin : spi_ctrl + sclk_en = 0; + sclk_rst = 0; + cs_n_new = 1; + cs_n_we = 0; + data_set = 0; + length_we = 0; + divisor_we = 0; + ready_new = 0; + ready_we = 0; + spi_ctrl_new = CTRL_IDLE; + spi_ctrl_we = 0; + + case (spi_ctrl_reg) + CTRL_IDLE: + begin + ready_new = 1; + ready_we = 1; + + if (set) + begin + data_set = 1; + length_we = 1; + divisor_we = 1; + end + + if (start) + begin + ready_new = 0; + ready_we = 1; + sclk_rst = 1; + spi_ctrl_new = CTRL_START; + spi_ctrl_we = 1; + end + end + + CTRL_START: + begin + cs_n_new = 0; + cs_n_we = 1; + spi_ctrl_new = CTRL_WAIT; + spi_ctrl_we = 1; + end + + CTRL_WAIT: + begin + sclk_en = 1; + if (bit_ctr_done) + begin + spi_ctrl_new = CTRL_DONE; + spi_ctrl_we = 1; + end + end + + CTRL_DONE: + begin + ready_new = 1; + ready_we = 1; + cs_n_new = 1; + cs_n_we = 1; + spi_ctrl_new = CTRL_IDLE; + spi_ctrl_we = 1; + end + + default: + begin + end + endcase // case (spi_ctrl_reg) + end // spi_ctrl + +endmodule // mkmif_spi + +//====================================================================== +// EOF mkmif_spi.v +//====================================================================== -- cgit v1.2.3