//====================================================================== // // Copyright (c) 2019, 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 modexpng_wrapper ( input clk, input rst_n, input clk_core, input cs, input we, input [11:0] address, input [31:0] write_data, output [31:0] read_data ); // // Headers // `include "modexpng_parameters.vh" // // Address Decoder // localparam ADDR_MSB_WRAP = 2'b00; wire [1:0] addr_msb = address[11:10]; wire [9:0] addr_lsb = address[ 9: 0]; wire addr_msb_is_wrap = addr_msb == ADDR_MSB_WRAP; // // Register Addresses // localparam ADDR_NAME0 = 10'h000; localparam ADDR_NAME1 = 10'h001; localparam ADDR_VERSION = 10'h002; localparam ADDR_CONTROL = 10'h008; // {next, init} localparam ADDR_STATUS = 10'h009; // {valid, ready} localparam ADDR_MODE = 10'h010; // {crt, dummy} localparam ADDR_MODULUS_BITS = 10'h011; // number of bits in modulus localparam ADDR_EXPONENT_BITS = 10'h012; // number of bits in exponent localparam ADDR_BANK_BITS = 10'h013; // largest supported number of bits localparam ADDR_NUM_MULTS = 10'h014; // number of parallel multipliers // // Register Bits // // localparam CONTROL_INIT_BIT = 0; -- not used localparam CONTROL_NEXT_BIT = 1; // localparam STATUS_READY_BIT = 0; -- hardcoded to always read 1 localparam STATUS_VALID_BIT = 1; // localparam MODE_FASTUNSAFE_BIT = 0; - not used localparam MODE_FULLCRT_BIT = 1; // // Default Values // `define MODEXPNG_DEFAULT_NAME0 32'h6D6F6465 // "mode" `define MODEXPNG_DEFAULT_NAME1 32'h78706E67 // "xpng" `define MODEXPNG_DEFAULT_VERSION 32'h302E3231 // "0.21" `define MODEXPNG_DEFAULT_CONTROL 1'b0 `define MODEXPNG_DEFAULT_MODE 1'b0 `define MODEXPNG_DEFAULT_MODULUS_BITS 13'd1024 `define MODEXPNG_DEFAULT_EXPONENT_BITS 13'd17 // // Handy Values // localparam MIN_OP_W = 2 * NUM_MULTS * WORD_W * 2; localparam MIN_EXP_W = 2 * 2; localparam LSB_BIT_INDEX_W = 1 + cryptech_clog2(NUM_MULTS) + cryptech_clog2(WORD_W); localparam MSB_BIT_INDEX_W = BIT_INDEX_W - LSB_BIT_INDEX_W; // // Register Values // localparam CORE_NAME0 = `MODEXPNG_DEFAULT_NAME0; localparam CORE_NAME1 = `MODEXPNG_DEFAULT_NAME1; localparam CORE_VERSION = `MODEXPNG_DEFAULT_VERSION; // // Registers // reg wrap_reg_control = `MODEXPNG_DEFAULT_CONTROL; reg core_reg_control = `MODEXPNG_DEFAULT_CONTROL; reg wrap_reg_mode = `MODEXPNG_DEFAULT_MODE; reg sync_reg_mode; reg core_reg_mode; reg [BIT_INDEX_W:LSB_BIT_INDEX_W] wrap_modulus_bits_msb; reg [BIT_INDEX_W: 0] wrap_exponent_bits; initial update_modulus_bits_user; initial update_exponent_bits_user; //wire sync_reg_control_rising = sync_reg_control & ~sync_reg_control_dly; // // Wires // reg wrap_reg_status = 1'b1; reg sync_reg_status = 1'b1; reg sync_reg_status_dly = 1'b1; wire core_reg_status; // // Output Mux // reg [31: 0] wrap_read_data; wire [31: 0] core_read_data; // // Reset Resync // wire core_rst_n; reg [15: 0] core_rst_shreg = {16{1'b0}}; always @(posedge clk_core or negedge rst_n) // if (!rst_n) core_rst_shreg <= {16{1'b0}}; else core_rst_shreg <= {core_rst_shreg[14:0], 1'b1}; assign core_rst_n = core_rst_shreg[15]; // // Trigger Logic // reg wrap_reg_control_dly = `MODEXPNG_DEFAULT_CONTROL; reg wrap_reg_control_posedge = 1'b0; reg sync_reg_control_posedge = 1'b0; reg core_reg_control_posedge = 1'b0; reg core_reg_control_posedge_dly = 1'b0; reg sync_reg_control_posedge_ack = 1'b0; reg wrap_reg_control_posedge_ack = 1'b0; always @(posedge clk or negedge rst_n) if (!rst_n) wrap_reg_control_dly <= `MODEXPNG_DEFAULT_CONTROL; else wrap_reg_control_dly <= wrap_reg_control; always @(posedge clk or negedge rst_n) if (!rst_n) wrap_reg_control_posedge <= 1'b0; else begin if (!wrap_reg_control_posedge) begin if (wrap_reg_control && !wrap_reg_control_dly) wrap_reg_control_posedge <= 1'b1; end else begin if (wrap_reg_control_posedge_ack) wrap_reg_control_posedge <= 1'b0; end end always @(posedge clk_core or negedge core_rst_n) if (!core_rst_n) sync_reg_control_posedge <= 1'b0; else sync_reg_control_posedge <= wrap_reg_control_posedge; always @(posedge clk_core or negedge core_rst_n) if (!core_rst_n) core_reg_control_posedge <= 1'b0; else core_reg_control_posedge <= sync_reg_control_posedge; always @(posedge clk_core or negedge core_rst_n) if (!core_rst_n) core_reg_control_posedge_dly <= 1'b0; else core_reg_control_posedge_dly <= core_reg_control_posedge; always @(posedge clk or negedge rst_n) if (!rst_n) sync_reg_control_posedge_ack <= 1'b0; else sync_reg_control_posedge_ack <= core_reg_control_posedge; always @(posedge clk or negedge rst_n) if (!rst_n) wrap_reg_control_posedge_ack <= 1'b0; else wrap_reg_control_posedge_ack <= sync_reg_control_posedge_ack; always @(posedge clk_core or negedge core_rst_n) if (!core_rst_n) core_reg_control <= `MODEXPNG_DEFAULT_CONTROL; else core_reg_control <= core_reg_control_posedge && !core_reg_control_posedge_dly; always @(posedge clk or negedge rst_n) if (!rst_n) sync_reg_status <= 1'b1; else sync_reg_status <= core_reg_status; always @(posedge clk or negedge rst_n) if (!rst_n) sync_reg_status_dly <= 1'b1; else sync_reg_status_dly <= sync_reg_status; always @(posedge clk or negedge rst_n) if (!rst_n) wrap_reg_status <= 1'b1; else begin if (wrap_reg_status) begin if (wrap_reg_control && !wrap_reg_control_dly) wrap_reg_status <= 1'b0; end else begin if (!wrap_reg_control_posedge && !wrap_reg_control_posedge_ack && sync_reg_status_dly) wrap_reg_status <= 1'b1; end end // // Parameters Resync // reg [OP_ADDR_W -1:0] wrap_word_index_last_n; reg [OP_ADDR_W -1:0] wrap_word_index_last_pq; reg [BIT_INDEX_W -1:0] wrap_bit_index_last_n; reg [BIT_INDEX_W -1:0] wrap_bit_index_last_pq; reg [OP_ADDR_W -1:0] sync_word_index_last_n; reg [OP_ADDR_W -1:0] sync_word_index_last_pq; reg [BIT_INDEX_W -1:0] sync_bit_index_last_n; reg [BIT_INDEX_W -1:0] sync_bit_index_last_pq; reg [OP_ADDR_W -1:0] core_word_index_last_n; reg [OP_ADDR_W -1:0] core_word_index_last_pq; reg [BIT_INDEX_W -1:0] core_bit_index_last_n; reg [BIT_INDEX_W -1:0] core_bit_index_last_pq; always @(posedge clk_core) begin // sync_reg_mode <= wrap_reg_mode; // sync_word_index_last_n <= wrap_word_index_last_n; sync_word_index_last_pq <= wrap_word_index_last_pq; // sync_bit_index_last_n <= wrap_bit_index_last_n; sync_bit_index_last_pq <= wrap_bit_index_last_pq; // end always @(posedge clk_core) // if (core_reg_control_posedge && !core_reg_control_posedge_dly) begin // core_reg_mode <= sync_reg_mode; // core_word_index_last_n <= sync_word_index_last_n; core_word_index_last_pq <= sync_word_index_last_pq; // core_bit_index_last_n <= sync_bit_index_last_n; core_bit_index_last_pq <= sync_bit_index_last_pq; // end // // ModExpNG // modexpng_core_top modexpng ( .clk (clk_core), .clk_bus (clk), .rst_n (core_rst_n), .next (core_reg_control), .valid (core_reg_status), .crt_mode (core_reg_mode), .word_index_last_n (core_word_index_last_n), .word_index_last_pq (core_word_index_last_pq), .bit_index_last_n (core_bit_index_last_n), .bit_index_last_pq (core_bit_index_last_pq), .bus_cs (cs), .bus_we (we), .bus_addr (address), .bus_data_wr (write_data), .bus_data_rd (core_read_data) ); // // Write Interface // wire [ BIT_INDEX_W :0] corrected_modulus_bits_user = correct_modulus_bits(write_data[BIT_INDEX_W:0]); wire [MSB_BIT_INDEX_W :0] corrected_modulus_bits_msb_user = corrected_modulus_bits_user[BIT_INDEX_W:LSB_BIT_INDEX_W]; wire [ OP_ADDR_W :0] modulus_num_words_n_user = {corrected_modulus_bits_msb_user, {(LSB_BIT_INDEX_W-WORD_MUX_W){1'b0}}} - 1'b1; wire [ OP_ADDR_W-1:0] modulus_num_words_n_lsb_user = modulus_num_words_n_user[OP_ADDR_W-1:0]; wire [ OP_ADDR_W-1:0] modulus_num_words_pq_user = {corrected_modulus_bits_msb_user, {(LSB_BIT_INDEX_W-WORD_MUX_W-1){1'b0}}} - 1'b1; wire [ BIT_INDEX_W :0] corrected_modulus_bits_default = `MODEXPNG_DEFAULT_MODULUS_BITS; wire [MSB_BIT_INDEX_W :0] corrected_modulus_bits_msb_default = corrected_modulus_bits_default[BIT_INDEX_W:LSB_BIT_INDEX_W]; wire [ OP_ADDR_W :0] modulus_num_words_n_default = {corrected_modulus_bits_msb_default, {(LSB_BIT_INDEX_W-WORD_MUX_W){1'b0}}} - 1'b1; wire [ OP_ADDR_W-1:0] modulus_num_words_n_lsb_default = modulus_num_words_n_default[OP_ADDR_W-1:0]; wire [ OP_ADDR_W-1:0] modulus_num_words_pq_default = {corrected_modulus_bits_msb_default, {(LSB_BIT_INDEX_W-WORD_MUX_W-1){1'b0}}} - 1'b1; wire [ BIT_INDEX_W :0] corrected_exponent_bits_user = correct_exponent_bits(write_data[BIT_INDEX_W:0]); wire [ BIT_INDEX_W-1:0] corrected_exponent_bits_msb_user = corrected_exponent_bits_user[BIT_INDEX_W:1]; wire [ BIT_INDEX_W :0] exponent_num_bits_n_user = corrected_exponent_bits_user - 1'b1; wire [ BIT_INDEX_W-1:0] exponent_num_bits_n_lsb_user = exponent_num_bits_n_user[BIT_INDEX_W-1:0]; wire [ BIT_INDEX_W-1:0] exponent_num_bits_pq_user = corrected_exponent_bits_msb_user - 1'b1; wire [ BIT_INDEX_W :0] corrected_exponent_bits_default = `MODEXPNG_DEFAULT_EXPONENT_BITS; wire [ BIT_INDEX_W-1:0] corrected_exponent_bits_msb_default = corrected_exponent_bits_default[BIT_INDEX_W:1]; wire [ BIT_INDEX_W :0] exponent_num_bits_n_default = corrected_exponent_bits_default - 1'b1; wire [ BIT_INDEX_W-1:0] exponent_num_bits_n_lsb_default = exponent_num_bits_n_default[BIT_INDEX_W-1:0]; wire [ BIT_INDEX_W-1:0] exponent_num_bits_pq_default = corrected_exponent_bits_msb_default - 1'b1; task update_modulus_bits_user; begin wrap_modulus_bits_msb <= corrected_modulus_bits_msb_user; wrap_word_index_last_n <= modulus_num_words_n_lsb_user; wrap_word_index_last_pq <= modulus_num_words_pq_user; end endtask task update_modulus_bits_default; begin wrap_modulus_bits_msb <= corrected_modulus_bits_msb_default; wrap_word_index_last_n <= modulus_num_words_n_lsb_default; wrap_word_index_last_pq <= modulus_num_words_pq_default; end endtask task update_exponent_bits_user; begin wrap_exponent_bits <= corrected_exponent_bits_user; wrap_bit_index_last_n <= exponent_num_bits_n_lsb_user; wrap_bit_index_last_pq <= exponent_num_bits_pq_user; end endtask task update_exponent_bits_default; begin wrap_exponent_bits <= corrected_exponent_bits_default; wrap_bit_index_last_n <= exponent_num_bits_n_lsb_default; wrap_bit_index_last_pq <= exponent_num_bits_pq_default; end endtask always @(posedge clk or negedge rst_n) // if (!rst_n) begin // wrap_reg_control <= `MODEXPNG_DEFAULT_CONTROL; wrap_reg_mode <= `MODEXPNG_DEFAULT_MODE; // update_modulus_bits_default; update_exponent_bits_default; // end else if (cs && we && addr_msb_is_wrap) // case (addr_lsb) ADDR_CONTROL: wrap_reg_control <= write_data[CONTROL_NEXT_BIT]; ADDR_MODE: wrap_reg_mode <= write_data[MODE_FULLCRT_BIT]; ADDR_MODULUS_BITS: update_modulus_bits_user; ADDR_EXPONENT_BITS: update_exponent_bits_user; endcase // // Only accept correct modulus width // function [BIT_INDEX_W:0] correct_modulus_bits; input [BIT_INDEX_W:0] width; if (width < MIN_OP_W) correct_modulus_bits = MIN_OP_W; else if (width > MAX_OP_W) correct_modulus_bits = MAX_OP_W; else correct_modulus_bits = width; endfunction // // Only accept correct exponent width // function [BIT_INDEX_W:0] correct_exponent_bits; input [BIT_INDEX_W:0] width; if (width < MIN_EXP_W) correct_exponent_bits = MIN_EXP_W; else if (width > MAX_OP_W ) correct_exponent_bits = MAX_OP_W; else correct_exponent_bits = width; endfunction // // Read Interface // always @(posedge clk) // if (cs && addr_msb_is_wrap) // case (address) // ADDR_NAME0: wrap_read_data <= CORE_NAME0; ADDR_NAME1: wrap_read_data <= CORE_NAME1; ADDR_VERSION: wrap_read_data <= CORE_VERSION; ADDR_CONTROL: wrap_read_data <= {{30{1'b0}}, wrap_reg_control, 1'b0}; ADDR_STATUS: wrap_read_data <= {{30{1'b0}}, wrap_reg_status, 1'b1}; // ADDR_MODE: wrap_read_data <= {{30{1'b0}}, wrap_reg_mode, 1'b0}; ADDR_MODULUS_BITS: wrap_read_data <= {{(31-BIT_INDEX_W){1'b0}}, wrap_modulus_bits_msb, {LSB_BIT_INDEX_W{1'b0}}}; ADDR_EXPONENT_BITS: wrap_read_data <= {{(31-BIT_INDEX_W){1'b0}}, wrap_exponent_bits}; ADDR_BANK_BITS: wrap_read_data <= MAX_OP_W; ADDR_NUM_MULTS: wrap_read_data <= NUM_MULTS; // default: wrap_read_data <= 32'h00000000; // endcase // // Register / Core Memory Selector // reg [1:0] addr_msb_last; wire addr_msb_last_is_wrap = addr_msb_last == ADDR_MSB_WRAP; always @(posedge clk) addr_msb_last <= addr_msb; assign read_data = addr_msb_last_is_wrap ? wrap_read_data : core_read_data; endmodule