aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2018-11-09 18:50:27 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2018-11-09 18:50:27 +0300
commit057c4c6fe15b2fb5ef08397eef832620c3e6dead (patch)
treeaea55ac95e7c303bfefb7d5800115ac78e80b427
Library for common Verilog modules.
-rw-r--r--README.md18
-rw-r--r--lowlevel/artix7/adder32_artix7.v96
-rw-r--r--lowlevel/artix7/adder47_artix7.v91
-rw-r--r--lowlevel/artix7/dsp48e1_wrapper.v159
-rw-r--r--lowlevel/artix7/dsp48e1_wrapper_modexp.v159
-rw-r--r--lowlevel/artix7/mac16_artix7.v90
-rw-r--r--lowlevel/artix7/modexp_systolic_pe_artix7.v126
-rw-r--r--lowlevel/artix7/subtractor32_artix7.v94
-rw-r--r--lowlevel/cryptech_primitive_switch.vh94
-rw-r--r--lowlevel/generic/adder32_generic.v67
-rw-r--r--lowlevel/generic/adder47_generic.v64
-rw-r--r--lowlevel/generic/mac16_generic.v74
-rw-r--r--lowlevel/generic/modexp_systolic_pe_generic.v85
-rw-r--r--lowlevel/generic/subtractor32_generic.v67
-rw-r--r--memory/bram_1rw_1ro_readfirst.v112
-rw-r--r--memory/bram_1rw_readfirst.v75
-rw-r--r--memory/bram_1wo_1ro_readfirst.v107
-rw-r--r--modular/modular_adder.v298
-rw-r--r--modular/modular_subtractor.v294
-rw-r--r--multiword/multiword_comparator.v232
-rw-r--r--multiword/multiword_mover.v169
-rw-r--r--util/cryptech_clog2.vh48
22 files changed, 2619 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4c6408c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# core/lib
+
+This repository contains common modules instantiated by other cores:
+
+* **lowlevel** contains modules for math operations (addition, subtraction, etc). Two sets of modules are provided: **generic** ones can be used during simulation and when porting to a different architecture, modules from **artix7** should be used when building a bitstream for the Alpha board. To use the modules first `` `include "cryptech_primitive_switch.vh"``, then instantiate them using `` `CRYPTECH_PRIMITIVE_*`` macro.
+
+* **memory** contains wrappers for block memories:
+ * ``bram_1rw_readfirst`` is single read-write port
+ * ``bram_1rw_1ro_readfirst`` is one read-write, one read-only port
+ * ``bram_1wo_1ro_readfirst`` is one write-only, one read-only port (useful for storing private keys)
+
+* **modular** contains multiprecision modular adder and subtractor
+
+* **multiword** contains multiprecision integer comparator and mover/copier
+
+* **util** has the following:
+ * ``cryptech_clog2.vh`` replacement for Xilinx' notorious clog2()
+
diff --git a/lowlevel/artix7/adder32_artix7.v b/lowlevel/artix7/adder32_artix7.v
new file mode 100644
index 0000000..dad2340
--- /dev/null
+++ b/lowlevel/artix7/adder32_artix7.v
@@ -0,0 +1,96 @@
+//------------------------------------------------------------------------------
+//
+// adder32_artix7.v
+// -----------------------------------------------------------------------------
+// Hardware (Artix-7 DSP48E1) 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_artix7
+ (
+ 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
+ );
+
+ //
+ // Lower and higher parts of operand
+ //
+ wire [17: 0] bl = b[17: 0];
+ wire [13: 0] bh = b[31:18];
+
+
+ //
+ // DSP48E1 Slice
+ //
+
+ /* Operation Mode */
+ wire [ 3: 0] dsp48e1_alumode = 4'b0000;
+ wire [ 6: 0] dsp48e1_opmode = 7'b0110011;
+
+ /* Internal Product */
+ wire [47: 0] p_int;
+
+ dsp48e1_wrapper dsp_adder
+ (
+ .clk (clk),
+
+ .ce (1'b1),
+
+ .carry (c_in),
+
+ .alumode (dsp48e1_alumode),
+ .opmode (dsp48e1_opmode),
+
+ .a ({{16{1'b0}}, bh}),
+ .b (bl),
+ .c ({{16{1'b0}}, a}),
+
+ .p (p_int)
+ );
+
+ //
+ // Output Mapping
+ //
+ assign s = p_int[31: 0];
+ assign c_out = p_int[32];
+
+
+endmodule
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/artix7/adder47_artix7.v b/lowlevel/artix7/adder47_artix7.v
new file mode 100644
index 0000000..caafc85
--- /dev/null
+++ b/lowlevel/artix7/adder47_artix7.v
@@ -0,0 +1,91 @@
+//------------------------------------------------------------------------------
+//
+// adder47_artix7.v
+// -----------------------------------------------------------------------------
+// Hardware (Artix-7 DSP48E1) 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_artix7
+ (
+ input clk, // clock
+ input [46: 0] a, // operand input
+ input [46: 0] b, // operand input
+ output [46: 0] s // sum output
+ );
+
+ //
+ // Lower and higher parts of operand
+ //
+ wire [17: 0] bl = b[17: 0];
+ wire [28: 0] bh = b[46:18];
+
+ //
+ // DSP48E1 Slice
+ //
+
+ /* Operation Mode */
+ wire [ 3: 0] dsp48e1_alumode = 4'b0000;
+ wire [ 6: 0] dsp48e1_opmode = 7'b0110011;
+
+ /* Internal Product */
+ wire [47: 0] p_int;
+
+ dsp48e1_wrapper dsp_adder
+ (
+ .clk (clk),
+
+ .ce (1'b1),
+
+ .carry (1'b0),
+
+ .alumode (dsp48e1_alumode),
+ .opmode (dsp48e1_opmode),
+
+ .a ({1'b0, bh}),
+ .b (bl),
+ .c ({1'b0, a}),
+
+ .p (p_int)
+ );
+
+ //
+ // Output Mapping
+ //
+ assign s = p_int[46: 0];
+
+endmodule
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/artix7/dsp48e1_wrapper.v b/lowlevel/artix7/dsp48e1_wrapper.v
new file mode 100644
index 0000000..4c272f0
--- /dev/null
+++ b/lowlevel/artix7/dsp48e1_wrapper.v
@@ -0,0 +1,159 @@
+//------------------------------------------------------------------------------
+//
+// dsp48e1_wrapper.v
+// -----------------------------------------------------------------------------
+// Hardware (Artix-7 DSP48E1) tile wrapper.
+//
+// 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 dsp48e1_wrapper
+ (
+ input clk,
+
+ input ce,
+
+ input [ 6: 0] opmode,
+ input [ 3: 0] alumode,
+
+ input carry,
+
+ input [29: 0] a,
+ input [17: 0] b,
+ input [47: 0] c,
+
+ output [47: 0] p
+ );
+
+
+ //
+ // Tile instantiation
+ //
+ DSP48E1 #
+ (
+ .AREG (0),
+ .BREG (0),
+ .CREG (0),
+ .DREG (0),
+ .MREG (0),
+ .PREG (1),
+ .ADREG (0),
+
+ .ACASCREG (0),
+ .BCASCREG (0),
+ .ALUMODEREG (0),
+ .INMODEREG (0),
+ .OPMODEREG (0),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+
+ .A_INPUT ("DIRECT"),
+ .B_INPUT ("DIRECT"),
+
+ .USE_DPORT ("FALSE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_SIMD ("ONE48"),
+
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .SEL_PATTERN ("PATTERN"),
+ .SEL_MASK ("MASK"),
+ .PATTERN (48'h000000000000),
+ .MASK (48'h3fffffffffff),
+ .AUTORESET_PATDET ("NO_RESET")
+ )
+ DSP48E1_inst
+ (
+ .CLK (clk),
+
+ .RSTA (1'b0),
+ .RSTB (1'b0),
+ .RSTC (1'b0),
+ .RSTD (1'b0),
+ .RSTM (1'b0),
+ .RSTP (1'b0),
+
+ .RSTCTRL (1'b0),
+ .RSTINMODE (1'b0),
+ .RSTALUMODE (1'b0),
+ .RSTALLCARRYIN (1'b0),
+
+ .CEA1 (1'b0),
+ .CEA2 (1'b0),
+ .CEB1 (1'b0),
+ .CEB2 (1'b0),
+ .CEC (1'b0),
+ .CED (1'b0),
+ .CEM (1'b0),
+ .CEP (ce),
+ .CEAD (1'b0),
+ .CEALUMODE (1'b0),
+ .CEINMODE (1'b0),
+
+ .CECTRL (1'b0),
+ .CECARRYIN (1'b0),
+
+ .A (a),
+ .B (b),
+ .C (c),
+ .D ({25{1'b1}}),
+ .P (p),
+
+ .CARRYIN (carry),
+ .CARRYOUT (),
+ .CARRYINSEL (3'b000),
+
+ .CARRYCASCIN (1'b0),
+ .CARRYCASCOUT (),
+
+ .PATTERNDETECT (),
+ .PATTERNBDETECT (),
+
+ .OPMODE (opmode),
+ .ALUMODE (alumode),
+ .INMODE (5'b00000),
+
+ .MULTSIGNIN (1'b0),
+ .MULTSIGNOUT (),
+
+ .UNDERFLOW (),
+ .OVERFLOW (),
+
+ .ACIN (30'd0),
+ .BCIN (18'd0),
+ .PCIN (48'd0),
+
+ .ACOUT (),
+ .BCOUT (),
+ .PCOUT ()
+ );
+
+endmodule
diff --git a/lowlevel/artix7/dsp48e1_wrapper_modexp.v b/lowlevel/artix7/dsp48e1_wrapper_modexp.v
new file mode 100644
index 0000000..17d8efe
--- /dev/null
+++ b/lowlevel/artix7/dsp48e1_wrapper_modexp.v
@@ -0,0 +1,159 @@
+//------------------------------------------------------------------------------
+//
+// dsp48e1_wrapper_modexp.v
+// -----------------------------------------------------------------------------
+// Extended hardware (Artix-7 DSP48E1) tile wrapper.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 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 modexpa7_dsp48e1_wrapper_modexp #
+ (
+ parameter AREG = 1'b0,
+ parameter PREG = 1'b0,
+
+ parameter A_INPUT = "DIRECT"
+ )
+ (
+ input clk,
+ input [ 6: 0] opmode,
+ input [29: 0] a,
+ input [17: 0] b,
+ output [47: 0] p,
+ input [29: 0] acin,
+ input [47: 0] pcin,
+ output [29: 0] acout,
+ output [47: 0] pcout
+ );
+
+ //
+ // Tile instantiation
+ //
+ DSP48E1 #
+ (
+ .AREG (AREG),
+ .BREG (1'b1),
+ .CREG (0),
+ .DREG (0),
+ .MREG (0),
+ .PREG (PREG),
+ .ADREG (0),
+
+ .ACASCREG (AREG),
+ .BCASCREG (1'b1),
+ .ALUMODEREG (0),
+ .INMODEREG (0),
+ .OPMODEREG (0),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+
+ .A_INPUT (A_INPUT),
+ .B_INPUT ("DIRECT"),
+
+ .USE_DPORT ("FALSE"),
+ .USE_MULT ("MULTIPLY"),
+ .USE_SIMD ("ONE48"),
+
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .SEL_PATTERN ("PATTERN"),
+ .SEL_MASK ("MASK"),
+ .PATTERN (48'h000000000000),
+ .MASK (48'h3fffffffffff),
+ .AUTORESET_PATDET ("NO_RESET")
+ )
+ DSP48E1_inst
+ (
+ .CLK (clk),
+
+ .RSTA (1'b0),
+ .RSTB (1'b0),
+ .RSTC (1'b0),
+ .RSTD (1'b0),
+ .RSTM (1'b0),
+ .RSTP (1'b0),
+
+ .RSTCTRL (1'b0),
+ .RSTINMODE (1'b0),
+ .RSTALUMODE (1'b0),
+ .RSTALLCARRYIN (1'b0),
+
+ .CEA1 (1'b0),
+ .CEA2 (AREG),
+ .CEB1 (1'b0),
+ .CEB2 (1'b1),
+ .CEC (1'b0),
+ .CED (1'b0),
+ .CEM (1'b0),
+ .CEP (PREG),
+ .CEAD (1'b0),
+ .CEALUMODE (1'b0),
+ .CEINMODE (1'b0),
+
+ .CECTRL (1'b0),
+ .CECARRYIN (1'b0),
+
+ .A (a),
+ .B (b),
+ .C ({48{1'b0}}),
+ .D ({25{1'b1}}),
+ .P (p),
+
+ .CARRYIN (1'b0),
+ .CARRYOUT (),
+ .CARRYINSEL (3'b000),
+
+ .CARRYCASCIN (1'b0),
+ .CARRYCASCOUT (),
+
+ .PATTERNDETECT (),
+ .PATTERNBDETECT (),
+
+ .OPMODE (opmode),
+ .ALUMODE (4'b0000),
+ .INMODE (5'b00000),
+
+ .MULTSIGNIN (1'b0),
+ .MULTSIGNOUT (),
+
+ .UNDERFLOW (),
+ .OVERFLOW (),
+
+ .ACIN (acin),
+ .BCIN (18'd0),
+ .PCIN (pcin),
+
+ .ACOUT (acout),
+ .BCOUT (),
+ .PCOUT (pcout)
+ );
+
+endmodule
diff --git a/lowlevel/artix7/mac16_artix7.v b/lowlevel/artix7/mac16_artix7.v
new file mode 100644
index 0000000..421e7ba
--- /dev/null
+++ b/lowlevel/artix7/mac16_artix7.v
@@ -0,0 +1,90 @@
+//------------------------------------------------------------------------------
+//
+// mac16_artix7.v
+// -----------------------------------------------------------------------------
+// Hardware (Artix-7 DSP48E1) 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_artix7
+ (
+ 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
+ );
+
+
+ //
+ // DSP48E1 Slice
+ //
+
+ /* Operation Mode */
+ wire [ 3: 0] dsp48e1_alumode = 4'b0000;
+ wire [ 6: 0] dsp48e1_opmode = {2'b01, clr, 4'b0101};
+
+ /* Internal Product */
+ wire [47: 0] p_int;
+
+ dsp48e1_wrapper dsp_adder
+ (
+ .clk (clk),
+
+ .ce (ce),
+
+ .carry (1'b0),
+
+ .alumode (dsp48e1_alumode),
+ .opmode (dsp48e1_opmode),
+
+ .a ({{14{1'b0}}, a}),
+ .b ({{ 2{1'b0}}, b}),
+ .c ({48{1'b0}}),
+
+ .p (p_int)
+ );
+
+ //
+ // Output Mapping
+ //
+ assign s = p_int[46:0];
+
+
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/artix7/modexp_systolic_pe_artix7.v b/lowlevel/artix7/modexp_systolic_pe_artix7.v
new file mode 100644
index 0000000..08391f5
--- /dev/null
+++ b/lowlevel/artix7/modexp_systolic_pe_artix7.v
@@ -0,0 +1,126 @@
+//------------------------------------------------------------------------------
+//
+// modexp_systolic_pe_artix7.v
+// -----------------------------------------------------------------------------
+// Hardware (Artix-7 DSP48E1) low-level systolic array processing element.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2016-2017, 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 modexp_systolic_pe_artix7
+ (
+ input clk,
+ input [31: 0] a,
+ input [31: 0] b,
+ input [31: 0] t,
+ input [31: 0] c_in,
+ output [31: 0] p,
+ output [31: 0] c_out
+ );
+
+ reg [31: 0] t_dly;
+ reg [31: 0] c_in_dly;
+
+ always @(posedge clk) t_dly <= t;
+ always @(posedge clk) c_in_dly <= c_in;
+
+ wire [31: 0] t_c_in_s;
+ wire t_c_in_c_out;
+
+ reg t_c_in_c_out_dly;
+
+ always @(posedge clk) t_c_in_c_out_dly <= t_c_in_c_out;
+
+ modexpa7_adder32_artix7 add_t_c_in
+ (
+ .clk (clk),
+ .ce (1'b1),
+ .a (t_dly),
+ .b (c_in_dly),
+ .c_in (1'b0),
+ .s (t_c_in_s),
+ .c_out (t_c_in_c_out)
+ );
+
+ wire [63: 0] a_b;
+
+ wire [31: 0] a_b_lsb = a_b[31: 0];
+ wire [31: 0] a_b_msb = a_b[63:32];
+
+ reg [31: 0] a_b_msb_dly;
+
+ always @(posedge clk) a_b_msb_dly <= a_b_msb;
+
+ modexpa7_multiplier32_artix7 mul_a_b
+ (
+ .clk (clk),
+ .a (a),
+ .b (b),
+ .p (a_b)
+ );
+
+ wire [31: 0] add_p_s;
+ wire add_p_c_out;
+
+ reg [31: 0] add_p_s_dly;
+
+ always @(posedge clk) add_p_s_dly <= add_p_s;
+
+ assign p = add_p_s_dly;
+
+ modexpa7_adder32_artix7 add_p
+ (
+ .clk (clk),
+ .ce (1'b1),
+ .a (a_b_lsb),
+ .b (t_c_in_s),
+ .c_in (1'b0),
+ .s (add_p_s),
+ .c_out (add_p_c_out)
+ );
+
+ modexpa7_adder32_artix7 add_c_out
+ (
+ .clk (clk),
+ .ce (1'b1),
+ .a (a_b_msb_dly),
+ .b ({{31{1'b0}}, t_c_in_c_out_dly}),
+ .c_in (add_p_c_out),
+ .s (c_out),
+ .c_out ()
+ );
+
+endmodule
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/artix7/subtractor32_artix7.v b/lowlevel/artix7/subtractor32_artix7.v
new file mode 100644
index 0000000..7377781
--- /dev/null
+++ b/lowlevel/artix7/subtractor32_artix7.v
@@ -0,0 +1,94 @@
+//------------------------------------------------------------------------------
+//
+// subtractor32_artix7.v
+// -----------------------------------------------------------------------------
+// Hardware (Artix-7 DSP48E1) 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_artix7
+ (
+ input clk,
+ input [31: 0] a,
+ input [31: 0] b,
+ output [31: 0] d,
+ input b_in,
+ output b_out
+ );
+
+ //
+ // Lower and higher parts of operand
+ //
+ wire [17: 0] bl = b[17: 0];
+ wire [13: 0] bh = b[31:18];
+
+ //
+ // DSP48E1 Slice
+ //
+
+ /* Operation Mode */
+ wire [ 3: 0] dsp48e1_alumode = 4'b0011;
+ wire [ 6: 0] dsp48e1_opmode = 7'b0110011;
+
+ /* Internal Product */
+ wire [47: 0] p_int;
+
+ dsp48e1_wrapper dsp_subtractor
+ (
+ .clk (clk),
+
+ .ce (1'b1),
+
+ .carry (b_in),
+
+ .alumode (dsp48e1_alumode),
+ .opmode (dsp48e1_opmode),
+
+ .a ({{16{1'b0}}, bh}),
+ .b (bl),
+ .c ({{16{1'b0}}, a}),
+
+ .p (p_int)
+ );
+
+ //
+ // Output Mapping
+ //
+ assign d = p_int[31: 0];
+ assign b_out = p_int[32];
+
+endmodule
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/cryptech_primitive_switch.vh b/lowlevel/cryptech_primitive_switch.vh
new file mode 100644
index 0000000..a4aad45
--- /dev/null
+++ b/lowlevel/cryptech_primitive_switch.vh
@@ -0,0 +1,94 @@
+//======================================================================
+//
+// Copyright (c) 2018, 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.
+//
+//======================================================================
+
+/* IMPORTANT: The scope of `define in Verilog is somewhat unevident (one
+ "compilation unit"), thus all `defines are prefixed with
+ CRYPTECH_ to prevent any potentical conflicts.
+ */
+
+/* NOTE: You can comment the following line when simulating to use generic
+ primitives and get some speedup, otherwise un-comment it to take
+ advantage of vendor-specific hardware math slices when building the
+ bitstream.
+ */
+
+
+ // generic/vendor switch
+`define CRYPTECH_USE_VENDOR_PRIMITIVES
+
+
+ //
+ // Generic Math Primitives
+ //
+`define CRYPTECH_PRIMITIVE_MAC16_GENERIC mac16_generic
+`define CRYPTECH_PRIMITIVE_ADD32_GENERIC adder32_generic
+`define CRYPTECH_PRIMITIVE_ADD47_GENERIC adder47_generic
+`define CRYPTECH_PRIMITIVE_SUB32_GENERIC subtractor32_generic
+
+
+ //
+ // Xilinx Math Primitives for Artix-7 Family
+ //
+`define CRYPTECH_PRIMITIVE_MAC16_VENDOR mac16_artix7
+`define CRYPTECH_PRIMITIVE_ADD32_VENDOR adder32_artix7
+`define CRYPTECH_PRIMITIVE_ADD47_VENDOR adder47_artix7
+`define CRYPTECH_PRIMITIVE_SUB32_VENDOR subtractor32_artix7
+
+
+
+/* map CRYPTECH_PRIMITIVE_* to either CRYPTECH_PRIMITIVE_*_GENERIC or
+ CRYPTECH_PRIMITIVE_*_VENDOR based on the value of the earlier generic/vendor
+ switch.
+ */
+
+`ifndef CRYPTECH_USE_VENDOR_PRIMITIVES
+
+ // generic primitives
+`define CRYPTECH_PRIMITIVE_MAC16 `CRYPTECH_PRIMITIVE_MAC16_GENERIC
+`define CRYPTECH_PRIMITIVE_ADD32 `CRYPTECH_PRIMITIVE_ADD32_GENERIC
+`define CRYPTECH_PRIMITIVE_ADD47 `CRYPTECH_PRIMITIVE_ADD47_GENERIC
+`define CRYPTECH_PRIMITIVE_SUB32 `CRYPTECH_PRIMITIVE_SUB32_GENERIC
+
+`else
+
+ // vendor-specific primitives
+`define CRYPTECH_PRIMITIVE_MAC16 `CRYPTECH_PRIMITIVE_MAC16_VENDOR
+`define CRYPTECH_PRIMITIVE_ADD47 `CRYPTECH_PRIMITIVE_ADD47_VENDOR
+`define CRYPTECH_PRIMITIVE_ADD32 `CRYPTECH_PRIMITIVE_ADD32_VENDOR
+`define CRYPTECH_PRIMITIVE_SUB32 `CRYPTECH_PRIMITIVE_SUB32_VENDOR
+
+`endif
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/generic/adder32_generic.v b/lowlevel/generic/adder32_generic.v
new file mode 100644
index 0000000..eadfb6f
--- /dev/null
+++ b/lowlevel/generic/adder32_generic.v
@@ -0,0 +1,67 @@
+//------------------------------------------------------------------------------
+//
+// adder32_generic.v
+// -----------------------------------------------------------------------------
+// Generic 32-bit adder.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2016, NORDUnet A/S
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//------------------------------------------------------------------------------
+
+module adder32_generic
+ (
+ input clk, // clock
+ input [31: 0] a, // operand input
+ input [31: 0] b, // operand input
+ output [31: 0] s, // sum output
+ input c_in, // carry input
+ output c_out // carry output
+ );
+
+ //
+ // Sum
+ //
+ reg [32: 0] s_int;
+
+ always @(posedge clk)
+ s_int <= {1'b0, a} + {1'b0, b} + {{32{1'b0}}, c_in};
+
+ //
+ // Output
+ //
+ assign s = s_int[31:0];
+ assign c_out = s_int[32];
+
+endmodule
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/generic/adder47_generic.v b/lowlevel/generic/adder47_generic.v
new file mode 100644
index 0000000..406c175
--- /dev/null
+++ b/lowlevel/generic/adder47_generic.v
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+//
+// adder47_generic.v
+// -----------------------------------------------------------------------------
+// Generic 47-bit adder.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2016, NORDUnet A/S
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//------------------------------------------------------------------------------
+
+module adder47_generic
+ (
+ input clk, // clock
+ input [46: 0] a, // operand input
+ input [46: 0] b, // operand input
+ output [46: 0] s // sum output
+ );
+
+ //
+ // Sum
+ //
+ reg [46: 0] s_int;
+
+ always @(posedge clk)
+ s_int <= a + b;
+
+ //
+ // Output
+ //
+ assign s = s_int;
+
+endmodule
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/generic/mac16_generic.v b/lowlevel/generic/mac16_generic.v
new file mode 100644
index 0000000..6d120a3
--- /dev/null
+++ b/lowlevel/generic/mac16_generic.v
@@ -0,0 +1,74 @@
+//------------------------------------------------------------------------------
+//
+// mac16_generic.v
+// -----------------------------------------------------------------------------
+// Generic 16-bit multiplier and 47-bit accumulator.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2016, NORDUnet A/S
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//------------------------------------------------------------------------------
+
+module mac16_generic
+ (
+ input clk, // clock
+ input clr, // clear accumulator (active-high)
+ input ce, // enable clock (active-high)
+ input [15: 0] a, // operand input
+ input [15: 0] b, // operand input
+ output [46: 0] s // sum output
+ );
+
+ //
+ // Multiplier
+ //
+ wire [31: 0] p = {{16{1'b0}}, a} * {{16{1'b0}}, b};
+ wire [46: 0] p_ext = {{15{1'b0}}, p};
+
+ //
+ // Accumulator
+ //
+ reg [46: 0] s_int;
+
+ always @(posedge clk)
+ //
+ if (ce) s_int <= clr ? p_ext : p_ext + s_int;
+
+ //
+ // Output
+ //
+ assign s = s_int;
+
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/lowlevel/generic/modexp_systolic_pe_generic.v b/lowlevel/generic/modexp_systolic_pe_generic.v
new file mode 100644
index 0000000..0e338ff
--- /dev/null
+++ b/lowlevel/generic/modexp_systolic_pe_generic.v
@@ -0,0 +1,85 @@
+//======================================================================
+//
+// modexp_systolic_pe_generic.v
+// -----------------------------------------------------------------------------
+// Generic low-level systolic array processing element for ModExp core.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2017-2018, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module modexp_systolic_pe_generic
+ (
+ input clk,
+ input [31: 0] a,
+ input [31: 0] b,
+ input [31: 0] t,
+ input [31: 0] c_in,
+ output [31: 0] p,
+ output [31: 0] c_out
+ );
+
+ //
+ // Customizable Latency
+ //
+ parameter LATENCY = 4;
+
+ //
+ // Delay Line
+ //
+ reg [63: 0] abct[1:LATENCY];
+
+ //
+ // Outputs
+ //
+ assign p = abct[LATENCY][31: 0];
+ assign c_out = abct[LATENCY][63:32];
+
+ //
+ // Sub-products
+ //
+ wire [63: 0] ab = {{32{1'b0}}, a} * {{32{1'b0}}, b};
+ wire [63: 0] ct = {{32{1'b0}}, c_in} + {{32{1'b0}}, t};
+
+ //
+ // Delay
+ //
+ integer i;
+ always @(posedge clk)
+ //
+ for (i=1; i<=LATENCY; i=i+1)
+ abct[i] <= (i == 1) ? ab + ct : abct[i-1];
+
+endmodule
+
+//======================================================================
+// End of file
+//======================================================================
diff --git a/lowlevel/generic/subtractor32_generic.v b/lowlevel/generic/subtractor32_generic.v
new file mode 100644
index 0000000..5137ace
--- /dev/null
+++ b/lowlevel/generic/subtractor32_generic.v
@@ -0,0 +1,67 @@
+//------------------------------------------------------------------------------
+//
+// subtractor32_generic.v
+// -----------------------------------------------------------------------------
+// Generic 32-bit subtractor.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2016, NORDUnet A/S
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//------------------------------------------------------------------------------
+
+module subtractor32_generic
+ (
+ input clk,
+ input [31: 0] a,
+ input [31: 0] b,
+ output [31: 0] d,
+ input b_in,
+ output b_out
+ );
+
+ //
+ // Difference
+ //
+ reg [32: 0] d_int;
+
+ always @(posedge clk)
+ d_int <= {1'b0, a} - {1'b0, b} - {{32{1'b0}}, b_in};
+
+ //
+ // Output
+ //
+ assign d = d_int[31:0];
+ assign b_out = d_int[32];
+
+endmodule
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/memory/bram_1rw_1ro_readfirst.v b/memory/bram_1rw_1ro_readfirst.v
new file mode 100644
index 0000000..29e0daa
--- /dev/null
+++ b/memory/bram_1rw_1ro_readfirst.v
@@ -0,0 +1,112 @@
+//======================================================================
+//
+// Copyright (c) 2015, 2018 NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module bram_1rw_1ro_readfirst #
+(
+ parameter MEM_WIDTH = 32,
+ parameter MEM_ADDR_BITS = 8
+)
+(
+ input clk,
+
+ input [MEM_ADDR_BITS-1:0] a_addr,
+ input a_wr,
+ input [MEM_WIDTH -1:0] a_in,
+ output [MEM_WIDTH -1:0] a_out,
+
+ input [MEM_ADDR_BITS-1:0] b_addr,
+ output [MEM_WIDTH -1:0] b_out
+);
+
+
+ //
+ // BRAM
+ //
+ (* RAM_STYLE="BLOCK" *)
+ reg [MEM_WIDTH-1:0] bram[0:(2**MEM_ADDR_BITS)-1];
+
+
+ //
+ // Initialization for Simulation
+ //
+ /*
+ 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;
+
+
+ //
+ // Note, that when both ports are accessing the same location, conflict can
+ // potentionally arise. See Xilinx UG473 (pages 19-20, "Conflict
+ // Avoidance") for more information. In our configuration to avoid that the
+ // write port must be coded to operate in READ_FIRST mode. If the write
+ // port is overwriting the same address the read port is accessing, the
+ // write port must read the previously stored data (not the data it is
+ // writing, as that would be WRITE_FIRST mode).
+ //
+
+
+ //
+ // 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/memory/bram_1rw_readfirst.v b/memory/bram_1rw_readfirst.v
new file mode 100644
index 0000000..9003e50
--- /dev/null
+++ b/memory/bram_1rw_readfirst.v
@@ -0,0 +1,75 @@
+//======================================================================
+//
+// Copyright (c) 2017, 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_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
+ );
+
+
+ //
+ // BRAM
+ //
+ (* RAM_STYLE="BLOCK" *)
+ reg [MEM_WIDTH-1:0] bram[0:(2**MEM_ADDR_BITS)-1];
+
+
+ //
+ // Output Register
+ //
+ reg [MEM_WIDTH-1:0] bram_reg_a;
+
+ assign a_out = bram_reg_a;
+
+
+ //
+ // Read-Write Port A
+ //
+ always @(posedge clk) begin
+ //
+ bram_reg_a <= bram[a_addr];
+ //
+ if (a_wr) bram[a_addr] <= a_in;
+ //
+ end
+
+
+endmodule
diff --git a/memory/bram_1wo_1ro_readfirst.v b/memory/bram_1wo_1ro_readfirst.v
new file mode 100644
index 0000000..6991c87
--- /dev/null
+++ b/memory/bram_1wo_1ro_readfirst.v
@@ -0,0 +1,107 @@
+//======================================================================
+//
+// Copyright (c) 2015, 2018 NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module bram_1wo_1ro_readfirst #
+(
+ parameter MEM_WIDTH = 32,
+ parameter MEM_ADDR_BITS = 8
+)
+(
+ input clk,
+
+ input [MEM_ADDR_BITS-1:0] a_addr,
+ input a_wr,
+ input [MEM_WIDTH -1:0] a_in,
+ output [MEM_WIDTH -1:0] a_out,
+
+ input [MEM_ADDR_BITS-1:0] b_addr,
+ output [MEM_WIDTH -1:0] b_out
+);
+
+
+ //
+ // BRAM
+ //
+ (* RAM_STYLE="BLOCK" *)
+ reg [MEM_WIDTH-1:0] bram[0:(2**MEM_ADDR_BITS)-1];
+
+
+ //
+ // Initialization for Simulation
+ //
+ /*
+ 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_b;
+
+ assign a_out = 32'hDEADCE11;
+ assign b_out = bram_reg_b;
+
+
+ //
+ // Note, that when both ports are accessing the same location, conflict can
+ // potentionally arise. See Xilinx UG473 (pages 19-20, "Conflict
+ // Avoidance") for more information. In our configuration to avoid that the
+ // write port must be coded to operate in READ_FIRST mode. If the write
+ // port is overwriting the same address the read port is accessing, the
+ // write port must read the previously stored data (not the data it is
+ // writing, as that would be WRITE_FIRST mode).
+ //
+
+
+ //
+ // Write-Only Port A
+ //
+ always @(posedge clk)
+ //
+ if (a_wr) bram[a_addr] <= a_in;
+
+
+ //
+ // Read-Only Port B
+ //
+ always @(posedge clk)
+ //
+ bram_reg_b <= bram[b_addr];
+
+
+endmodule
diff --git a/modular/modular_adder.v b/modular/modular_adder.v
new file mode 100644
index 0000000..c2f5a4e
--- /dev/null
+++ b/modular/modular_adder.v
@@ -0,0 +1,298 @@
+//------------------------------------------------------------------------------
+//
+// modular_adder.v
+// -----------------------------------------------------------------------------
+// Modular adder.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 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 modular_adder
+(
+ clk, rst_n,
+ ena, rdy,
+ ab_addr, n_addr, s_addr, s_wren,
+ a_din, b_din, n_din, s_dout
+);
+
+
+ //
+ // Settings
+ //
+ `include "cryptech_primitive_switch.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 clk; // system clock
+ input rst_n; // active-low async reset
+
+ input ena; // enable input
+ output rdy; // ready output
+
+ output [WORD_COUNTER_WIDTH-1:0] ab_addr; // index of current A and B words
+ output [WORD_COUNTER_WIDTH-1:0] n_addr; // index of current N word
+ output [WORD_COUNTER_WIDTH-1:0] s_addr; // index of current S word
+ output s_wren; // store current S word now
+
+ input [ 32-1:0] a_din; // A
+ input [ 32-1:0] b_din; // B
+ input [ 32-1:0] n_din; // N
+ output [ 32-1: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;
+
+ `CRYPTECH_PRIMITIVE_ADD32 add32
+ (
+ .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;
+
+ `CRYPTECH_PRIMITIVE_SUB32 sub
+ (
+ .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/modular/modular_subtractor.v b/modular/modular_subtractor.v
new file mode 100644
index 0000000..4ac5e44
--- /dev/null
+++ b/modular/modular_subtractor.v
@@ -0,0 +1,294 @@
+//------------------------------------------------------------------------------
+//
+// modular_subtractor.v
+// -----------------------------------------------------------------------------
+// Modular subtractor.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 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 modular_subtractor
+(
+ clk, rst_n,
+ ena, rdy,
+ ab_addr, n_addr, d_addr, d_wren,
+ a_din, b_din, n_din, d_dout
+);
+
+
+ //
+ // Settings
+ //
+ `include "cryptech_primitive_switch.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 clk; // system clock
+ input rst_n; // active-low async reset
+
+ input ena; // enable input
+ output rdy; // ready output
+
+ output [WORD_COUNTER_WIDTH-1:0] ab_addr; // index of current A and B words
+ output [WORD_COUNTER_WIDTH-1:0] n_addr; // index of current N word
+ output [WORD_COUNTER_WIDTH-1:0] d_addr; // index of current D word
+ output d_wren; // store current D word now
+
+ input [ 32-1:0] a_din; // A
+ input [ 32-1:0] b_din; // B
+ input [ 32-1:0] n_din; // N
+ output [ 32-1: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;
+
+ `CRYPTECH_PRIMITIVE_SUB32 sub32
+ (
+ .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;
+
+ `CRYPTECH_PRIMITIVE_ADD32 add32
+ (
+ .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 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 Difference 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/multiword/multiword_comparator.v b/multiword/multiword_comparator.v
new file mode 100644
index 0000000..bbdb2a6
--- /dev/null
+++ b/multiword/multiword_comparator.v
@@ -0,0 +1,232 @@
+//------------------------------------------------------------------------------
+//
+// multiword_comparator.v
+// -----------------------------------------------------------------------------
+// Multi-word comparator.
+//
+// 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 multiword_comparator
+(
+ clk, rst_n,
+ ena, rdy,
+ xy_addr, x_din, y_din,
+ cmp_l, cmp_e, cmp_g
+);
+
+ //
+ // Settings
+ //
+ `include "cryptech_primitive_switch.vh"
+
+
+ //
+ // 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_PREV_OR_LAST;
+ input [WORD_COUNTER_WIDTH-1:0] WORD_INDEX_CURRENT;
+ begin
+ WORD_INDEX_PREV_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] xy_addr; // address of current X and Y words
+ input [ 32-1:0] x_din; // current X word
+ input [ 32-1:0] y_din; // current Y word
+
+ output cmp_l; // X < Y ?
+ output cmp_e; // X = Y ?
+ output cmp_g; // X > Y ?
+
+
+ //
+ // Word Indices
+ //
+ reg [WORD_COUNTER_WIDTH-1:0] index_xy;
+
+
+ //
+ // Comparison Result
+ //
+ reg reg_cmp_l;
+ reg reg_cmp_e;
+ reg reg_cmp_g;
+
+
+ //
+ // Output Mapping
+ //
+ assign xy_addr = index_xy;
+
+ assign cmp_l = reg_cmp_l;
+ assign cmp_e = reg_cmp_e;
+ assign cmp_g = reg_cmp_g;
+
+
+ //
+ // FSM
+ //
+ localparam FSM_SHREG_WIDTH = 1 * OPERAND_NUM_WORDS + 3;
+ 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_dec_index_xy = 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_calc_leg = fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 3) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 2)];
+ wire fsm_shreg_calc_leg_last = fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 2)];
+
+ wire dec_index_xy = |fsm_shreg_dec_index_xy;
+ wire calc_leg = |fsm_shreg_calc_leg;
+ wire calc_leg_last = fsm_shreg_calc_leg_last;
+
+
+ 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) index_xy <= WORD_INDEX_LAST;
+ else if (dec_index_xy) index_xy <= WORD_INDEX_PREV_OR_LAST(index_xy);
+
+
+ //
+ // 32-bit Subtractor
+ //
+ wire [31: 0] sub32_d_out;
+ wire sub32_b_in;
+ wire sub32_b_out;
+
+ `CRYPTECH_PRIMITIVE_SUB32 sub32_inst
+ (
+ .clk (clk),
+
+ .a (x_din),
+ .b (y_din),
+
+ .d (sub32_d_out),
+
+ .b_in (sub32_b_in),
+ .b_out (sub32_b_out)
+ );
+
+
+ //
+ // Borrow Masking Logic
+ //
+ reg sub32_b_mask;
+
+ always @(posedge clk)
+ //
+ sub32_b_mask <= (index_xy == WORD_INDEX_LAST) ? 1'b1 : 1'b0;
+
+ assign sub32_b_in = sub32_b_out & ~sub32_b_mask;
+
+
+ //
+ // Output Logic
+ //
+ wire cmp_unresolved = !(cmp_l || cmp_g);
+
+ wire cmp_borrow_is_set = (sub32_b_out == 1'b1) ? 1'b1 : 1'b0;
+ wire cmp_difference_is_nonzero = (sub32_d_out != 32'd0) ? 1'b1 : 1'b0;
+
+ always @(posedge clk)
+ //
+ if (rdy) begin
+ //
+ if (ena) begin
+ //
+ reg_cmp_l <= 1'b0;
+ reg_cmp_e <= 1'b0;
+ reg_cmp_g <= 1'b0;
+ //
+ end
+ //
+ end else if (cmp_unresolved && calc_leg) begin
+ //
+ if ( cmp_borrow_is_set) reg_cmp_l <= 1'b1;
+ if (!cmp_borrow_is_set && cmp_difference_is_nonzero) reg_cmp_g <= 1'b1;
+ if (!cmp_borrow_is_set && !cmp_difference_is_nonzero && calc_leg_last) reg_cmp_e <= 1'b1;
+ //
+ end
+
+
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/multiword/multiword_mover.v b/multiword/multiword_mover.v
new file mode 100644
index 0000000..8a7a015
--- /dev/null
+++ b/multiword/multiword_mover.v
@@ -0,0 +1,169 @@
+//------------------------------------------------------------------------------
+//
+// multiword_mover.v
+// -----------------------------------------------------------------------------
+// Multi-word data mover.
+//
+// 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 multiword_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 = 1'b0;
+
+ 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
+//------------------------------------------------------------------------------
diff --git a/util/cryptech_clog2.vh b/util/cryptech_clog2.vh
new file mode 100644
index 0000000..06120c4
--- /dev/null
+++ b/util/cryptech_clog2.vh
@@ -0,0 +1,48 @@
+//======================================================================
+//
+// Copyright (c) 2015, 2018 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.
+//
+//======================================================================
+
+function integer cryptech_clog2;
+ input integer value;
+ integer result;
+ //
+ begin
+ value = value - 1;
+ for (result = 0; value > 0; result = result + 1)
+ value = value >> 1;
+ clog2 = result;
+ end
+ //
+endfunction
+
+//======================================================================
+// End of file
+//======================================================================