diff options
author | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2016-10-31 00:14:51 +0300 |
---|---|---|
committer | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2016-10-31 00:14:51 +0300 |
commit | 25e338149fdb8e06c82d99600769a8498a85ef2c (patch) | |
tree | cf4b855bcf1083f3cffebf6a98b5aaad45baf362 /rtl/modular/modular_invertor/modular_invertor.v |
Initial commit of base point multiplier core for ECDSA curve P-256.
Diffstat (limited to 'rtl/modular/modular_invertor/modular_invertor.v')
-rw-r--r-- | rtl/modular/modular_invertor/modular_invertor.v | 981 |
1 files changed, 981 insertions, 0 deletions
diff --git a/rtl/modular/modular_invertor/modular_invertor.v b/rtl/modular/modular_invertor/modular_invertor.v new file mode 100644 index 0000000..e9f2460 --- /dev/null +++ b/rtl/modular/modular_invertor/modular_invertor.v @@ -0,0 +1,981 @@ +//------------------------------------------------------------------------------ +// +// modular_invertor.v +// ----------------------------------------------------------------------------- +// Modular invertor.
+// +// 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 modular_invertor
+ (
+ clk, rst_n,
+ ena, rdy,
+ a_addr, q_addr, a1_addr, a1_wren, + a_din, q_din, a1_dout
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter MAX_OPERAND_WIDTH = 256;
+
+
+ //
+ // clog2
+ //
+`include "modinv_clog2.v"
+
+
+ //
+ // More Parameters
+ //
+ localparam OPERAND_NUM_WORDS = MAX_OPERAND_WIDTH / 32;
+ localparam OPERAND_ADDR_BITS = clog2(OPERAND_NUM_WORDS);
+
+ localparam BUFFER_NUM_WORDS = OPERAND_NUM_WORDS + 1;
+ localparam BUFFER_ADDR_BITS = clog2(BUFFER_NUM_WORDS);
+
+ localparam LOOP_NUM_ROUNDS = 2 * MAX_OPERAND_WIDTH;
+ localparam ROUND_COUNTER_BITS = clog2(LOOP_NUM_ROUNDS);
+
+ localparam K_NUM_BITS = clog2(LOOP_NUM_ROUNDS + 1);
+
+
+ //
+ // Ports
+ // + input wire clk;
+ input wire rst_n;
+
+ input wire ena;
+ output wire rdy;
+
+ output wire [OPERAND_ADDR_BITS-1:0] a_addr;
+ output reg [OPERAND_ADDR_BITS-1:0] q_addr;
+ output wire [OPERAND_ADDR_BITS-1:0] a1_addr;
+ output wire a1_wren;
+ + input wire [32-1:0] a_din;
+ input wire [32-1:0] q_din;
+ output wire [32-1:0] a1_dout;
+
+
+ //
+ // "Redundant" Power of 2 (K)
+ //
+ reg [K_NUM_BITS-1:0] k;
+
+
+ //
+ // Buffers
+ //
+ reg [BUFFER_ADDR_BITS-1:0] buf_r_wr_addr;
+ reg [BUFFER_ADDR_BITS-1:0] buf_r_rd_addr;
+ reg buf_r_wr_en;
+ reg [ 32-1:0] buf_r_wr_din;
+ wire [ 32-1:0] buf_r_wr_dout;
+ wire [ 32-1:0] buf_r_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_r
+ ( .clk(clk), + .a_addr(buf_r_wr_addr), .a_out(buf_r_wr_dout), .a_wr(buf_r_wr_en), .a_in(buf_r_wr_din), + .b_addr(buf_r_rd_addr), .b_out(buf_r_rd_dout) + );
+
+ reg [BUFFER_ADDR_BITS-1:0] buf_s_wr_addr;
+ reg [BUFFER_ADDR_BITS-1:0] buf_s_rd_addr;
+ reg buf_s_wr_en;
+ reg [ 32-1:0] buf_s_wr_din;
+ wire [ 32-1:0] buf_s_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_s
+ ( .clk(clk), + .a_addr(buf_s_wr_addr), .a_out(), .a_wr(buf_s_wr_en), .a_in(buf_s_wr_din), + .b_addr(buf_s_rd_addr), .b_out(buf_s_rd_dout) + );
+
+ reg [BUFFER_ADDR_BITS-1:0] buf_u_wr_addr;
+ reg [BUFFER_ADDR_BITS-1:0] buf_u_rd_addr;
+ reg buf_u_wr_en;
+ reg [ 32-1:0] buf_u_wr_din;
+ wire [ 32-1:0] buf_u_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_u
+ ( .clk(clk), + .a_addr(buf_u_wr_addr), .a_out(), .a_wr(buf_u_wr_en), .a_in(buf_u_wr_din), + .b_addr(buf_u_rd_addr), .b_out(buf_u_rd_dout) + );
+
+ reg [BUFFER_ADDR_BITS-1:0] buf_v_wr_addr;
+ reg [BUFFER_ADDR_BITS-1:0] buf_v_rd_addr;
+ reg buf_v_wr_en;
+ reg [ 32-1:0] buf_v_wr_din;
+ wire [ 32-1:0] buf_v_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_v
+ ( .clk(clk), + .a_addr(buf_v_wr_addr), .a_out(), .a_wr(buf_v_wr_en), .a_in(buf_v_wr_din), + .b_addr(buf_v_rd_addr), .b_out(buf_v_rd_dout) + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_r_dbl_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_r_dbl_rd_addr;
+ wire buf_r_dbl_wr_en;
+ wire [ 32-1:0] buf_r_dbl_wr_din;
+ wire [ 32-1:0] buf_r_dbl_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_r_dbl
+ ( .clk(clk), + .a_addr(buf_r_dbl_wr_addr), .a_out(), .a_wr(buf_r_dbl_wr_en), .a_in(buf_r_dbl_wr_din), + .b_addr(buf_r_dbl_rd_addr), .b_out(buf_r_dbl_rd_dout) + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_s_dbl_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_s_dbl_rd_addr;
+ wire buf_s_dbl_wr_en;
+ wire [ 32-1:0] buf_s_dbl_wr_din;
+ wire [ 32-1:0] buf_s_dbl_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_s_dbl
+ ( .clk(clk), + .a_addr(buf_s_dbl_wr_addr), .a_out(), .a_wr(buf_s_dbl_wr_en), .a_in(buf_s_dbl_wr_din), + .b_addr(buf_s_dbl_rd_addr), .b_out(buf_s_dbl_rd_dout) + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_r_plus_s_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_r_plus_s_rd_addr;
+ wire buf_r_plus_s_wr_en;
+ wire [ 32-1:0] buf_r_plus_s_wr_din;
+ wire [ 32-1:0] buf_r_plus_s_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_r_plus_s
+ ( .clk(clk), + .a_addr(buf_r_plus_s_wr_addr), .a_out(), .a_wr(buf_r_plus_s_wr_en), .a_in(buf_r_plus_s_wr_din), + .b_addr(buf_r_plus_s_rd_addr), .b_out(buf_r_plus_s_rd_dout) + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_u_minus_v_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_u_minus_v_rd_addr;
+ wire buf_u_minus_v_wr_en;
+ wire [ 32-1:0] buf_u_minus_v_wr_din;
+ wire [ 32-1:0] buf_u_minus_v_wr_dout;
+
+ assign buf_u_minus_v_rd_addr = ~buf_u_minus_v_wr_addr;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_u_minus_v
+ ( .clk(clk), + .a_addr(buf_u_minus_v_wr_addr), .a_out(buf_u_minus_v_wr_dout), .a_wr(buf_u_minus_v_wr_en), .a_in(buf_u_minus_v_wr_din), + .b_addr(buf_u_minus_v_rd_addr), .b_out() + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_v_minus_u_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_v_minus_u_rd_addr;
+ wire buf_v_minus_u_wr_en;
+ wire [ 32-1:0] buf_v_minus_u_wr_din;
+ wire [ 32-1:0] buf_v_minus_u_wr_dout;
+
+ assign buf_v_minus_u_rd_addr = ~buf_v_minus_u_wr_addr;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_v_minus_u
+ ( .clk(clk), + .a_addr(buf_v_minus_u_wr_addr), .a_out(buf_v_minus_u_wr_dout), .a_wr(buf_v_minus_u_wr_en), .a_in(buf_v_minus_u_wr_din), + .b_addr(buf_v_minus_u_rd_addr), .b_out() + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_u_half_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_u_half_rd_addr;
+ wire buf_u_half_wr_en;
+ wire [ 32-1:0] buf_u_half_wr_din;
+ wire [ 32-1:0] buf_u_half_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_u_half
+ ( .clk(clk), + .a_addr(buf_u_half_wr_addr), .a_out(), .a_wr(buf_u_half_wr_en), .a_in(buf_u_half_wr_din), + .b_addr(buf_u_half_rd_addr), .b_out(buf_u_half_rd_dout) + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_v_half_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_v_half_rd_addr;
+ wire buf_v_half_wr_en;
+ wire [ 32-1:0] buf_v_half_wr_din;
+ wire [ 32-1:0] buf_v_half_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_v_half
+ ( .clk(clk), + .a_addr(buf_v_half_wr_addr), .a_out(), .a_wr(buf_v_half_wr_en), .a_in(buf_v_half_wr_din), + .b_addr(buf_v_half_rd_addr), .b_out(buf_v_half_rd_dout) + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_u_minus_v_half_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_u_minus_v_half_rd_addr;
+ wire buf_u_minus_v_half_wr_en;
+ wire [ 32-1:0] buf_u_minus_v_half_wr_din;
+ wire [ 32-1:0] buf_u_minus_v_half_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_u_minus_v_half
+ ( .clk(clk), + .a_addr(buf_u_minus_v_half_wr_addr), .a_out(), .a_wr(buf_u_minus_v_half_wr_en), .a_in(buf_u_minus_v_half_wr_din), + .b_addr(buf_u_minus_v_half_rd_addr), .b_out(buf_u_minus_v_half_rd_dout) + );
+
+ wire [BUFFER_ADDR_BITS-1:0] buf_v_minus_u_half_wr_addr;
+ wire [BUFFER_ADDR_BITS-1:0] buf_v_minus_u_half_rd_addr;
+ wire buf_v_minus_u_half_wr_en;
+ wire [ 32-1:0] buf_v_minus_u_half_wr_din;
+ wire [ 32-1:0] buf_v_minus_u_half_rd_dout;
+
+ bram_1rw_1ro_readfirst #
+ ( .MEM_WIDTH(32), .MEM_ADDR_BITS(BUFFER_ADDR_BITS) + )
+ buf_v_minus_u_half
+ ( .clk(clk), + .a_addr(buf_v_minus_u_half_wr_addr), .a_out(), .a_wr(buf_v_minus_u_half_wr_en), .a_in(buf_v_minus_u_half_wr_din), + .b_addr(buf_v_minus_u_half_rd_addr), .b_out(buf_v_minus_u_half_rd_dout) + );
+
+
+ //
+ // Helper Modules
+ //
+ wire helper_init_ena;
+ wire helper_invert_precalc_ena;
+ wire helper_invert_compare_ena;
+ wire helper_invert_update_ena;
+ wire helper_reduce_precalc_ena;
+ wire helper_reduce_update_ena;
+ wire helper_copy_ena;
+
+ wire helper_init_rdy;
+ wire helper_invert_precalc_rdy;
+ wire helper_invert_compare_rdy;
+ wire helper_invert_update_rdy;
+ wire helper_reduce_precalc_rdy;
+ wire helper_reduce_update_rdy;
+ wire helper_copy_rdy;
+
+ wire helper_init_done = helper_init_rdy && !helper_init_ena;
+ wire helper_invert_precalc_done = helper_invert_precalc_rdy && !helper_invert_precalc_ena;
+ wire helper_invert_compare_done = helper_invert_compare_rdy && !helper_invert_compare_ena;
+ wire helper_invert_update_done = helper_invert_update_rdy && !helper_invert_update_ena;
+ wire helper_reduce_precalc_done = helper_reduce_precalc_rdy && !helper_reduce_precalc_ena;
+ wire helper_reduce_update_done = helper_reduce_update_rdy && !helper_reduce_update_ena;
+ wire helper_copy_done = helper_copy_rdy && !helper_copy_ena;
+
+
+ //
+ // Helper Module - Initialization
+ //
+ wire [ BUFFER_ADDR_BITS-1:0] helper_init_r_addr;
+ wire [ BUFFER_ADDR_BITS-1:0] helper_init_s_addr;
+ wire [ BUFFER_ADDR_BITS-1:0] helper_init_u_addr;
+ wire [ BUFFER_ADDR_BITS-1:0] helper_init_v_addr;
+ wire [OPERAND_ADDR_BITS-1:0] helper_init_q_addr;
+
+ wire helper_init_r_wren;
+ wire helper_init_s_wren;
+ wire helper_init_u_wren;
+ wire helper_init_v_wren;
+
+ wire [ 32-1:0] helper_init_r_data;
+ wire [ 32-1:0] helper_init_s_data;
+ wire [ 32-1:0] helper_init_u_data;
+ wire [ 32-1:0] helper_init_v_data;
+
+ modinv_helper_init #
+ (
+ .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS),
+ .OPERAND_ADDR_BITS (OPERAND_ADDR_BITS),
+
+ .BUFFER_NUM_WORDS (BUFFER_NUM_WORDS),
+ .BUFFER_ADDR_BITS (BUFFER_ADDR_BITS)
+ )
+ helper_init
+ (
+ .clk (clk),
+ .rst_n (rst_n),
+
+ .ena (helper_init_ena),
+ .rdy (helper_init_rdy),
+
+ .a_addr (a_addr),
+ .q_addr (helper_init_q_addr),
+
+ .r_addr (helper_init_r_addr),
+ .s_addr (helper_init_s_addr),
+ .u_addr (helper_init_u_addr),
+ .v_addr (helper_init_v_addr),
+
+ .q_din (q_din),
+ .a_din (a_din),
+
+ .r_dout (helper_init_r_data),
+ .s_dout (helper_init_s_data),
+ .u_dout (helper_init_u_data),
+ .v_dout (helper_init_v_data),
+
+ .r_wren (helper_init_r_wren),
+ .s_wren (helper_init_s_wren),
+ .u_wren (helper_init_u_wren),
+ .v_wren (helper_init_v_wren)
+ );
+
+
+ //
+ // Helper Module - Inversion Pre-Calculation
+ //
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_precalc_r_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_precalc_s_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_precalc_u_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_precalc_v_addr;
+
+ modinv_helper_invert_precalc #
+ (
+ .BUFFER_NUM_WORDS (BUFFER_NUM_WORDS),
+ .BUFFER_ADDR_BITS (BUFFER_ADDR_BITS)
+ )
+ helper_invert_precalc
+ (
+ .clk (clk),
+ .rst_n (rst_n),
+
+ .ena (helper_invert_precalc_ena),
+ .rdy (helper_invert_precalc_rdy),
+
+ .r_addr (helper_invert_precalc_r_addr),
+ .s_addr (helper_invert_precalc_s_addr),
+ .u_addr (helper_invert_precalc_u_addr),
+ .v_addr (helper_invert_precalc_v_addr),
+
+ .r_din (buf_r_rd_dout),
+ .s_din (buf_s_rd_dout),
+ .u_din (buf_u_rd_dout),
+ .v_din (buf_v_rd_dout),
+
+ .r_dbl_addr (buf_r_dbl_wr_addr),
+ .s_dbl_addr (buf_s_dbl_wr_addr),
+ .r_plus_s_addr (buf_r_plus_s_wr_addr),
+
+ .u_half_addr (buf_u_half_wr_addr),
+ .v_half_addr (buf_v_half_wr_addr),
+ .u_minus_v_addr (buf_u_minus_v_wr_addr),
+ .v_minus_u_addr (buf_v_minus_u_wr_addr),
+ .u_minus_v_half_addr (buf_u_minus_v_half_wr_addr),
+ .v_minus_u_half_addr (buf_v_minus_u_half_wr_addr),
+
+ .r_dbl_dout (buf_r_dbl_wr_din),
+ .s_dbl_dout (buf_s_dbl_wr_din),
+ .r_plus_s_dout (buf_r_plus_s_wr_din),
+
+ .u_half_dout (buf_u_half_wr_din),
+ .v_half_dout (buf_v_half_wr_din),
+ .u_minus_v_dout (buf_u_minus_v_wr_din),
+ .v_minus_u_dout (buf_v_minus_u_wr_din),
+ .u_minus_v_half_dout (buf_u_minus_v_half_wr_din),
+ .v_minus_u_half_dout (buf_v_minus_u_half_wr_din),
+
+ .r_dbl_wren (buf_r_dbl_wr_en),
+ .s_dbl_wren (buf_s_dbl_wr_en),
+ .r_plus_s_wren (buf_r_plus_s_wr_en),
+
+ .u_half_wren (buf_u_half_wr_en),
+ .v_half_wren (buf_v_half_wr_en),
+ .u_minus_v_wren (buf_u_minus_v_wr_en),
+ .v_minus_u_wren (buf_v_minus_u_wr_en),
+ .u_minus_v_half_wren (buf_u_minus_v_half_wr_en),
+ .v_minus_u_half_wren (buf_v_minus_u_half_wr_en),
+
+ .u_minus_v_din (buf_u_minus_v_wr_dout),
+ .v_minus_u_din (buf_v_minus_u_wr_dout)
+ );
+
+
+ //
+ // Helper Module - Inversion Comparison
+ //
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_compare_u_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_compare_v_addr;
+
+ wire flag_invert_u_gt_v;
+ wire flag_invert_v_eq_1; + wire flag_invert_u_is_even;
+ wire flag_invert_v_is_even;
+
+ modinv_helper_invert_compare #
+ (
+ .BUFFER_NUM_WORDS (BUFFER_NUM_WORDS),
+ .BUFFER_ADDR_BITS (BUFFER_ADDR_BITS)
+ )
+ helper_invert_compare
+ (
+ .clk (clk),
+ .rst_n (rst_n),
+
+ .ena (helper_invert_compare_ena),
+ .rdy (helper_invert_compare_rdy),
+
+ .u_addr (helper_invert_compare_u_addr),
+ .v_addr (helper_invert_compare_v_addr),
+
+ .u_din (buf_u_rd_dout),
+ .v_din (buf_v_rd_dout),
+
+ .u_gt_v (flag_invert_u_gt_v),
+ .v_eq_1 (flag_invert_v_eq_1), + .u_is_even (flag_invert_u_is_even),
+ .v_is_even (flag_invert_v_is_even)
+ );
+
+
+ //
+ // Helper Module - Inversion Update
+ //
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_update_r_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_update_s_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_update_u_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_invert_update_v_addr;
+
+ wire helper_invert_update_r_wren;
+ wire helper_invert_update_s_wren;
+ wire helper_invert_update_u_wren;
+ wire helper_invert_update_v_wren;
+
+ wire [ 32-1:0] helper_invert_update_r_data;
+ wire [ 32-1:0] helper_invert_update_s_data;
+ wire [ 32-1:0] helper_invert_update_u_data;
+ wire [ 32-1:0] helper_invert_update_v_data;
+
+ modinv_helper_invert_update #
+ (
+ .BUFFER_NUM_WORDS (BUFFER_NUM_WORDS),
+ .BUFFER_ADDR_BITS (BUFFER_ADDR_BITS)
+ )
+ helper_invert_update
+ (
+ .clk (clk),
+ .rst_n (rst_n),
+
+ .ena (helper_invert_update_ena),
+ .rdy (helper_invert_update_rdy),
+
+ .u_gt_v (flag_invert_u_gt_v),
+ .v_eq_1 (flag_invert_v_eq_1), + .u_is_even (flag_invert_u_is_even),
+ .v_is_even (flag_invert_v_is_even),
+
+ .r_addr (helper_invert_update_r_addr),
+ .s_addr (helper_invert_update_s_addr),
+ .u_addr (helper_invert_update_u_addr),
+ .v_addr (helper_invert_update_v_addr),
+
+ .r_wren (helper_invert_update_r_wren),
+ .s_wren (helper_invert_update_s_wren),
+ .u_wren (helper_invert_update_u_wren),
+ .v_wren (helper_invert_update_v_wren),
+
+ .r_dout (helper_invert_update_r_data),
+ .s_dout (helper_invert_update_s_data),
+ .u_dout (helper_invert_update_u_data),
+ .v_dout (helper_invert_update_v_data),
+
+ .r_dbl_addr (buf_r_dbl_rd_addr),
+ .s_dbl_addr (buf_s_dbl_rd_addr),
+ .r_plus_s_addr (buf_r_plus_s_rd_addr),
+ .u_half_addr (buf_u_half_rd_addr),
+ .v_half_addr (buf_v_half_rd_addr),
+ .u_minus_v_half_addr (buf_u_minus_v_half_rd_addr),
+ .v_minus_u_half_addr (buf_v_minus_u_half_rd_addr),
+
+ .r_dbl_din (buf_r_dbl_rd_dout),
+ .s_dbl_din (buf_s_dbl_rd_dout),
+ .r_plus_s_din (buf_r_plus_s_rd_dout),
+ .u_half_din (buf_u_half_rd_dout),
+ .v_half_din (buf_v_half_rd_dout),
+ .u_minus_v_half_din (buf_u_minus_v_half_rd_dout),
+ .v_minus_u_half_din (buf_v_minus_u_half_rd_dout)
+ );
+
+
+ //
+ // Helper Module - Reduction Pre-Calculation
+ //
+ wire [ BUFFER_ADDR_BITS-1:0] helper_reduce_precalc_r_addr;
+ wire [ BUFFER_ADDR_BITS-1:0] helper_reduce_precalc_s_addr;
+ wire [ BUFFER_ADDR_BITS-1:0] helper_reduce_precalc_u_addr;
+ wire [ BUFFER_ADDR_BITS-1:0] helper_reduce_precalc_v_addr;
+ wire [OPERAND_ADDR_BITS-1:0] helper_reduce_precalc_q_addr;
+
+ wire helper_reduce_precalc_r_wren;
+ wire helper_reduce_precalc_u_wren;
+ wire helper_reduce_precalc_v_wren;
+
+ wire [ 32-1:0] helper_reduce_precalc_r_data;
+ wire [ 32-1:0] helper_reduce_precalc_u_data;
+ wire [ 32-1:0] helper_reduce_precalc_v_data;
+
+ wire flag_reduce_s_is_odd;
+ wire flag_invert_k_is_nul; +
+ modinv_helper_reduce_precalc #
+ (
+ .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS),
+ .OPERAND_ADDR_BITS (OPERAND_ADDR_BITS),
+ .BUFFER_NUM_WORDS (BUFFER_NUM_WORDS),
+ .BUFFER_ADDR_BITS (BUFFER_ADDR_BITS),
+ .K_NUM_BITS (K_NUM_BITS)
+ )
+ helper_reduce_precalc
+ (
+ .clk (clk),
+ .rst_n (rst_n),
+
+ .ena (helper_reduce_precalc_ena),
+ .rdy (helper_reduce_precalc_rdy),
+
+ .r_addr (helper_reduce_precalc_r_addr),
+ .s_addr (helper_reduce_precalc_s_addr),
+ .u_addr (helper_reduce_precalc_u_addr),
+ .v_addr (helper_reduce_precalc_v_addr),
+ .q_addr (helper_reduce_precalc_q_addr),
+
+ .k (k),
+
+ .s_is_odd (flag_reduce_s_is_odd),
+ .k_is_nul (flag_reduce_k_is_nul),
+
+ .r_din (buf_r_wr_dout),
+ .s_din (buf_s_rd_dout),
+ .q_din (q_din),
+
+ .r_wren (helper_reduce_precalc_r_wren),
+ .u_wren (helper_reduce_precalc_u_wren),
+ .v_wren (helper_reduce_precalc_v_wren),
+
+ .r_dout (helper_reduce_precalc_r_data),
+ .u_dout (helper_reduce_precalc_u_data),
+ .v_dout (helper_reduce_precalc_v_data)
+ );
+
+ //
+ // Helper Module - Reduction Update
+ //
+ wire [BUFFER_ADDR_BITS-1:0] helper_reduce_update_s_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_reduce_update_u_addr;
+ wire [BUFFER_ADDR_BITS-1:0] helper_reduce_update_v_addr;
+
+ wire helper_reduce_update_s_wren;
+
+ wire [ 32-1:0] helper_reduce_update_s_data;
+
+ modinv_helper_reduce_update #
+ (
+ .BUFFER_NUM_WORDS (BUFFER_NUM_WORDS),
+ .BUFFER_ADDR_BITS (BUFFER_ADDR_BITS)
+ )
+ helper_reduce_update
+ (
+ .clk (clk),
+ .rst_n (rst_n),
+
+ .ena (helper_reduce_update_ena),
+ .rdy (helper_reduce_update_rdy),
+
+ .s_is_odd (flag_reduce_s_is_odd),
+ .k_is_nul (flag_reduce_k_is_nul),
+
+ .s_addr (helper_reduce_update_s_addr),
+ .u_addr (helper_reduce_update_u_addr),
+ .v_addr (helper_reduce_update_v_addr),
+
+ .s_wren (helper_reduce_update_s_wren),
+
+ .s_dout (helper_reduce_update_s_data),
+
+ .u_din (buf_u_rd_dout),
+ .v_din (buf_v_rd_dout)
+ );
+
+
+ //
+ // Helper Module - Copying
+ //
+ wire [BUFFER_ADDR_BITS-1:0] helper_copy_s_addr;
+
+ modinv_helper_copy #
+ (
+ .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS),
+ .OPERAND_ADDR_BITS (OPERAND_ADDR_BITS),
+
+ .BUFFER_NUM_WORDS (BUFFER_NUM_WORDS),
+ .BUFFER_ADDR_BITS (BUFFER_ADDR_BITS)
+ )
+ helper_copy
+ (
+ .clk (clk),
+ .rst_n (rst_n),
+
+ .ena (helper_copy_ena),
+ .rdy (helper_copy_rdy),
+
+ .s_addr (helper_copy_s_addr),
+ .a1_addr (a1_addr),
+
+ .s_din (buf_s_rd_dout),
+
+ .a1_dout (a1_dout),
+
+ .a1_wren (a1_wren)
+ );
+
+
+ //
+ // Round Counter
+ //
+ reg [ROUND_COUNTER_BITS-1:0] round_counter;
+ wire [ROUND_COUNTER_BITS-1:0] round_counter_max = LOOP_NUM_ROUNDS - 1;
+ wire [ROUND_COUNTER_BITS-1:0] round_counter_zero = {ROUND_COUNTER_BITS{1'b0}};
+ wire [ROUND_COUNTER_BITS-1:0] round_counter_next =
+ (round_counter < round_counter_max) ? round_counter + 1'b1 : round_counter_zero;
+
+
+ //
+ // FSM
+ //
+ localparam FSM_STATE_IDLE = 4'd0;
+
+ localparam FSM_STATE_INIT = 4'd1;
+
+ localparam FSM_STATE_INVERT_PRECALC = 4'd11;
+ localparam FSM_STATE_INVERT_COMPARE = 4'd12;
+ localparam FSM_STATE_INVERT_UPDATE = 4'd13;
+
+ localparam FSM_STATE_REDUCE_PRECALC = 4'd14;
+ localparam FSM_STATE_REDUCE_UPDATE = 4'd15;
+
+ localparam FSM_STATE_COPY = 4'd2;
+
+ localparam FSM_STATE_DONE = 4'd3;
+
+ reg [3:0] fsm_state = FSM_STATE_IDLE;
+ reg [3:0] fsm_state_dly = FSM_STATE_IDLE;
+
+ wire fsm_state_new = (fsm_state != fsm_state_dly);
+
+ wire [3:0] fsm_state_invert_next = (round_counter < round_counter_max) ?
+ FSM_STATE_INVERT_PRECALC : FSM_STATE_REDUCE_PRECALC;
+
+ wire [3:0] fsm_state_reduce_next = (round_counter < round_counter_max) ?
+ FSM_STATE_REDUCE_PRECALC : FSM_STATE_COPY;
+ + always @(posedge clk or negedge rst_n) + // + if (rst_n == 1'b0) fsm_state <= FSM_STATE_IDLE; + else case (fsm_state)
+ FSM_STATE_IDLE: fsm_state <= ena ? FSM_STATE_INIT : FSM_STATE_IDLE;
+ FSM_STATE_INIT: fsm_state <= helper_init_done ? FSM_STATE_INVERT_PRECALC : FSM_STATE_INIT;
+ FSM_STATE_INVERT_PRECALC: fsm_state <= helper_invert_precalc_done ? FSM_STATE_INVERT_COMPARE : FSM_STATE_INVERT_PRECALC;
+ FSM_STATE_INVERT_COMPARE: fsm_state <= helper_invert_compare_done ? FSM_STATE_INVERT_UPDATE : FSM_STATE_INVERT_COMPARE;
+ FSM_STATE_INVERT_UPDATE: fsm_state <= helper_invert_update_done ? fsm_state_invert_next : FSM_STATE_INVERT_UPDATE;
+ FSM_STATE_REDUCE_PRECALC: fsm_state <= helper_reduce_precalc_done ? FSM_STATE_REDUCE_UPDATE : FSM_STATE_REDUCE_PRECALC;
+ FSM_STATE_REDUCE_UPDATE: fsm_state <= helper_reduce_update_done ? fsm_state_reduce_next : FSM_STATE_REDUCE_UPDATE;
+ FSM_STATE_COPY: fsm_state <= helper_copy_done ? FSM_STATE_DONE : FSM_STATE_COPY;
+ FSM_STATE_DONE: fsm_state <= FSM_STATE_IDLE;
+ default: fsm_state <= FSM_STATE_IDLE; + endcase
+
+ always @(posedge clk or negedge rst_n) + // + if (rst_n == 1'b0) fsm_state_dly <= FSM_STATE_IDLE; + else fsm_state_dly <= fsm_state;
+
+
+ assign helper_init_ena = (fsm_state == FSM_STATE_INIT) && fsm_state_new;
+ assign helper_invert_precalc_ena = (fsm_state == FSM_STATE_INVERT_PRECALC) && fsm_state_new;
+ assign helper_invert_compare_ena = (fsm_state == FSM_STATE_INVERT_COMPARE) && fsm_state_new;
+ assign helper_invert_update_ena = (fsm_state == FSM_STATE_INVERT_UPDATE) && fsm_state_new;
+ assign helper_reduce_precalc_ena = (fsm_state == FSM_STATE_REDUCE_PRECALC) && fsm_state_new;
+ assign helper_reduce_update_ena = (fsm_state == FSM_STATE_REDUCE_UPDATE) && fsm_state_new;
+ assign helper_copy_ena = (fsm_state == FSM_STATE_COPY) && fsm_state_new;
+
+
+ //
+ // Counter Increment
+ // + always @(posedge clk) begin
+ //
+ if ((fsm_state == FSM_STATE_INIT) && helper_init_done)
+ round_counter <= round_counter_zero;
+ //
+ if ((fsm_state == FSM_STATE_INVERT_UPDATE) && helper_invert_update_done)
+ round_counter <= round_counter_next;
+ //
+ if ((fsm_state == FSM_STATE_REDUCE_UPDATE) && helper_reduce_update_done)
+ round_counter <= round_counter_next;
+ //
+ end
+
+
+ //
+ // Q Address Selector
+ //
+ always @(*) begin
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: q_addr = helper_init_q_addr;
+ FSM_STATE_REDUCE_PRECALC: q_addr = helper_reduce_precalc_q_addr;
+ default: q_addr = {OPERAND_ADDR_BITS{1'bX}};
+ endcase
+ //
+ end
+
+
+ //
+ // Buffer Address Selector
+ //
+ always @(*) begin
+ //
+ // Write Ports
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_r_wr_addr = helper_init_r_addr;
+ FSM_STATE_INVERT_UPDATE: buf_r_wr_addr = helper_invert_update_r_addr;
+ FSM_STATE_REDUCE_PRECALC: buf_r_wr_addr = helper_reduce_precalc_r_addr;
+ default: buf_r_wr_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_s_wr_addr = helper_init_s_addr;
+ FSM_STATE_INVERT_UPDATE: buf_s_wr_addr = helper_invert_update_s_addr;
+ FSM_STATE_REDUCE_UPDATE: buf_s_wr_addr = helper_reduce_update_s_addr;
+ default: buf_s_wr_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_u_wr_addr = helper_init_u_addr;
+ FSM_STATE_INVERT_UPDATE: buf_u_wr_addr = helper_invert_update_u_addr;
+ FSM_STATE_REDUCE_PRECALC: buf_u_wr_addr = helper_reduce_precalc_u_addr;
+ default: buf_u_wr_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_v_wr_addr = helper_init_v_addr;
+ FSM_STATE_INVERT_UPDATE: buf_v_wr_addr = helper_invert_update_v_addr;
+ FSM_STATE_REDUCE_PRECALC: buf_v_wr_addr = helper_reduce_precalc_v_addr;
+ default: buf_v_wr_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ // Read Ports
+ //
+ case (fsm_state)
+ FSM_STATE_INVERT_PRECALC: buf_r_rd_addr = helper_invert_precalc_r_addr;
+ default: buf_r_rd_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INVERT_PRECALC: buf_s_rd_addr = helper_invert_precalc_s_addr;
+ FSM_STATE_REDUCE_PRECALC: buf_s_rd_addr = helper_reduce_precalc_s_addr;
+ FSM_STATE_COPY: buf_s_rd_addr = helper_copy_s_addr;
+ default: buf_s_rd_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INVERT_PRECALC: buf_u_rd_addr = helper_invert_precalc_u_addr;
+ FSM_STATE_INVERT_COMPARE: buf_u_rd_addr = helper_invert_compare_u_addr;
+ FSM_STATE_REDUCE_UPDATE: buf_u_rd_addr = helper_reduce_update_u_addr;
+ default: buf_u_rd_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INVERT_PRECALC: buf_v_rd_addr = helper_invert_precalc_v_addr;
+ FSM_STATE_INVERT_COMPARE: buf_v_rd_addr = helper_invert_compare_v_addr;
+ FSM_STATE_REDUCE_UPDATE: buf_v_rd_addr = helper_reduce_update_v_addr;
+ default: buf_v_rd_addr = {BUFFER_ADDR_BITS{1'bX}};
+ endcase
+ //
+ end
+
+
+ //
+ // Buffer Write Enable Logic
+ //
+ always @(*) begin
+ //
+ // Write Ports
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_r_wr_en = helper_init_r_wren;
+ FSM_STATE_INVERT_UPDATE: buf_r_wr_en = helper_invert_update_r_wren;
+ FSM_STATE_REDUCE_PRECALC: buf_r_wr_en = helper_reduce_precalc_r_wren;
+ default: buf_r_wr_en = 1'b0;
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_s_wr_en = helper_init_s_wren;
+ FSM_STATE_INVERT_UPDATE: buf_s_wr_en = helper_invert_update_s_wren;
+ FSM_STATE_REDUCE_UPDATE: buf_s_wr_en = helper_reduce_update_s_wren;
+ default: buf_s_wr_en = 1'b0;
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_u_wr_en = helper_init_u_wren;
+ FSM_STATE_INVERT_UPDATE: buf_u_wr_en = helper_invert_update_u_wren;
+ FSM_STATE_REDUCE_PRECALC: buf_u_wr_en = helper_reduce_precalc_u_wren;
+ default: buf_u_wr_en = 1'b0;
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_v_wr_en = helper_init_v_wren;
+ FSM_STATE_INVERT_UPDATE: buf_v_wr_en = helper_invert_update_v_wren;
+ FSM_STATE_REDUCE_PRECALC: buf_v_wr_en = helper_reduce_precalc_v_wren;
+ default: buf_v_wr_en = 1'b0;
+ endcase
+ //
+ end
+
+
+ //
+ // Buffer Write Data Selector
+ //
+ always @(*) begin
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_r_wr_din = helper_init_r_data;
+ FSM_STATE_INVERT_UPDATE: buf_r_wr_din = helper_invert_update_r_data;
+ FSM_STATE_REDUCE_PRECALC: buf_r_wr_din = helper_reduce_precalc_r_data;
+ default: buf_r_wr_din = {32{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_s_wr_din = helper_init_s_data;
+ FSM_STATE_INVERT_UPDATE: buf_s_wr_din = helper_invert_update_s_data;
+ FSM_STATE_REDUCE_UPDATE: buf_s_wr_din = helper_reduce_update_s_data;
+ default: buf_s_wr_din = {32{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_u_wr_din = helper_init_u_data;
+ FSM_STATE_INVERT_UPDATE: buf_u_wr_din = helper_invert_update_u_data;
+ FSM_STATE_REDUCE_PRECALC: buf_u_wr_din = helper_reduce_precalc_u_data;
+ default: buf_u_wr_din = {32{1'bX}};
+ endcase
+ //
+ case (fsm_state)
+ FSM_STATE_INIT: buf_v_wr_din = helper_init_v_data;
+ FSM_STATE_INVERT_UPDATE: buf_v_wr_din = helper_invert_update_v_data;
+ FSM_STATE_REDUCE_PRECALC: buf_v_wr_din = helper_reduce_precalc_v_data;
+ default: buf_v_wr_din = {32{1'bX}};
+ endcase
+ //
+ end
+
+
+ //
+ // Ready Logic
+ //
+ reg rdy_reg = 1'b1;
+
+ assign rdy = rdy_reg;
+
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) rdy_reg <= 1'b1;
+ else begin
+
+ /* clear */
+ if (rdy && ena) rdy_reg <= 1'b0;
+
+ /* set */
+ if (!rdy && (fsm_state == FSM_STATE_DONE)) rdy_reg <= 1'b1;
+
+ end
+
+
+ //
+ // Store Redundant Power of 2 (K)
+ //
+ always @(posedge clk)
+ //
+ if (helper_init_ena)
+ k <= {K_NUM_BITS{1'b0}};
+ else begin
+
+ if (helper_invert_update_ena && !flag_invert_v_eq_1)
+ k <= k + 1'b1;
+
+ if (helper_reduce_update_ena && (k != {K_NUM_BITS{1'b0}}))
+ k <= k - 1'b1;
+
+ end
+
+endmodule
+
+
+//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------
|