diff options
-rw-r--r-- | src/rtl/adder32.v | 54 | ||||
-rw-r--r-- | src/rtl/blockmem1r1w.v | 70 | ||||
-rw-r--r-- | src/rtl/blockmem2r1w.v | 76 | ||||
-rw-r--r-- | src/rtl/modexp.v | 807 | ||||
-rw-r--r-- | src/rtl/montprod.v | 590 | ||||
-rw-r--r-- | src/rtl/residue.v | 224 | ||||
-rw-r--r-- | src/rtl/shr32.v | 53 |
7 files changed, 1874 insertions, 0 deletions
diff --git a/src/rtl/adder32.v b/src/rtl/adder32.v new file mode 100644 index 0000000..d9cac45 --- /dev/null +++ b/src/rtl/adder32.v @@ -0,0 +1,54 @@ +//====================================================================== +// +// adder32.v +// --------- +// 32bit adder with carry in / carry out +// +// +// Author: Peter Magnusson +// Copyright (c) 2015, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + + +module adder32( + input [31 : 0] a, + input [31 : 0] b, + input carry_in, + output wire [31 : 0] sum, + output wire carry_out); + + reg [32 : 0] adder_result; + + assign sum = adder_result[31:0]; + assign carry_out = adder_result[32]; + + always @(a, b, carry_in) + adder_result = {1'b0, a} + {1'b0, b} + {32'b0, carry_in}; +endmodule diff --git a/src/rtl/blockmem1r1w.v b/src/rtl/blockmem1r1w.v new file mode 100644 index 0000000..1d84369 --- /dev/null +++ b/src/rtl/blockmem1r1w.v @@ -0,0 +1,70 @@ +//====================================================================== +// +// blockmem1rw1.v +// -------------- +// Synchronous block memory with one read and one write port. +// The data size is the same for both read and write operations. +// +// The memory is used in the modexp core. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2015, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module blockmem1r1w( + input wire clk, + + input wire [07 : 0] read_addr, + output wire [31 : 0] read_data, + + input wire wr, + input wire [07 : 0] write_addr, + input wire [31 : 0] write_data + ); + + reg [31 : 0] mem [0 : 255]; + reg [31 : 0] tmp_read_data; + + assign read_data = tmp_read_data; + + always @ (posedge clk) + begin : reg_mem + if (wr) + mem[write_addr] <= write_data; + + tmp_read_data <= mem[read_addr]; + end + +endmodule // blockmem1r1w + +//====================================================================== +// EOF blockmem1r1w.v +//====================================================================== diff --git a/src/rtl/blockmem2r1w.v b/src/rtl/blockmem2r1w.v new file mode 100644 index 0000000..252764f --- /dev/null +++ b/src/rtl/blockmem2r1w.v @@ -0,0 +1,76 @@ +//====================================================================== +// +// blockmem2r1w.v +// -------------- +// Synchronous block memory with two read ports and one write port. +// The data size is the same for both read and write operations. +// +// The memory is used in the modexp core. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2015, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module blockmem2r1w( + input wire clk, + + input wire [07 : 0] read_addr0, + output wire [31 : 0] read_data0, + + input wire [07 : 0] read_addr1, + output wire [31 : 0] read_data1, + + input wire wr, + input wire [07 : 0] write_addr, + input wire [31 : 0] write_data + ); + + reg [31 : 0] mem [0 : 255]; + reg [31 : 0] tmp_read_data0; + reg [31 : 0] tmp_read_data1; + + assign read_data0 = tmp_read_data0; + assign read_data1 = tmp_read_data1; + + always @ (posedge clk) + begin : reg_mem + if (wr) + mem[write_addr] <= write_data; + + tmp_read_data0 <= mem[read_addr0]; + tmp_read_data1 <= mem[read_addr1]; + end + +endmodule // blockmem2r1w + +//====================================================================== +// EOF blockmem2r1w.v +//====================================================================== diff --git a/src/rtl/modexp.v b/src/rtl/modexp.v new file mode 100644 index 0000000..b0e8aa3 --- /dev/null +++ b/src/rtl/modexp.v @@ -0,0 +1,807 @@ +//====================================================================== +// +// modexp.v +// -------- +// Modular exponentiation core for implementing public key algorithms +// such as RSA, DH, ElGamal etc. +// +// The core calculates the following function: +// +// C = M ** e mod N +// +// M is a message with a length of n bits +// e is the exponent with a length of at most 32 bits +// N is the modulus with a length of n bits +// n is can be 32 and up to and including 8192 bits in steps +// of 32 bits. +// +// The core has a 32-bit memory like interface, but provides +// status signals to inform the system that a given operation +// has is done. Additionally, any errors will also be asserted. +// +// +// Author: Peter Magnusson, Joachim Strombergson +// Copyright (c) 2015, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module modexp( + input wire clk, + input wire reset_n, + + input wire cs, + input wire we, + + input wire [11 : 0] address, + input wire [31 : 0] write_data, + output wire [31 : 0] read_data + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam GENERAL_PREFIX = 4'h0; + localparam ADDR_NAME0 = 8'h00; + localparam ADDR_NAME1 = 8'h01; + localparam ADDR_VERSION = 8'h02; + + localparam ADDR_MODSIZE = 8'h10; + localparam ADDR_EXPONENT = 8'h20; + + localparam MODULUS_PREFIX = 4'h1; + localparam ADDR_MODULUS_START = 8'h00; + localparam ADDR_MODULUS_END = 8'hff; + + localparam EXPONENT_PREFIX = 4'h2; + localparam ADDR_EXPONENT_START = 8'h00; + localparam ADDR_EXPONENT_END = 8'hff; + + localparam MESSAGE_PREFIX = 4'h3; + localparam MESSAGE_START = 8'h00; + localparam MESSAGE_END = 8'hff; + + localparam RESULT_PREFIX = 4'h4; + localparam RESULT_START = 8'h00; + localparam RESULT_END = 8'hff; + + localparam LENGTH_PREFIX = 4'h5; + + localparam DEFAULT_MODLENGTH = 8'h80; + localparam DEFAULT_EXPLENGTH = 8'h80; + + localparam MONTPROD_SELECT_ONE_NR = 3'h0; + localparam MONTPROD_SELECT_X_NR = 3'h1; + localparam MONTPROD_SELECT_Z_P = 3'h2; + localparam MONTPROD_SELECT_P_P = 3'h3; + localparam MONTPROD_SELECT_ONE_Z = 3'h4; + + localparam MONTPROD_DEST_Z = 2'b00; + localparam MONTPROD_DEST_P = 2'b01; + localparam MONTPROD_DEST_NOWHERE = 2'b10; + + localparam CTRL_IDLE = 4'h0; + localparam CTRL_RESIDUE = 4'h1; + localparam CTRL_CALCULATE_Z0 = 4'h2; + localparam CTRL_CALCULATE_P0 = 4'h3; + localparam CTRL_ITERATE = 4'h4; + localparam CTRL_ITERATE_Z_P = 4'h5; + localparam CTRL_ITERATE_P_P = 4'h6; + localparam CTRL_ITERATE_END = 4'h7; + localparam CTRL_CALCULATE_ZN = 4'h8; + localparam CTRL_DONE = 4'h9; + + localparam CORE_NAME0 = 32'h72736120; // "rsa " + localparam CORE_NAME1 = 32'h38313932; // "8192" + localparam CORE_VERSION = 32'h302e3031; // "0.01" + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [07 : 0] modulus_mem_int_rd_addr; + wire [31 : 0] modulus_mem_int_rd_data; + wire [31 : 0] modulus_mem_api_rd_data; + reg modulus_mem_api_we; + + reg [07 : 0] message_mem_int_rd_addr; + wire [31 : 0] message_mem_int_rd_data; + wire [31 : 0] message_mem_api_rd_data; + reg message_mem_api_we; + + reg [07 : 0] exponent_mem_int_rd_addr; + wire [31 : 0] exponent_mem_int_rd_data; + wire [31 : 0] exponent_mem_api_rd_data; + reg exponent_mem_api_we; + + wire [31 : 0] result_mem_api_rd_data; + reg [07 : 0] result_mem_int_rd_addr; + wire [31 : 0] result_mem_int_rd_data; + reg [07 : 0] result_mem_int_wr_addr; + reg [31 : 0] result_mem_int_wr_data; + reg result_mem_int_we; + + reg residue_calculator_start; //TODO not implemented yet + reg residue_calculator_ready; //TODO not implemented yet + + reg [31 : 0] residue_mem [0 : 255]; + reg [07 : 0] residue_mem_rd_addr; + wire [31 : 0] residue_mem_rd_data; + reg [07 : 0] residue_mem_wr_addr; + reg [31 : 0] residue_mem_wr_data; + reg residue_mem_we; + + + reg [07 : 0] p_mem_rd0_addr; + wire [31 : 0] p_mem_rd0_data; + reg [07 : 0] p_mem_rd1_addr; + wire [31 : 0] p_mem_rd1_data; + reg [07 : 0] p_mem_wr_addr; + reg [31 : 0] p_mem_wr_data; + reg p_mem_we; + + reg [07 : 0] length_reg; + reg [07 : 0] length_m1_reg; + reg [07 : 0] length_new; + reg [07 : 0] length_m1_new; + reg length_we; + + reg start_reg; + reg start_new; + reg start_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [2 : 0] montprod_select_reg; + reg [2 : 0] montprod_select_new; + reg montprod_select_we; + reg [1 : 0] montprod_dest_reg; + reg [1 : 0] montprod_dest_new; + reg [1 : 0] montprod_dest_we; + + reg [3 : 0] modexp_ctrl_reg; + reg [3 : 0] modexp_ctrl_new; + reg modexp_ctrl_we; + + reg [31 : 0] one; + reg [31 : 0] one_new; + + reg [12 : 0] loop_counter_reg; + reg [12 : 0] loop_counter_new; + reg [12 : 0] loop_counter_we; + reg [07 : 0] E_word_index; + reg [04 : 0] E_bit_index; + reg last_iteration; + reg ei_reg; + reg ei_new; + reg ei_we; + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [31 : 0] tmp_read_data; + reg tmp_error; + + reg montprod_calc; + wire montprod_ready; + reg [07 : 0] montprod_length; + + wire [07 : 0] montprod_opa_addr; + reg [31 : 0] montprod_opa_data; + + wire [07 : 0] montprod_opb_addr; + reg [31 : 0] montprod_opb_data; + + wire [07 : 0] montprod_opm_addr; + reg [31 : 0] montprod_opm_data; + + wire [07 : 0] montprod_result_addr; + wire [31 : 0] montprod_result_data; + wire montprod_result_we; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign read_data = tmp_read_data; + + + //---------------------------------------------------------------- + // core instantiations. + //---------------------------------------------------------------- + montprod montprod_inst( + .clk(clk), + .reset_n(reset_n), + + .calculate(montprod_calc), + .ready(montprod_ready), + + .length(montprod_length), + + .opa_addr(montprod_opa_addr), + .opa_data(montprod_opa_data), + + .opb_addr(montprod_opb_addr), + .opb_data(montprod_opb_data), + + .opm_addr(montprod_opm_addr), + .opm_data(message_mem_int_rd_data), + + .result_addr(montprod_result_addr), + .result_data(montprod_result_data), + .result_we(montprod_result_we) + ); + + + blockmem2r1w modulus_mem( + .clk(clk), + .read_addr0(modulus_mem_int_rd_addr), + .read_data0(modulus_mem_int_rd_data), + .read_addr1(address[7 : 0]), + .read_data1(modulus_mem_api_rd_data), + .wr(modulus_mem_api_we), + .write_addr(address[7 : 0]), + .write_data(write_data) + ); + + + blockmem2r1w message_mem( + .clk(clk), + .read_addr0(message_mem_int_rd_addr), + .read_data0(message_mem_int_rd_data), + .read_addr1(address[7 : 0]), + .read_data1(message_mem_api_rd_data), + .wr(message_mem_api_we), + .write_addr(address[7 : 0]), + .write_data(write_data) + ); + + + blockmem2r1w exponent_mem( + .clk(clk), + .read_addr0(exponent_mem_int_rd_addr), + .read_data0(exponent_mem_int_rd_data), + .read_addr1(address[7 : 0]), + .read_data1(exponent_mem_api_rd_data), + .wr(exponent_mem_api_we), + .write_addr(address[7 : 0]), + .write_data(write_data) + ); + + + blockmem2r1w result_mem( + .clk(clk), + .read_addr0(result_mem_int_rd_addr[7 : 0]), + .read_data0(result_mem_int_rd_data), + .read_addr1(address[7 : 0]), + .read_data1(result_mem_api_rd_data), + .wr(result_mem_int_we), + .write_addr(result_mem_int_wr_addr), + .write_data(result_mem_int_wr_data) + ); + + blockmem2r1w p_mem( + .clk(clk), + .read_addr0(p_mem_rd0_addr), + .read_data0(p_mem_rd0_data), + .read_addr1(p_mem_rd1_addr), + .read_data1(p_mem_rd1_data), + .wr(p_mem_we), + .write_addr(p_mem_wr_addr), + .write_data(p_mem_wr_data) + ); + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin + if (!reset_n) + begin + ready_reg <= 1'b1; + montprod_select_reg <= MONTPROD_SELECT_ONE_NR; + montprod_dest_reg <= MONTPROD_DEST_NOWHERE; + modexp_ctrl_reg <= CTRL_IDLE; + one <= 32'h0; + length_reg <= 8'h0; + length_m1_reg <= 8'h0; + loop_counter_reg <= 13'b0; + ei_reg <= 1'b0; + end + else + begin + if (ready_we) + ready_reg <= ready_new; + + if (montprod_select_we) + montprod_select_reg <= montprod_select_new; + + if (montprod_dest_we) + montprod_dest_reg <= montprod_dest_new; + + if (modexp_ctrl_we) + modexp_ctrl_reg <= modexp_ctrl_new; + + if (length_we) + begin + length_reg <= length_new; + length_m1_reg <= length_m1_new; + end + + if (loop_counter_we) + loop_counter_reg <= loop_counter_new; + + if (ei_we) + ei_reg <= ei_new; + + one <= one_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // api + // + // The interface command decoding logic. + //---------------------------------------------------------------- + always @* + begin : api + modulus_mem_api_we = 1'b0; + exponent_mem_api_we = 1'b0; + message_mem_api_we = 1'b0; + tmp_read_data = 32'h00000000; + + length_new = write_data[7 : 0]; + length_m1_new = write_data[7 : 0] - 8'h1; + length_we = 1'b0; + + if (cs) + begin + case (address[11 : 8]) + GENERAL_PREFIX: + begin +// if (we) +// begin +// case (address) +// // Write operations. +// ADDR_MODSIZE: +// begin +// modsize_we = 1; +// end +// +// ADDR_EXPONENT: +// begin +// exponent_we = 1; +// end +// +// default: +// begin +// tmp_error = 1; +// end +// endcase // case (addr) +// end // if (write_read) +// else +// begin +// case (address) +// // Read operations. +// ADDR_NAME0: +// begin +// tmp_read_data = CORE_NAME0; +// end +// +// ADDR_NAME1: +// begin +// tmp_read_data = CORE_NAME1; +// end +// +// ADDR_VERSION: +// begin +// tmp_read_data = CORE_VERSION; +// end +// +// ADDR_MODSIZE: +// begin +// tmp_read_data = {28'h0000000, modsize_reg}; +// end +// +// default: +// begin +// tmp_error = 1; +// end +// endcase // case (addr) +// end + end + + MODULUS_PREFIX: + begin + if (we) + begin + modulus_mem_api_we = 1'b1; + end + else + begin + tmp_read_data = modulus_mem_api_rd_data; + end + end + + EXPONENT_PREFIX: + begin + if (we) + begin + exponent_mem_api_we = 1'b1; + end + else + begin + tmp_read_data = exponent_mem_api_rd_data; + end + end + + MESSAGE_PREFIX: + begin + if (we) + begin + message_mem_api_we = 1'b1; + end + else + begin + tmp_read_data = message_mem_api_rd_data; + end + end + + RESULT_PREFIX: + begin + tmp_read_data = result_mem_api_rd_data; + end + + LENGTH_PREFIX: + begin + if (we) + length_we = 1'b1; + end + +// RESULT_PREFIX: +// begin +// if (we) +// begin +// modulus_mem_api_we = 1'b1; +// end +// else +// begin +// tmp_read_data = modulus_mem_int_rd_data; +// end +// end + + default: + begin + + end + endcase // case (address[11 : 8]) + end // if (cs) + end // api + + + //---------------------------------------------------------------- + // montprod_op_select + // + // Select operands used during montprod calculations depending + // on what operation we want to do + //---------------------------------------------------------------- + always @* + begin : montprod_op_select + message_mem_int_rd_addr = montprod_opa_addr; + p_mem_rd0_addr = montprod_opa_addr; + + residue_mem_rd_addr = montprod_opb_addr; + p_mem_rd1_addr = montprod_opb_addr; + + modulus_mem_int_rd_addr = montprod_opm_addr; + + montprod_opa_data = 32'h00000000; + montprod_opb_data = 32'h00000000; + + if (montprod_opa_addr == length_m1_reg) + one_new = 32'h00000001; + else + one_new = 32'h00000000; + + case (montprod_select_reg) + MONTPROD_SELECT_ONE_NR: + begin + montprod_opa_data = one; + montprod_opb_data = residue_mem_rd_data; + end + + MONTPROD_SELECT_X_NR: + begin + montprod_opa_data = message_mem_int_rd_data; + montprod_opb_data = residue_mem_rd_data; + end + + MONTPROD_SELECT_Z_P: + begin + montprod_opa_data = result_mem_int_rd_data; + montprod_opb_data = p_mem_rd1_data; + end + + MONTPROD_SELECT_P_P: + begin + montprod_opa_data = p_mem_rd0_data; + montprod_opb_data = p_mem_rd1_data; + end + + MONTPROD_SELECT_ONE_Z: + begin + montprod_opa_data = one; + montprod_opb_data = result_mem_int_rd_data; + end + + default: + begin + end + endcase // case (montprod_selcect_reg) + end + + //---------------------------------------------------------------- + // memory write mux + // + // direct memory write signals to correct memory + //---------------------------------------------------------------- + always @* + begin : memory_write_process + result_mem_int_wr_addr = montprod_result_addr; + result_mem_int_wr_data = montprod_result_data; + result_mem_int_we = 1'b0; + + p_mem_wr_addr = montprod_result_addr; + p_mem_wr_data = montprod_result_data; + p_mem_we = 1'b0; + + case (montprod_dest_reg) + MONTPROD_DEST_Z: + result_mem_int_we = montprod_result_we; + MONTPROD_DEST_P: + p_mem_we = montprod_result_we; + default: + begin + end + endcase + + // inhibit Z=Z*P when ei = 0 + if (modexp_ctrl_reg == CTRL_ITERATE_Z_P) + result_mem_int_we = result_mem_int_we & ei_reg; + end + + //---------------------------------------------------------------- + // loop_counter + // + // Calculate the loop counter and related variables + //---------------------------------------------------------------- + always @* + begin : loop_counters_process + E_bit_index = loop_counter_reg[ 04 : 0 ]; + + if (loop_counter_reg == { length_m1_reg, 5'b11111 }) + last_iteration = 1'b1; + else + last_iteration = 1'b0; + + case (modexp_ctrl_reg) + CTRL_CALCULATE_P0: + begin + loop_counter_new = 13'b0; + loop_counter_we = 1'b1; + end + + CTRL_ITERATE_END: + begin + loop_counter_new = loop_counter_reg + 1'b1; + loop_counter_we = 1'b1; + end + + default: + begin + loop_counter_new = 13'b0; + loop_counter_we = 1'b0; + end + + endcase + end + + //---------------------------------------------------------------- + // exponent + // + // reads the exponent + //---------------------------------------------------------------- + always @* + begin : exponent_process + // accessing new instead of reg - pick up update at CTRL_ITERATE_NEW to remove a pipeline stall + E_word_index = loop_counter_new[ 12 : 5 ]; + + exponent_mem_int_rd_addr = E_word_index; + + ei_new = exponent_mem_int_rd_data[ E_bit_index ]; + + if (modexp_ctrl_reg == CTRL_ITERATE) + ei_we = 1'b1; + else + ei_we = 1'b0; + end + + //---------------------------------------------------------------- + // modexp_ctrl + // + // Control FSM logic needed to perform the modexp operation. + //---------------------------------------------------------------- + always @* + begin + ready_new = 0; + ready_we = 0; + montprod_select_new = MONTPROD_SELECT_ONE_NR; + montprod_select_we = 0; + montprod_dest_new = MONTPROD_DEST_NOWHERE; + montprod_dest_we = 0; + montprod_calc = 0; + modexp_ctrl_new = CTRL_IDLE; + modexp_ctrl_we = 0; + + residue_calculator_start = 1'b0; + + case (modexp_ctrl_reg) + CTRL_IDLE: + begin + ready_new = 0; + ready_we = 1; + if (start_reg == 1'b1) + begin + modexp_ctrl_new = CTRL_RESIDUE; + modexp_ctrl_we = 1; + residue_calculator_start = 1'b1; + end + end + + CTRL_RESIDUE: + begin + if (residue_calculator_ready == 1'b1) + begin + montprod_select_new = MONTPROD_SELECT_ONE_NR; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_Z; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_CALCULATE_Z0; + modexp_ctrl_we = 1; + end + end + + CTRL_CALCULATE_Z0: + begin + if (montprod_ready == 1'b1) + begin + montprod_select_new = MONTPROD_SELECT_X_NR; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_P; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_CALCULATE_P0; + modexp_ctrl_we = 1; + end + end + + CTRL_CALCULATE_P0: + begin + if (montprod_ready == 1'b1) + begin + modexp_ctrl_new = CTRL_ITERATE; + modexp_ctrl_we = 1; + end + end + + CTRL_ITERATE: + begin + montprod_select_new = MONTPROD_SELECT_Z_P; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_Z; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_ITERATE_Z_P; + modexp_ctrl_we = 1; + end + + CTRL_ITERATE_Z_P: + if (montprod_ready == 1'b1) + begin + montprod_select_new = MONTPROD_SELECT_P_P; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_P; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_ITERATE_P_P; + modexp_ctrl_we = 1; + end + + CTRL_ITERATE_P_P: + if (montprod_ready == 1'b1) + begin + modexp_ctrl_new = CTRL_ITERATE_END; + modexp_ctrl_we = 1; + end + + CTRL_ITERATE_END: + begin + if (last_iteration == 1'b0) + begin + modexp_ctrl_new = CTRL_ITERATE; + modexp_ctrl_we = 1; + end + else + begin + montprod_select_new = MONTPROD_SELECT_ONE_Z; + montprod_select_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_CALCULATE_ZN; + modexp_ctrl_we = 1; + end + end + + CTRL_CALCULATE_ZN: + begin + if (montprod_ready == 1'b1) + begin + modexp_ctrl_new = CTRL_DONE; + modexp_ctrl_we = 1; + end + end + + CTRL_DONE: + begin + ready_new = 1; + ready_we = 1; + modexp_ctrl_new = CTRL_IDLE; + modexp_ctrl_we = 1; + end + + default: + begin + end + + endcase // case (modexp_ctrl_reg) + end + +endmodule // modexp + +//====================================================================== +// EOF modexp.v +//====================================================================== diff --git a/src/rtl/montprod.v b/src/rtl/montprod.v new file mode 100644 index 0000000..32bbdec --- /dev/null +++ b/src/rtl/montprod.v @@ -0,0 +1,590 @@ +//====================================================================== +// +// montprod.v +// --------- +// Montgomery product calculator for the modular exponentiantion core. +// +// +// Author: Peter Magnusson, Joachim Strombergson +// Copyright (c) 2015, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module montprod( + input wire clk, + input wire reset_n, + + input wire calculate, + output wire ready, + + input [7 : 0] length, + + output wire [7 : 0] opa_addr, + input wire [31 : 0] opa_data, + + output wire [7 : 0] opb_addr, + input wire [31 : 0] opb_data, + + output wire [7 : 0] opm_addr, + input wire [31 : 0] opm_data, + + output wire [7 : 0] result_addr, + output wire [31 : 0] result_data, + output wire result_we + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam CTRL_IDLE = 4'h0; + localparam CTRL_INIT_S = 4'h1; + localparam CTRL_LOOP_INIT = 4'h2; + localparam CTRL_LOOP_ITER = 4'h3; + localparam CTRL_LOOP_BQ = 4'h4; + localparam CTRL_L_CALC_SM = 4'h5; + localparam CTRL_L_STALLPIPE_SM = 4'h6; + localparam CTRL_L_CALC_SA = 4'h7; + localparam CTRL_L_STALLPIPE_SA = 4'h8; + localparam CTRL_L_CALC_SDIV2 = 4'h9; + localparam CTRL_L_STALLPIPE_D2 = 4'hA; + localparam CTRL_L_STALLPIPE_ES = 4'hB; + localparam CTRL_EMIT_S = 4'hC; + localparam CTRL_DONE = 4'hD; + + localparam SMUX_0 = 2'h0; + localparam SMUX_ADD_SM = 2'h1; + localparam SMUX_ADD_SA = 2'h2; + localparam SMUX_SHR = 2'h3; + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + + reg [07 : 0] opa_addr_reg; + reg [07 : 0] opb_addr_reg; + reg [07 : 0] opm_addr_reg; + + reg [07 : 0] result_addr_reg; + reg [31 : 0] result_data_reg; + + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [3 : 0] montprod_ctrl_reg; + reg [3 : 0] montprod_ctrl_new; + reg montprod_ctrl_we; + + reg [1 : 0] s_mux_new; + reg [1 : 0] s_mux_reg; + + reg [31 : 0] s_mem_new; + reg s_mem_we; + reg s_mem_we_new; + reg [07 : 0] s_mem_addr; + reg [07 : 0] s_mem_wr_addr; + wire [31 : 0] s_mem_read_data; + + reg q; //q = (s - b * A) & 1 + reg q_reg; + reg b; //b: bit of B + reg b_reg; + + reg [12 : 0] loop_counter; + reg [12 : 0] loop_counter_new; + reg [12 : 0] loop_counter_dec; + reg [07 : 0] B_word_index; //loop counter as a word index + reg [04 : 0] B_bit_index; //loop counter as a bit index + reg [04 : 0] B_bit_index_reg; //loop counter as a bit index + + reg [07 : 0] word_index; //register of what word is being read + reg [07 : 0] word_index_new; //calculation of what word to be read + reg [07 : 0] word_index_prev; //register of what word was read previously (result address to emit) + reg [07 : 0] length_m1; + + reg add_carry_in_sa; + reg add_carry_new_sa; + reg add_carry_in_sm; + reg add_carry_new_sm; + + reg shr_carry_in; + reg shr_carry_new; + + reg reset_word_index_LSW; + reg reset_word_index_MSW; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg tmp_result_we; + wire [31 : 0] add_result_sa; + wire add_carry_out_sa; + wire [31 : 0] add_result_sm; + wire add_carry_out_sm; + + wire shr_carry_out; + wire [31 : 0] shr_adiv2; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign opa_addr = opa_addr_reg; + assign opb_addr = opb_addr_reg; + assign opm_addr = opm_addr_reg; + + assign result_addr = result_addr_reg; + assign result_data = result_data_reg; + assign result_we = tmp_result_we; + + assign ready = ready_reg; + + + //---------------------------------------------------------------- + // Instantions + //---------------------------------------------------------------- + + blockmem1r1w s_mem( + .clk(clk), + .read_addr(s_mem_addr), + .read_data(s_mem_read_data), + .wr(s_mem_we), + .write_addr(s_mem_wr_addr), + .write_data(s_mem_new) + ); + + + adder32 s_adder_sa( + .a(s_mem_read_data), + .b(opa_data), + .carry_in(add_carry_in_sa), + .sum(add_result_sa), + .carry_out(add_carry_out_sa) + ); + + adder32 s_adder_sm( + .a(s_mem_read_data), + .b(opm_data), + .carry_in(add_carry_in_sm), + .sum(add_result_sm), + .carry_out(add_carry_out_sm) + ); + + shr32 shifter( + .a( s_mem_read_data ), + .carry_in( shr_carry_in ), + .adiv2( shr_adiv2 ), + .carry_out( shr_carry_out ) + ); + + always @* + begin : s_mux + case (s_mux_reg) + SMUX_0: + s_mem_new = 32'b0; + SMUX_ADD_SA: + s_mem_new = add_result_sa; + SMUX_ADD_SM: + s_mem_new = add_result_sm; + SMUX_SHR: + s_mem_new = shr_adiv2; + endcase + $display("SMUX%x: %x", s_mux_reg, s_mem_new); + end + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin : reg_update + if (!reset_n) + begin + ready_reg <= 1'b0; + loop_counter <= 13'h0; + word_index <= 8'h0; + word_index_prev <= 8'h0; + add_carry_in_sa <= 1'b0; + add_carry_in_sm <= 1'b0; + shr_carry_in <= 1'b0; + montprod_ctrl_reg <= CTRL_IDLE; + b_reg <= 1'b0; + q_reg <= 1'b0; + s_mux_reg <= SMUX_0; + s_mem_we <= 1'b0; + s_mem_wr_addr <= 8'h0; + B_bit_index_reg <= 5'h0; + end + else + begin + if (ready_we) + ready_reg <= ready_new; + + if (montprod_ctrl_we) + begin + montprod_ctrl_reg <= montprod_ctrl_new; + end + + s_mem_wr_addr <= s_mem_addr; + + s_mem_we <= s_mem_we_new; + + word_index <= word_index_new; + word_index_prev <= word_index; + + loop_counter <= loop_counter_new; + shr_carry_in <= shr_carry_new; + add_carry_in_sa <= add_carry_new_sa; + add_carry_in_sm <= add_carry_new_sm; + + B_bit_index_reg <= B_bit_index; + q_reg <= q; + b_reg <= b; + + s_mux_reg <= s_mux_new; + end + end // reg_update + + always @* + begin : bq_process + b = b_reg; + q = q_reg; + if (montprod_ctrl_reg == CTRL_LOOP_BQ) + begin + b = opb_data[ B_bit_index_reg ]; + //opa_addr will point to length-1 to get A LSB. + //s_read_addr will point to length-1 + q = s_mem_read_data[0] ^ (opa_data[0] & b); + $display("s_mem_read_data: %x opa_data %x b %x q %x B_bit_index_reg %x", s_mem_read_data, opa_data, b, q, B_bit_index_reg); + end + end + + + //---------------------------------------------------------------- + // Process for iterating the loop counter and setting related B indexes + //---------------------------------------------------------------- + always @* + begin : loop_counter_process + length_m1 = length - 1'b1; + loop_counter_dec = loop_counter - 1'b1; + B_word_index = loop_counter[12:5]; + B_bit_index = B_bit_index_reg; + + case (montprod_ctrl_reg) + CTRL_LOOP_INIT: + loop_counter_new = {length, 5'b00000}-1; + + CTRL_LOOP_ITER: + begin + B_word_index = loop_counter[12:5]; + B_bit_index = 5'h1f - loop_counter[4:0]; + end + + CTRL_L_STALLPIPE_D2: + loop_counter_new = loop_counter_dec; + + default: + loop_counter_new = loop_counter; + endcase + end + + + //---------------------------------------------------------------- + // prodcalc + //---------------------------------------------------------------- + always @* + begin : prodcalc + + case (montprod_ctrl_reg) + CTRL_LOOP_ITER: + //q = (s[length-1] ^ A[length-1]) & 1; + opa_addr_reg = length_m1; + + default: + opa_addr_reg = word_index; + endcase + + opb_addr_reg = B_word_index; + opm_addr_reg = word_index; + + case (montprod_ctrl_reg) + CTRL_LOOP_ITER: + s_mem_addr = length_m1; + default: + s_mem_addr = word_index; + endcase + + + + + result_addr_reg = word_index_prev; + result_data_reg = s_mem_read_data; + + case (montprod_ctrl_reg) + CTRL_EMIT_S: + tmp_result_we = 1'b1; + default: + tmp_result_we = 1'b0; + endcase + + + if (reset_word_index_LSW == 1'b1) + word_index_new = length_m1; + else if (reset_word_index_MSW == 1'b1) + word_index_new = 8'h0; + else if (montprod_ctrl_reg == CTRL_L_CALC_SDIV2) + word_index_new = word_index + 1'b1; + else + word_index_new = word_index - 1'b1; + end // prodcalc + + + always @* + begin : s_writer_process + shr_carry_new = 1'b0; + s_mux_new = SMUX_0; + + s_mem_we_new = 1'b0; + case (montprod_ctrl_reg) + CTRL_INIT_S: + begin + s_mem_we_new = 1'b1; + s_mux_new = SMUX_0; // write 0 + end + + CTRL_L_CALC_SM: + begin + //s = (s + q*M + b*A) >>> 1;, if(q==1) S+= M. Takes (1..length) cycles. + s_mem_we_new = q_reg; + s_mux_new = SMUX_ADD_SM; + end + + CTRL_L_CALC_SA: + begin + //s = (s + q*M + b*A) >>> 1;, if(b==1) S+= A. Takes (1..length) cycles. + s_mem_we_new = b_reg; + s_mux_new = SMUX_ADD_SA; + end + + CTRL_L_CALC_SDIV2: + begin + //s = (s + q*M + b*A) >>> 1; s>>=1. Takes (1..length) cycles. + s_mux_new = SMUX_SHR; + s_mem_we_new = 1'b1; + end + + default: + begin + end + endcase + + add_carry_new_sa = 1'b0; + add_carry_new_sm = 1'b0; + + case (s_mux_reg) + SMUX_ADD_SM: + add_carry_new_sm = add_carry_out_sm; + + SMUX_ADD_SA: + add_carry_new_sa = add_carry_out_sa; + + SMUX_SHR: + shr_carry_new = shr_carry_out; + + default: + begin + end + endcase + + end // prodcalc + + + //---------------------------------------------------------------- + // montprod_ctrl + // + // Control FSM for the montgomery product calculator. + //---------------------------------------------------------------- + always @* + begin : montprod_ctrl + ready_new = 1'b0; + ready_we = 1'b0; + montprod_ctrl_new = CTRL_IDLE; + montprod_ctrl_we = 1'b0; + + reset_word_index_LSW = 1'b0; + reset_word_index_MSW = 1'b0; + + case (montprod_ctrl_reg) + CTRL_IDLE: + begin + if (calculate) + begin + ready_new = 1'b0; + ready_we = 1'b1; + montprod_ctrl_new = CTRL_INIT_S; + montprod_ctrl_we = 1'b1; + reset_word_index_LSW = 1'b1; + end + else + begin + ready_new = 1'b1; + ready_we = 1'b1; + end + end + + CTRL_INIT_S: + begin + if (word_index == 8'h0) + begin + montprod_ctrl_new = CTRL_LOOP_INIT; + montprod_ctrl_we = 1'b1; + end + end + + + CTRL_LOOP_INIT: + begin + montprod_ctrl_new = CTRL_LOOP_ITER; + montprod_ctrl_we = 1'b1; + end + + //calculate q = (s - b * A) & 1;. + // Also abort loop if done. + CTRL_LOOP_ITER: + begin + reset_word_index_LSW = 1'b1; + montprod_ctrl_new = CTRL_LOOP_BQ; + montprod_ctrl_we = 1'b1; + end + + CTRL_LOOP_BQ: + begin + reset_word_index_LSW = 1'b1; + montprod_ctrl_new = CTRL_L_CALC_SM; + montprod_ctrl_we = 1'b1; + end + + CTRL_L_CALC_SM: + begin + if (word_index == 8'h0) + begin + reset_word_index_LSW = 1'b1; + montprod_ctrl_we = 1'b1; + montprod_ctrl_new = CTRL_L_STALLPIPE_SM; + end + end + + CTRL_L_STALLPIPE_SM: + begin + montprod_ctrl_new = CTRL_L_CALC_SA; + montprod_ctrl_we = 1'b1; + reset_word_index_LSW = 1'b1; + end + + CTRL_L_CALC_SA: + begin + if (word_index == 8'h0) + begin + reset_word_index_LSW = 1'b1; + montprod_ctrl_new = CTRL_L_STALLPIPE_SA; + montprod_ctrl_we = 1'b1; + end + end + + CTRL_L_STALLPIPE_SA: + begin + montprod_ctrl_new = CTRL_L_CALC_SDIV2; + montprod_ctrl_we = 1'b1; + reset_word_index_MSW = 1'b1; + end + + CTRL_L_CALC_SDIV2: + begin + if (word_index == length_m1) + begin + montprod_ctrl_new = CTRL_L_STALLPIPE_D2; + montprod_ctrl_we = 1'b1; + //reset_word_index = 1'b1; + end + end + + CTRL_L_STALLPIPE_D2: + begin + montprod_ctrl_new = CTRL_LOOP_ITER; //loop + montprod_ctrl_we = 1'b1; + reset_word_index_LSW = 1'b1; + if (loop_counter == 0) + begin + montprod_ctrl_new = CTRL_L_STALLPIPE_ES; + montprod_ctrl_we = 1'b1; + end + end + + CTRL_L_STALLPIPE_ES: + begin + montprod_ctrl_new = CTRL_EMIT_S; + montprod_ctrl_we = 1'b1; + //reset_word_index_LSW = 1'b1; + end + + CTRL_EMIT_S: + begin + $display("EMIT_S word_index: %d", word_index); + if (word_index_prev == 8'h0) + begin + montprod_ctrl_new = CTRL_DONE; + montprod_ctrl_we = 1'b1; + end + end + + CTRL_DONE: + begin + ready_new = 1'b1; + ready_we = 1'b1; + montprod_ctrl_new = CTRL_IDLE; + montprod_ctrl_we = 1'b1; + end + + default: + begin + end + + endcase // case (montprod_ctrl_reg) + end // montprod_ctrl + +endmodule // montprod + +//====================================================================== +// EOF montprod.v +//====================================================================== diff --git a/src/rtl/residue.v b/src/rtl/residue.v new file mode 100644 index 0000000..2991dd6 --- /dev/null +++ b/src/rtl/residue.v @@ -0,0 +1,224 @@ +//====================================================================== +// +// residue.v +// --------- +// Modulus 2**2N residue calculator for montgomery calculations. +// +// m_residue_2_2N_array( N, M, Nr) +// Nr = 00...01 ; Nr = 1 == 2**(2N-2N) +// for (int i = 0; i < 2 * N; i++) +// Nr = Nr shift left 1 +// if (Nr less than M) continue; +// Nr = Nr - M +// return Nr +// +// +// +// Author: Peter Magnusson +// Copyright (c) 2015, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module residue( + input wire clk, + input wire reset_n, + + input wire calculate, + output wire ready, + + input wire [07 : 0] nn, + input wire [07 : 0] length, + + output wire [07 : 0] opa_rd_addr, + input wire [31 : 0] opa_rd_data, + output wire [07 : 0] opa_wr_addr, + output wire [31 : 0] opa_wr_data, + output wire opa_wr_we, + + output wire [07 : 0] opm_addr, + input wire [31 : 0] opm_data + +); + +//---------------------------------------------------------------- +// Internal constant and parameter definitions. +//---------------------------------------------------------------- + + +localparam CTRL_IDLE = 4'h0; +localparam CTRL_INIT = 4'h1; +localparam CTRL_INIT_STALL = 4'h2; +localparam CTRL_SHL = 4'h3; +localparam CTRL_SHL_STALL = 4'h4; +localparam CTRL_COMPARE = 4'h5; +localparam CTRL_COMPARE_STALL = 4'h6; +localparam CTRL_SUB = 4'h7; +localparam CTRL_SUB_STALL = 4'h8; +localparam CTRL_LOOP = 4'h9; + +//---------------------------------------------------------------- +// Registers including update variables and write enable. +//---------------------------------------------------------------- + +reg [07 : 0] opa_rd_addr_reg; +reg [07 : 0] opa_wr_addr_reg; +reg [31 : 0] opa_wr_data_reg; +reg opa_wr_we_reg; +reg [07 : 0] opm_addr_reg; +reg ready_reg; +reg ready_new; +reg ready_we; +reg [03 : 0] residue_ctrl_reg; +reg [03 : 0] residue_ctrl_new; +reg residue_ctrl_we; +reg reset_word_index; +reg reset_n_counter; +reg [07 : 0] word_index; + +//---------------------------------------------------------------- +// Concurrent connectivity for ports etc. +//---------------------------------------------------------------- +assign opa_rd_addr = opa_rd_addr_reg; +assign opa_wr_addr = opa_wr_addr_reg; +assign opa_wr_data = opa_wr_data_reg; +assign opm_addr = opm_addr_reg; +assign ready = ready_reg; + + + + + //---------------------------------------------------------------- + // reg_update + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin + if (!reset_n) + begin + residue_ctrl_reg <= CTRL_IDLE; + end + else + begin + if (residue_ctrl_we) + residue_ctrl_reg <= residue_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + //---------------------------------------------------------------- + always @* + begin : process_1_to_2n + end + + //---------------------------------------------------------------- + //---------------------------------------------------------------- + always @* + begin : word_index_process + end + +//---------------------------------------------------------------- +// residue_ctrl +// +// Control FSM for residue +//---------------------------------------------------------------- +always @* + begin : residue_ctrl + ready_new = 1'b0; + ready_we = 1'b0; + residue_ctrl_new = CTRL_IDLE; + residue_ctrl_we = 1'b0; + reset_word_index = 1'b0; + reset_n_counter = 1'b0; + + case (residue_ctrl_reg) + CTRL_IDLE: + if (calculate) + begin + ready_new = 1'b0; + ready_we = 1'b1; + residue_ctrl_new = CTRL_INIT; + residue_ctrl_we = 1'b1; + reset_word_index = 1'b1; + end + + CTRL_INIT: + if (word_index == 8'h0) + begin + residue_ctrl_new = CTRL_INIT_STALL; + residue_ctrl_we = 1'b1; + end + + CTRL_INIT_STALL: + begin + reset_word_index = 1'b1; + reset_n_counter = 1'b1; + residue_ctrl_new = CTRL_COMPARE; + residue_ctrl_we = 1'b1; + end + + CTRL_COMPARE: + begin + end + + CTRL_COMPARE_STALL: + begin + end + + CTRL_SUB: + begin + end + + CTRL_SUB_STALL: + begin + end + + CTRL_SHL: + begin + end + + CTRL_SHL_STALL: + begin + end + + CTRL_LOOP: + begin + end + + default: + begin + end + + endcase + end + +endmodule // residue + +//====================================================================== +// EOF residue.v +//====================================================================== diff --git a/src/rtl/shr32.v b/src/rtl/shr32.v new file mode 100644 index 0000000..840f9df --- /dev/null +++ b/src/rtl/shr32.v @@ -0,0 +1,53 @@ +//====================================================================== +// +// shr32.v +// --------- +// 32bit shifter with carry in / carry out +// +// +// Author: Peter Magnusson +// Copyright (c) 2015, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + + +module shr32( + input [31 : 0] a, + input carry_in, + output wire [31 : 0] adiv2, + output wire carry_out); + + reg [32 : 0] shr_result; + + assign adiv2 = shr_result[32:1]; + assign carry_out = shr_result[0]; + + always @(a, carry_in) + shr_result = { carry_in, a }; +endmodule |