[Cryptech-Commits] [core/math/curve25519lib] branch master updated: Moved to core/lib/

git at cryptech.is git at cryptech.is
Fri Nov 9 15:57:10 UTC 2018


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch master
in repository core/math/curve25519lib.

The following commit(s) were added to refs/heads/master by this push:
     new b3d1418  Moved to core/lib/
b3d1418 is described below

commit b3d1418ef8a7caac63e5af73eb6aa3008071adae
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Fri Nov 9 18:21:56 2018 +0300

    Moved to core/lib/
---
 bram_1rw_1ro_readfirst.v                | 101 ------
 curve25519_modular_multiplier.v         | 624 ++++++++++++++++++++++++++++++++
 lowlevel/generic/adder32_generic.v      |  67 ----
 lowlevel/generic/adder47_generic.v      |  64 ----
 lowlevel/generic/mac16_generic.v        |  74 ----
 lowlevel/generic/subtractor32_generic.v |  67 ----
 mod_adder.v                             | 304 ----------------
 mod_subtractor.v                        | 298 ---------------
 mw_mover.v                              | 170 ---------
 9 files changed, 624 insertions(+), 1145 deletions(-)

diff --git a/bram_1rw_1ro_readfirst.v b/bram_1rw_1ro_readfirst.v
deleted file mode 100644
index db62726..0000000
--- a/bram_1rw_1ro_readfirst.v
+++ /dev/null
@@ -1,101 +0,0 @@
-//======================================================================
-//
-// 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.
-//
-//======================================================================
-
-`timescale 1ns / 1ps
-
-module bram_1rw_1ro_readfirst
-  #(parameter MEM_WIDTH            = 32,
-    parameter MEM_ADDR_BITS        = 8)
-   (
-    input wire 			   clk,
-
-    input wire [MEM_ADDR_BITS-1:0] a_addr,
-    input wire 			   a_wr,
-    input wire [MEM_WIDTH-1:0] 	   a_in,
-    output wire [MEM_WIDTH-1:0]    a_out,
-
-    input wire [MEM_ADDR_BITS-1:0] b_addr,
-    output wire [MEM_WIDTH-1:0]    b_out
-    );
-
-
-   //
-   // BRAM
-   //
-   (* RAM_STYLE="BLOCK" *)
-   reg [MEM_WIDTH-1:0] 		   bram[0:(2**MEM_ADDR_BITS)-1];
-
-
-   //
-   // Initialization
-   //
-   /**
-    integer c;
-    initial begin
-    for (c=0; c<(2**MEM_ADDR_BITS); c=c+1)
-    bram[c] = {MEM_WIDTH{1'b0}};
-	end
-    **/
-
-
-
-   //
-   // Output Registers
-   //
-   reg [MEM_WIDTH-1:0] 		   bram_reg_a;
-   reg [MEM_WIDTH-1:0] 		   bram_reg_b;
-
-   assign a_out = bram_reg_a;
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Write Port A
-   //
-   always @(posedge clk) begin
-      //
-      bram_reg_a <= bram[a_addr];
-      //
-      if (a_wr) bram[a_addr] <= a_in;
-      //
-   end
-
-
-   //
-   // Read-Only Port B
-   //
-   always @(posedge clk)
-     //
-     bram_reg_b <= bram[b_addr];
-
-
-endmodule
diff --git a/curve25519_modular_multiplier.v b/curve25519_modular_multiplier.v
new file mode 100644
index 0000000..6ce0525
--- /dev/null
+++ b/curve25519_modular_multiplier.v
@@ -0,0 +1,624 @@
+//------------------------------------------------------------------------------
+//
+// Curve25519_modular_multiplier.v
+// -----------------------------------------------------------------------------
+// Curve25519 Modular Multiplier.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2015-2016, 2018 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 curve25519_modular_multiplier
+(
+    clk, rst_n,
+    ena, rdy,
+    a_addr, b_addr, p_addr, p_wren,
+    a_din, b_din, p_dout
+);
+
+
+    //
+    // Settings
+    //
+    `include "cryptech_primitive_switch.vh"
+
+
+    //
+    // Constants
+    //
+    localparam integer OPERAND_NUM_WORDS    = 8;
+    localparam integer 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
+
+    function [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_PREVIOUS_OR_LAST;
+    input    [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_CURRENT;
+    begin
+        WORD_INDEX_PREVIOUS_OR_LAST = (WORD_INDEX_CURRENT > WORD_INDEX_ZERO) ?
+            WORD_INDEX_CURRENT - 1'b1 : WORD_INDEX_LAST;
+    end
+    endfunction
+
+
+    //
+    // Ports
+    //
+    input   clk;    // system clock
+    input   rst_n;  // active-low async reset
+
+    input   ena;    // enable input
+    output  rdy;    // ready output
+
+    output  [WORD_COUNTER_WIDTH-1:0]    a_addr;    // index of current A word
+    output  [WORD_COUNTER_WIDTH-1:0]    b_addr;    // index of current B word
+    output  [WORD_COUNTER_WIDTH-1:0]    p_addr;    // index of current P word
+    
+    output  p_wren;    // store current P word now
+
+    input   [31:0]  a_din;      // current word of A
+    input   [31:0]  b_din;      // current word of B
+    output  [31:0]  p_dout;     // current word of P
+
+
+    //
+    // Word Indices
+    //
+    reg [WORD_COUNTER_WIDTH-1:0] index_a;
+    reg [WORD_COUNTER_WIDTH-1:0] index_b;
+
+    // map registers to output ports
+    assign a_addr    = index_a;
+    assign b_addr    = index_b;
+
+
+    //
+    // FSM
+    //
+
+    
+    localparam integer PHASE_INCREMENT_INDEX_A_OFFSET           =   0;
+    localparam integer PHASE_INCREMENT_INDEX_A_DURATION         =   OPERAND_NUM_WORDS;
+    
+    localparam integer PHASE_DECREMENT_INDEX_B_OFFSET           =   PHASE_INCREMENT_INDEX_A_DURATION;
+    localparam integer PHASE_DECREMENT_INDEX_B_DURATION         =   OPERAND_NUM_WORDS * 2;
+
+    localparam integer PHASE_STORE_MSB_SI_OFFSET                =   PHASE_DECREMENT_INDEX_B_OFFSET + 2;
+    localparam integer PHASE_STORE_MSB_SI_DURATION              =   OPERAND_NUM_WORDS * 2 - 1;
+
+    localparam integer PHASE_STORE_LSB_SI_OFFSET                =   PHASE_STORE_MSB_SI_OFFSET +
+                                                                    PHASE_STORE_MSB_SI_DURATION;
+    localparam integer PHASE_STORE_LSB_SI_DURATION              =   1;
+    
+    localparam integer PHASE_SHIFT_SI_OFFSET                    =   PHASE_STORE_LSB_SI_OFFSET + 1;
+    localparam integer PHASE_SHIFT_SI_DURATION                  =   OPERAND_NUM_WORDS * 2 - 1;
+
+    localparam integer PHASE_MASK_SUM_CW1_OFFSET                =   PHASE_SHIFT_SI_OFFSET + 1;
+    localparam integer PHASE_MASK_SUM_CW1_DURATION              =   1;    
+    
+    localparam integer PHASE_STORE_LSB_C_OFFSET                 =   PHASE_MASK_SUM_CW1_OFFSET + 1;
+    localparam integer PHASE_STORE_LSB_C_DURATION               =   OPERAND_NUM_WORDS;
+
+    localparam integer PHASE_STORE_MSB_C_OFFSET                 =   PHASE_STORE_LSB_C_OFFSET +
+                                                                    PHASE_STORE_LSB_C_DURATION;
+    localparam integer PHASE_STORE_MSB_C_DURATION               =   OPERAND_NUM_WORDS;
+
+    localparam integer PHASE_MASK_B_R3_OFFSET                   =   PHASE_STORE_MSB_C_OFFSET + 3;
+    localparam integer PHASE_MASK_B_R3_DURATION                 =   1;
+
+    localparam integer PHASE_CALCULATE_CARRY_MSB_S1_OFFSET      =   PHASE_STORE_MSB_C_OFFSET +
+                                                                    PHASE_STORE_MSB_C_DURATION + 4;
+    localparam integer PHASE_CALCULATE_CARRY_MSB_S1_DURATION    =   1;
+    
+    localparam integer PHASE_STORE_LSB_S1_OFFSET                =   PHASE_STORE_MSB_C_OFFSET + 4;
+    localparam integer PHASE_STORE_LSB_S1_DURATION              =   OPERAND_NUM_WORDS;
+    
+    localparam integer PHASE_SHIFT_S1_OFFSET                    =   PHASE_STORE_LSB_S1_OFFSET +
+                                                                    PHASE_STORE_LSB_S1_DURATION + 1;
+    localparam integer PHASE_SHIFT_S1_DURATION                  =   OPERAND_NUM_WORDS;
+
+    localparam integer PHASE_CHANGE_LSB_B_P_OFFSET              =   PHASE_SHIFT_S1_OFFSET;
+    localparam integer PHASE_CHANGE_LSB_B_P_DURATION            =   1;
+
+    localparam integer PHASE_SELECT_S2_OR_PN_OFFSET             =   PHASE_SHIFT_S1_OFFSET +
+                                                                    PHASE_SHIFT_S1_DURATION + 1;
+    localparam integer PHASE_SELECT_S2_OR_PN_DURATION           =   1;
+
+    localparam integer PHASE_UPDATE_P_DOUT_OFFSET               =   PHASE_SHIFT_S1_OFFSET +
+                                                                    PHASE_SHIFT_S1_DURATION + 2;
+    localparam integer PHASE_UPDATE_P_DOUT_DURATION             =   OPERAND_NUM_WORDS;
+
+    
+    
+    localparam integer FSM_SHREG_WIDTH =    PHASE_INCREMENT_INDEX_A_DURATION +
+                                            PHASE_DECREMENT_INDEX_B_DURATION +
+                                            1 +
+                                            PHASE_STORE_LSB_SI_DURATION +
+                                            PHASE_SHIFT_SI_DURATION +
+                                            -1 +
+                                            PHASE_STORE_LSB_S1_DURATION +
+                                            PHASE_CALCULATE_CARRY_MSB_S1_DURATION +
+                                            PHASE_SHIFT_S1_DURATION +
+                                            1 +
+                                            PHASE_SELECT_S2_OR_PN_DURATION +
+                                            PHASE_UPDATE_P_DOUT_DURATION +
+                                            2;
+
+    localparam [FSM_SHREG_WIDTH-1:0] FSM_SHREG_INIT = {{(FSM_SHREG_WIDTH-1){1'b0}}, 1'b1};
+
+    reg [FSM_SHREG_WIDTH-1:0] fsm_shreg = FSM_SHREG_INIT;
+
+    assign rdy = fsm_shreg[0];
+
+    
+    
+    
+    
+    
+    
+    wire [PHASE_INCREMENT_INDEX_A_DURATION     -1:0] fsm_shreg_increment_index_a      = fsm_shreg[FSM_SHREG_WIDTH - PHASE_INCREMENT_INDEX_A_OFFSET      - 1 -: PHASE_INCREMENT_INDEX_A_DURATION];
+    wire [PHASE_DECREMENT_INDEX_B_DURATION     -1:0] fsm_shreg_decrement_index_b      = fsm_shreg[FSM_SHREG_WIDTH - PHASE_DECREMENT_INDEX_B_OFFSET      - 1 -: PHASE_DECREMENT_INDEX_B_DURATION];
+    wire [PHASE_STORE_MSB_SI_DURATION          -1:0] fsm_shreg_store_msb_si           = fsm_shreg[FSM_SHREG_WIDTH - PHASE_STORE_MSB_SI_OFFSET           - 1 -: PHASE_STORE_MSB_SI_DURATION];
+    wire [PHASE_STORE_LSB_SI_DURATION          -1:0] fsm_shreg_store_lsb_si           = fsm_shreg[FSM_SHREG_WIDTH - PHASE_STORE_LSB_SI_OFFSET           - 1 -: PHASE_STORE_LSB_SI_DURATION];
+    wire [PHASE_SHIFT_SI_DURATION              -1:0] fsm_shreg_shift_si               = fsm_shreg[FSM_SHREG_WIDTH - PHASE_SHIFT_SI_OFFSET               - 1 -: PHASE_SHIFT_SI_DURATION];
+    wire [PHASE_MASK_SUM_CW1_DURATION          -1:0] fsm_shreg_mask_sum_cw1           = fsm_shreg[FSM_SHREG_WIDTH - PHASE_MASK_SUM_CW1_OFFSET           - 1 -: PHASE_MASK_SUM_CW1_DURATION];
+    wire [PHASE_STORE_LSB_C_DURATION           -1:0] fsm_shreg_store_lsb_c            = fsm_shreg[FSM_SHREG_WIDTH - PHASE_STORE_LSB_C_OFFSET            - 1 -: PHASE_STORE_LSB_C_DURATION];
+    wire [PHASE_STORE_MSB_C_DURATION           -1:0] fsm_shreg_store_msb_c            = fsm_shreg[FSM_SHREG_WIDTH - PHASE_STORE_MSB_C_OFFSET            - 1 -: PHASE_STORE_MSB_C_DURATION];
+    wire [PHASE_MASK_B_R3_DURATION             -1:0] fsm_shreg_mask_b_r3              = fsm_shreg[FSM_SHREG_WIDTH - PHASE_MASK_B_R3_OFFSET              - 1 -: PHASE_MASK_B_R3_DURATION];
+    wire [PHASE_CALCULATE_CARRY_MSB_S1_DURATION-1:0] fsm_shreg_calculate_carry_msb_s1 = fsm_shreg[FSM_SHREG_WIDTH - PHASE_CALCULATE_CARRY_MSB_S1_OFFSET - 1 -: PHASE_CALCULATE_CARRY_MSB_S1_DURATION];
+    wire [PHASE_STORE_LSB_S1_DURATION          -1:0] fsm_shreg_store_lsb_s1           = fsm_shreg[FSM_SHREG_WIDTH - PHASE_STORE_LSB_S1_OFFSET           - 1 -: PHASE_STORE_LSB_S1_DURATION];
+    wire [PHASE_SHIFT_S1_DURATION              -1:0] fsm_shreg_shift_s1               = fsm_shreg[FSM_SHREG_WIDTH - PHASE_SHIFT_S1_OFFSET               - 1 -: PHASE_SHIFT_S1_DURATION];
+    wire [PHASE_CHANGE_LSB_B_P_DURATION        -1:0] fsm_shreg_change_lsb_b_p         = fsm_shreg[FSM_SHREG_WIDTH - PHASE_CHANGE_LSB_B_P_OFFSET         - 1 -: PHASE_CHANGE_LSB_B_P_DURATION];
+    wire [PHASE_SELECT_S2_OR_PN_DURATION       -1:0] fsm_shreg_select_s2_or_pn        = fsm_shreg[FSM_SHREG_WIDTH - PHASE_SELECT_S2_OR_PN_OFFSET        - 1 -: PHASE_SELECT_S2_OR_PN_DURATION];
+    wire [PHASE_UPDATE_P_DOUT_DURATION         -1:0] fsm_shreg_update_p_dout          = fsm_shreg[FSM_SHREG_WIDTH - PHASE_UPDATE_P_DOUT_OFFSET          - 1 -: PHASE_UPDATE_P_DOUT_DURATION];
+
+    wire flag_increment_index_a      = |fsm_shreg_increment_index_a;
+    wire flag_decrement_index_b      = |fsm_shreg_decrement_index_b;
+    wire flag_store_msb_si           = |fsm_shreg_store_msb_si;
+    wire flag_store_lsb_si           = |fsm_shreg_store_lsb_si;
+    wire flag_shift_si               = |fsm_shreg_shift_si;
+    wire flag_mask_sum_cw1           = |fsm_shreg_mask_sum_cw1;
+    wire flag_store_lsb_c            = |fsm_shreg_store_lsb_c;
+    wire flag_store_msb_c            = |fsm_shreg_store_msb_c;
+    wire flag_mask_b_r3              = |fsm_shreg_mask_b_r3;
+    wire flag_calculate_carry_msb_s1 = |fsm_shreg_calculate_carry_msb_s1;
+    wire flag_store_lsb_s1           = |fsm_shreg_store_lsb_s1;
+    wire flag_shift_s1               = |fsm_shreg_shift_s1;
+    wire flag_change_lsb_b_p         = |fsm_shreg_change_lsb_b_p;
+    wire flag_select_s2_or_pn        = |fsm_shreg_select_s2_or_pn;
+    wire flag_update_p_dout          = |fsm_shreg_update_p_dout;
+    
+    reg flag_store_word_a   = 0;
+    reg flag_enable_mac_ab  = 0;
+    reg flag_delay_msb_c    = 0;
+    reg flag_mask_a_s2      = 0;
+    reg flag_mask_b_out_p   = 0;
+    reg flag_store_s2       = 0;
+    reg flag_store_pn       = 0;
+    
+    always @(posedge clk) begin
+        flag_store_word_a   <= flag_increment_index_a;
+        flag_enable_mac_ab  <= flag_decrement_index_b;
+        flag_delay_msb_c    <= flag_store_msb_c;
+        flag_mask_a_s2      <= flag_calculate_carry_msb_s1;
+        flag_mask_b_out_p   <= flag_change_lsb_b_p;
+        flag_store_s2       <= flag_shift_s1;
+        flag_store_pn       <= flag_store_s2;
+    end    
+
+
+    //
+    // FSM Logic
+    //    
+    always @(posedge clk or negedge rst_n)
+        //
+        if (rst_n == 1'b0)
+            //
+            fsm_shreg <= FSM_SHREG_INIT;
+        //
+        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
+
+
+    //
+    // A Word Index Increment Logic
+    //
+    always @(posedge clk)
+        //
+        if (rdy)              index_a <= WORD_INDEX_ZERO;
+        else if (flag_increment_index_a) index_a <= WORD_INDEX_NEXT_OR_ZERO(index_a);
+
+
+    //
+    // B Word Index Decrement Logic
+    //
+    always @(posedge clk)
+        //
+        if (rdy)                                index_b <= WORD_INDEX_LAST;
+        else if (flag_decrement_index_b && !index_b_ff)    index_b <= WORD_INDEX_PREVIOUS_OR_LAST(index_b);
+
+        
+    //
+    // Wide Operand Buffer
+    //
+    reg [255:0] buf_a_wide;
+
+    
+
+    //
+    // B Word Splitter
+    //
+    
+    /*
+     * 0: store the upper 16-bit part of the current B word
+     * 1: store the lower 16-bit part of the current B word
+     */
+    
+    reg index_b_ff = 1'b0;
+
+    always @(posedge clk)
+        //
+        if (flag_decrement_index_b)    index_b_ff <= ~index_b_ff;
+        else                index_b_ff <= 1'b0;
+        
+
+    //
+    // Narrow Operand Buffer
+    //
+    reg [15:0] buf_b_narrow;
+    
+    always @(posedge clk)
+        //
+        if (flag_decrement_index_b) buf_b_narrow <= !index_b_ff ? b_din[31:16] : b_din[15:0];
+
+
+    //
+    // MAC Clear Logic
+    //
+    reg  [15:0] mac_clear;
+
+    always @(posedge clk)
+        //
+        if (!flag_enable_mac_ab) mac_clear <= {16{1'b1}};
+        else begin
+            if (mac_clear[0])       mac_clear <= 16'b0000000000000010;
+            else if (mac_clear[15]) mac_clear <= 16'b1111111111111111;
+            else                    mac_clear <= {mac_clear[14:0], 1'b0};
+        end
+
+
+    //
+    // MAC Array
+    //
+    wire [46:0] mac_accum[0:15];
+
+    genvar i;
+    
+    generate for (i=0; i<16; i=i+1)
+        //
+        begin : gen_mac16_array
+            //
+            `CRYPTECH_PRIMITIVE_MAC16 mac16_inst
+            (
+                .clk    (clk),
+                .ce     (flag_enable_mac_ab),
+
+                .clr    (mac_clear[i]),
+
+                .a      (buf_a_wide[16 * i +: 16]),
+                .b      (buf_b_narrow),
+                .s      (mac_accum[i])
+            );
+            //
+        end
+        //
+    endgenerate
+
+
+    //
+    // Intermediate Words
+    //
+    reg [47*(2*OPERAND_NUM_WORDS-1)-1:0] si_msb;
+    reg [47*(2*OPERAND_NUM_WORDS-0)-1:0] si_lsb;
+
+    wire [47*(2*OPERAND_NUM_WORDS-1)-1:0] si_msb_new;
+    wire [47*(2*OPERAND_NUM_WORDS-0)-1:0] si_lsb_new;
+    
+    generate for (i=0; i<16; i=i+1)
+        begin : gen_si_lsb_new
+            assign si_lsb_new[47*i+:47] = mac_accum[15-i];
+        end
+    endgenerate
+
+    generate for (i=1; i<16; i=i+1)
+        begin : gen_si_msb_new
+            assign si_msb_new[47*(15-i)+:47] = mac_clear[i] ? mac_accum[i] : si_msb[47*(15-i)+:47];
+        end
+    endgenerate
+
+    always @(posedge clk)
+        //
+        if (flag_shift_si) begin
+            si_msb <= {{2*47{1'b0}}, si_msb[15*47-1:2*47]};
+            si_lsb <= {si_msb[2*47-1:0], si_lsb[16*47-1:2*47]};
+        end else begin
+            if (flag_store_msb_si)   si_msb <= si_msb_new;
+            if (flag_store_lsb_si)   si_lsb <= si_lsb_new;
+        end
+
+
+    //
+    // Accumulators
+    //
+    wire [46:0] add47_cw0_s;
+    wire [46:0] add47_cw1_s;
+    wire [14:0] add47_cw1_s_masked = flag_mask_sum_cw1 ? {15{1'b0}} : add47_cw1_s[32+:15];
+    
+    wire [46:0] add47_r3_b_masked = {{32{1'b0}}, flag_mask_b_r3 ? {15{1'b0}} : add47_r3_s[46:32]};
+
+    
+    //
+    // cw0, cw1
+    //
+    reg [30: 0] si_prev_dly;
+    reg [15: 0] si_next_dly;
+
+    always @(posedge clk)
+        //
+        if (flag_shift_si) si_prev_dly <= si_lsb[93:63];
+        else          si_prev_dly <= {31{1'b0}};
+
+    always @(posedge clk)
+        //
+        si_next_dly <= si_lsb[47+:16];
+
+    wire [46:0] add47_cw0_a = si_lsb[46:0];
+    wire [46:0] add47_cw0_b = {{16{1'b0}}, si_prev_dly};
+
+    wire [46:0] add47_cw1_a = add47_cw0_s;
+    wire [46:0] add47_cw1_b = {{15{1'b0}}, si_next_dly, 1'b0, add47_cw1_s_masked};
+
+    `CRYPTECH_PRIMITIVE_ADD47 add47_cw0_inst
+    (
+        .clk    (clk),
+        .a      (add47_cw0_a),
+        .b      (add47_cw0_b),
+        .s      (add47_cw0_s)
+    );
+
+    `CRYPTECH_PRIMITIVE_ADD47 add47_cw1_inst
+    (
+        .clk    (clk),
+        .a      (add47_cw1_a),
+        .b      (add47_cw1_b),
+        .s      (add47_cw1_s)
+    );
+    
+    
+    //
+    // Full-Size Product
+    //
+    wire [31:0] c_word_lower = add47_cw1_s[31:0];
+
+     
+    wire [46:0] add47_r0_s;
+    wire [46:0] add47_r1_s;
+    wire [46:0] add47_r2_s;
+    wire [46:0] add47_r3_s;
+    
+    reg [255:0] c_lsb_s1_shreg;
+    reg [ 31:0] c_msb_latch;
+            
+    
+        
+
+        
+    always @(posedge clk)
+        //
+        if (flag_store_msb_c) c_msb_latch <= c_word_lower;
+        else             c_msb_latch <= {32{1'b0}};
+    
+        
+    reg [4:0] c_msb_latch_upper_dly;
+    reg [31:0] c_lsb_shreg_lower_dly;
+    
+    always @(posedge clk)
+        //
+        if (flag_delay_msb_c) c_msb_latch_upper_dly <= c_msb_latch[31:27];
+        else             c_msb_latch_upper_dly <= {5{1'b0}};
+            
+    
+    always @(posedge clk)
+        //
+        if (flag_store_msb_c) c_lsb_shreg_lower_dly <= c_lsb_s1_shreg[31:0];
+        else             c_lsb_shreg_lower_dly <= {32{1'b0}};
+    
+    
+    
+    reg [11:0] carry_msb_s1;
+    
+    always @(posedge clk)
+        //
+        if (flag_calculate_carry_msb_s1) carry_msb_s1 <= {{6{1'b0}}, 6'd38} * {{6{1'b0}}, add47_r3_s[5:0]};
+    
+    
+    wire [46:0] add47_s2_a_masked = {{32{1'b0}}, flag_mask_a_s2 ? {3'b000, carry_msb_s1} : add47_s2_s[46:32]};
+    
+    `CRYPTECH_PRIMITIVE_ADD47 add47_r0
+    (
+        .clk    (clk),
+        .a      ({{15{1'b0}}, c_msb_latch[30:0], c_msb_latch_upper_dly[4]}),
+        .b      ({{15{1'b0}}, c_msb_latch[29:0], c_msb_latch_upper_dly[4:3]}),
+        .s      (add47_r0_s)
+    );
+    `CRYPTECH_PRIMITIVE_ADD47 add47_r1
+    (
+        .clk    (clk),
+        .a      ({{15{1'b0}}, c_msb_latch[26:0], c_msb_latch_upper_dly[4:0]}),
+        .b      ({{15{1'b0}}, c_lsb_shreg_lower_dly}),
+        .s      (add47_r1_s)
+    );
+    `CRYPTECH_PRIMITIVE_ADD47 add47_r2
+    (
+        .clk    (clk),
+        .a      (add47_r0_s),
+        .b      (add47_r1_s),
+        .s      (add47_r2_s)
+    );
+    `CRYPTECH_PRIMITIVE_ADD47 add47_r3
+    (
+        .clk    (clk),
+        .a      (add47_r2_s),
+        .b      (add47_r3_b_masked),
+        .s      (add47_r3_s)
+    );
+    
+          
+    
+    wire [46:0] add47_s2_s;
+    `CRYPTECH_PRIMITIVE_ADD47 add47_s2
+    (
+        .clk    (clk),
+        .a      (add47_s2_a_masked),
+        .b      ({{15{1'b0}}, c_lsb_s1_shreg[31:0]}),
+        .s      (add47_s2_s)
+    );
+    
+    
+    reg sub32_b_bit;
+    
+    wire [31:0] sub32_b = {{26{1'b1}},  // ...*11*1*
+        sub32_b_bit, {2{1'b1}}, sub32_b_bit, 1'b1, sub32_b_bit};
+    
+    always @(posedge clk)
+        //
+        if (!fsm_shreg_change_lsb_b_p) sub32_b_bit <= 1'b1;
+        else                           sub32_b_bit <= 1'b0;
+    
+    wire [31:0] sub32_pn_d;
+    wire        sub32_b_in;
+    wire        sub32_b_out;
+
+    assign sub32_b_in = sub32_b_out & !flag_mask_b_out_p;
+    
+    `CRYPTECH_PRIMITIVE_SUB32 sub32_pn
+    (
+        .clk    (clk),
+        .a      (add47_s2_s[31:0]),
+        .b      (sub32_b),
+        .d      (sub32_pn_d),
+        .b_in   (sub32_b_in),
+        .b_out  (sub32_b_out)
+    );
+    
+
+    wire [31:0] add47_r3_s_lower = add47_r3_s[31:0];
+    
+
+    always @(posedge clk)
+        //
+        if (flag_store_word_a)       buf_a_wide <= {buf_a_wide[16+:256-3*16], {a_din[15:0], a_din[31:16]}, buf_a_wide[256-2*16+:16]};
+        else if (flag_enable_mac_ab) buf_a_wide <= {buf_a_wide[256-(16+1):0], buf_a_wide[256-16+:16]};
+        else if (flag_store_s2)      buf_a_wide <= {add47_s2_s[31:0], buf_a_wide[255:32]};
+        else if (flag_update_p_dout)  buf_a_wide <= {{32{1'bX}}, buf_a_wide[255:32]};
+
+        
+    always @(posedge clk)
+        //
+        if      (flag_store_lsb_c)                  c_lsb_s1_shreg <= {c_word_lower,     c_lsb_s1_shreg[255:32]};
+        else if (flag_store_lsb_s1)                 c_lsb_s1_shreg <= {add47_r3_s_lower, c_lsb_s1_shreg[255:32]};
+        else if (flag_store_pn)                     c_lsb_s1_shreg <= {sub32_pn_d,       c_lsb_s1_shreg[255:32]};
+        else if (flag_store_msb_c || flag_shift_s1) c_lsb_s1_shreg <= {{32{1'b0}},       c_lsb_s1_shreg[255:32]};
+        else if (flag_update_p_dout)                 c_lsb_s1_shreg <= {{32{1'b0}},       c_lsb_s1_shreg[255:32]};
+
+
+    reg sel_pn; // 0: output in S2, 1: output in PN
+    
+    always @(posedge clk)
+        //
+        if (flag_select_s2_or_pn) sel_pn <= sub32_b_out & add47_s2_s[0];
+        
+        
+    reg [31:0] p_dout_reg;
+    
+    assign p_dout = p_dout_reg;
+    
+    always @(posedge clk)
+        //
+        if (flag_update_p_dout) p_dout_reg <= sel_pn ? c_lsb_s1_shreg[31:0] : buf_a_wide[31:0];
+        else                    p_dout_reg <= {32{1'bX}};
+        
+
+    reg p_wren_reg = 0;
+    
+    assign p_wren = p_wren_reg;
+    
+    always @(posedge clk)
+        //
+        p_wren_reg <= flag_update_p_dout;
+
+        
+    reg [WORD_COUNTER_WIDTH-1:0] p_addr_reg;
+        
+    assign p_addr = p_addr_reg;
+        
+    always @(posedge clk)
+        //
+        if (p_wren_reg) p_addr_reg <= WORD_INDEX_NEXT_OR_ZERO(p_addr_reg);
+        else            p_addr_reg <= WORD_INDEX_ZERO;
+    
+        
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/generic/adder32_generic.v b/lowlevel/generic/adder32_generic.v
deleted file mode 100644
index eadfb6f..0000000
--- a/lowlevel/generic/adder32_generic.v
+++ /dev/null
@@ -1,67 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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
deleted file mode 100644
index 406c175..0000000
--- a/lowlevel/generic/adder47_generic.v
+++ /dev/null
@@ -1,64 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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
deleted file mode 100644
index 6d120a3..0000000
--- a/lowlevel/generic/mac16_generic.v
+++ /dev/null
@@ -1,74 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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
deleted file mode 100644
index 5137ace..0000000
--- a/lowlevel/generic/subtractor32_generic.v
+++ /dev/null
@@ -1,67 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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
deleted file mode 100644
index e6e0db8..0000000
--- a/mod_adder.v
+++ /dev/null
@@ -1,304 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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
deleted file mode 100644
index 9b4b7e9..0000000
--- a/mod_subtractor.v
+++ /dev/null
@@ -1,298 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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
-//------------------------------------------------------------------------------
diff --git a/mw_mover.v b/mw_mover.v
deleted file mode 100644
index 9a88150..0000000
--- a/mw_mover.v
+++ /dev/null
@@ -1,170 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// mw_mover.v
-// -----------------------------------------------------------------------------
-// Multi-word data mover.
-//
-// Authors: Pavel Shatov
-//
-// Copyright (c) 2015-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 mw_mover
-(
-    clk, rst_n,
-    ena, rdy,
-    x_addr, y_addr, y_wren,
-    x_din, y_dout
-);
-
-
-    //
-    // Parameters
-    //
-    parameter WORD_COUNTER_WIDTH    = 3;
-    parameter OPERAND_NUM_WORDS     = 8;
-
-
-    //
-    // 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   clk;    // system clock
-    input   rst_n;  // active-low async reset
-
-    input   ena;    // enable input
-    output  rdy;    // ready output
-
-    output  [WORD_COUNTER_WIDTH-1:0]    x_addr;     // address of current X word
-    output  [WORD_COUNTER_WIDTH-1:0]    y_addr;     // address of current Y word
-    output                              y_wren;     // store current Y word
-
-    input   [                32-1:0]    x_din;      // current X word
-    output  [                32-1:0]    y_dout;     // current Y word
-
-
-    //
-    // Word Indices
-    //
-    reg [WORD_COUNTER_WIDTH-1:0] index_x;
-    reg [WORD_COUNTER_WIDTH-1:0] index_y;
-
-
-    //
-    // Output Mapping
-    //
-    assign x_addr   = index_x;
-    assign y_addr   = index_y;
-
-
-    //
-    // FSM
-    //
-    localparam FSM_SHREG_WIDTH = 1 * OPERAND_NUM_WORDS + 2;
-    localparam [FSM_SHREG_WIDTH-1:0] FSM_SHREG_INIT = {{(FSM_SHREG_WIDTH-1){1'b0}}, 1'b1};
-    
-    reg [FSM_SHREG_WIDTH-1:0] fsm_shreg = FSM_SHREG_INIT;
-
-    assign rdy = fsm_shreg[0];
-
-    wire [OPERAND_NUM_WORDS-1:0] fsm_shreg_inc_index_x = 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_y = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 2) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 1)];
-
-    wire inc_index_x    = |fsm_shreg_inc_index_x;
-    wire inc_index_y    = |fsm_shreg_inc_index_y;
-    wire store_word_y   = |fsm_shreg_inc_index_x;
-
-
-    always @(posedge clk or negedge rst_n)
-        //
-        if (rst_n == 1'b0)  fsm_shreg <= FSM_SHREG_INIT;
-        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
-
-
-    //
-    // Word Index Increment Logic
-    //
-    always @(posedge clk)
-    //
-    if (rdy) begin
-        index_x <= WORD_INDEX_ZERO;
-        index_y <= WORD_INDEX_ZERO;
-    end else begin
-        if (inc_index_x)    index_x <= WORD_INDEX_NEXT_OR_ZERO(index_x);
-        if (inc_index_y)    index_y <= WORD_INDEX_NEXT_OR_ZERO(index_y);
-    end
-
-
-    //
-    // Write Enable Logic
-    //
-    reg y_wren_reg;
-
-    assign y_wren = y_wren_reg;
-
-    always @(posedge clk)
-    //
-    if (rdy)    y_wren_reg  <= 1'b0;
-    else        y_wren_reg  <= store_word_y;
-
-
-    //
-    // Output Logic
-    //
-    assign y_dout = x_din;
-
-
-endmodule
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Commits mailing list