From 86311d72381423582f2de5f91fa9fbb447098934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Mon, 2 Feb 2015 16:45:38 +0100 Subject: Changed core_selector to instead use the cryptech sha256 core. --- rtl/src/verilog/core_selector.v | 95 +++++------------------------------------ 1 file changed, 10 insertions(+), 85 deletions(-) (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index 8ce2003..7f92e43 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -48,94 +48,19 @@ module core_selector input wire [31 : 0] write_data ); - // - // Internal Registers - // - reg [31: 0] reg_x = {32{1'b0}}; - reg [31: 0] reg_y = {32{1'b0}}; - reg [15: 0] reg_ctl = {16{1'b0}}; - reg [31: 0] read_data_reg = {32{1'b0}}; + sha256 sha256_inst( + .clk(sys_clk), + .reset_n(~sys_rst), - // - // Parameters - // - localparam ADDER_BASE_ADDR = 12'h321; // upper 12 bits of address - localparam ADDER_OFFSET_REG_X = 2'd0; // X - localparam ADDER_OFFSET_REG_Y = 2'd1; // Y - localparam ADDER_OFFSET_REG_Z = 2'd2; // Z - localparam ADDER_OFFSET_REG_SC = 2'd3; // {STATUS, CONTROL} - - - /* This flag detects whether adder core is being addressed. */ - wire eim_access_adder = (sys_eim_addr[13:2] == ADDER_BASE_ADDR) ? 1'b1 : 1'b0; - - /* These flags detect whether write or read access is requested. */ - wire eim_access_write = sys_eim_wr & eim_access_adder; - wire eim_access_read = sys_eim_rd & eim_access_adder; - - - // - // Write Request Handler - // - always @(posedge sys_clk) - // - if (sys_rst) begin - reg_x <= {32{1'b0}}; - reg_y <= {32{1'b0}}; - reg_ctl <= {16{1'b0}}; - end else if (eim_access_write) begin - // - case (sys_eim_addr[1:0]) - ADDER_OFFSET_REG_X: reg_x <= write_data; - ADDER_OFFSET_REG_Y: reg_y <= write_data; - ADDER_OFFSET_REG_SC: reg_ctl <= write_data[15 : 0]; - endcase - // - end - - - // - // Read Request Handler - // - wire [31: 0] reg_z; - wire [15: 0] reg_sts; - - always @(posedge sys_clk) - // - if (sys_rst) read_data_reg <= {32{1'b0}}; - // - else if (eim_access_read) begin - // - case (sys_eim_addr[1:0]) - ADDER_OFFSET_REG_X: read_data_reg <= reg_x; - ADDER_OFFSET_REG_Y: read_data_reg <= reg_y; - ADDER_OFFSET_REG_Z: read_data_reg <= reg_z; - ADDER_OFFSET_REG_SC: read_data_reg <= {reg_sts, reg_ctl}; - endcase - // - end - - assign read_data = read_data_reg; - - - // - // Demo Adder Core - // - demo_adder adder_core - ( - .clk (sys_clk), - .rst (sys_rst), - - .x (reg_x), - .y (reg_y), - .z (reg_z), - - .ctl (reg_ctl), - .sts (reg_sts) - ); - + .cs(sys_eim_rd | sys_eim_wr), + .we(sys_eim_wr), + .address(sys_eim_addr[7 : 0]), + .write_data(write_data), + .read_data(read_data), + .error() + ); endmodule -- cgit v1.2.3 From f1fe0708e988356413f3160c6a85dc8d82eba3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Mon, 2 Feb 2015 20:54:59 +0100 Subject: Added real prefix detection of sha255 core. --- rtl/src/verilog/core_selector.v | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index 7f92e43..092b8ca 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -48,12 +48,15 @@ module core_selector input wire [31 : 0] write_data ); + parameter SHA256_BASE = 6'h14; + wire is_sha256 = ~(sys_eim_addr[13:8] ^ SHA256_BASE); + wire sha256_cs = (is_sha256 & sys_eim_rd) | (is_sha256 & sys_eim_wr); sha256 sha256_inst( .clk(sys_clk), .reset_n(~sys_rst), - .cs(sys_eim_rd | sys_eim_wr), + .cs(sha256_cs), .we(sys_eim_wr), .address(sys_eim_addr[7 : 0]), -- cgit v1.2.3 From eff75209176003629d3840809fc220a458fd89f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Mon, 2 Feb 2015 21:06:21 +0100 Subject: Passes build without any warnings. --- rtl/src/verilog/core_selector.v | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index 092b8ca..4d3a218 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -48,16 +48,22 @@ module core_selector input wire [31 : 0] write_data ); - parameter SHA256_BASE = 6'h14; - wire is_sha256 = ~(sys_eim_addr[13:8] ^ SHA256_BASE); - wire sha256_cs = (is_sha256 & sys_eim_rd) | (is_sha256 & sys_eim_wr); +// parameter SHA256_BASE = 6'h14; +// wire is_sha256 = ~(sys_eim_addr[13:8] ^ SHA256_BASE); +// wire sha256_cs = (is_sha256 & sys_eim_rd) | (is_sha256 & sys_eim_wr); + + localparam SHA256_BASE_ADDR = 6'h14; + wire access_sha256 = (sys_eim_addr[13 : 8] == SHA256_BASE_ADDR) ? 1'b1 : 1'b0; + wire read_access = sys_eim_wr & access_sha256; + wire write_access = sys_eim_rd & access_sha256; + wire select = read_access | write_access; sha256 sha256_inst( .clk(sys_clk), .reset_n(~sys_rst), - .cs(sha256_cs), - .we(sys_eim_wr), + .cs(select), + .we(write_access), .address(sys_eim_addr[7 : 0]), .write_data(write_data), -- cgit v1.2.3 From 8bcab15be72dc172cbb06c05407f6778ea3190ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Tue, 3 Feb 2015 05:18:36 +0100 Subject: More attempts at getting the addresss decoder to work... --- rtl/src/verilog/core_selector.v | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index 4d3a218..a18bfe6 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -48,28 +48,26 @@ module core_selector input wire [31 : 0] write_data ); -// parameter SHA256_BASE = 6'h14; -// wire is_sha256 = ~(sys_eim_addr[13:8] ^ SHA256_BASE); -// wire sha256_cs = (is_sha256 & sys_eim_rd) | (is_sha256 & sys_eim_wr); - localparam SHA256_BASE_ADDR = 6'h14; wire access_sha256 = (sys_eim_addr[13 : 8] == SHA256_BASE_ADDR) ? 1'b1 : 1'b0; - wire read_access = sys_eim_wr & access_sha256; - wire write_access = sys_eim_rd & access_sha256; + wire read_access = sys_eim_rd & access_sha256; + wire write_access = sys_eim_wr & access_sha256; wire select = read_access | write_access; - sha256 sha256_inst( - .clk(sys_clk), - .reset_n(~sys_rst), - - .cs(select), - .we(write_access), + assign read_data = (sys_eim_rd) ? 32'hdeadbeef : 32'haa55aa55; - .address(sys_eim_addr[7 : 0]), - .write_data(write_data), - .read_data(read_data), - .error() - ); +// sha256 sha256_inst( +// .clk(sys_clk), +// .reset_n(~sys_rst), +// +// .cs(select), +// .we(write_access), +// +// .address(sys_eim_addr[7 : 0]), +// .write_data(write_data), +// .read_data(read_data), +// .error() +// ); endmodule -- cgit v1.2.3 From f0ded923cc20dbc39336f3f2e8f083033dba6f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Tue, 3 Feb 2015 21:45:24 +0100 Subject: (1) Updated core selector with logic to connect sha256. (2) Adding test sw that is able to talk to the sha256 core and perform a hash operation. --- rtl/src/verilog/core_selector.v | 106 ++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 16 deletions(-) (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index a18bfe6..3f74a26 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -48,26 +48,100 @@ module core_selector input wire [31 : 0] write_data ); - localparam SHA256_BASE_ADDR = 6'h14; - wire access_sha256 = (sys_eim_addr[13 : 8] == SHA256_BASE_ADDR) ? 1'b1 : 1'b0; - wire read_access = sys_eim_rd & access_sha256; - wire write_access = sys_eim_wr & access_sha256; - wire select = read_access | write_access; - assign read_data = (sys_eim_rd) ? 32'hdeadbeef : 32'haa55aa55; + // + // Parameters + // + localparam ADDER_BASE_ADDR = 6'h00; // upper 6 bits of address + localparam ADDER_OFFSET_X_REG = 8'h00; // X + localparam ADDER_OFFSET_Y_REG = 8'h01; // Y -// sha256 sha256_inst( -// .clk(sys_clk), -// .reset_n(~sys_rst), + + /* This flag detects whether adder core is being addressed. */ + wire eim_access_adder = (sys_eim_addr[13:8] == ADDER_BASE_ADDR) ? 1'b1 : 1'b0; + + /* These flags detect whether write or read access is requested. */ + wire eim_access_write = sys_eim_wr & eim_access_adder; + wire eim_access_read = sys_eim_rd & eim_access_adder; + wire select = eim_access_read | eim_access_write; + +// reg [31 : 0] read_data_reg; +// reg [31 : 0] y_reg; +// reg [31 : 0] x_reg; +// +// // +// // Write Request Handler +// // +// always @(posedge sys_clk) +// // +// if (sys_rst) begin +// x_reg <= 32'hdeaddead; +// y_reg <= 32'hbeefbeef; +// end +// else if (eim_access_write) begin +// case (sys_eim_addr[7:0]) +// ADDER_OFFSET_X_REG: x_reg <= write_data; +// ADDER_OFFSET_Y_REG: y_reg <= write_data; +// endcase +// end +// +// +// // +// // Read Request Handler +// always @(posedge sys_clk) +// // +// if (sys_rst) +// read_data_reg <= 32'h00000000; +// // +// else if (eim_access_read) begin +// // +// case (sys_eim_addr[7:0]) +// ADDER_OFFSET_X_REG: read_data_reg <= x_reg; +// ADDER_OFFSET_Y_REG: read_data_reg <= y_reg; +// endcase +// // +// end + +// assign read_data = read_data_reg; + + + // localparam SHA256_BASE_ADDR = 6'h14; + // + // wire access_sha256 = (sys_eim_addr[13 : 8] == SHA256_BASE_ADDR) ? 1'b1 : 1'b0; + // wire read_access = sys_eim_rd & access_sha256; + // wire write_access = sys_eim_wr & access_sha256; + // wire select = read_access | write_access; + +// reg [31 : 0] read_data_reg; +// wire [31 : 0] sha_read_data; // -// .cs(select), -// .we(write_access), +// assign read_data = read_data_reg; // -// .address(sys_eim_addr[7 : 0]), -// .write_data(write_data), -// .read_data(read_data), -// .error() -// ); +// always @ (posedge sys_clk) +// begin +// if (sys_rst) +// begin +// read_data_reg <= 32'h00000000; +// end +// else +// begin +// read_data_reg <= sha_read_data; +// end +// end + + + sha256 sha256_inst( + .clk(sys_clk), + .reset_n(1'b1), + + .cs(eim_access_adder), + .we(sys_eim_wr), + + .address(sys_eim_addr[7 : 0]), + .write_data(write_data), + .read_data(read_data), + .error() + ); endmodule -- cgit v1.2.3 From 13b8166c8989b5e83b0c998279c60c17bf46e890 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 5 Feb 2015 15:31:33 -0500 Subject: add all SHA cores (hello coretest_hashes) --- rtl/src/verilog/core_selector.v | 296 +++++++++++++++++++++++++--------------- 1 file changed, 186 insertions(+), 110 deletions(-) (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index 3f74a26..7479848 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -1,18 +1,21 @@ //====================================================================== // -// core_selector.v -// --------------- -// Core selector Cryptech Novena FPGA framework. +// 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, NORDUnet A/S All rights reserved. -// +// 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. +// 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 @@ -37,111 +40,184 @@ //====================================================================== module core_selector - ( - input wire sys_clk, + ( + input wire sys_clk, input wire sys_rst, - input wire [13: 0] sys_eim_addr, + 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 - ); - - - // - // Parameters - // - localparam ADDER_BASE_ADDR = 6'h00; // upper 6 bits of address - localparam ADDER_OFFSET_X_REG = 8'h00; // X - localparam ADDER_OFFSET_Y_REG = 8'h01; // Y - - - /* This flag detects whether adder core is being addressed. */ - wire eim_access_adder = (sys_eim_addr[13:8] == ADDER_BASE_ADDR) ? 1'b1 : 1'b0; - - /* These flags detect whether write or read access is requested. */ - wire eim_access_write = sys_eim_wr & eim_access_adder; - wire eim_access_read = sys_eim_rd & eim_access_adder; - wire select = eim_access_read | eim_access_write; - -// reg [31 : 0] read_data_reg; -// reg [31 : 0] y_reg; -// reg [31 : 0] x_reg; -// -// // -// // Write Request Handler -// // -// always @(posedge sys_clk) -// // -// if (sys_rst) begin -// x_reg <= 32'hdeaddead; -// y_reg <= 32'hbeefbeef; -// end -// else if (eim_access_write) begin -// case (sys_eim_addr[7:0]) -// ADDER_OFFSET_X_REG: x_reg <= write_data; -// ADDER_OFFSET_Y_REG: y_reg <= write_data; -// endcase -// end -// -// -// // -// // Read Request Handler -// always @(posedge sys_clk) -// // -// if (sys_rst) -// read_data_reg <= 32'h00000000; -// // -// else if (eim_access_read) begin -// // -// case (sys_eim_addr[7:0]) -// ADDER_OFFSET_X_REG: read_data_reg <= x_reg; -// ADDER_OFFSET_Y_REG: read_data_reg <= y_reg; -// endcase -// // -// end - -// assign read_data = read_data_reg; - - - // localparam SHA256_BASE_ADDR = 6'h14; - // - // wire access_sha256 = (sys_eim_addr[13 : 8] == SHA256_BASE_ADDR) ? 1'b1 : 1'b0; - // wire read_access = sys_eim_rd & access_sha256; - // wire write_access = sys_eim_wr & access_sha256; - // wire select = read_access | write_access; - -// reg [31 : 0] read_data_reg; -// wire [31 : 0] sha_read_data; -// -// assign read_data = read_data_reg; -// -// always @ (posedge sys_clk) -// begin -// if (sys_rst) -// begin -// read_data_reg <= 32'h00000000; -// end -// else -// begin -// read_data_reg <= sha_read_data; -// end -// end - - - sha256 sha256_inst( - .clk(sys_clk), - .reset_n(1'b1), - - .cs(eim_access_adder), - .we(sys_eim_wr), - - .address(sys_eim_addr[7 : 0]), - .write_data(write_data), - .read_data(read_data), - .error() - ); + input wire [31 : 0] 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 endmodule -- cgit v1.2.3 From 560ebacb0c576b92d7b64d728423683ad974885e Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 10 Feb 2015 12:03:47 -0500 Subject: 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. --- rtl/src/verilog/cipher_selector.v | 115 +++++++++++ rtl/src/verilog/core_selector.v | 365 ++++++++++++++++++---------------- rtl/src/verilog/eim_arbiter.v | 20 +- rtl/src/verilog/eim_arbiter_cdc.v | 28 +-- rtl/src/verilog/eim_memory.v | 182 +++++++++++++++++ rtl/src/verilog/novena_baseline_top.v | 40 ++-- rtl/src/verilog/novena_regs.v | 80 ++++++++ rtl/src/verilog/rng_selector.v | 114 +++++++++++ 8 files changed, 730 insertions(+), 214 deletions(-) create mode 100644 rtl/src/verilog/cipher_selector.v create mode 100644 rtl/src/verilog/eim_memory.v create mode 100644 rtl/src/verilog/novena_regs.v create mode 100644 rtl/src/verilog/rng_selector.v (limited to 'rtl/src/verilog') 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 +//====================================================================== -- cgit v1.2.3 From 0e4e0b5d71b15e1f4edf31295fc95d45d4ae3890 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 10 Feb 2015 13:51:40 -0500 Subject: First stage of integration cleanup. Add local SHA core wrappers, due to the need for registered outputs. Remove unused demo-adder code, and reorganize sw directory. --- rtl/src/verilog/core_selector.v | 11 +- rtl/src/verilog/demo_adder.v | 108 ------------------ rtl/src/verilog/sha1.v | 204 ++++++++++++++++++++++++++++++++++ rtl/src/verilog/sha256.v | 204 ++++++++++++++++++++++++++++++++++ rtl/src/verilog/sha512.v | 241 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 653 insertions(+), 115 deletions(-) delete mode 100644 rtl/src/verilog/demo_adder.v create mode 100644 rtl/src/verilog/sha1.v create mode 100644 rtl/src/verilog/sha256.v create mode 100644 rtl/src/verilog/sha512.v (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index e39a8b1..8ac8909 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -1,7 +1,7 @@ //====================================================================== // // core_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 @@ -170,8 +170,7 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_sha1), - .error() + .read_data(read_data_sha1) ); `endif @@ -192,8 +191,7 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_sha256), - .error() + .read_data(read_data_sha256) ); `endif @@ -214,8 +212,7 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_sha512), - .error() + .read_data(read_data_sha512) ); `endif diff --git a/rtl/src/verilog/demo_adder.v b/rtl/src/verilog/demo_adder.v deleted file mode 100644 index 54e7f72..0000000 --- a/rtl/src/verilog/demo_adder.v +++ /dev/null @@ -1,108 +0,0 @@ -//====================================================================== -// -// demo_adder.v -// ------------ -// Simple test core for the Cryptech Novena FPGA framework. The core -// s a 32-bit adder that allows us to verfy that we can write registers -// get a computation done and read out the registers via the EIM. -// -// -// Author: Pavel Shatov -// Copyright (c) 2014, 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 demo_adder - ( - clk, rst, - x, y, z, - ctl, sts - ); - - // - // Ports - // - input wire clk; // clock - input wire rst; // reset - - input wire [31: 0] x; // x - input wire [31: 0] y; // y - output wire [31: 0] z; // z = x + y - - input wire [15: 0] ctl; // control - output wire [15: 0] sts; // status - - - // - // Internal Registers - // - reg [31: 0] z_reg = {32{1'b0}}; - reg [15: 0] sts_reg = {16{1'b0}}; - reg [15: 0] ctl_dly = {16{1'b0}}; - - assign z = z_reg; - assign sts = sts_reg; - - - // - // Control Logic - // - always @(posedge clk) - // - if (rst) ctl_dly <= {16{1'b0}}; - else ctl_dly <= ctl; - - /* This flag is set whenever different value is written to control register. */ - - wire adder_go = (ctl != ctl_dly) ? 1'b1 : 1'b0; - - - // - // Adder Logic - // - always @(posedge clk) - // - if (rst) z_reg <= {32{1'b0}}; - else if (adder_go) z_reg <= x + y; - - - // - // Status Logic - // - always @(posedge clk) - // - if (rst) sts_reg <= {16{1'b0}}; - else if (adder_go) sts_reg <= ctl; - - -endmodule - -//====================================================================== -// EOF demo_adder.v -//====================================================================== diff --git a/rtl/src/verilog/sha1.v b/rtl/src/verilog/sha1.v new file mode 100644 index 0000000..2595132 --- /dev/null +++ b/rtl/src/verilog/sha1.v @@ -0,0 +1,204 @@ +//====================================================================== +// +// sha1.v +// ------ +// Top level wrapper for the SHA-1 hash function providing +// a simple memory like interface with 32 bit data access. +// +// Authors: Joachim Strömbergson, Paul Selkirk +// Copyright (c) 2014, 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 sha1( + // 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 + ); + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + parameter ADDR_NAME0 = 8'h00; + parameter ADDR_NAME1 = 8'h01; + parameter ADDR_VERSION = 8'h02; + + parameter ADDR_CTRL = 8'h08; + parameter CTRL_INIT_BIT = 0; + parameter CTRL_NEXT_BIT = 1; + + parameter ADDR_STATUS = 8'h09; + parameter STATUS_READY_BIT = 0; + parameter STATUS_VALID_BIT = 1; + + parameter ADDR_BLOCK = 8'h10; + + parameter ADDR_DIGEST = 8'h20; + + parameter CORE_NAME0 = 32'h73686131; // "sha1" + parameter CORE_NAME1 = 32'h20202020; // " " + parameter CORE_VERSION = 32'h302e3530; // "0.50" + + parameter BLOCK_BITS = 512; + parameter DIGEST_BITS = 160; + parameter BLOCK_WORDS = BLOCK_BITS / 32; + parameter DIGEST_WORDS = DIGEST_BITS / 32; + + //---------------------------------------------------------------- + // Registers. + //---------------------------------------------------------------- + reg [0 : BLOCK_BITS - 1] block_reg; + reg [0 : DIGEST_BITS - 1] digest_reg; + reg init_reg; + reg next_reg; + + reg [31 : 0] tmp_read_data; + reg [31 : 0] tmp_read_data_reg; + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + wire core_init; + wire core_next; + wire core_ready; + wire [0 : BLOCK_BITS - 1] core_block; + wire [0 : DIGEST_BITS - 1] core_digest; + wire core_digest_valid; + + wire [31 : 0] core_name0 = CORE_NAME0; + wire [31 : 0] core_name1 = CORE_NAME1; + wire [31 : 0] core_version = CORE_VERSION; + wire [31 : 0] core_ctrl; + wire [31 : 0] core_status; + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign core_init = init_reg; + assign core_next = next_reg; + assign core_ctrl = { 30'b0, next_reg, init_reg }; + assign core_status = { 30'b0, core_digest_valid, core_ready }; + assign core_block = block_reg; + + assign read_data = tmp_read_data_reg; + + //---------------------------------------------------------------- + // core instantiation. + //---------------------------------------------------------------- + sha1_core core( + .clk(clk), + .reset_n(reset_n), + + .init(core_init), + .next(core_next), + + .block(core_block), + + .ready(core_ready), + + .digest(core_digest), + .digest_valid(core_digest_valid) + ); + + + //---------------------------------------------------------------- + // latch in digest when ready + //---------------------------------------------------------------- + always @(posedge clk) + begin + if (core_digest_valid) + digest_reg <= core_digest; + end + + //---------------------------------------------------------------- + // storage registers for mapping memory to core interface + //---------------------------------------------------------------- + always @(posedge clk) + begin + init_reg <= 0; + next_reg <= 0; + + if (cs && we) + begin + // write operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; + else if (address == ADDR_CTRL) + begin + init_reg <= write_data[CTRL_INIT_BIT]; + next_reg <= write_data[CTRL_NEXT_BIT]; + end + end + end + + always @* + begin + tmp_read_data = 32'h00000000; + + if (cs && !we) + begin + // read operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; + else if ((address >= ADDR_DIGEST) && + (address < ADDR_DIGEST + DIGEST_WORDS)) + tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; + else + case (address) + ADDR_NAME0: + tmp_read_data = core_name0; + ADDR_NAME1: + tmp_read_data = core_name1; + ADDR_VERSION: + tmp_read_data = core_version; + ADDR_CTRL: + tmp_read_data = core_ctrl; + ADDR_STATUS: + tmp_read_data = core_status; + endcase + end + end + + always @(posedge clk) + begin + tmp_read_data_reg <= tmp_read_data; + end + +endmodule // sha1 diff --git a/rtl/src/verilog/sha256.v b/rtl/src/verilog/sha256.v new file mode 100644 index 0000000..d6fb133 --- /dev/null +++ b/rtl/src/verilog/sha256.v @@ -0,0 +1,204 @@ +//====================================================================== +// +// sha256.v +// ------ +// Top level wrapper for the SHA-256 hash function providing +// a simple memory like interface with 32 bit data access. +// +// Authors: Joachim Strömbergson, Paul Selkirk +// Copyright (c) 2014, 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 sha256( + // 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 + ); + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + parameter ADDR_NAME0 = 8'h00; + parameter ADDR_NAME1 = 8'h01; + parameter ADDR_VERSION = 8'h02; + + parameter ADDR_CTRL = 8'h08; + parameter CTRL_INIT_BIT = 0; + parameter CTRL_NEXT_BIT = 1; + + parameter ADDR_STATUS = 8'h09; + parameter STATUS_READY_BIT = 0; + parameter STATUS_VALID_BIT = 1; + + parameter ADDR_BLOCK = 8'h10; + + parameter ADDR_DIGEST = 8'h20; + + parameter CORE_NAME0 = 32'h73686132; // "sha2" + parameter CORE_NAME1 = 32'h2d323536; // "-256" + parameter CORE_VERSION = 32'h302e3830; // "0.80" + + parameter BLOCK_BITS = 512; + parameter DIGEST_BITS = 256; + parameter BLOCK_WORDS = BLOCK_BITS / 32; + parameter DIGEST_WORDS = DIGEST_BITS / 32; + + //---------------------------------------------------------------- + // Registers. + //---------------------------------------------------------------- + reg [0 : BLOCK_BITS - 1] block_reg; + reg [0 : DIGEST_BITS - 1] digest_reg; + reg init_reg; + reg next_reg; + + reg [31 : 0] tmp_read_data; + reg [31 : 0] tmp_read_data_reg; + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + wire core_init; + wire core_next; + wire core_ready; + wire [0 : BLOCK_BITS - 1] core_block; + wire [0 : DIGEST_BITS - 1] core_digest; + wire core_digest_valid; + + wire [31 : 0] core_name0 = CORE_NAME0; + wire [31 : 0] core_name1 = CORE_NAME1; + wire [31 : 0] core_version = CORE_VERSION; + wire [31 : 0] core_ctrl; + wire [31 : 0] core_status; + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign core_init = init_reg; + assign core_next = next_reg; + assign core_ctrl = { 30'b0, next_reg, init_reg }; + assign core_status = { 30'b0, core_digest_valid, core_ready }; + assign core_block = block_reg; + + assign read_data = tmp_read_data_reg; + + //---------------------------------------------------------------- + // core instantiation. + //---------------------------------------------------------------- + sha256_core core( + .clk(clk), + .reset_n(reset_n), + + .init(core_init), + .next(core_next), + + .block(core_block), + + .ready(core_ready), + + .digest(core_digest), + .digest_valid(core_digest_valid) + ); + + + //---------------------------------------------------------------- + // latch in digest when ready + //---------------------------------------------------------------- + always @(posedge clk) + begin + if (core_digest_valid) + digest_reg <= core_digest; + end + + //---------------------------------------------------------------- + // storage registers for mapping memory to core interface + //---------------------------------------------------------------- + always @(posedge clk) + begin + init_reg <= 0; + next_reg <= 0; + + if (cs && we) + begin + // write operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; + else if (address == ADDR_CTRL) + begin + init_reg <= write_data[CTRL_INIT_BIT]; + next_reg <= write_data[CTRL_NEXT_BIT]; + end + end + end + + always @* + begin + tmp_read_data = 32'h00000000; + + if (cs && !we) + begin + // read operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; + else if ((address >= ADDR_DIGEST) && + (address < ADDR_DIGEST + DIGEST_WORDS)) + tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; + else + case (address) + ADDR_NAME0: + tmp_read_data = core_name0; + ADDR_NAME1: + tmp_read_data = core_name1; + ADDR_VERSION: + tmp_read_data = core_version; + ADDR_CTRL: + tmp_read_data = core_ctrl; + ADDR_STATUS: + tmp_read_data = core_status; + endcase + end + end + + always @(posedge clk) + begin + tmp_read_data_reg <= tmp_read_data; + end + +endmodule // sha256 diff --git a/rtl/src/verilog/sha512.v b/rtl/src/verilog/sha512.v new file mode 100644 index 0000000..4d2a9e7 --- /dev/null +++ b/rtl/src/verilog/sha512.v @@ -0,0 +1,241 @@ +//====================================================================== +// +// sha512.v +// ------ +// Top level wrapper for the SHA-512 hash function providing +// a simple memory like interface with 32 bit data access. +// +// Authors: Joachim Strömbergson, Paul Selkirk +// Copyright (c) 2014, 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 sha512( + // 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 + ); + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + parameter ADDR_NAME0 = 8'h00; + parameter ADDR_NAME1 = 8'h01; + parameter ADDR_VERSION = 8'h02; + + parameter ADDR_CTRL = 8'h08; + parameter CTRL_INIT_BIT = 0; + parameter CTRL_NEXT_BIT = 1; + parameter CTRL_MODE_LOW_BIT = 2; + parameter CTRL_MODE_HIGH_BIT = 3; + parameter CTRL_WORK_FACTOR_BIT = 7; + + parameter ADDR_STATUS = 8'h09; + parameter STATUS_READY_BIT = 0; + parameter STATUS_VALID_BIT = 1; + + parameter ADDR_WORK_FACTOR_NUM = 8'h0a; + + parameter ADDR_BLOCK = 8'h10; + + parameter ADDR_DIGEST = 8'h40; + + parameter CORE_NAME0 = 32'h73686132; // "sha2" + parameter CORE_NAME1 = 32'h2d353132; // "-512" + parameter CORE_VERSION = 32'h302e3830; // "0.80" + + parameter MODE_SHA_512_224 = 2'h0; + parameter MODE_SHA_512_256 = 2'h1; + parameter MODE_SHA_384 = 2'h2; + parameter MODE_SHA_512 = 2'h3; + + parameter DEFAULT_WORK_FACTOR_NUM = 32'h000f0000; + + parameter BLOCK_BITS = 1024; + parameter DIGEST_BITS = 512; + parameter BLOCK_WORDS = BLOCK_BITS / 32; + parameter DIGEST_WORDS = DIGEST_BITS / 32; + + //---------------------------------------------------------------- + // Registers. + //---------------------------------------------------------------- + reg [0 : BLOCK_BITS - 1] block_reg; + reg [0 : DIGEST_BITS - 1] digest_reg; + reg init_reg; + reg next_reg; + reg [1 : 0] mode_reg; + reg work_factor_reg; + reg [31 : 0] work_factor_num_reg; + + reg [31 : 0] tmp_read_data; + reg [31 : 0] tmp_read_data_reg; + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + wire core_init; + wire core_next; + wire core_ready; + wire [1 : 0] core_mode; + wire core_work_factor; + wire [31 : 0] core_work_factor_num; + wire [0 : BLOCK_BITS - 1] core_block; + wire [0 : DIGEST_BITS - 1] core_digest; + wire core_digest_valid; + + wire [31 : 0] core_name0 = CORE_NAME0; + wire [31 : 0] core_name1 = CORE_NAME1; + wire [31 : 0] core_version = CORE_VERSION; + wire [31 : 0] core_ctrl; + wire [31 : 0] core_status; + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign core_init = init_reg; + assign core_next = next_reg; + assign core_mode = mode_reg; + assign core_work_factor = work_factor_reg; + assign core_work_factor_num = work_factor_num_reg; + assign core_ctrl = {24'h000000, work_factor_reg, 3'b000, + mode_reg, next_reg, init_reg}; + assign core_status = { 30'b0, core_digest_valid, core_ready }; + assign core_block = block_reg; + + assign read_data = tmp_read_data_reg; + + //---------------------------------------------------------------- + // core instantiation. + //---------------------------------------------------------------- + sha512_core core( + .clk(clk), + .reset_n(reset_n), + + .init(core_init), + .next(core_next), + .mode(core_mode), + + .work_factor(core_work_factor), + .work_factor_num(core_work_factor_num), + + .block(core_block), + + .ready(core_ready), + + .digest(core_digest), + .digest_valid(core_digest_valid) + ); + + + //---------------------------------------------------------------- + // latch in digest when ready + //---------------------------------------------------------------- + always @(posedge clk) + begin + if (core_digest_valid) + digest_reg <= core_digest; + end + + //---------------------------------------------------------------- + // storage registers for mapping memory to core interface + //---------------------------------------------------------------- + always @(posedge clk) + begin + init_reg <= 0; + next_reg <= 0; + mode_reg <= MODE_SHA_512; + work_factor_reg <= 0; + work_factor_num_reg <= DEFAULT_WORK_FACTOR_NUM; + + if (cs && we) + begin + // write operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; + else if (address == ADDR_CTRL) + begin + init_reg <= write_data[CTRL_INIT_BIT]; + next_reg <= write_data[CTRL_NEXT_BIT]; + mode_reg <= write_data[CTRL_MODE_HIGH_BIT : CTRL_MODE_LOW_BIT]; + work_factor_reg <= write_data[CTRL_WORK_FACTOR_BIT]; + end + else if (address == ADDR_WORK_FACTOR_NUM) + begin + work_factor_num_reg <= write_data; + end + end + end + + always @* + begin + tmp_read_data = 32'h00000000; + + if (cs && !we) + begin + // read operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; + else if ((address >= ADDR_DIGEST) && + (address < ADDR_DIGEST + DIGEST_WORDS)) + tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; + else + case (address) + ADDR_NAME0: + tmp_read_data = core_name0; + ADDR_NAME1: + tmp_read_data = core_name1; + ADDR_VERSION: + tmp_read_data = core_version; + ADDR_CTRL: + tmp_read_data = core_ctrl; + ADDR_STATUS: + tmp_read_data = core_status; + ADDR_WORK_FACTOR_NUM: + tmp_read_data = work_factor_num_reg; + endcase + end + end + + always @(posedge clk) + begin + tmp_read_data_reg <= tmp_read_data; + end + +endmodule // sha512 -- cgit v1.2.3 From 5f769e9b78a61d6b69355a6aae8572128a8f54a3 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 10 Feb 2015 15:06:55 -0500 Subject: Reformat verilog code for readability. --- rtl/src/verilog/cdc_bus_pulse.v | 199 +++++++------- rtl/src/verilog/cipher_selector.v | 134 ++++----- rtl/src/verilog/core_selector.v | 388 +++++++++++++------------- rtl/src/verilog/eim_arbiter.v | 505 ++++++++++++++++++---------------- rtl/src/verilog/eim_arbiter_cdc.v | 200 +++++++------- rtl/src/verilog/eim_da_phy.v | 74 +++-- rtl/src/verilog/eim_indicator.v | 49 ++-- rtl/src/verilog/eim_memory.v | 266 +++++++++--------- rtl/src/verilog/novena_baseline_top.v | 284 +++++++++---------- rtl/src/verilog/novena_clkmgr.v | 142 +++++----- rtl/src/verilog/novena_regs.v | 198 ++++++++----- rtl/src/verilog/rng_selector.v | 128 +++++---- rtl/src/verilog/sha1.v | 98 +++---- rtl/src/verilog/sha256.v | 98 +++---- rtl/src/verilog/sha512.v | 116 ++++---- 15 files changed, 1467 insertions(+), 1412 deletions(-) (limited to 'rtl/src/verilog') diff --git a/rtl/src/verilog/cdc_bus_pulse.v b/rtl/src/verilog/cdc_bus_pulse.v index 6f1fa34..cc2d8db 100644 --- a/rtl/src/verilog/cdc_bus_pulse.v +++ b/rtl/src/verilog/cdc_bus_pulse.v @@ -11,7 +11,7 @@ // // // Author: Pavel Shatov -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -42,109 +42,100 @@ //====================================================================== module cdc_bus_pulse - ( - src_clk, src_din, src_req, - dst_clk, dst_dout, dst_pulse - ); - - // - // Parameters - // - parameter DATA_WIDTH = 32; // width of data bus - - - // - // Ports - // - 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 + #(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 diff --git a/rtl/src/verilog/cipher_selector.v b/rtl/src/verilog/cipher_selector.v index 31dfe4b..ea18e14 100644 --- a/rtl/src/verilog/cipher_selector.v +++ b/rtl/src/verilog/cipher_selector.v @@ -40,73 +40,75 @@ //====================================================================== module cipher_selector - ( - input wire sys_clk, - input wire sys_rst, - input wire sys_ena, + ( + 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 - + 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 + endcase + // + end + // + end + endmodule diff --git a/rtl/src/verilog/core_selector.v b/rtl/src/verilog/core_selector.v index 8ac8909..eef0a75 100644 --- a/rtl/src/verilog/core_selector.v +++ b/rtl/src/verilog/core_selector.v @@ -40,202 +40,220 @@ //====================================================================== module core_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 - ); - - - /* 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)), + ( + 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 + ); + + + /* 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)), + .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), + .address(addr_core_reg), + .write_data(sys_write_data), .read_data(read_data_sha1) - ); - `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)), + ); + `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), + .address(addr_core_reg), + .write_data(sys_write_data), .read_data(read_data_sha256) - ); - `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)), + ); + `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), + .address(addr_core_reg), + .write_data(sys_write_data), .read_data(read_data_sha512) - ); - `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 - + ); + `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 d21799f..e9b2c76 100644 --- a/rtl/src/verilog/eim_arbiter.v +++ b/rtl/src/verilog/eim_arbiter.v @@ -7,7 +7,7 @@ // // // Author: Pavel Shatov -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -38,249 +38,268 @@ //====================================================================== module eim_arbiter - ( - eim_bclk, eim_cs0_n, eim_da, eim_a, - eim_lba_n, eim_wr_n, - eim_oe_n, eim_wait_n, - - sys_clk, - sys_addr, - sys_wren, sys_data_out, - sys_rden, sys_data_in - ); - - - // - // Ports - // - input wire eim_bclk; // | eim bus - input wire eim_cs0_n; // | - 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; // | - output wire eim_wait_n; // | - - input wire sys_clk; // system clock - - output wire [16: 0] sys_addr; // | user bus - output wire sys_wren; // | - output wire [31: 0] sys_data_out; // | - output wire sys_rden; // | - input wire [31: 0] sys_data_in; // | - - - // - // Data/Address PHY - // - - /* PHY is needed to control bi-directional address/data bus. */ - - wire [15: 0] da_ro; // value read from pins - reg [15: 0] da_di; // value drives onto pins - - eim_da_phy da_phy - ( - .buf_io (eim_da), // <-- connect directly top-level port - .buf_di (da_di), - .buf_ro (da_ro), - .buf_t (eim_oe_n) // <-- driven by EIM directly - ); - - - // - // FSM - // - localparam EIM_FSM_STATE_INIT = 5'b0_0_000; // arbiter is idle - - localparam EIM_FSM_STATE_WRITE_START = 5'b1_1_000; // got address to write at - localparam EIM_FSM_STATE_WRITE_LSB = 5'b1_1_001; // got lower 16 bits of data to write - localparam EIM_FSM_STATE_WRITE_MSB = 5'b1_1_010; // got upper 16 bits of data to write - localparam EIM_FSM_STATE_WRITE_WAIT = 5'b1_1_100; // request to user-side logic sent - localparam EIM_FSM_STATE_WRITE_DONE = 5'b1_1_111; // user-side logic acknowledged transaction - - localparam EIM_FSM_STATE_READ_START = 5'b1_0_000; // got address to read from - localparam EIM_FSM_STATE_READ_WAIT = 5'b1_0_100; // request to user-side logic sent - localparam EIM_FSM_STATE_READ_READY = 5'b1_0_011; // got acknowledge from user logic - localparam EIM_FSM_STATE_READ_LSB = 5'b1_0_001; // returned lower 16 bits to master - localparam EIM_FSM_STATE_READ_MSB = 5'b1_0_010; // returned upper 16 bits to master - 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 [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. */ - wire eim_write_start_flag = (eim_lba_n == 1'b0) && (eim_wr_n == 1'b0) && (da_ro[1:0] == 2'b00); - wire eim_read_start_flag = (eim_lba_n == 1'b0) && (eim_wr_n == 1'b1) && (da_ro[1:0] == 2'b00); - - /* These are transaction response flag and data from user-side logic. */ - wire eim_user_ack; - wire [31: 0] eim_user_data; - - /* FSM is reset whenever Chip Select is de-asserted. */ - - // - // FSM Transition Logic - // - always @(posedge eim_bclk or posedge eim_cs0_n) begin - // - if (eim_cs0_n == 1'b1) eim_fsm_state <= EIM_FSM_STATE_INIT; - // - else begin - // - case (eim_fsm_state) - // - // INIT -> WRITE, INIT -> READ - // - EIM_FSM_STATE_INIT: begin - if (eim_write_start_flag) eim_fsm_state <= EIM_FSM_STATE_WRITE_START; - if (eim_read_start_flag) eim_fsm_state <= EIM_FSM_STATE_READ_START; - end - // - // WRITE - // - EIM_FSM_STATE_WRITE_START: eim_fsm_state <= EIM_FSM_STATE_WRITE_LSB; - // - EIM_FSM_STATE_WRITE_LSB: eim_fsm_state <= EIM_FSM_STATE_WRITE_MSB; - // - EIM_FSM_STATE_WRITE_MSB: eim_fsm_state <= EIM_FSM_STATE_WRITE_WAIT; - // - EIM_FSM_STATE_WRITE_WAIT: - if (eim_user_ack) eim_fsm_state <= EIM_FSM_STATE_WRITE_DONE; - // - EIM_FSM_STATE_WRITE_DONE: eim_fsm_state <= EIM_FSM_STATE_INIT; - // - // READ - // - EIM_FSM_STATE_READ_START: eim_fsm_state <= EIM_FSM_STATE_READ_WAIT; - // - EIM_FSM_STATE_READ_WAIT: - if (eim_user_ack) eim_fsm_state <= EIM_FSM_STATE_READ_READY; - // - EIM_FSM_STATE_READ_READY: eim_fsm_state <= EIM_FSM_STATE_READ_LSB; - // - EIM_FSM_STATE_READ_LSB: eim_fsm_state <= EIM_FSM_STATE_READ_MSB; - // - EIM_FSM_STATE_READ_MSB: eim_fsm_state <= EIM_FSM_STATE_READ_DONE; - // - EIM_FSM_STATE_READ_DONE: eim_fsm_state <= EIM_FSM_STATE_INIT; - // - // - // - default: eim_fsm_state <= EIM_FSM_STATE_INIT; - // - endcase - // - end - // - end - - - // - // Address Latch - // - always @(posedge eim_bclk) - // - if ((eim_fsm_state == EIM_FSM_STATE_INIT) && (eim_write_start_flag || eim_read_start_flag)) - eim_addr_latch <= {eim_a[18:16], da_ro[15:2]}; - - - // - // Additional Write Logic - // - always @(posedge eim_bclk) - // - if (eim_fsm_state == EIM_FSM_STATE_WRITE_START) - eim_write_lsb_latch <= da_ro; - - - // - // Additional Read Logic - // - - /* Note that this stuff operates on falling clock edge, because the cpu + ( + // eim bus + input wire eim_bclk, + input wire eim_cs0_n, + 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, + output wire eim_wait_n, + + // system clock + input wire sys_clk, + + // user bus + output wire [16: 0] sys_addr, + output wire sys_wren, + output wire [31: 0] sys_data_out, + output wire sys_rden, + input wire [31: 0] sys_data_in + ); + + + // + // Data/Address PHY + // + + /* PHY is needed to control bi-directional address/data bus. */ + + wire [15: 0] da_ro; // value read from pins + reg [15: 0] da_di; // value drives onto pins + + eim_da_phy da_phy + ( + .buf_io(eim_da), // <-- connect directly top-level port + .buf_di(da_di), + .buf_ro(da_ro), + .buf_t(eim_oe_n) // <-- driven by EIM directly + ); + + + // + // FSM + // + localparam EIM_FSM_STATE_INIT = 5'b0_0_000; // arbiter is idle + + localparam EIM_FSM_STATE_WRITE_START = 5'b1_1_000; // got address to write at + localparam EIM_FSM_STATE_WRITE_LSB = 5'b1_1_001; // got lower 16 bits of data to write + localparam EIM_FSM_STATE_WRITE_MSB = 5'b1_1_010; // got upper 16 bits of data to write + localparam EIM_FSM_STATE_WRITE_WAIT = 5'b1_1_100; // request to user-side logic sent + localparam EIM_FSM_STATE_WRITE_DONE = 5'b1_1_111; // user-side logic acknowledged transaction + + localparam EIM_FSM_STATE_READ_START = 5'b1_0_000; // got address to read from + localparam EIM_FSM_STATE_READ_WAIT = 5'b1_0_100; // request to user-side logic sent + localparam EIM_FSM_STATE_READ_READY = 5'b1_0_011; // got acknowledge from user logic + localparam EIM_FSM_STATE_READ_LSB = 5'b1_0_001; // returned lower 16 bits to master + localparam EIM_FSM_STATE_READ_MSB = 5'b1_0_010; // returned upper 16 bits to master + 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 [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. */ + wire eim_write_start_flag = (eim_lba_n == 1'b0) && (eim_wr_n == 1'b0) && (da_ro[1:0] == 2'b00); + wire eim_read_start_flag = (eim_lba_n == 1'b0) && (eim_wr_n == 1'b1) && (da_ro[1:0] == 2'b00); + + /* These are transaction response flag and data from user-side logic. */ + wire eim_user_ack; + wire [31: 0] eim_user_data; + + /* FSM is reset whenever Chip Select is de-asserted. */ + + // + // FSM Transition Logic + // + always @(posedge eim_bclk or posedge eim_cs0_n) + begin + // + if (eim_cs0_n == 1'b1) + eim_fsm_state <= EIM_FSM_STATE_INIT; + // + else + begin + // + case (eim_fsm_state) + // + // INIT -> WRITE, INIT -> READ + // + EIM_FSM_STATE_INIT: + begin + if (eim_write_start_flag) + eim_fsm_state <= EIM_FSM_STATE_WRITE_START; + if (eim_read_start_flag) + eim_fsm_state <= EIM_FSM_STATE_READ_START; + end + // + // WRITE + // + EIM_FSM_STATE_WRITE_START: + eim_fsm_state <= EIM_FSM_STATE_WRITE_LSB; + // + EIM_FSM_STATE_WRITE_LSB: + eim_fsm_state <= EIM_FSM_STATE_WRITE_MSB; + // + EIM_FSM_STATE_WRITE_MSB: + eim_fsm_state <= EIM_FSM_STATE_WRITE_WAIT; + // + EIM_FSM_STATE_WRITE_WAIT: + if (eim_user_ack) + eim_fsm_state <= EIM_FSM_STATE_WRITE_DONE; + // + EIM_FSM_STATE_WRITE_DONE: + eim_fsm_state <= EIM_FSM_STATE_INIT; + // + // READ + // + EIM_FSM_STATE_READ_START: + eim_fsm_state <= EIM_FSM_STATE_READ_WAIT; + // + EIM_FSM_STATE_READ_WAIT: + if (eim_user_ack) + eim_fsm_state <= EIM_FSM_STATE_READ_READY; + // + EIM_FSM_STATE_READ_READY: + eim_fsm_state <= EIM_FSM_STATE_READ_LSB; + // + EIM_FSM_STATE_READ_LSB: + eim_fsm_state <= EIM_FSM_STATE_READ_MSB; + // + EIM_FSM_STATE_READ_MSB: + eim_fsm_state <= EIM_FSM_STATE_READ_DONE; + // + EIM_FSM_STATE_READ_DONE: + eim_fsm_state <= EIM_FSM_STATE_INIT; + // + // + // + default: + eim_fsm_state <= EIM_FSM_STATE_INIT; + // + endcase + // + end + // + end + + + // + // Address Latch + // + always @(posedge eim_bclk) + // + if ((eim_fsm_state == EIM_FSM_STATE_INIT) && (eim_write_start_flag || eim_read_start_flag)) + eim_addr_latch <= {eim_a[18:16], da_ro[15:2]}; + + + // + // Additional Write Logic + // + always @(posedge eim_bclk) + // + if (eim_fsm_state == EIM_FSM_STATE_WRITE_START) + eim_write_lsb_latch <= da_ro; + + + // + // Additional Read Logic + // + + /* Note that this stuff operates on falling clock edge, because the cpu * samples our bi-directional data bus on rising clock edge. - */ - - always @(negedge eim_bclk or posedge eim_cs0_n) - // - if (eim_cs0_n == 1'b1) da_di <= {16{1'bX}}; // don't care what to drive - else begin - // - if (eim_fsm_state == EIM_FSM_STATE_READ_LSB) da_di <= eim_user_data[15: 0]; // drive lower 16 bits at first... - if (eim_fsm_state == EIM_FSM_STATE_READ_MSB) da_di <= eim_user_data[31:16]; // ...then drive upper 16 bits - // - end - - - // - // Wait Logic - // - - /* Note that this stuff operates on falling clock edge, because the cpu - * samples our WAIT_N flag on rising clock edge. - */ - - reg eim_wait_reg = 1'b0; - - always @(negedge eim_bclk or posedge eim_cs0_n) - // - if (eim_cs0_n == 1'b1) eim_wait_reg <= 1'b0; // clear wait - else begin - // - if (eim_fsm_state == EIM_FSM_STATE_WRITE_START) eim_wait_reg <= 1'b1; // start waiting for write to complete - if (eim_fsm_state == EIM_FSM_STATE_READ_START) eim_wait_reg <= 1'b1; // start waiting for read to complete - // - if (eim_fsm_state == EIM_FSM_STATE_WRITE_DONE) eim_wait_reg <= 1'b0; // write transaction done - if (eim_fsm_state == EIM_FSM_STATE_READ_READY) eim_wait_reg <= 1'b0; // read transaction done - // - if (eim_fsm_state == EIM_FSM_STATE_INIT) eim_wait_reg <= 1'b0; // fsm is idle, no need to wait any more - // - end - - assign eim_wait_n = ~eim_wait_reg; - - - /* These flags are used to generate 1-cycle pulses to trigger CDC transaction. - * Note that FSM goes from WRITE_LSB to WRITE_MSB and from READ_START 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 = (eim_fsm_state == EIM_FSM_STATE_WRITE_LSB) ? 1'b1 : 1'b0; - wire arbiter_read_req_pulse = (eim_fsm_state == EIM_FSM_STATE_READ_START) ? 1'b1 : 1'b0; - - // - // CDC Block - // - - /* 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+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 - ( - .eim_clk (eim_bclk), - - .eim_req (arbiter_write_req_pulse | arbiter_read_req_pulse), - .eim_ack (eim_user_ack), - - .eim_din ({arbiter_write_req_pulse, arbiter_read_req_pulse, eim_addr_latch, da_ro, eim_write_lsb_latch}), - .eim_dout (eim_user_data), - - .sys_clk (sys_clk), - .sys_addr (sys_addr), - .sys_wren (sys_wren), - .sys_data_out (sys_data_out), - .sys_rden (sys_rden), - .sys_data_in (sys_data_in) - ); + */ + + always @(negedge eim_bclk or posedge eim_cs0_n) + // + if (eim_cs0_n == 1'b1) da_di <= {16{1'bX}}; // don't care what to drive + else begin + // + if (eim_fsm_state == EIM_FSM_STATE_READ_LSB) + da_di <= eim_user_data[15: 0]; // drive lower 16 bits at first... + if (eim_fsm_state == EIM_FSM_STATE_READ_MSB) + da_di <= eim_user_data[31:16]; // ...then drive upper 16 bits + // + end + + + // + // Wait Logic + // + + /* Note that this stuff operates on falling clock edge, because the cpu + * samples our WAIT_N flag on rising clock edge. + */ + + reg eim_wait_reg = 1'b0; + + always @(negedge eim_bclk or posedge eim_cs0_n) + // + if (eim_cs0_n == 1'b1) + eim_wait_reg <= 1'b0; // clear wait + else begin + // + if (eim_fsm_state == EIM_FSM_STATE_WRITE_START) + eim_wait_reg <= 1'b1; // start waiting for write to complete + if (eim_fsm_state == EIM_FSM_STATE_READ_START) + eim_wait_reg <= 1'b1; // start waiting for read to complete + // + if (eim_fsm_state == EIM_FSM_STATE_WRITE_DONE) + eim_wait_reg <= 1'b0; // write transaction done + if (eim_fsm_state == EIM_FSM_STATE_READ_READY) + eim_wait_reg <= 1'b0; // read transaction done + // + if (eim_fsm_state == EIM_FSM_STATE_INIT) + eim_wait_reg <= 1'b0; // fsm is idle, no need to wait any more + // + end + + assign eim_wait_n = ~eim_wait_reg; + + + /* These flags are used to generate 1-cycle pulses to trigger CDC + * transaction. Note that FSM goes from WRITE_LSB to WRITE_MSB and from + * READ_START 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 = (eim_fsm_state == EIM_FSM_STATE_WRITE_LSB) ? 1'b1 : 1'b0; + wire arbiter_read_req_pulse = (eim_fsm_state == EIM_FSM_STATE_READ_START) ? 1'b1 : 1'b0; + + // + // CDC Block + // + + /* 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+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 + ( + .eim_clk(eim_bclk), + + .eim_req(arbiter_write_req_pulse | arbiter_read_req_pulse), + .eim_ack(eim_user_ack), + + .eim_din({arbiter_write_req_pulse, arbiter_read_req_pulse, + eim_addr_latch, da_ro, eim_write_lsb_latch}), + .eim_dout(eim_user_data), + + .sys_clk(sys_clk), + .sys_addr(sys_addr), + .sys_wren(sys_wren), + .sys_data_out(sys_data_out), + .sys_rden(sys_rden), + .sys_data_in(sys_data_in) + ); endmodule diff --git a/rtl/src/verilog/eim_arbiter_cdc.v b/rtl/src/verilog/eim_arbiter_cdc.v index a0412fe..15dc433 100644 --- a/rtl/src/verilog/eim_arbiter_cdc.v +++ b/rtl/src/verilog/eim_arbiter_cdc.v @@ -7,7 +7,7 @@ // // // Author: Pavel Shatov -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -38,107 +38,103 @@ //====================================================================== module eim_arbiter_cdc - ( - eim_clk, eim_req, eim_ack, eim_din, eim_dout, - sys_clk, sys_addr, - sys_wren, sys_data_out, - sys_rden, sys_data_in - ); - - - input wire eim_clk; // eim clock - input wire eim_req; // eim transaction request - output wire eim_ack; // eim transaction acknowledge - 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 [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 - input wire [31: 0] sys_data_in; // user read data - - - // - // EIM_CLK -> SYS_CLK Request - // - wire sys_req; // request pulse in sys_clk clock domain - wire [50: 0] sys_dout; // transaction data in sys_clk clock domain - - cdc_bus_pulse # - ( - .DATA_WIDTH (51) // {write, read, msb addr, lsb addr, data} - ) - cdc_eim_sys - ( - .src_clk (eim_clk), - .src_din (eim_din), - .src_req (eim_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 [16: 0] sys_addr_reg = {17{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) begin // request detected? - 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 - end else begin // no request active - sys_wren_reg <= 1'b0; // clear write flag - sys_rden_reg <= 1'b0; // clear read flag - end - - - // - // System Request 2-cycle delay to compensate registered mux delay in user-side logic - // - reg [ 1: 0] sys_req_dly = 2'b00; - - always @(posedge sys_clk) - sys_req_dly <= {sys_req_dly[0], sys_req}; - - - // - // SYS_CLK -> EIM_CLK Acknowledge - // - cdc_bus_pulse # - ( - .DATA_WIDTH (32) // {data} - ) - cdc_sys_eim - ( - .src_clk (sys_clk), - .src_din (sys_data_in), - .src_req (sys_req_dly[1]), - - .dst_clk (eim_clk), - .dst_dout (eim_dout), - .dst_pulse (eim_ack) - ); - + ( + input wire eim_clk, // eim clock + input wire eim_req, // eim transaction request + output wire eim_ack, // eim transaction acknowledge + 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 [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 + input wire [31: 0] sys_data_in // user read data + ); + + + // + // EIM_CLK -> SYS_CLK Request + // + wire sys_req; // request pulse in sys_clk clock domain + wire [50: 0] sys_dout; // transaction data in sys_clk clock domain + + cdc_bus_pulse # + ( + .DATA_WIDTH(51) // {write, read, msb addr, lsb addr, data} + ) + cdc_eim_sys + ( + .src_clk(eim_clk), + .src_din(eim_din), + .src_req(eim_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 [16: 0] sys_addr_reg = {17{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[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 + 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 2-cycle delay to compensate registered mux delay in user-side logic + // + reg [ 1: 0] sys_req_dly = 2'b00; + + always @(posedge sys_clk) + sys_req_dly <= {sys_req_dly[0], sys_req}; + + + // + // SYS_CLK -> EIM_CLK Acknowledge + // + cdc_bus_pulse # + ( + .DATA_WIDTH(32) + ) + cdc_sys_eim + ( + .src_clk(sys_clk), + .src_din(sys_data_in), + .src_req(sys_req_dly[1]), + + .dst_clk(eim_clk), + .dst_dout(eim_dout), + .dst_pulse(eim_ack) + ); endmodule diff --git a/rtl/src/verilog/eim_da_phy.v b/rtl/src/verilog/eim_da_phy.v index 9ef6042..8a4a8d7 100644 --- a/rtl/src/verilog/eim_da_phy.v +++ b/rtl/src/verilog/eim_da_phy.v @@ -6,7 +6,7 @@ // // // Author: Pavel Shatov -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -37,48 +37,38 @@ //====================================================================== module eim_da_phy - ( - buf_io, - buf_di, buf_ro, - buf_t - ); + #(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) + ); - // - // Parameters - // - parameter BUS_WIDTH = 16; - - // - // Ports - // - 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 {CNT_BITS{1'b0}}) cnt <= cnt - 1'b1; + else if (eim_active) cnt <= {CNT_BITS{1'b1}}; - 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 (eim_active) cnt <= {CNT_BITS{1'b1}}; - - assign led_out = ~cnt[CNT_BITS-1]; + assign led_out = ~cnt[CNT_BITS-1]; endmodule diff --git a/rtl/src/verilog/eim_memory.v b/rtl/src/verilog/eim_memory.v index 5258376..c570ee6 100644 --- a/rtl/src/verilog/eim_memory.v +++ b/rtl/src/verilog/eim_memory.v @@ -37,146 +37,146 @@ // 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, +//====================================================================== + +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 - 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_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_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_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_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_write_data(sys_write_data), + .sys_read_data(segment_ciphers_read_data) // output from CIPHERS segment + ); + + +endmodule - .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 cc9e5e7..3499fa3 100644 --- a/rtl/src/verilog/novena_baseline_top.v +++ b/rtl/src/verilog/novena_baseline_top.v @@ -8,7 +8,7 @@ // // // Author: Pavel Shatov -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -39,147 +39,147 @@ //====================================================================== module novena_baseline_top - ( - // Differential input for 50 MHz general clock. - input wire gclk_p_pin, - input wire gclk_n_pin, - - // Reset controlled by the CPU. - // this must be configured as input w/pullup - input wire reset_mcu_b_pin, - - // Cryptech avalanche noise board input and LED outputs - 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. - 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). - output wire eim_wait_n, // Data wait signal (active low). - - // Novena utility ports - apoptosis_pin, // Hold low to not restart after config. - led_pin // LED on edge close to the FPGA. - ); - - - //---------------------------------------------------------------- - // Clock Manager - // - // Clock manager is used to buffer BCLK, generate SYS_CLK - // from GCLK and implement the reset logic. - //---------------------------------------------------------------- - wire sys_clk; - wire sys_rst; - wire eim_bclk_buf; - - novena_clkmgr clkmgr - ( - .gclk_p(gclk_p_pin), - .gclk_n(gclk_n_pin), - - .reset_mcu_b(reset_mcu_b_pin), - - .sys_clk(sys_clk), - .sys_rst(sys_rst), - - .bclk_in(eim_bclk), - .bclk_out(eim_bclk_buf) - ); - - - //---------------------------------------------------------------- - // EIM Arbiter - // - // EIM arbiter handles EIM access and transfers it into - // `sys_clk' clock domain. - //---------------------------------------------------------------- - wire [16: 0] sys_eim_addr; - wire sys_eim_wr; - wire sys_eim_rd; - wire [31: 0] sys_eim_dout; - wire [31: 0] sys_eim_din; - - eim_arbiter eim - ( - .eim_bclk(eim_bclk_buf), - .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), - - .sys_clk(sys_clk), - - .sys_addr(sys_eim_addr), - .sys_wren(sys_eim_wr), - .sys_data_out(sys_eim_dout), - .sys_rden(sys_eim_rd), - .sys_data_in(sys_eim_din) - ); - - - //---------------------------------------------------------------- - // Memory Mapper - // - // 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), - - .sys_write_data(sys_eim_dout), - .sys_read_data(sys_eim_din) - ); - - - //---------------------------------------------------------------- - // LED Driver - // - // A simple utility LED driver that turns on the Novena - // board LED when the EIM interface is active. - //---------------------------------------------------------------- - eim_indicator led - ( - .sys_clk(sys_clk), - .sys_rst(sys_rst), - .eim_active(sys_eim_wr | sys_eim_rd), - .led_out(led_pin) - ); - - - //---------------------------------------------------------------- - // Cryptech Logic - // - // Logic specific to the Cryptech use of the Novena. - // Currently we just hard wire the LED outputs. - //---------------------------------------------------------------- - assign ct_led = {8{ct_noise}}; - - - //---------------------------------------------------------------- - // Novena Patch - // - // Patch logic to keep the Novena 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; - + ( + // Differential input for 50 MHz general clock. + input wire gclk_p_pin, + input wire gclk_n_pin, + + // Reset controlled by the CPU. + // this must be configured as input w/pullup + input wire reset_mcu_b_pin, + + // Cryptech avalanche noise board input and LED outputs + input wire ct_noise, + output wire [7 : 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. + 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). + output wire eim_wait_n, // Data wait signal (active low). + + // Novena utility ports + apoptosis_pin, // Hold low to not restart after config. + led_pin // LED on edge close to the FPGA. + ); + + + //---------------------------------------------------------------- + // Clock Manager + // + // Clock manager is used to buffer BCLK, generate SYS_CLK + // from GCLK and implement the reset logic. + //---------------------------------------------------------------- + wire sys_clk; + wire sys_rst; + wire eim_bclk_buf; + + novena_clkmgr clkmgr + ( + .gclk_p(gclk_p_pin), + .gclk_n(gclk_n_pin), + + .reset_mcu_b(reset_mcu_b_pin), + + .sys_clk(sys_clk), + .sys_rst(sys_rst), + + .bclk_in(eim_bclk), + .bclk_out(eim_bclk_buf) + ); + + + //---------------------------------------------------------------- + // EIM Arbiter + // + // EIM arbiter handles EIM access and transfers it into + // `sys_clk' clock domain. + //---------------------------------------------------------------- + wire [16: 0] sys_eim_addr; + wire sys_eim_wr; + wire sys_eim_rd; + wire [31: 0] sys_eim_dout; + wire [31: 0] sys_eim_din; + + eim_arbiter eim + ( + .eim_bclk(eim_bclk_buf), + .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), + + .sys_clk(sys_clk), + + .sys_addr(sys_eim_addr), + .sys_wren(sys_eim_wr), + .sys_data_out(sys_eim_dout), + .sys_rden(sys_eim_rd), + .sys_data_in(sys_eim_din) + ); + + + //---------------------------------------------------------------- + // Memory Mapper + // + // 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), + + .sys_write_data(sys_eim_dout), + .sys_read_data(sys_eim_din) + ); + + + //---------------------------------------------------------------- + // LED Driver + // + // A simple utility LED driver that turns on the Novena + // board LED when the EIM interface is active. + //---------------------------------------------------------------- + eim_indicator led + ( + .sys_clk(sys_clk), + .sys_rst(sys_rst), + .eim_active(sys_eim_wr | sys_eim_rd), + .led_out(led_pin) + ); + + + //---------------------------------------------------------------- + // Cryptech Logic + // + // Logic specific to the Cryptech use of the Novena. + // Currently we just hard wire the LED outputs. + //---------------------------------------------------------------- + assign ct_led = {8{ct_noise}}; + + + //---------------------------------------------------------------- + // Novena Patch + // + // Patch logic to keep the Novena 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/src/verilog/novena_clkmgr.v b/rtl/src/verilog/novena_clkmgr.v index c68cb43..00b2e5b 100644 --- a/rtl/src/verilog/novena_clkmgr.v +++ b/rtl/src/verilog/novena_clkmgr.v @@ -7,7 +7,7 @@ // // // Author: Pavel Shatov -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -38,100 +38,102 @@ //====================================================================== module novena_clkmgr - ( - gclk_p, gclk_n, - reset_mcu_b, - sys_clk, sys_rst, - bclk_in, bclk_out - ); + ( + input wire gclk_p, // signal from clock pins + input wire gclk_n, // - // - // Ports - // - input wire gclk_p; // signal from clock pins - input wire gclk_n; // + input wire reset_mcu_b, // cpu reset (async) - input wire reset_mcu_b; // cpu reset (async) + output wire sys_clk, // buffered system clock output + output wire sys_rst, // system reset output (sync) - output wire sys_clk; // buffered system clock output - output wire sys_rst; // system reset output (sync) + input wire bclk_in, // signal from clock pin + output wire bclk_out // buffered clock output + ); - input wire bclk_in; // signal from clock pin - output wire bclk_out; // buffered clock output + // + // Ports + // - // - // IBUFGDS - // - (* BUFFER_TYPE="NONE" *) - wire gclk; + // + // IBUFGDS + // + (* BUFFER_TYPE="NONE" *) + wire gclk; - IBUFGDS IBUFGDS_gclk - ( - .I (gclk_p), - .IB (gclk_n), - .O (gclk) - ); + IBUFGDS IBUFGDS_gclk + ( + .I(gclk_p), + .IB(gclk_n), + .O(gclk) + ); - // - // DCM - // - wire dcm_reset; // dcm reset - wire dcm_locked; // output clock valid - wire gclk_missing; // no input clock + // + // DCM + // + wire dcm_reset; // dcm reset + wire dcm_locked; // output clock valid + wire gclk_missing; // no input clock - clkmgr_dcm dcm - ( - .CLK_IN1 (gclk), - .RESET (dcm_reset), - .INPUT_CLK_STOPPED (gclk_missing), + clkmgr_dcm dcm + ( + .CLK_IN1(gclk), + .RESET(dcm_reset), + .INPUT_CLK_STOPPED(gclk_missing), - .CLK_OUT1 (sys_clk), - .CLK_VALID (dcm_locked) - ); + .CLK_OUT1(sys_clk), + .CLK_VALID(dcm_locked) + ); - // - // DCM Reset Logic - // + // + // DCM Reset Logic + // - /* DCM should be reset on power-up, when input clock is stopped or when the CPU gets reset. */ + /* DCM should be reset on power-up, when input clock is stopped or when the + * CPU gets reset. + */ - reg [15: 0] dcm_rst_shreg = {16{1'b1}}; // 16-bit shift register + 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}; + 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]; + assign dcm_reset = dcm_rst_shreg[15]; - // - // System Reset Logic - // + // + // System Reset Logic + // - /* System reset is asserted for 16 cycles whenever DCM aquires lock. */ + /* System reset is asserted for 16 cycles whenever DCM aquires lock. */ - reg [15: 0] sys_rst_shreg = {16{1'b1}}; // 16-bit shift register + reg [15: 0] sys_rst_shreg = {16{1'b1}}; // 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'b1}}; - else if (dcm_locked == 1'b1) sys_rst_shreg <= {sys_rst_shreg[14:0], 1'b0}; + 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'b1}}; + else if (dcm_locked == 1'b1) + sys_rst_shreg <= {sys_rst_shreg[14:0], 1'b0}; - assign sys_rst = sys_rst_shreg[15]; + assign sys_rst = sys_rst_shreg[15]; - // - // BCLK BUFG - // - BUFG BUFG_BCLK - ( - .I (bclk_in), - .O (bclk_out) - ); + // + // BCLK BUFG + // + BUFG BUFG_BCLK + ( + .I(bclk_in), + .O(bclk_out) + ); endmodule diff --git a/rtl/src/verilog/novena_regs.v b/rtl/src/verilog/novena_regs.v index 88b35ab..7341092 100644 --- a/rtl/src/verilog/novena_regs.v +++ b/rtl/src/verilog/novena_regs.v @@ -1,80 +1,126 @@ -`timescale 1ns / 1ps - -module novena_regs - ( - input wire clk, - input wire rst, +//====================================================================== +// +// novena_regs.v +// ------------- +// Global registers 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. +// +//====================================================================== - input wire cs, - input wire we, +`timescale 1ns / 1ps - 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 +module novena_regs + ( + input wire clk, + input wire rst, + input wire cs, + input wire we, - // - // 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 + 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 + endcase + // + end + // + end + +endmodule + +//====================================================================== +// EOF novena_regs.v +//====================================================================== diff --git a/rtl/src/verilog/rng_selector.v b/rtl/src/verilog/rng_selector.v index 7a1fe7c..f86b3e9 100644 --- a/rtl/src/verilog/rng_selector.v +++ b/rtl/src/verilog/rng_selector.v @@ -40,72 +40,70 @@ //====================================================================== module rng_selector - ( - input wire sys_clk, - input wire sys_rst, - input wire sys_ena, + ( + 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 + 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 + endcase + // + end + // + end endmodule diff --git a/rtl/src/verilog/sha1.v b/rtl/src/verilog/sha1.v index 2595132..d0b4a4e 100644 --- a/rtl/src/verilog/sha1.v +++ b/rtl/src/verilog/sha1.v @@ -6,7 +6,7 @@ // a simple memory like interface with 32 bit data access. // // Authors: Joachim Strömbergson, Paul Selkirk -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -38,15 +38,15 @@ module sha1( // Clock and reset. - input wire clk, - input wire reset_n, + input wire clk, + input wire reset_n, // Control. - input wire cs, - input wire we, + input wire cs, + input wire we, // Data ports. - input wire [7 : 0] address, + input wire [7 : 0] address, input wire [31 : 0] write_data, output wire [31 : 0] read_data ); @@ -87,8 +87,8 @@ module sha1( reg init_reg; reg next_reg; - reg [31 : 0] tmp_read_data; - reg [31 : 0] tmp_read_data_reg; + reg [31 : 0] tmp_read_data; + reg [31 : 0] tmp_read_data_reg; //---------------------------------------------------------------- // Wires. @@ -150,55 +150,55 @@ module sha1( //---------------------------------------------------------------- always @(posedge clk) begin - init_reg <= 0; - next_reg <= 0; - - if (cs && we) - begin - // write operations - if ((address >= ADDR_BLOCK) && - (address < ADDR_BLOCK + BLOCK_WORDS)) - block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; - else if (address == ADDR_CTRL) - begin - init_reg <= write_data[CTRL_INIT_BIT]; - next_reg <= write_data[CTRL_NEXT_BIT]; - end - end + init_reg <= 0; + next_reg <= 0; + + if (cs && we) + begin + // write operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; + else if (address == ADDR_CTRL) + begin + init_reg <= write_data[CTRL_INIT_BIT]; + next_reg <= write_data[CTRL_NEXT_BIT]; + end + end end always @* begin - tmp_read_data = 32'h00000000; - - if (cs && !we) - begin - // read operations - if ((address >= ADDR_BLOCK) && - (address < ADDR_BLOCK + BLOCK_WORDS)) - tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; - else if ((address >= ADDR_DIGEST) && - (address < ADDR_DIGEST + DIGEST_WORDS)) - tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; - else - case (address) - ADDR_NAME0: - tmp_read_data = core_name0; - ADDR_NAME1: - tmp_read_data = core_name1; - ADDR_VERSION: - tmp_read_data = core_version; - ADDR_CTRL: - tmp_read_data = core_ctrl; - ADDR_STATUS: - tmp_read_data = core_status; - endcase - end + tmp_read_data = 32'h00000000; + + if (cs && !we) + begin + // read operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; + else if ((address >= ADDR_DIGEST) && + (address < ADDR_DIGEST + DIGEST_WORDS)) + tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; + else + case (address) + ADDR_NAME0: + tmp_read_data = core_name0; + ADDR_NAME1: + tmp_read_data = core_name1; + ADDR_VERSION: + tmp_read_data = core_version; + ADDR_CTRL: + tmp_read_data = core_ctrl; + ADDR_STATUS: + tmp_read_data = core_status; + endcase + end end always @(posedge clk) begin - tmp_read_data_reg <= tmp_read_data; + tmp_read_data_reg <= tmp_read_data; end endmodule // sha1 diff --git a/rtl/src/verilog/sha256.v b/rtl/src/verilog/sha256.v index d6fb133..04048b1 100644 --- a/rtl/src/verilog/sha256.v +++ b/rtl/src/verilog/sha256.v @@ -6,7 +6,7 @@ // a simple memory like interface with 32 bit data access. // // Authors: Joachim Strömbergson, Paul Selkirk -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -38,15 +38,15 @@ module sha256( // Clock and reset. - input wire clk, - input wire reset_n, + input wire clk, + input wire reset_n, // Control. - input wire cs, - input wire we, + input wire cs, + input wire we, // Data ports. - input wire [7 : 0] address, + input wire [7 : 0] address, input wire [31 : 0] write_data, output wire [31 : 0] read_data ); @@ -87,8 +87,8 @@ module sha256( reg init_reg; reg next_reg; - reg [31 : 0] tmp_read_data; - reg [31 : 0] tmp_read_data_reg; + reg [31 : 0] tmp_read_data; + reg [31 : 0] tmp_read_data_reg; //---------------------------------------------------------------- // Wires. @@ -150,55 +150,55 @@ module sha256( //---------------------------------------------------------------- always @(posedge clk) begin - init_reg <= 0; - next_reg <= 0; - - if (cs && we) - begin - // write operations - if ((address >= ADDR_BLOCK) && - (address < ADDR_BLOCK + BLOCK_WORDS)) - block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; - else if (address == ADDR_CTRL) - begin - init_reg <= write_data[CTRL_INIT_BIT]; - next_reg <= write_data[CTRL_NEXT_BIT]; - end - end + init_reg <= 0; + next_reg <= 0; + + if (cs && we) + begin + // write operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; + else if (address == ADDR_CTRL) + begin + init_reg <= write_data[CTRL_INIT_BIT]; + next_reg <= write_data[CTRL_NEXT_BIT]; + end + end end always @* begin - tmp_read_data = 32'h00000000; - - if (cs && !we) - begin - // read operations - if ((address >= ADDR_BLOCK) && - (address < ADDR_BLOCK + BLOCK_WORDS)) - tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; - else if ((address >= ADDR_DIGEST) && - (address < ADDR_DIGEST + DIGEST_WORDS)) - tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; - else - case (address) - ADDR_NAME0: - tmp_read_data = core_name0; - ADDR_NAME1: - tmp_read_data = core_name1; - ADDR_VERSION: - tmp_read_data = core_version; - ADDR_CTRL: - tmp_read_data = core_ctrl; - ADDR_STATUS: - tmp_read_data = core_status; - endcase - end + tmp_read_data = 32'h00000000; + + if (cs && !we) + begin + // read operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; + else if ((address >= ADDR_DIGEST) && + (address < ADDR_DIGEST + DIGEST_WORDS)) + tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; + else + case (address) + ADDR_NAME0: + tmp_read_data = core_name0; + ADDR_NAME1: + tmp_read_data = core_name1; + ADDR_VERSION: + tmp_read_data = core_version; + ADDR_CTRL: + tmp_read_data = core_ctrl; + ADDR_STATUS: + tmp_read_data = core_status; + endcase + end end always @(posedge clk) begin - tmp_read_data_reg <= tmp_read_data; + tmp_read_data_reg <= tmp_read_data; end endmodule // sha256 diff --git a/rtl/src/verilog/sha512.v b/rtl/src/verilog/sha512.v index 4d2a9e7..8826782 100644 --- a/rtl/src/verilog/sha512.v +++ b/rtl/src/verilog/sha512.v @@ -6,7 +6,7 @@ // a simple memory like interface with 32 bit data access. // // Authors: Joachim Strömbergson, Paul Selkirk -// Copyright (c) 2014, NORDUnet A/S All rights reserved. +// 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 @@ -38,15 +38,15 @@ module sha512( // Clock and reset. - input wire clk, - input wire reset_n, + input wire clk, + input wire reset_n, // Control. - input wire cs, - input wire we, + input wire cs, + input wire we, // Data ports. - input wire [7 : 0] address, + input wire [7 : 0] address, input wire [31 : 0] write_data, output wire [31 : 0] read_data ); @@ -98,12 +98,12 @@ module sha512( reg [0 : DIGEST_BITS - 1] digest_reg; reg init_reg; reg next_reg; - reg [1 : 0] mode_reg; - reg work_factor_reg; - reg [31 : 0] work_factor_num_reg; + reg [1 : 0] mode_reg; + reg work_factor_reg; + reg [31 : 0] work_factor_num_reg; - reg [31 : 0] tmp_read_data; - reg [31 : 0] tmp_read_data_reg; + reg [31 : 0] tmp_read_data; + reg [31 : 0] tmp_read_data_reg; //---------------------------------------------------------------- // Wires. @@ -111,9 +111,9 @@ module sha512( wire core_init; wire core_next; wire core_ready; - wire [1 : 0] core_mode; - wire core_work_factor; - wire [31 : 0] core_work_factor_num; + wire [1 : 0] core_mode; + wire core_work_factor; + wire [31 : 0] core_work_factor_num; wire [0 : BLOCK_BITS - 1] core_block; wire [0 : DIGEST_BITS - 1] core_digest; wire core_digest_valid; @@ -176,66 +176,66 @@ module sha512( //---------------------------------------------------------------- always @(posedge clk) begin - init_reg <= 0; - next_reg <= 0; + init_reg <= 0; + next_reg <= 0; mode_reg <= MODE_SHA_512; work_factor_reg <= 0; work_factor_num_reg <= DEFAULT_WORK_FACTOR_NUM; - if (cs && we) - begin - // write operations - if ((address >= ADDR_BLOCK) && - (address < ADDR_BLOCK + BLOCK_WORDS)) - block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; - else if (address == ADDR_CTRL) - begin - init_reg <= write_data[CTRL_INIT_BIT]; - next_reg <= write_data[CTRL_NEXT_BIT]; + if (cs && we) + begin + // write operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data; + else if (address == ADDR_CTRL) + begin + init_reg <= write_data[CTRL_INIT_BIT]; + next_reg <= write_data[CTRL_NEXT_BIT]; mode_reg <= write_data[CTRL_MODE_HIGH_BIT : CTRL_MODE_LOW_BIT]; work_factor_reg <= write_data[CTRL_WORK_FACTOR_BIT]; - end - else if (address == ADDR_WORK_FACTOR_NUM) - begin - work_factor_num_reg <= write_data; - end - end + end + else if (address == ADDR_WORK_FACTOR_NUM) + begin + work_factor_num_reg <= write_data; + end + end end always @* begin - tmp_read_data = 32'h00000000; - - if (cs && !we) - begin - // read operations - if ((address >= ADDR_BLOCK) && - (address < ADDR_BLOCK + BLOCK_WORDS)) - tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; - else if ((address >= ADDR_DIGEST) && - (address < ADDR_DIGEST + DIGEST_WORDS)) - tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; - else - case (address) - ADDR_NAME0: - tmp_read_data = core_name0; - ADDR_NAME1: - tmp_read_data = core_name1; - ADDR_VERSION: - tmp_read_data = core_version; - ADDR_CTRL: - tmp_read_data = core_ctrl; - ADDR_STATUS: - tmp_read_data = core_status; + tmp_read_data = 32'h00000000; + + if (cs && !we) + begin + // read operations + if ((address >= ADDR_BLOCK) && + (address < ADDR_BLOCK + BLOCK_WORDS)) + tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32]; + else if ((address >= ADDR_DIGEST) && + (address < ADDR_DIGEST + DIGEST_WORDS)) + tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32]; + else + case (address) + ADDR_NAME0: + tmp_read_data = core_name0; + ADDR_NAME1: + tmp_read_data = core_name1; + ADDR_VERSION: + tmp_read_data = core_version; + ADDR_CTRL: + tmp_read_data = core_ctrl; + ADDR_STATUS: + tmp_read_data = core_status; ADDR_WORK_FACTOR_NUM: tmp_read_data = work_factor_num_reg; - endcase - end + endcase + end end always @(posedge clk) begin - tmp_read_data_reg <= tmp_read_data; + tmp_read_data_reg <= tmp_read_data; end endmodule // sha512 -- cgit v1.2.3