aboutsummaryrefslogtreecommitdiff
path: root/rtl/src/verilog
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2015-02-10 12:03:47 -0500
committerPaul Selkirk <paul@psgd.org>2015-02-10 12:03:47 -0500
commit560ebacb0c576b92d7b64d728423683ad974885e (patch)
tree20e7922961a6d28d85ebdfe51dc76e391bc18e2c /rtl/src/verilog
parent13b8166c8989b5e83b0c998279c60c17bf46e890 (diff)
Updates from Pavel with new mux.
1. EIM arbiter was updated to take advantage of 3 additional address lines, that bunnie routed from the CPU to the FPGA. Now we have 19 address lines instead of 16, that means 19-2=17 effective bits when using 32-bit access. 2. In the doc directory there's a draft version of current EIM memory map. 3. I've figured out why you guys could not use read and write signals from the arbiter the way they were supposed to be used. I was wrong when I expected Joachim's cores to have registered outputs. They have a combinatorial output in fact. EIM arbiter's minimum latency is 1 cycle, so we have to register data coming out of cores. I've added these three lines to every core wrapper (sha1.v, sha256.v and sha512.v): reg [31 : 0] tmp_read_data_reg; always @(posedge clk) tmp_read_data_reg <= tmp_read_data; assign read_data = tmp_read_data_reg; 4. Joachim told me, that we are going to have different types of cores (HASH, RNG, CIPHER and so on), so I redesigned EIM multiplexor to have separate modules for every core type. RNG and CIPHER selectors right now are just templates with some dummy registers. Here is what was modified in the HASH multiplexor: 4a. Core number 0 was added. It is not an actual HASH core, but a set of global (board-level) registers. I've added three registers so far: board type, bitstream version and one writeable dummy general-purpose register. 4b. Core instantiation was made conditional to allow selecting of what cores to actually implement. We can have a project that offers a large number of cores, so people can disable unnecessary cores to speed up compile time and to save some slices for something else. 4c. I have disconnected .error() output from cores. As far as I understand it gets asserted when some non-existent register is being addressed. In most projects that I've seen writes to empty regions of memory are discarded and reads return zeroes. If you really need this kind of error checking, please re-connect this output as needed. 4d. core_selector.v has an instruction on how to add new HASH cores to our design. 5. TC11() was added to hash_tester.c to check that we can read global board-level registers and that we have access to segments other than HASH. The last check reads dummy registers from RNG and CIPHER segments (which are just templates now), this effectively tests the 3 new added address bits.
Diffstat (limited to 'rtl/src/verilog')
-rw-r--r--rtl/src/verilog/cipher_selector.v115
-rw-r--r--rtl/src/verilog/core_selector.v365
-rw-r--r--rtl/src/verilog/eim_arbiter.v20
-rw-r--r--rtl/src/verilog/eim_arbiter_cdc.v28
-rw-r--r--rtl/src/verilog/eim_memory.v182
-rw-r--r--rtl/src/verilog/novena_baseline_top.v40
-rw-r--r--rtl/src/verilog/novena_regs.v80
-rw-r--r--rtl/src/verilog/rng_selector.v114
8 files changed, 730 insertions, 214 deletions
diff --git a/rtl/src/verilog/cipher_selector.v b/rtl/src/verilog/cipher_selector.v
new file mode 100644
index 0000000..31dfe4b
--- /dev/null
+++ b/rtl/src/verilog/cipher_selector.v
@@ -0,0 +1,115 @@
+//======================================================================
+//
+// cipher_selector.v
+// -----------------
+// Top level wrapper that creates the Cryptech coretest system.
+// The wrapper contains instances of external interface, coretest
+// and the core to be tested. And if more than one core is
+// present the wrapper also includes address and data muxes.
+//
+//
+// Authors: Joachim Strombergson, Paul Selkirk, Pavel Shatov
+// Copyright (c) 2014-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 cipher_selector
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+ input wire sys_ena,
+
+ input wire [13: 0] sys_eim_addr,
+ input wire sys_eim_wr,
+ input wire sys_eim_rd,
+ output wire [31 : 0] sys_read_data,
+ input wire [31 : 0] sys_write_data
+ );
+
+
+ //
+ // Output Register
+ //
+ reg [31: 0] tmp_read_data;
+ assign sys_read_data = tmp_read_data;
+
+
+ /* So far we have no CIPHER cores, let's make some dummy 32-bit registers here
+ * to prevent ISE from complaining that we don't use input ports.
+ */
+
+ reg [31: 0] reg_dummy_first;
+ reg [31: 0] reg_dummy_second;
+ reg [31: 0] reg_dummy_third;
+
+ always @(posedge sys_clk)
+ //
+ if (sys_rst) begin
+ reg_dummy_first <= {8{4'hD}};
+ reg_dummy_second <= {8{4'hE}};
+ reg_dummy_third <= {8{4'hF}};
+ end else if (sys_ena) begin
+ //
+ if (sys_eim_wr) begin
+ //
+ // WRITE handler
+ //
+ case (sys_eim_addr)
+ 14'd0: reg_dummy_first <= sys_write_data;
+ 14'd1: reg_dummy_second <= sys_write_data;
+ 14'd2: reg_dummy_third <= sys_write_data;
+ endcase
+ //
+ end
+ //
+ if (sys_eim_rd) begin
+ //
+ // READ handler
+ //
+ case (sys_eim_addr)
+ 14'd0: tmp_read_data <= reg_dummy_first;
+ 14'd1: tmp_read_data <= reg_dummy_second;
+ 14'd2: tmp_read_data <= reg_dummy_third;
+ //
+ default: tmp_read_data <= {32{1'b0}}; // read non-existent locations as zeroes
+ /*
+ default: tmp_read_data <= {32{1'bX}}; // don't care what to read from non-existent locations
+ */
+ endcase
+ //
+ end
+ //
+ end
+
+
+endmodule
+
+//======================================================================
+// EOF core_selector.v
+//======================================================================
diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v
index 7479848..e39a8b1 100644
--- a/rtl/src/verilog/core_selector.v
+++ b/rtl/src/verilog/core_selector.v
@@ -1,6 +1,6 @@
//======================================================================
//
-// coretest_hashes.v
+// core_selector.v
// -----------------
// Top level wrapper that creates the Cryptech coretest system.
// The wrapper contains instances of external interface, coretest
@@ -42,182 +42,203 @@
module core_selector
(
input wire sys_clk,
- input wire sys_rst,
+ input wire sys_rst,
+ input wire sys_ena,
input wire [13: 0] sys_eim_addr,
input wire sys_eim_wr,
input wire sys_eim_rd,
- output wire [31 : 0] read_data,
- input wire [31 : 0] write_data
+ output wire [31 : 0] sys_read_data,
+ input wire [31 : 0] sys_write_data
);
-
-
- //----------------------------------------------------------------
- // Internal constant and parameter definitions.
- //----------------------------------------------------------------
- parameter SHA1_ADDR_PREFIX = 6'b000100; // 0x1000 - 0x13ff
- parameter SHA256_ADDR_PREFIX = 6'b001000; // 0x2000 - 0x23ff
- parameter SHA512_ADDR_PREFIX = 6'b001100; // 0x3000 - 0x33ff
-
-
- //----------------------------------------------------------------
- // Wires and registers
- //----------------------------------------------------------------
- wire clk = sys_clk;
- wire reset_n = !sys_rst;
- wire [13:0] address = sys_eim_addr;
- wire cs = sys_eim_wr | sys_eim_rd;
- wire we = sys_eim_wr;
-
- reg [31:0] read_reg;
- reg error_reg;
-
- // sha1 connections.
- reg sha1_cs;
- reg sha1_we;
- reg [7:0] sha1_address;
- reg [31:0] sha1_write_data;
- wire [31:0] sha1_read_data;
- wire sha1_error;
-
- // sha256 connections.
- reg sha256_cs;
- reg sha256_we;
- reg [7:0] sha256_address;
- reg [31:0] sha256_write_data;
- wire [31:0] sha256_read_data;
- wire sha256_error;
-
- // sha512 connections.
- reg sha512_cs;
- reg sha512_we;
- reg [7:0] sha512_address;
- reg [31:0] sha512_write_data;
- wire [31:0] sha512_read_data;
- wire sha512_error;
-
-
- //----------------------------------------------------------------
- // Concurrent assignment.
- //----------------------------------------------------------------
- assign read_data = read_reg;
-
- //----------------------------------------------------------------
- // Core instantiations.
- //----------------------------------------------------------------
- sha1 sha1(
- // Clock and reset.
- .clk(clk),
- .reset_n(reset_n),
-
- // Control.
- .cs(sha1_cs),
- .we(sha1_we),
-
- // Data ports.
- .address(sha1_address),
- .write_data(sha1_write_data),
- .read_data(sha1_read_data),
- .error(sha1_error)
- );
-
-
- sha256 sha256(
- // Clock and reset.
- .clk(clk),
- .reset_n(reset_n),
-
- // Control.
- .cs(sha256_cs),
- .we(sha256_we),
-
- // Data ports.
- .address(sha256_address),
- .write_data(sha256_write_data),
- .read_data(sha256_read_data),
- .error(sha256_error)
- );
-
-
- sha512 sha512(
- // Clock and reset.
- .clk(clk),
- .reset_n(reset_n),
-
- // Control.
- .cs(sha512_cs),
- .we(sha512_we),
-
- // Data ports.
- .address(sha512_address),
- .write_data(sha512_write_data),
- .read_data(sha512_read_data),
- .error(sha512_error)
- );
-
- //----------------------------------------------------------------
- // address_mux
- //
- // Combinational data mux that handles addressing between
- // cores using the 32-bit memory like interface.
- //----------------------------------------------------------------
- always @*
- begin : address_mux
- // Default assignments.
- sha1_cs = 0;
- sha1_we = 0;
- sha1_address = 8'h00;
- sha1_write_data = 32'h00000000;
-
- sha256_cs = 0;
- sha256_we = 0;
- sha256_address = 8'h00;
- sha256_write_data = 32'h00000000;
-
- sha512_cs = 0;
- sha512_we = 0;
- sha512_address = 8'h00;
- sha512_write_data = 32'h00000000;
-
- // address mux
- case (address[13:8])
- SHA1_ADDR_PREFIX:
- begin
- sha1_cs = 1;
- sha1_we = we;
- sha1_address = address[7:0];
- sha1_write_data = write_data;
- read_reg = sha1_read_data;
- error_reg = sha1_error;
- end
-
- SHA256_ADDR_PREFIX:
- begin
- sha256_cs = 1;
- sha256_we = we;
- sha256_address = address[7:0];
- sha256_write_data = write_data;
- read_reg = sha256_read_data;
- error_reg = sha256_error;
- end
-
- SHA512_ADDR_PREFIX:
- begin
- sha512_cs = 1;
- sha512_we = we;
- sha512_address = address[7:0];
- sha512_write_data = write_data;
- read_reg = sha512_read_data;
- error_reg = sha512_error;
- end
-
- default:
- begin
- read_reg = 32'hZZZZ;
- end
- endcase
-
- end // address_mux
+
+
+ /* In this memory segment (HASHES) we have 14 address bits. Every core has 8-bit internal address space,
+ * so we can have up to 2^(14-8) = 64 cores here.
+ *
+ * Core #0 is not an actual HASH core, but a set of board-level (global) registers, that can be used to
+ * get information about hardware (board type, bitstream version and so on).
+ *
+ * So far we have three cores: SHA-1, SHA-256 and SHA-512.
+ */
+
+ /*********************************************************
+ * To add new HASH core named XXX follow the steps below *
+ *********************************************************
+ *
+ * 1. Add corresponding `define under "List of Available Cores", this will allow users to exclude your
+ * core from implementation to save some slices in case they don't need it.
+ *
+ * `define USE_CORE_XXX
+ *
+ *
+ * 2. Choose address of your new core and add corresponding line under "Core Address Table". Core addresses
+ * can be in the range from 1 to 63 inclusively. Core address 0 is reserved for a page of global registers
+ * and must not be used.
+ *
+ * localparam CORE_ADDR_XXX = 6'dN;
+ *
+ *
+ * 3. Add instantiation of your new core after all existing cores surrounded by conditional synthesis directives.
+ * You also need a 32-bit output (read data) bus for your core and an enable flag. Note that sys_rst in
+ * an active-high sync reset signal.
+ *
+ * `ifdef USE_CORE_XXX
+ * wire [31: 0] read_data_xxx;
+ * wire enable_xxx = sys_ena && (addr_core_num == CORE_ADDR_XXX);
+ * xxx xxx_inst
+ * (
+ * .clk(sys_clk),
+ * .reset_n(~sys_rst),
+ * .cs(enable_xxx & (sys_eim_rd | sys_eim_wr)),
+ * .we(sys_eim_wr),
+ * .address(addr_core_reg),
+ * .write_data(sys_write_data),
+ * .read_data(read_data_xxx),
+ * .error()
+ * );
+ * `endif
+ *
+ *
+ * 4. Add previously created data bus to "Output (Read Data) Multiplexor" in the end of this file.
+ *
+ * `ifdef USE_CORE_XXX CORE_ADDR_XXX: sys_read_data_mux = read_data_xxx; `endif
+ *
+ */
+
+
+ //----------------------------------------------------------------
+ // Address Decoder
+ //----------------------------------------------------------------
+ wire [ 5: 0] addr_core_num = sys_eim_addr[13: 8]; // upper 6 bits specify core being addressed
+ wire [ 7: 0] addr_core_reg = sys_eim_addr[ 7: 0]; // lower 8 bits specify register offset in core
+
+
+ /* We can comment following lines to exclude cores from implementation
+ * in case we run out of slices.
+ */
+
+ //----------------------------------------------------------------
+ // List of Available Cores
+ //----------------------------------------------------------------
+ `define USE_CORE_SHA1
+ `define USE_CORE_SHA256
+ `define USE_CORE_SHA512
+
+
+ //----------------------------------------------------------------
+ // Core Address Table
+ //----------------------------------------------------------------
+ localparam CORE_ADDR_GLOBAL_REGS = 6'd0;
+ localparam CORE_ADDR_SHA1 = 6'd1;
+ localparam CORE_ADDR_SHA256 = 6'd2;
+ localparam CORE_ADDR_SHA512 = 6'd3;
+
+
+ //----------------------------------------------------------------
+ // Global Registers
+ //----------------------------------------------------------------
+ wire [31: 0] read_data_global;
+ wire enable_global = sys_ena && (addr_core_num == CORE_ADDR_GLOBAL_REGS);
+ novena_regs novena_regs_inst
+ (
+ .clk(sys_clk),
+ .rst(sys_rst),
+
+ .cs(enable_global & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_global)
+ );
+
+
+ //----------------------------------------------------------------
+ // SHA-1
+ //----------------------------------------------------------------
+ `ifdef USE_CORE_SHA1
+ wire [31: 0] read_data_sha1;
+ wire enable_sha1 = sys_ena && (addr_core_num == CORE_ADDR_SHA1);
+ sha1 sha1_inst
+ (
+ .clk(sys_clk),
+ .reset_n(~sys_rst),
+
+ .cs(enable_sha1 & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_sha1),
+ .error()
+ );
+ `endif
+
+
+ //----------------------------------------------------------------
+ // SHA-256
+ //----------------------------------------------------------------
+ `ifdef USE_CORE_SHA256
+ wire [31: 0] read_data_sha256;
+ wire enable_sha256 = sys_ena && (addr_core_num == CORE_ADDR_SHA256);
+ sha256 sha256_inst
+ (
+ .clk(sys_clk),
+ .reset_n(~sys_rst),
+
+ .cs(enable_sha256 & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_sha256),
+ .error()
+ );
+ `endif
+
+
+ //----------------------------------------------------------------
+ // SHA-512
+ //----------------------------------------------------------------
+ `ifdef USE_CORE_SHA512
+ wire [31: 0] read_data_sha512;
+ wire enable_sha512 = sys_ena && (addr_core_num == CORE_ADDR_SHA512);
+ sha512 sha512_inst
+ (
+ .clk(sys_clk),
+ .reset_n(~sys_rst),
+
+ .cs(enable_sha512 & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_sha512),
+ .error()
+ );
+ `endif
+
+
+ //----------------------------------------------------------------
+ // Output (Read Data) Multiplexor
+ //----------------------------------------------------------------
+ reg [31: 0] sys_read_data_mux;
+ assign sys_read_data = sys_read_data_mux;
+
+ always @*
+ //
+ case (addr_core_num)
+ //
+ CORE_ADDR_GLOBAL_REGS: sys_read_data_mux = read_data_global;
+ `ifdef USE_CORE_SHA1 CORE_ADDR_SHA1: sys_read_data_mux = read_data_sha1; `endif
+ `ifdef USE_CORE_SHA256 CORE_ADDR_SHA256: sys_read_data_mux = read_data_sha256; `endif
+ `ifdef USE_CORE_SHA512 CORE_ADDR_SHA512: sys_read_data_mux = read_data_sha512; `endif
+ //
+ default: sys_read_data_mux = {32{1'b0}};
+ //
+ endcase
+
endmodule
diff --git a/rtl/src/verilog/eim_arbiter.v b/rtl/src/verilog/eim_arbiter.v
index 3dc6260..d21799f 100644
--- a/rtl/src/verilog/eim_arbiter.v
+++ b/rtl/src/verilog/eim_arbiter.v
@@ -39,7 +39,7 @@
module eim_arbiter
(
- eim_bclk, eim_cs0_n, eim_da,
+ eim_bclk, eim_cs0_n, eim_da, eim_a,
eim_lba_n, eim_wr_n,
eim_oe_n, eim_wait_n,
@@ -55,7 +55,8 @@ module eim_arbiter
//
input wire eim_bclk; // | eim bus
input wire eim_cs0_n; // |
- inout wire [15: 0] eim_da; // |
+ inout wire [15: 0] eim_da; // |
+ input wire [18:16] eim_a; // |
input wire eim_lba_n; // |
input wire eim_wr_n; // |
input wire eim_oe_n; // |
@@ -63,7 +64,7 @@ module eim_arbiter
input wire sys_clk; // system clock
- output wire [13: 0] sys_addr; // | user bus
+ output wire [16: 0] sys_addr; // | user bus
output wire sys_wren; // |
output wire [31: 0] sys_data_out; // |
output wire sys_rden; // |
@@ -107,7 +108,7 @@ module eim_arbiter
localparam EIM_FSM_STATE_READ_DONE = 5'b1_0_111; // transaction complete
reg [ 4: 0] eim_fsm_state = EIM_FSM_STATE_INIT; // fsm state
- reg [13: 0] eim_addr_latch = {14{1'bX}}; // transaction address
+ reg [16: 0] eim_addr_latch = {17{1'bX}}; // transaction address
reg [15: 0] eim_write_lsb_latch = {16{1'bX}}; // lower 16 bits of data to write
/* These flags are used to wake up from INIT state. */
@@ -183,7 +184,7 @@ module eim_arbiter
always @(posedge eim_bclk)
//
if ((eim_fsm_state == EIM_FSM_STATE_INIT) && (eim_write_start_flag || eim_read_start_flag))
- eim_addr_latch <= da_ro[15:2];
+ eim_addr_latch <= {eim_a[18:16], da_ro[15:2]};
//
@@ -256,10 +257,11 @@ module eim_arbiter
//
/* This block is used to transfer request data from BCLK clock domain to SYS_CLK clock domain and
- * then transfer acknowledge from SYS_CLK to BCLK clock domain in return. Af first 1+1+14+32 = 48 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.
+ * then transfer acknowledge from SYS_CLK to BCLK clock domain in return. Af first 1+1+3+14+32 = 51 bits
+ * are transfered, these are: write flag, read flag, msb part of address, lsb part of 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.
*/
eim_arbiter_cdc eim_cdc
diff --git a/rtl/src/verilog/eim_arbiter_cdc.v b/rtl/src/verilog/eim_arbiter_cdc.v
index c9df62e..a0412fe 100644
--- a/rtl/src/verilog/eim_arbiter_cdc.v
+++ b/rtl/src/verilog/eim_arbiter_cdc.v
@@ -49,11 +49,11 @@ module eim_arbiter_cdc
input wire eim_clk; // eim clock
input wire eim_req; // eim transaction request
output wire eim_ack; // eim transaction acknowledge
- input wire [47: 0] eim_din; // data from cpu to fpga (write access)
+ input wire [50: 0] eim_din; // data from cpu to fpga (write access)
output wire [31: 0] eim_dout; // data from fpga to cpu (read access)
input wire sys_clk; // user internal clock
- output wire [13: 0] sys_addr; // user access address
+ output wire [16: 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
@@ -64,11 +64,11 @@ module eim_arbiter_cdc
// EIM_CLK -> SYS_CLK Request
//
wire sys_req; // request pulse in sys_clk clock domain
- wire [47: 0] sys_dout; // transaction data in sys_clk clock domain
+ wire [50: 0] sys_dout; // transaction data in sys_clk clock domain
cdc_bus_pulse #
(
- .DATA_WIDTH (48) // {write, read, addr, data}
+ .DATA_WIDTH (51) // {write, read, msb addr, lsb addr, data}
)
cdc_eim_sys
(
@@ -85,16 +85,16 @@ module eim_arbiter_cdc
//
// Output Registers
//
- reg [13: 0] sys_addr_reg = {14{1'bX}}; //
- reg sys_wren_reg = 1'b0; //
+ reg sys_wren_reg = 1'b0; //
+ reg sys_rden_reg = 1'b0; //
+ reg [16: 0] sys_addr_reg = {17{1'bX}}; //
reg [31: 0] sys_data_out_reg = {32{1'bX}}; //
- reg sys_rden_reg = 1'b0; //
-
+
+ assign sys_wren = sys_wren_reg;
+ assign sys_rden = sys_rden_reg;
assign sys_addr = sys_addr_reg;
- assign sys_wren = sys_wren_reg;
assign sys_data_out = sys_data_out_reg;
- assign sys_rden = sys_rden_reg;
-
+
//
// System (User) Clock Access Handler
@@ -102,10 +102,10 @@ module eim_arbiter_cdc
always @(posedge sys_clk)
//
if (sys_req) begin // request detected?
- sys_wren_reg <= sys_dout[47]; // set write flag if needed
- sys_addr_reg <= sys_dout[45:32]; // set operation address
+ sys_wren_reg <= sys_dout[50]; // set write flag if needed
+ sys_rden_reg <= sys_dout[49]; // set read flag if needed
+ sys_addr_reg <= sys_dout[48:32]; // set operation address
sys_data_out_reg <= sys_dout[31: 0]; // set data to write
- sys_rden_reg <= sys_dout[46]; // set read flag if needed
end else begin // no request active
sys_wren_reg <= 1'b0; // clear write flag
sys_rden_reg <= 1'b0; // clear read flag
diff --git a/rtl/src/verilog/eim_memory.v b/rtl/src/verilog/eim_memory.v
new file mode 100644
index 0000000..5258376
--- /dev/null
+++ b/rtl/src/verilog/eim_memory.v
@@ -0,0 +1,182 @@
+//======================================================================
+//
+// coretest_hashes.v
+// -----------------
+// Top level wrapper that creates the Cryptech coretest system.
+// The wrapper contains instances of external interface, coretest
+// and the core to be tested. And if more than one core is
+// present the wrapper also includes address and data muxes.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2014-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 eim_memory
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+
+ input wire [16: 0] sys_eim_addr,
+ input wire sys_eim_wr,
+ input wire sys_eim_rd,
+ output wire [31: 0] sys_read_data,
+ input wire [31: 0] sys_write_data
+ );
+
+
+ /* Three upper bits of address [16:14] are used to select memory segment.
+ * There can be eight segments. So far segment 0 is used for hashes,
+ * segment 1 is reserved for random number generators, segment 2 is reserved
+ * for chiphers. Other segments are not used so far.
+ */
+
+ /* Every segment has its own memory map, take at look at corresponding selectors
+ * for more information.
+ */
+
+ //----------------------------------------------------------------
+ // Segment Decoder
+ //----------------------------------------------------------------
+ localparam SEGMENT_ADDR_HASHES = 3'd0;
+ localparam SEGMENT_ADDR_RNGS = 3'd1;
+ localparam SEGMENT_ADDR_CIPHERS = 3'd2;
+
+ wire [ 2: 0] addr_segment = sys_eim_addr[16:14]; // 3 upper bits are decoded here
+ wire [13: 0] addr_segment_int = sys_eim_addr[13: 0]; // 14 lower bits are decoded individually
+ // in corresponding segment selectors
+
+ wire [31: 0] segment_hashes_read_data; // data read from HASHES segment
+ wire [31: 0] segment_rngs_read_data; // data read from RNGS segment
+ wire [31: 0] segment_ciphers_read_data; // data read from CIPHERS segment
+
+ wire segment_enable_hashes = (addr_segment == SEGMENT_ADDR_HASHES) ? 1'b1 : 1'b0; // HASHES segment is being addressed
+ wire segment_enable_rngs = (addr_segment == SEGMENT_ADDR_RNGS) ? 1'b1 : 1'b0; // RNGS segment is being addressed
+ wire segment_enable_ciphers = (addr_segment == SEGMENT_ADDR_CIPHERS) ? 1'b1 : 1'b0; // CIPHERS segment is being addressed
+
+
+ //----------------------------------------------------------------
+ // Output (Read Data) Bus
+ //----------------------------------------------------------------
+ reg [31: 0] sys_read_data_reg;
+ assign sys_read_data = sys_read_data_reg;
+
+ always @*
+ //
+ case (addr_segment)
+ SEGMENT_ADDR_HASHES: sys_read_data_reg = segment_hashes_read_data;
+ SEGMENT_ADDR_RNGS: sys_read_data_reg = segment_rngs_read_data;
+ SEGMENT_ADDR_CIPHERS: sys_read_data_reg = segment_ciphers_read_data;
+ default: sys_read_data_reg = {32{1'b0}};
+ endcase
+
+
+
+ //----------------------------------------------------------------
+ // HASH Core Selector
+ //
+ // This selector is used to map core registers into
+ // EIM address space and select which core to send EIM read and
+ // write operations to.
+ //----------------------------------------------------------------
+ core_selector segment_cores
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_ena(segment_enable_hashes), // only enable active selector
+
+ .sys_eim_addr(addr_segment_int), // we only connect 14 lower bits of address here,
+ // because we have already decoded 3 upper bits earlier,
+ // every segment can have its own address decoder.
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(sys_write_data),
+ .sys_read_data(segment_hashes_read_data) // output from HASHES segment
+ );
+
+
+ //----------------------------------------------------------------
+ // RNG Selector
+ //
+ // This selector is used to map random number generator registers into
+ // EIM address space and select which RNG to send EIM read and
+ // write operations to. So far there are no RNG cores.
+ //----------------------------------------------------------------
+ rng_selector segment_rngs
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_ena(segment_enable_rngs), // only enable active selector
+
+ .sys_eim_addr(addr_segment_int), // we only connect 14 lower bits of address here,
+ // because we have already decoded 3 upper bits earlier,
+ // every segment can have its own address decoder.
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(sys_write_data),
+ .sys_read_data(segment_rngs_read_data) // output from RNGS segment
+ );
+
+
+ //----------------------------------------------------------------
+ // CIPHER Selector
+ //
+ // This selector is used to map cipher registers into
+ // EIM address space and select which CIPHER to send EIM read and
+ // write operations to. So far there are no CIPHER cores.
+ //----------------------------------------------------------------
+ cipher_selector segment_ciphers
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_ena(segment_enable_ciphers), // only enable active selector
+
+ .sys_eim_addr(addr_segment_int), // we only connect 14 lower bits of address here,
+ // because we have already decoded 3 upper bits earlier,
+ // every segment can have its own address decoder.
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(sys_write_data),
+ .sys_read_data(segment_ciphers_read_data) // output from CIPHERS segment
+ );
+
+
+endmodule
+
+
+//======================================================================
+// EOF eim_memory.v
+//======================================================================
diff --git a/rtl/src/verilog/novena_baseline_top.v b/rtl/src/verilog/novena_baseline_top.v
index 20bf28d..cc9e5e7 100644
--- a/rtl/src/verilog/novena_baseline_top.v
+++ b/rtl/src/verilog/novena_baseline_top.v
@@ -49,13 +49,14 @@ module novena_baseline_top
input wire reset_mcu_b_pin,
// Cryptech avalanche noise board input and LED outputs
- input wire ct_avalanche_noise,
- output wire [07 : 0] ct_avalanche_led,
+ input wire ct_noise,
+ output wire [07 : 0] ct_led,
// EIM interface
input wire eim_bclk, // EIM burst clock. Started by the CPU.
input wire eim_cs0_n, // Chip select (active low).
- inout wire [15 : 0] eim_da, // Bidirectional address and data port.
+ inout wire [15 : 0] eim_da, // Bidirectional address and data port.
+ input wire [18: 16] eim_a, // MSB part of address port.
input wire eim_lba_n, // Latch address signal (active low).
input wire eim_wr_n, // write enable signal (active low).
input wire eim_oe_n, // output enable signal (active low).
@@ -98,7 +99,7 @@ module novena_baseline_top
// EIM arbiter handles EIM access and transfers it into
// `sys_clk' clock domain.
//----------------------------------------------------------------
- wire [13: 0] sys_eim_addr;
+ wire [16: 0] sys_eim_addr;
wire sys_eim_wr;
wire sys_eim_rd;
wire [31: 0] sys_eim_dout;
@@ -107,9 +108,10 @@ module novena_baseline_top
eim_arbiter eim
(
.eim_bclk(eim_bclk_buf),
- .eim_cs0_n (eim_cs0_n),
- .eim_da(eim_da),
- .eim_lba_n (eim_lba_n),
+ .eim_cs0_n(eim_cs0_n),
+ .eim_da(eim_da),
+ .eim_a(eim_a),
+ .eim_lba_n(eim_lba_n),
.eim_wr_n(eim_wr_n),
.eim_oe_n(eim_oe_n),
.eim_wait_n(eim_wait_n),
@@ -125,24 +127,23 @@ module novena_baseline_top
//----------------------------------------------------------------
- // Core Selector (MUX)
+ // Memory Mapper
//
- // This multiplexer is used to map ore registers into
- // EIM address space and select which core to send EIM read and
- // write operations to.
- //----------------------------------------------------------------
- core_selector mux
- (
- .sys_clk(sys_clk),
+ // This multiplexer is used to map different types of cores, such as
+ // hashes, RNGs and ciphers to different regions (segments) of memory.
+ //----------------------------------------------------------------
+ eim_memory mem
+ (
+ .sys_clk(sys_clk),
.sys_rst(sys_rst),
.sys_eim_addr(sys_eim_addr),
.sys_eim_wr(sys_eim_wr),
.sys_eim_rd(sys_eim_rd),
- .write_data(sys_eim_dout),
- .read_data(sys_eim_din)
- );
+ .sys_write_data(sys_eim_dout),
+ .sys_read_data(sys_eim_din)
+ );
//----------------------------------------------------------------
@@ -166,7 +167,7 @@ module novena_baseline_top
// Logic specific to the Cryptech use of the Novena.
// Currently we just hard wire the LED outputs.
//----------------------------------------------------------------
- assign ct_avalanche_led = 8'h55;
+ assign ct_led = {8{ct_noise}};
//----------------------------------------------------------------
@@ -178,6 +179,7 @@ module novena_baseline_top
// been configured.
//----------------------------------------------------------------
assign apoptosis_pin = 1'b0;
+
endmodule
diff --git a/rtl/src/verilog/novena_regs.v b/rtl/src/verilog/novena_regs.v
new file mode 100644
index 0000000..88b35ab
--- /dev/null
+++ b/rtl/src/verilog/novena_regs.v
@@ -0,0 +1,80 @@
+`timescale 1ns / 1ps
+
+module novena_regs
+ (
+ input wire clk,
+ input wire rst,
+
+ input wire cs,
+ input wire we,
+
+ input wire [ 7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data
+ );
+
+
+ //----------------------------------------------------------------
+ // Board-Level Registers
+ //----------------------------------------------------------------
+ localparam ADDR_BOARD_TYPE = 8'h00; // board id
+ localparam ADDR_FIRMWARE_VER = 8'h01; // bitstream version
+ localparam ADDR_DUMMY_REG = 8'hFF; // general-purpose register
+
+
+ //----------------------------------------------------------------
+ // Constants
+ //----------------------------------------------------------------
+ localparam NOVENA_BOARD_TYPE = 32'h50565431; // PVT1
+ localparam NOVENA_DESIGN_VER = 32'h00_01_00_0b; // v0.1.0b
+
+
+ //
+ // Output Register
+ //
+ reg [31: 0] tmp_read_data;
+ assign read_data = tmp_read_data;
+
+
+ /* This dummy register can be used by users to check that they can actually write something.
+ */
+
+ reg [31: 0] reg_dummy;
+
+
+ //
+ // Access Handler
+ //
+ always @(posedge clk)
+ //
+ if (rst) reg_dummy <= {32{1'b0}};
+ else if (cs) begin
+ //
+ if (we) begin
+ //
+ // WRITE handler
+ //
+ case (address)
+ ADDR_DUMMY_REG: reg_dummy <= write_data;
+ endcase
+ //
+ end else begin
+ //
+ // READ handler
+ //
+ case (address)
+ ADDR_BOARD_TYPE: tmp_read_data <= NOVENA_BOARD_TYPE;
+ ADDR_FIRMWARE_VER: tmp_read_data <= NOVENA_DESIGN_VER;
+ ADDR_DUMMY_REG: tmp_read_data <= reg_dummy;
+ //
+ default: tmp_read_data <= {32{1'b0}}; // read non-existent locations as zeroes
+ /*
+ default: tmp_read_data <= {32{1'bX}}; // don't care what to read from non-existent locations
+ */
+ endcase
+ //
+ end
+ //
+ end
+
+endmodule
diff --git a/rtl/src/verilog/rng_selector.v b/rtl/src/verilog/rng_selector.v
new file mode 100644
index 0000000..7a1fe7c
--- /dev/null
+++ b/rtl/src/verilog/rng_selector.v
@@ -0,0 +1,114 @@
+//======================================================================
+//
+// rng_selector.v
+// -----------------
+// Top level wrapper that creates the Cryptech coretest system.
+// The wrapper contains instances of external interface, coretest
+// and the core to be tested. And if more than one core is
+// present the wrapper also includes address and data muxes.
+//
+//
+// Authors: Joachim Strombergson, Paul Selkirk, Pavel Shatov
+// Copyright (c) 2014-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 rng_selector
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+ input wire sys_ena,
+
+ input wire [13: 0] sys_eim_addr,
+ input wire sys_eim_wr,
+ input wire sys_eim_rd,
+ output wire [31 : 0] sys_read_data,
+ input wire [31 : 0] sys_write_data
+ );
+
+
+ //
+ // Output Register
+ //
+ reg [31: 0] tmp_read_data;
+ assign sys_read_data = tmp_read_data;
+
+
+ /* So far we have no RNG cores, let's make some dummy 32-bit registers here
+ * to prevent ISE from complaining that we don't use input ports.
+ */
+
+ reg [31: 0] reg_dummy_first;
+ reg [31: 0] reg_dummy_second;
+ reg [31: 0] reg_dummy_third;
+
+ always @(posedge sys_clk)
+ //
+ if (sys_rst) begin
+ reg_dummy_first <= {8{4'hA}};
+ reg_dummy_second <= {8{4'hB}};
+ reg_dummy_third <= {8{4'hC}};
+ end else if (sys_ena) begin
+ //
+ if (sys_eim_wr) begin
+ //
+ // WRITE handler
+ //
+ case (sys_eim_addr)
+ 14'd0: reg_dummy_first <= sys_write_data;
+ 14'd1: reg_dummy_second <= sys_write_data;
+ 14'd2: reg_dummy_third <= sys_write_data;
+ endcase
+ //
+ end
+ //
+ if (sys_eim_rd) begin
+ //
+ // READ handler
+ //
+ case (sys_eim_addr)
+ 14'd0: tmp_read_data <= reg_dummy_first;
+ 14'd1: tmp_read_data <= reg_dummy_second;
+ 14'd2: tmp_read_data <= reg_dummy_third;
+ //
+ default: tmp_read_data <= {32{1'b0}}; // read non-existent locations as zeroes
+ /*
+ default: tmp_read_data <= {32{1'bX}}; // don't care what to read from non-existent locations
+ */
+ endcase
+ //
+ end
+ //
+ end
+
+endmodule
+
+//======================================================================
+// EOF core_selector.v
+//======================================================================