diff options
author | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2018-10-15 15:42:33 +0300 |
---|---|---|
committer | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2018-10-15 15:42:33 +0300 |
commit | 237ea6a8a5012f52a75c7d259a4d71b67da0086a (patch) | |
tree | c99be1f55202fd49b282242cf10331fa4141e675 | |
parent | aec5c7d6333d161282bcb8e0bd928e07b62640ab (diff) |
Some more temporary modules.
-rw-r--r-- | lowlevel/generic/adder32_generic.v | 67 | ||||
-rw-r--r-- | lowlevel/generic/adder47_generic.v | 64 | ||||
-rw-r--r-- | lowlevel/generic/mac16_generic.v | 74 | ||||
-rw-r--r-- | lowlevel/generic/subtractor32_generic.v | 67 | ||||
-rw-r--r-- | mod_adder.v | 304 | ||||
-rw-r--r-- | mod_subtractor.v | 298 |
6 files changed, 874 insertions, 0 deletions
diff --git a/lowlevel/generic/adder32_generic.v b/lowlevel/generic/adder32_generic.v new file mode 100644 index 0000000..eadfb6f --- /dev/null +++ b/lowlevel/generic/adder32_generic.v @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +// +// adder32_generic.v +// ----------------------------------------------------------------------------- +// Generic 32-bit adder. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2016, NORDUnet A/S +// +// 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_generic + ( + input clk, // clock + input [31: 0] a, // operand input + input [31: 0] b, // operand input + output [31: 0] s, // sum output + input c_in, // carry input + output c_out // carry output + ); + + // + // Sum + // + reg [32: 0] s_int; + + always @(posedge clk) + s_int <= {1'b0, a} + {1'b0, b} + {{32{1'b0}}, c_in}; + + // + // Output + // + assign s = s_int[31:0]; + assign c_out = s_int[32]; + +endmodule + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ diff --git a/lowlevel/generic/adder47_generic.v b/lowlevel/generic/adder47_generic.v new file mode 100644 index 0000000..406c175 --- /dev/null +++ b/lowlevel/generic/adder47_generic.v @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +// +// adder47_generic.v +// ----------------------------------------------------------------------------- +// Generic 47-bit adder. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2016, NORDUnet A/S +// +// 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 adder47_generic + ( + input clk, // clock + input [46: 0] a, // operand input + input [46: 0] b, // operand input + output [46: 0] s // sum output + ); + + // + // Sum + // + reg [46: 0] s_int; + + always @(posedge clk) + s_int <= a + b; + + // + // Output + // + assign s = s_int; + +endmodule + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ diff --git a/lowlevel/generic/mac16_generic.v b/lowlevel/generic/mac16_generic.v new file mode 100644 index 0000000..6d120a3 --- /dev/null +++ b/lowlevel/generic/mac16_generic.v @@ -0,0 +1,74 @@ +//------------------------------------------------------------------------------ +// +// mac16_generic.v +// ----------------------------------------------------------------------------- +// Generic 16-bit multiplier and 47-bit accumulator. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2016, NORDUnet A/S +// +// 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 mac16_generic + ( + input clk, // clock + input clr, // clear accumulator (active-high) + input ce, // enable clock (active-high) + input [15: 0] a, // operand input + input [15: 0] b, // operand input + output [46: 0] s // sum output + ); + + // + // Multiplier + // + wire [31: 0] p = {{16{1'b0}}, a} * {{16{1'b0}}, b}; + wire [46: 0] p_ext = {{15{1'b0}}, p}; + + // + // Accumulator + // + reg [46: 0] s_int; + + always @(posedge clk) + // + if (ce) s_int <= clr ? p_ext : p_ext + s_int; + + // + // Output + // + assign s = s_int; + +endmodule + + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ diff --git a/lowlevel/generic/subtractor32_generic.v b/lowlevel/generic/subtractor32_generic.v new file mode 100644 index 0000000..5137ace --- /dev/null +++ b/lowlevel/generic/subtractor32_generic.v @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +// +// subtractor32_generic.v +// ----------------------------------------------------------------------------- +// Generic 32-bit subtractor. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2016, NORDUnet A/S +// +// 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 subtractor32_generic + ( + input clk, + input [31: 0] a, + input [31: 0] b, + output [31: 0] d, + input b_in, + output b_out + ); + + // + // Difference + // + reg [32: 0] d_int; + + always @(posedge clk) + d_int <= {1'b0, a} - {1'b0, b} - {{32{1'b0}}, b_in}; + + // + // Output + // + assign d = d_int[31:0]; + assign b_out = d_int[32]; + +endmodule + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ diff --git a/mod_adder.v b/mod_adder.v new file mode 100644 index 0000000..e6e0db8 --- /dev/null +++ b/mod_adder.v @@ -0,0 +1,304 @@ +//------------------------------------------------------------------------------ +// +// mod_adder.v +// ----------------------------------------------------------------------------- +// Modular adder. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2016, NORDUnet A/S +// +// 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 mod_adder + ( + clk, rst_n, + ena, rdy, + ab_addr, n_addr, s_addr, s_wren, + a_din, b_din, n_din, s_dout + ); + + + // + // Settings + // +`include "ed25519_settings.vh" + + + // + // Parameters + // + parameter OPERAND_NUM_WORDS = 8; + parameter WORD_COUNTER_WIDTH = 3; + + + // + // Handy Numbers + // + localparam [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_ZERO = 0; + localparam [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_LAST = OPERAND_NUM_WORDS - 1; + + + // + // Handy Functions + // + function [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_NEXT_OR_ZERO; + input [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_CURRENT; + begin + WORD_INDEX_NEXT_OR_ZERO = (WORD_INDEX_CURRENT < WORD_INDEX_LAST) ? + WORD_INDEX_CURRENT + 1'b1 : WORD_INDEX_ZERO; + end + endfunction + + + // + // Ports + // + input wire clk; // system clock + input wire rst_n; // active-low async reset + + input wire ena; // enable input + output wire rdy; // ready output + + output wire [WORD_COUNTER_WIDTH-1:0] ab_addr; // index of current A and B words + output wire [WORD_COUNTER_WIDTH-1:0] n_addr; // index of current N word + output wire [WORD_COUNTER_WIDTH-1:0] s_addr; // index of current S word + output wire s_wren; // store current S word now + + input wire [ 31:0] a_din; // A + input wire [ 31:0] b_din; // B + input wire [ 31:0] n_din; // N + output wire [ 31:0] s_dout; // S = (A + B) mod N + + + // + // Word Indices + // + reg [WORD_COUNTER_WIDTH-1:0] index_ab; + reg [WORD_COUNTER_WIDTH-1:0] index_n; + reg [WORD_COUNTER_WIDTH-1:0] index_s; + + /* map registers to output ports */ + assign ab_addr = index_ab; + assign n_addr = index_n; + assign s_addr = index_s; + + + // + // Adder + // + wire [31: 0] add32_s; + wire add32_c_in; + wire add32_c_out; + + `ED25519_ADD32_PRIMITIVE adder32 + ( + .clk (clk), + .a (a_din), + .b (b_din), + .s (add32_s), + .c_in (add32_c_in), + .c_out (add32_c_out) + ); + + + // + // Subtractor + // + wire [31: 0] sub32_d; + wire sub32_b_in; + wire sub32_b_out; + + `ED25519_SUB32_PRIMITIVE subtractor32 + ( + .clk (clk), + .a (add32_s), + .b (n_din), + .d (sub32_d), + .b_in (sub32_b_in), + .b_out (sub32_b_out) + ); + + + // + // FSM + // + + localparam FSM_SHREG_WIDTH = 2*OPERAND_NUM_WORDS + 5; + + reg [FSM_SHREG_WIDTH-1:0] fsm_shreg; + + assign rdy = fsm_shreg[0]; + + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_inc_index_ab = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 1) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 0)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_inc_index_n = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 2) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 1)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_store_sum_ab = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 3) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 2)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_store_sum_ab_n = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 4) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 3)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_store_data_s = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 4) : FSM_SHREG_WIDTH - (2 * OPERAND_NUM_WORDS + 3)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_inc_index_s = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 5) : FSM_SHREG_WIDTH - (2 * OPERAND_NUM_WORDS + 4)]; + + wire fsm_latch_msb_carry = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 2)]; + wire fsm_latch_msb_borrow = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 3)]; + + wire inc_index_ab = |fsm_shreg_inc_index_ab; + wire inc_index_n = |fsm_shreg_inc_index_n; + wire store_sum_ab = |fsm_shreg_store_sum_ab; + wire store_sum_ab_n = |fsm_shreg_store_sum_ab_n; + wire store_data_s = |fsm_shreg_store_data_s; + wire inc_index_s = |fsm_shreg_inc_index_s; + + always @(posedge clk or negedge rst_n) + // + if (rst_n == 1'b0) + // + fsm_shreg <= {{FSM_SHREG_WIDTH-1{1'b0}}, 1'b1}; + // + else begin + // + if (rdy) fsm_shreg <= {ena, {FSM_SHREG_WIDTH-2{1'b0}}, ~ena}; + // + else fsm_shreg <= {1'b0, fsm_shreg[FSM_SHREG_WIDTH-1:1]}; + // + end + + + + + + + + // + // Carry & Borrow Masking Logic + // + reg add32_c_mask; + reg sub32_b_mask; + + always @(posedge clk) begin + // + add32_c_mask <= (index_ab == WORD_INDEX_ZERO) ? 1'b1 : 1'b0; + sub32_b_mask <= (index_n == WORD_INDEX_ZERO) ? 1'b1 : 1'b0; + // + end + + assign add32_c_in = add32_c_out & ~add32_c_mask; + assign sub32_b_in = sub32_b_out & ~sub32_b_mask; + + + // + // Carry & Borrow Latch Logic + // + reg add32_carry_latch; + reg sub32_borrow_latch; + + always @(posedge clk) begin + // + if (fsm_latch_msb_carry) add32_carry_latch <= add32_c_out; + if (fsm_latch_msb_borrow) sub32_borrow_latch <= sub32_b_out; + // + end + + + // + // Intermediate Results + // + reg [32*OPERAND_NUM_WORDS-1:0] s_ab; + reg [32*OPERAND_NUM_WORDS-1:0] s_ab_n; + + always @(posedge clk) + // + if (store_data_s) begin + // + s_ab <= {{32{1'bX}}, s_ab[32*OPERAND_NUM_WORDS-1:32]}; + s_ab_n <= {{32{1'bX}}, s_ab_n[32*OPERAND_NUM_WORDS-1:32]}; + // + end else begin + // + if (store_sum_ab) s_ab <= {add32_s, s_ab[32*OPERAND_NUM_WORDS-1:32]}; + if (store_sum_ab_n) s_ab_n <= {sub32_d, s_ab_n[32*OPERAND_NUM_WORDS-1:32]}; + // + end + + + // + // Word Index Increment Logic + // + always @(posedge clk) + // + if (rdy) begin + // + index_ab <= WORD_INDEX_ZERO; + index_n <= WORD_INDEX_ZERO; + index_s <= WORD_INDEX_ZERO; + // + end else begin + // + if (inc_index_ab) index_ab <= WORD_INDEX_NEXT_OR_ZERO(index_ab); + if (inc_index_n) index_n <= WORD_INDEX_NEXT_OR_ZERO(index_n); + if (inc_index_s) index_s <= WORD_INDEX_NEXT_OR_ZERO(index_s); + // + end + + + // + // Output Sum Selector + // + wire mux_select_ab = sub32_borrow_latch && !add32_carry_latch; + + + // + // Output Data and Write Enable Logic + // + reg s_wren_reg; + reg [31: 0] s_dout_reg; + wire [31: 0] s_dout_mux = mux_select_ab ? s_ab[31:0] : s_ab_n[31:0]; + + assign s_wren = s_wren_reg; + assign s_dout = s_dout_reg; + + always @(posedge clk) + // + if (rdy) begin + // + s_wren_reg <= 1'b0; + s_dout_reg <= {32{1'bX}}; + // + end else begin + // + s_wren_reg <= store_data_s; + s_dout_reg <= store_data_s ? s_dout_mux : {32{1'bX}}; + // + end + + +endmodule + + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ diff --git a/mod_subtractor.v b/mod_subtractor.v new file mode 100644 index 0000000..9b4b7e9 --- /dev/null +++ b/mod_subtractor.v @@ -0,0 +1,298 @@ +//------------------------------------------------------------------------------ +// +// mod_subtractor.v +// ----------------------------------------------------------------------------- +// Modular subtractor. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2016, NORDUnet A/S +// +// 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 mod_subtractor + ( + clk, rst_n, + ena, rdy, + ab_addr, n_addr, d_addr, d_wren, + a_din, b_din, n_din, d_dout + ); + + + // + // Settings + // + `include "ed25519_settings.vh" + + + // + // Parameters + // + parameter OPERAND_NUM_WORDS = 8; + parameter WORD_COUNTER_WIDTH = 3; + + + // + // Handy Numbers + // + localparam [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_ZERO = 0; + localparam [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_LAST = OPERAND_NUM_WORDS - 1; + + + // + // Handy Functions + // + function [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_NEXT_OR_ZERO; + input [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_CURRENT; + begin + WORD_INDEX_NEXT_OR_ZERO = (WORD_INDEX_CURRENT < WORD_INDEX_LAST) ? + WORD_INDEX_CURRENT + 1'b1 : WORD_INDEX_ZERO; + end + endfunction + + + // + // Ports + // + input wire clk; // system clock + input wire rst_n; // active-low async reset + + input wire ena; // enable input + output wire rdy; // ready output + + output wire [WORD_COUNTER_WIDTH-1:0] ab_addr; // index of current A and B words + output wire [WORD_COUNTER_WIDTH-1:0] n_addr; // index of current N word + output wire [WORD_COUNTER_WIDTH-1:0] d_addr; // index of current D word + output wire d_wren; // store current D word now + + input wire [ 31:0] a_din; // A + input wire [ 31:0] b_din; // B + input wire [ 31:0] n_din; // N + output wire [ 31:0] d_dout; // D = (A - B) mod N + + + // + // Word Indices + // + reg [WORD_COUNTER_WIDTH-1:0] index_ab; + reg [WORD_COUNTER_WIDTH-1:0] index_n; + reg [WORD_COUNTER_WIDTH-1:0] index_d; + + /* map registers to output ports */ + assign ab_addr = index_ab; + assign n_addr = index_n; + assign d_addr = index_d; + + + // + // Subtractor + // + wire [31: 0] sub32_d; + wire sub32_b_in; + wire sub32_b_out; + + `ED25519_SUB32_PRIMITIVE subtractor32 + ( + .clk (clk), + .a (a_din), + .b (b_din), + .d (sub32_d), + .b_in (sub32_b_in), + .b_out (sub32_b_out) + ); + + + // + // Adder + // + wire [31: 0] add32_s; + wire add32_c_in; + wire add32_c_out; + + `ED25519_ADD32_PRIMITIVE adder32 + ( + .clk (clk), + .a (sub32_d), + .b (n_din), + .s (add32_s), + .c_in (add32_c_in), + .c_out (add32_c_out) + ); + + + // + // FSM + // + + localparam FSM_SHREG_WIDTH = 2*OPERAND_NUM_WORDS + 5; + + reg [FSM_SHREG_WIDTH-1:0] fsm_shreg; + + assign rdy = fsm_shreg[0]; + + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_inc_index_ab = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 1) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 0)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_inc_index_n = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 2) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 1)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_store_dif_ab = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 3) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 2)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_store_dif_ab_n = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 4) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 3)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_store_data_d = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 4) : FSM_SHREG_WIDTH - (2 * OPERAND_NUM_WORDS + 3)]; + wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_inc_index_d = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 5) : FSM_SHREG_WIDTH - (2 * OPERAND_NUM_WORDS + 4)]; + + wire fsm_latch_msb_borrow = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 2)]; + + wire inc_index_ab = |fsm_shreg_inc_index_ab; + wire inc_index_n = |fsm_shreg_inc_index_n; + wire store_dif_ab = |fsm_shreg_store_dif_ab; + wire store_dif_ab_n = |fsm_shreg_store_dif_ab_n; + wire store_data_d = |fsm_shreg_store_data_d; + wire inc_index_d = |fsm_shreg_inc_index_d; + + always @(posedge clk or negedge rst_n) + // + if (rst_n == 1'b0) + // + fsm_shreg <= {{FSM_SHREG_WIDTH-1{1'b0}}, 1'b1}; + // + else begin + // + if (rdy) fsm_shreg <= {ena, {FSM_SHREG_WIDTH-2{1'b0}}, ~ena}; + // + else fsm_shreg <= {1'b0, fsm_shreg[FSM_SHREG_WIDTH-1:1]}; + // + end + + + // + // Borrow & Carry Masking Logic + // + reg sub32_b_mask; + reg add32_c_mask; + + + always @(posedge clk) begin + // + sub32_b_mask <= (index_ab == WORD_INDEX_ZERO) ? 1'b1 : 1'b0; + add32_c_mask <= (index_n == WORD_INDEX_ZERO) ? 1'b1 : 1'b0; + // + end + + assign sub32_b_in = sub32_b_out & ~sub32_b_mask; + assign add32_c_in = add32_c_out & ~add32_c_mask; + + + + // + // Borrow & Carry Latch Logic + // + reg sub32_borrow_latch; + + always @(posedge clk) begin + // + if (fsm_latch_msb_borrow) sub32_borrow_latch <= sub32_b_out; + // + end + + + // + // Intermediate Results + // + reg [32*OPERAND_NUM_WORDS-1:0] d_ab; + reg [32*OPERAND_NUM_WORDS-1:0] d_ab_n; + + always @(posedge clk) + // + if (store_data_d) begin + // + d_ab <= {{32{1'bX}}, d_ab[32*OPERAND_NUM_WORDS-1:32]}; + d_ab_n <= {{32{1'bX}}, d_ab_n[32*OPERAND_NUM_WORDS-1:32]}; + // + end else begin + // + if (store_dif_ab) d_ab <= {sub32_d, d_ab[32*OPERAND_NUM_WORDS-1:32]}; + if (store_dif_ab_n) d_ab_n <= {add32_s, d_ab_n[32*OPERAND_NUM_WORDS-1:32]}; + // + end + + + // + // Word Index Increment Logic + // + always @(posedge clk) + // + if (rdy) begin + // + index_ab <= WORD_INDEX_ZERO; + index_n <= WORD_INDEX_ZERO; + index_d <= WORD_INDEX_ZERO; + // + end else begin + // + if (inc_index_ab) index_ab <= WORD_INDEX_NEXT_OR_ZERO(index_ab); + if (inc_index_n) index_n <= WORD_INDEX_NEXT_OR_ZERO(index_n); + if (inc_index_d) index_d <= WORD_INDEX_NEXT_OR_ZERO(index_d); + // + end + + + // + // Output Sum Selector + // + wire mux_select_ab_n = sub32_borrow_latch; + + + // + // Output Data and Write Enable Logic + // + reg d_wren_reg; + reg [31: 0] d_dout_reg; + wire [31: 0] d_dout_mux = mux_select_ab_n ? d_ab_n[31:0] : d_ab[31:0]; + + assign d_wren = d_wren_reg; + assign d_dout = d_dout_reg; + + always @(posedge clk) + // + if (rdy) begin + // + d_wren_reg <= 1'b0; + d_dout_reg <= {32{1'bX}}; + // + end else begin + // + d_wren_reg <= store_data_d; + d_dout_reg <= store_data_d ? d_dout_mux : {32{1'bX}}; + // + end + + +endmodule + + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ |