[Cryptech-Commits] [core/pkey/ecdsa256] branch master updated: * Rewritten from scratch, uses the same hardware architecture as the Ed25519 core for better timing performance

git at cryptech.is git at cryptech.is
Thu Dec 20 10:46:48 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/pkey/ecdsa256.

The following commit(s) were added to refs/heads/master by this push:
     new c617c0c   * Rewritten from scratch, uses the same hardware architecture as the Ed25519    core for better timing performance
c617c0c is described below

commit c617c0c711620f58eb3ead22edcdfe57fed06088
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Wed Dec 19 15:34:55 2018 +0300

     * Rewritten from scratch, uses the same hardware architecture as the Ed25519
       core for better timing performance
    
     * Removed custom modular inversion sub-module, now uses micro-coded modular
       inversion routine based on Fermat's little theorem (~10% faster)
    
     * Uses math primitives from core/lib
    
     * Added randomized test vector
      (see user/shatov/ecdsa_fpga_model/test_vectors/)
---
 bench/ecdsa256_test_vector_nsa.vh     |  26 +
 bench/ecdsa_test_vector_randomized.vh |  29 ++
 bench/tb_curve_adder_256.v            | 420 ----------------
 bench/tb_curve_doubler_256.v          | 409 ----------------
 bench/tb_curve_multiplier_256.v       | 525 ++++++++++----------
 bench/tb_lowlevel_adder32.v           | 175 -------
 bench/tb_lowlevel_adder47.v           | 151 ------
 bench/tb_lowlevel_subtractor32.v      | 174 -------
 bench/tb_modular_adder.v              | 357 --------------
 bench/tb_modular_invertor.v           | 225 ---------
 bench/tb_modular_multiplier_256.v     | 366 --------------
 bench/tb_modular_subtractor.v         | 356 --------------
 bench/tb_mw_comparator.v              | 322 ------------
 bench/tb_mw_mover.v                   | 282 -----------
 rtl/curve/curve_dbl_add_256.v         | 893 ----------------------------------
 rtl/curve/curve_mul_256.v             | 719 ---------------------------
 rtl/curve/rom/brom_p256_delta.v       |  68 ---
 rtl/curve/rom/brom_p256_g_x.v         |  68 ---
 rtl/curve/rom/brom_p256_g_y.v         |  68 ---
 rtl/curve/rom/brom_p256_h_x.v         |  68 ---
 rtl/curve/rom/brom_p256_h_y.v         |  68 ---
 rtl/curve/rom/brom_p256_one.v         |  68 ---
 rtl/curve/rom/brom_p256_q.v           |  68 ---
 rtl/curve/rom/brom_p256_zero.v        |  70 ---
 rtl/ecdsa256.v                        | 160 ------
 rtl/ecdsa256_banks_array.v            | 119 +++++
 rtl/ecdsa256_base_point_multiplier.v  | 310 ++++++++++++
 rtl/ecdsa256_core_top.v               | 150 ++++++
 rtl/ecdsa256_microcode_rom.v          | 424 ++++++++++++++++
 rtl/ecdsa256_operand_bank.v           | 160 ++++++
 rtl/ecdsa256_uop_worker.v             | 604 +++++++++++++++++++++++
 rtl/ecdsa256_wrapper.v                |  72 +--
 rtl/modular/modular_multiplier_256.v  | 402 ---------------
 rtl/modular/modular_reductor_256.v    | 692 --------------------------
 stm32_driver/ecdsa256_driver_sample.c | 100 ++--
 35 files changed, 2185 insertions(+), 6983 deletions(-)

diff --git a/bench/ecdsa256_test_vector_nsa.vh b/bench/ecdsa256_test_vector_nsa.vh
new file mode 100644
index 0000000..e62b657
--- /dev/null
+++ b/bench/ecdsa256_test_vector_nsa.vh
@@ -0,0 +1,26 @@
+/* Values from "Suite B Implementer's Guide to FIPS 186-3 (ECDSA)" */
+
+localparam [255:0] ECDSA_P256_D_NSA =
+	{32'h70a12c2d, 32'hb16845ed, 32'h56ff68cf, 32'hc21a472b,
+	 32'h3f04d7d6, 32'h851bf634, 32'h9f2d7d5b, 32'h3452b38a};
+
+localparam [255:0] ECDSA_P256_QX_NSA =
+	{32'h8101ece4, 32'h7464a6ea, 32'hd70cf69a, 32'h6e2bd3d8,
+	 32'h8691a326, 32'h2d22cba4, 32'hf7635eaf, 32'hf26680a8};
+	 
+localparam [255:0] ECDSA_P256_QY_NSA =
+	{32'hd8a12ba6, 32'h1d599235, 32'hf67d9cb4, 32'hd58f1783,
+	 32'hd3ca43e7, 32'h8f0a5aba, 32'ha6240799, 32'h36c0c3a9};
+	 
+localparam [255:0] ECDSA_P256_K_NSA =
+	{32'h580ec00d, 32'h85643433, 32'h4cef3f71, 32'hecaed496,
+	 32'h5b12ae37, 32'hfa47055b, 32'h1965c7b1, 32'h34ee45d0};
+
+localparam [255:0] ECDSA_P256_RX_NSA =
+	{32'h7214bc96, 32'h47160bbd, 32'h39ff2f80, 32'h533f5dc6,
+	 32'hddd70ddf, 32'h86bb8156, 32'h61e805d5, 32'hd4e6f27c};
+	 
+localparam [255:0] ECDSA_P256_RY_NSA =
+	{32'h8b81e3e9, 32'h77597110, 32'hc7cf2633, 32'h435b2294,
+	 32'hb7264298, 32'h7defd3d4, 32'h007e1cfc, 32'h5df84541};
+
diff --git a/bench/ecdsa_test_vector_randomized.vh b/bench/ecdsa_test_vector_randomized.vh
new file mode 100644
index 0000000..6c5cf80
--- /dev/null
+++ b/bench/ecdsa_test_vector_randomized.vh
@@ -0,0 +1,29 @@
+/* Generated automatically, do not edit. */
+
+localparam [255:0] ECDSA_P256_D_RANDOM  =
+	{32'h503e58af, 32'hcf3af333, 32'h7bf53409, 32'h445012b8, 
+	 32'h1fb4548c, 32'h4d2b1302, 32'ha617f9b1, 32'hd00d7de0};
+
+localparam [255:0] ECDSA_P256_QX_RANDOM =
+	{32'hd9349b48, 32'hb0ee8c36, 32'h139b1d78, 32'hedc1911b, 
+	 32'h250877fb, 32'h7ad44ae1, 32'h8bb2f8a6, 32'hf4dccae5};
+
+localparam [255:0] ECDSA_P256_QY_RANDOM =
+	{32'he0a056e8, 32'hb5092a6c, 32'h728f4bc8, 32'h9043fbe2, 
+	 32'h7c262744, 32'hdfbdaf17, 32'h83fc2e01, 32'hb060771b};
+
+localparam [383:0] ECDSA_P384_D_RANDOM  =
+	{32'hbb4a09d8, 32'he527f062, 32'h665eb4d0, 32'hb39a1dce, 
+	 32'h94daa2c5, 32'h935b3163, 32'hb090f079, 32'h3ee36a5a, 
+	 32'h62a7055d, 32'h5d850d1b, 32'h15dc656d, 32'h65d8b3a2};
+
+localparam [383:0] ECDSA_P384_QX_RANDOM =
+	{32'hb8023e60, 32'hae42ea14, 32'h6330f2c3, 32'h883096ca, 
+	 32'h961b11f5, 32'hdfea4a1d, 32'h65e98e64, 32'hb33527fb, 
+	 32'h57226db4, 32'h8a514325, 32'h1ef06bde, 32'hf78eb57a};
+
+localparam [383:0] ECDSA_P384_QY_RANDOM =
+	{32'hd3c66469, 32'h625aaaad, 32'ha347e103, 32'h3c1474b6, 
+	 32'h343a9368, 32'hff294501, 32'hbbd53b1c, 32'hc49fd972, 
+	 32'hda439c9d, 32'ha827e230, 32'h2720e2b7, 32'h8dd14f9e};
+
diff --git a/bench/tb_curve_adder_256.v b/bench/tb_curve_adder_256.v
deleted file mode 100644
index c9b50ce..0000000
--- a/bench/tb_curve_adder_256.v
+++ /dev/null
@@ -1,420 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_curve_adder_256.v
-// -----------------------------------------------------------------------------
-// Testbench for 256-bit curve point 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.
-//
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_curve_adder_256;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[255:0]	PX_1	= 256'ha536512112e4bb911ae72744a914761ddc53700f889c88e583e0edd45c179b08;
-   localparam	[255:0]	PY_1	= 256'h239e73bf40f4831ab71ccea072291893ac8582982ea6fec6bd6aaf36ac32d22e;
-   localparam	[255:0]	PZ_1	= 256'h32258ae04c5498bb34b29c54a7f95afc10c009540c51731eae164750ca385029;
-
-   localparam	[255:0]	RX_1	= 256'he4fcdd1a151b405b2a567d20d7674031c6d5b207b0b5dcf277015d81784492d5;
-   localparam	[255:0]	RY_1	= 256'h4782c540b58988b07bb8e0c5ad3ff562dd45c075a39ee71896d5eb33702dd656;
-   localparam	[255:0]	RZ_1	= 256'hae637ff2fd5468780241afb3a8ebaeb8618e86b4a1a211b350546c9e6fea93d4;
-
-   localparam	[255:0]	PX_2	= 256'he58a6470e038f6b261d5a9a72fb2bd96b6bad433ff7baea6a40b5facf5085189;
-   localparam	[255:0]	PY_2	= 256'h03dd8785b592307811ee5512e2d713c5dc65f60f01883340fe0f56f858a39474;
-   localparam	[255:0]	PZ_2	= 256'h1b4657b1e79c9074fbf7f63f96ce2854db4808afc72841fac623dc68d9bff64d;
-
-   localparam	[255:0]	RX_2	= 256'hc354e99a827a3f1c30f29f6b1d72273eb0daaeb06bb373ed315e305b89d857ca;
-   localparam	[255:0]	RY_2	= 256'h0cb054f95589c1fcbe763df3b8d7badd568d5e93a667076dddfc70dcfab74948;
-   localparam	[255:0]	RZ_2	= 256'hd79d9170dd628aee82d149715a6ec6cc44426ccae236d2a146edbd15a564ea53;
-
-   localparam	[255:0]	PX_3	= 256'hbf5fe30c79025a0b638b0fd62bf1349aee0a9fc7fc2719291b0c23535c16eb52;
-   localparam	[255:0]	PY_3	= 256'h8a637c7c0b9459de664d40a717e1abc0f843f03169fae943e0835cbe767da06b;
-   localparam	[255:0]	PZ_3	= 256'h0871d93601d654216912866514a788a92e8a9b6047611bf185d459e204727377;
-
-   localparam	[255:0]	RX_3	= 256'h1ba6259b5b750e4d6e4f490f661646cd9491be16965f47044ac2688048e567c5;
-   localparam	[255:0]	RY_3	= 256'h80e55c16f403f8d7282bca628477771a45330567caa5aaab9a54919dbe05e3e4;
-   localparam	[255:0]	RZ_3	= 256'hb99663f045c9602b05f23aaaa508e6167d15740be900175dbeceb957a9dad951;
-
-   localparam	[255:0]	PX_4	= 256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-   localparam	[255:0]	PY_4	= 256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-   localparam	[255:0]	PZ_4	= 256'h0000000000000000000000000000000000000000000000000000000000000000;
-
-   localparam	[255:0]	RX_4	= 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; // G.x
-   localparam	[255:0]	RY_4	= 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; // G.y
-   localparam	[255:0]	RZ_4	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[255:0]	PX_5	= 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; // G.x
-   localparam	[255:0]	PY_5	= 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; // G.y
-   localparam	[255:0]	PZ_5	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[255:0]	RX_5	= 256'h29d05c193da77b710e86323538b77e1b11f904fea42998be16bd8d744ece7ad0; // H.x
-   localparam	[255:0]	RY_5	= 256'hb01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae07; // H.y
-   localparam	[255:0]	RZ_5	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[255:0]	PX_6	= 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; // G.x
-   localparam	[255:0]	PY_6	= 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; // G.y
-   localparam	[255:0]	PZ_6	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[255:0]	RX_6	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-   localparam	[255:0]	RY_6	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-   localparam	[255:0]	RZ_6	= 256'h0000000000000000000000000000000000000000000000000000000000000000;
-
-   localparam	[255:0]	Q		= 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  3;
-   localparam	OPERAND_NUM_WORDS	=  8;
-
-
-   //
-   // Clock (100 MHz)
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-
-   //
-   // Buffers (PX, PY, PZ, RX, RY, RZ, Q)
-   //
-   wire [WORD_COUNTER_WIDTH-1:0] core_px_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_py_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_pz_addr;
-
-   wire [WORD_COUNTER_WIDTH-1:0] core_rx_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_ry_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_rz_addr;
-
-   wire [WORD_COUNTER_WIDTH-1:0] core_q_addr;
-
-   wire 			 core_rx_wren;
-   wire 			 core_ry_wren;
-   wire 			 core_rz_wren;
-
-   wire [                32-1:0] core_px_data;
-   wire [                32-1:0] core_py_data;
-   wire [                32-1:0] core_pz_data;
-
-   wire [                32-1:0] core_rx_data_wr;
-   wire [                32-1:0] core_ry_data_wr;
-   wire [                32-1:0] core_rz_data_wr;
-
-   wire [                32-1:0] core_rx_data_rd;
-   wire [                32-1:0] core_ry_data_rd;
-   wire [                32-1:0] core_rz_data_rd;
-
-   wire [                32-1:0] core_q_data;
-
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_xyzq_addr;
-   reg 				 tb_xyzq_wren;
-
-   reg [                  31:0]  tb_px_data;
-   reg [                  31:0]  tb_py_data;
-   reg [                  31:0]  tb_pz_data;
-   wire [                  31:0] tb_rx_data;
-   wire [                  31:0] tb_ry_data;
-   wire [                  31:0] tb_rz_data;
-   reg [                  31:0]  tb_q_data;
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_px
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_px_data), .a_out(),
-	.b_addr(core_px_addr), .b_out(core_px_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_py
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_py_data), .a_out(),
-	.b_addr(core_py_addr), .b_out(core_py_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_pz
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_pz_data), .a_out(),
-	.b_addr(core_pz_addr), .b_out(core_pz_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_q
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_q_data), .a_out(),
-	.b_addr(core_q_addr), .b_out(core_q_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_rx
-     (	.clk(clk),
-	.a_addr(core_rx_addr), .a_wr(core_rx_wren), .a_in(core_rx_data_wr), .a_out(core_rx_data_rd),
-	.b_addr(tb_xyzq_addr), .b_out(tb_rx_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_ry
-     (	.clk(clk),
-	.a_addr(core_ry_addr), .a_wr(core_ry_wren), .a_in(core_ry_data_wr), .a_out(core_ry_data_rd),
-	.b_addr(tb_xyzq_addr), .b_out(tb_ry_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_rz
-     (	.clk(clk),
-	.a_addr(core_rz_addr), .a_wr(core_rz_wren), .a_in(core_rz_data_wr), .a_out(core_rz_data_rd),
-	.b_addr(tb_xyzq_addr), .b_out(tb_rz_data)
-	);
-
-
-   //
-   // Opcode
-   //
-   wire [ 5: 0] 	 add_uop_addr;
-   wire [19: 0] 	 add_uop;
-
-   uop_add_rom add_rom
-     (
-      .clk		(clk),
-      .addr		(add_uop_addr),
-      .data		(add_uop)
-      );
-
-   //
-   // UUT
-   //
-   curve_dbl_add_256 uut
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(ena),
-      .rdy		(rdy),
-
-      .uop_addr	(add_uop_addr),
-      .uop		(add_uop),
-
-      .px_addr	(core_px_addr),
-      .py_addr	(core_py_addr),
-      .pz_addr	(core_pz_addr),
-      .rx_addr	(core_rx_addr),
-      .ry_addr	(core_ry_addr),
-      .rz_addr	(core_rz_addr),
-      .q_addr	(core_q_addr),
-
-      .rx_wren	(core_rx_wren),
-      .ry_wren	(core_ry_wren),
-      .rz_wren	(core_rz_wren),
-
-      .px_din	(core_px_data),
-      .py_din	(core_py_data),
-      .pz_din	(core_pz_data),
-      .rx_din	(core_rx_data_rd),
-      .ry_din	(core_ry_data_rd),
-      .rz_din	(core_rz_data_rd),
-      .rx_dout	(core_rx_data_wr),
-      .ry_dout	(core_ry_data_wr),
-      .rz_dout	(core_rz_data_wr),
-      .q_din	(core_q_data)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 			 ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n		= 0;
-      ena		= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n		= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_curve_adder(PX_1,     PY_1, PZ_1, RX_1, RY_1, RZ_1);
-      test_curve_adder(PX_2,     PY_2, PZ_2, RX_2, RY_2, RZ_2);
-      test_curve_adder(PX_3,     PY_3, PZ_3, RX_3, RY_3, RZ_3);
-      test_curve_adder(PX_4,     PY_4, PZ_4, RX_4, RY_4, RZ_4);
-      test_curve_adder(PX_5,     PY_5, PZ_5, RX_5, RY_5, RZ_5);
-      test_curve_adder(PX_6, Q - PY_6, PZ_6, RX_6, RY_6, RZ_6);
-
-      /* print result */
-      if (ok)	$display("tb_curve_adder_256: SUCCESS");
-      else	$display("tb_curve_adder_256: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg		t_ok;
-
-   integer	w;
-
-   task test_curve_adder;
-
-      input [255:0]	px;
-      input [255:0] 	py;
-      input [255:0] 	pz;
-
-      input [255:0] 	rx;
-      input [255:0] 	ry;
-      input [255:0] 	rz;
-
-      reg [255:0] 	px_shreg;
-      reg [255:0] 	py_shreg;
-      reg [255:0] 	pz_shreg;
-
-      reg [255:0] 	rx_shreg;
-      reg [255:0] 	ry_shreg;
-      reg [255:0] 	rz_shreg;
-
-      reg [255:0] 	q_shreg;
-
-      begin
-
-	 /* start filling memories */
-	 tb_xyzq_wren = 1;
-
-	 /* initialize shift registers */
-	 px_shreg = px;
-	 py_shreg = py;
-	 pz_shreg = pz;
-	 q_shreg  = Q;
-
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set addresses */
-	    tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* set data words */
-	    tb_px_data	= px_shreg[31:0];
-	    tb_py_data	= py_shreg[31:0];
-	    tb_pz_data	= pz_shreg[31:0];
-	    tb_q_data	= q_shreg[31:0];
-
-	    /* shift inputs */
-	    px_shreg = {{32{1'bX}}, px_shreg[255:32]};
-	    py_shreg = {{32{1'bX}}, py_shreg[255:32]};
-	    pz_shreg = {{32{1'bX}}, pz_shreg[255:32]};
-	    q_shreg  = {{32{1'bX}}, q_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_xyzq_addr = {WORD_COUNTER_WIDTH{1'bX}};
-
-	 /* wipe data words */
-	 tb_px_data = {32{1'bX}};
-	 tb_py_data = {32{1'bX}};
-	 tb_pz_data = {32{1'bX}};
-	 tb_q_data  = {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_xyzq_wren = 0;
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* read result */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set address */
-	    tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	    /* store data word */
-	    rx_shreg = {tb_rx_data, rx_shreg[255:32]};
-	    ry_shreg = {tb_ry_data, ry_shreg[255:32]};
-	    rz_shreg = {tb_rz_data, rz_shreg[255:32]};
-
-	 end
-
-	 /* compare */
-	 t_ok =	(rx_shreg == rx) &&
-	       (ry_shreg == ry) &&
-	       (rz_shreg == rz);
-
-	 /* display results */
-	 $display("test_curve_adder(): %s", t_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && t_ok;
-
-      end
-
-   endtask
-
-endmodule
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_curve_doubler_256.v b/bench/tb_curve_doubler_256.v
deleted file mode 100644
index c7a1c0f..0000000
--- a/bench/tb_curve_doubler_256.v
+++ /dev/null
@@ -1,409 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_curve_doubler_256.v
-// -----------------------------------------------------------------------------
-// Testbench for 256-bit curve point doubler.
-//
-// 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.
-//
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_curve_doubler_256;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[255:0]	PX_1	= 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296;
-   localparam	[255:0]	PY_1	= 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5;
-   localparam	[255:0]	PZ_1	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[255:0]	RX_1	= 256'h9a978f59acd1b5ad570e7d52dcfcde43804b42274f61ddcf1e7d848391d6c70f;
-   localparam	[255:0]	RY_1	= 256'h4126885e7f786af905338238e5346d5fe77fc46388668bd0fd59be3190d2f5d1;
-   localparam	[255:0]	RZ_1	= 256'h9fc685c5fc34ff371dcfd694f81f3c2c579c66aed662bd9d976c80d06f7ea3ea;
-
-   localparam	[255:0]	PX_2	= 256'h0ec88440c8b00a9e572bf1bceb7d0c5906bd65990a9b7081130bd72e2c136ca0;
-   localparam	[255:0]	PY_2	= 256'hc0bc77e1339e899101f8e8eccf79c3f7f4bbdd1bf96f6446199bd423026a60d6;
-   localparam	[255:0]	PZ_2	= 256'hdd27cb52a31d1f6e041accf1103de05ba0a5edd74b738d51fe3397de0e3fc306;
-
-   localparam	[255:0]	RX_2	= 256'he6afae63e774df21244609cb4c35d17d28b36b8b9fb7c58929af247f34ac72f9;
-   localparam	[255:0]	RY_2	= 256'h061076db7a5745adc90b2e9eebe0ad6482309690f50b60835c265cf83a1b34eb;
-   localparam	[255:0]	RZ_2	= 256'h1b6bfd04f2a41d68e85423655db1142d97ebaec0c67c450408f427e35c4f054f;
-
-   localparam	[255:0]	PX_3	= 256'hb0f824c88ec62df89912ca9ffbcbbb4ffb4d80f8a7d7b4a992273261a2f7be7f;
-   localparam	[255:0]	PY_3	= 256'h403e34c78c2b816fce2b1f8d73cfeef28113b8de8bda4a447d17b619bef73705;
-   localparam	[255:0]	PZ_3	= 256'h0e3e81bb8e954f3164ae54a6cffa7fcc9631dfddee55fac61e46415f1f5fe5e2;
-
-   localparam	[255:0]	RX_3	= 256'hd4e725920c88cc2f57847a315f3b6c180abb278b8fa2a47da3d1a191a8c29e19;
-   localparam	[255:0]	RY_3	= 256'ha798ad8dbd66c98b53414ab1d04b0f871929a90fea996c88b96d9d68eb8eb0dc;
-   localparam	[255:0]	RZ_3	= 256'ha7ead72c01294eaf2899bb6b84f7d26417e6758e3db29f3b5c2ca8e9911067f5;
-
-   localparam	[255:0]	PX_4	= 256'hXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
-   localparam	[255:0]	PY_4	= 256'hXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
-   localparam	[255:0]	PZ_4	= 256'h0000000000000000000000000000000000000000000000000000000000000000;
-
-   localparam	[255:0]	RX_4	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-   localparam	[255:0]	RY_4	= 256'h0000000000000000000000000000000000000000000000000000000000000001;
-   localparam	[255:0]	RZ_4	= 256'h0000000000000000000000000000000000000000000000000000000000000000;
-
-   localparam	[255:0]	Q		= 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff;
-
-
-
-   //
-   // TODO: Test special cases!
-   //
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  3;
-   localparam	OPERAND_NUM_WORDS		=  8;
-
-
-   //
-   // Clock (100 MHz)
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-
-   //
-   // Buffers (PX, PY, PZ, RX, RY, RZ, Q)
-   //
-   wire [WORD_COUNTER_WIDTH-1:0] core_px_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_py_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_pz_addr;
-
-   wire [WORD_COUNTER_WIDTH-1:0] core_rx_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_ry_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_rz_addr;
-
-   wire [WORD_COUNTER_WIDTH-1:0] core_q_addr;
-
-   wire 			 core_rx_wren;
-   wire 			 core_ry_wren;
-   wire 			 core_rz_wren;
-
-   wire [                32-1:0] core_px_data;
-   wire [                32-1:0] core_py_data;
-   wire [                32-1:0] core_pz_data;
-
-   wire [                32-1:0] core_rx_data_wr;
-   wire [                32-1:0] core_ry_data_wr;
-   wire [                32-1:0] core_rz_data_wr;
-
-   wire [                32-1:0] core_rx_data_rd;
-   wire [                32-1:0] core_ry_data_rd;
-   wire [                32-1:0] core_rz_data_rd;
-
-   wire [                32-1:0] core_q_data;
-
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_xyzq_addr;
-   reg 				 tb_xyzq_wren;
-
-   reg [                  31:0]  tb_px_data;
-   reg [                  31:0]  tb_py_data;
-   reg [                  31:0]  tb_pz_data;
-   wire [                  31:0] tb_rx_data;
-   wire [                  31:0] tb_ry_data;
-   wire [                  31:0] tb_rz_data;
-   reg [                  31:0]  tb_q_data;
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_px
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_px_data), .a_out(),
-	.b_addr(core_px_addr), .b_out(core_px_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_py
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_py_data), .a_out(),
-	.b_addr(core_py_addr), .b_out(core_py_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_pz
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_pz_data), .a_out(),
-	.b_addr(core_pz_addr), .b_out(core_pz_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_q
-     (	.clk(clk),
-	.a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_q_data), .a_out(),
-	.b_addr(core_q_addr), .b_out(core_q_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_rx
-     (	.clk(clk),
-	.a_addr(core_rx_addr), .a_wr(core_rx_wren), .a_in(core_rx_data_wr), .a_out(core_rx_data_rd),
-	.b_addr(tb_xyzq_addr), .b_out(tb_rx_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_ry
-     (	.clk(clk),
-	.a_addr(core_ry_addr), .a_wr(core_ry_wren), .a_in(core_ry_data_wr), .a_out(core_ry_data_rd),
-	.b_addr(tb_xyzq_addr), .b_out(tb_ry_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_rz
-     (	.clk(clk),
-	.a_addr(core_rz_addr), .a_wr(core_rz_wren), .a_in(core_rz_data_wr), .a_out(core_rz_data_rd),
-	.b_addr(tb_xyzq_addr), .b_out(tb_rz_data)
-	);
-
-
-   //
-   // Opcode
-   //
-   wire [ 5: 0] 		 dbl_uop_addr;
-   wire [19: 0] 		 dbl_uop;
-
-   uop_dbl_rom dbl_rom
-     (
-      .clk		(clk),
-      .addr		(dbl_uop_addr),
-      .data		(dbl_uop)
-      );
-
-
-   //
-   // UUT
-   //
-   curve_dbl_add_256 uut
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(ena),
-      .rdy		(rdy),
-
-      .uop_addr	(dbl_uop_addr),
-      .uop			(dbl_uop),
-
-      .px_addr	(core_px_addr),
-      .py_addr	(core_py_addr),
-      .pz_addr	(core_pz_addr),
-      .rx_addr	(core_rx_addr),
-      .ry_addr	(core_ry_addr),
-      .rz_addr	(core_rz_addr),
-      .q_addr	(core_q_addr),
-
-      .rx_wren	(core_rx_wren),
-      .ry_wren	(core_ry_wren),
-      .rz_wren	(core_rz_wren),
-
-      .px_din	(core_px_data),
-      .py_din	(core_py_data),
-      .pz_din	(core_pz_data),
-      .rx_din	(core_rx_data_rd),
-      .ry_din	(core_ry_data_rd),
-      .rz_din	(core_rz_data_rd),
-      .rx_dout	(core_rx_data_wr),
-      .ry_dout	(core_ry_data_wr),
-      .rz_dout	(core_rz_data_wr),
-      .q_din	(core_q_data)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 				 ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n		= 0;
-      ena		= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n		= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_curve_doubler(PX_1, PY_1, PZ_1, RX_1, RY_1, RZ_1);
-      test_curve_doubler(PX_2, PY_2, PZ_2, RX_2, RY_2, RZ_2);
-      test_curve_doubler(PX_3, PY_3, PZ_3, RX_3, RY_3, RZ_3);
-      test_curve_doubler(PX_4, PY_4, PZ_4, RX_4, RY_4, RZ_4);
-
-      /* print result */
-      if (ok)	$display("tb_curve_doubler_256: SUCCESS");
-      else	$display("tb_curve_doubler_256: FAILURE");
-      //
-      //	$finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg		t_ok;
-
-   integer	w;
-
-   task test_curve_doubler;
-
-      input	[255:0]	px;
-      input [255:0] 	py;
-      input [255:0] 	pz;
-
-      input [255:0] 	rx;
-      input [255:0] 	ry;
-      input [255:0] 	rz;
-
-      reg [255:0] 	px_shreg;
-      reg [255:0] 	py_shreg;
-      reg [255:0] 	pz_shreg;
-
-      reg [255:0] 	rx_shreg;
-      reg [255:0] 	ry_shreg;
-      reg [255:0] 	rz_shreg;
-
-      reg [255:0] 	q_shreg;
-
-      begin
-
-	 /* start filling memories */
-	 tb_xyzq_wren = 1;
-
-	 /* initialize shift registers */
-	 px_shreg = px;
-	 py_shreg = py;
-	 pz_shreg = pz;
-	 q_shreg  = Q;
-
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set addresses */
-	    tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* set data words */
-	    tb_px_data	= px_shreg[31:0];
-	    tb_py_data	= py_shreg[31:0];
-	    tb_pz_data	= pz_shreg[31:0];
-	    tb_q_data	= q_shreg[31:0];
-
-	    /* shift inputs */
-	    px_shreg = {{32{1'bX}}, px_shreg[255:32]};
-	    py_shreg = {{32{1'bX}}, py_shreg[255:32]};
-	    pz_shreg = {{32{1'bX}}, pz_shreg[255:32]};
-	    q_shreg  = {{32{1'bX}}, q_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_xyzq_addr = {WORD_COUNTER_WIDTH{1'bX}};
-
-	 /* wipe data words */
-	 tb_px_data = {32{1'bX}};
-	 tb_py_data = {32{1'bX}};
-	 tb_pz_data = {32{1'bX}};
-	 tb_q_data  = {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_xyzq_wren = 0;
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* read result */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set address */
-	    tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	    /* store data word */
-	    rx_shreg = {tb_rx_data, rx_shreg[255:32]};
-	    ry_shreg = {tb_ry_data, ry_shreg[255:32]};
-	    rz_shreg = {tb_rz_data, rz_shreg[255:32]};
-
-	 end
-
-	 /* compare */
-	 t_ok =	(rx_shreg == rx) &&
-	       (ry_shreg == ry) &&
-	       (rz_shreg == rz);
-
-	 /* display results */
-	 $display("test_curve_doubler(): %s", t_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && t_ok;
-
-      end
-
-   endtask
-
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_curve_multiplier_256.v b/bench/tb_curve_multiplier_256.v
index c7839e0..a2a6769 100644
--- a/bench/tb_curve_multiplier_256.v
+++ b/bench/tb_curve_multiplier_256.v
@@ -2,11 +2,11 @@
 //
 // tb_curve_multiplier_256.v
 // -----------------------------------------------------------------------------
-// Testbench for 256-bit curve point scalar multiplier.
+// Testbench for 256-bit curve base point scalar multiplier.
 //
 // Authors: Pavel Shatov
 //
-// Copyright (c) 2016, NORDUnet A/S
+// 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:
@@ -36,265 +36,274 @@
 //
 //------------------------------------------------------------------------------
 
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
 module tb_curve_multiplier_256;
 
 
-		//
-		// Test Vectors
-		//
-		 
-		/* Q = d * G */
-	localparam	[255:0]	K_1	= 256'h70a12c2db16845ed56ff68cfc21a472b3f04d7d6851bf6349f2d7d5b3452b38a;
-	localparam	[255:0]	PX_1	= 256'h8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8;
-	localparam	[255:0]	PY_1	= 256'hd8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9;
-
-		/* R = k * G */
-	localparam	[255:0]	K_2	= 256'h580ec00d856434334cef3f71ecaed4965b12ae37fa47055b1965c7b134ee45d0;
-	localparam	[255:0]	PX_2	= 256'h7214bc9647160bbd39ff2f80533f5dc6ddd70ddf86bb815661e805d5d4e6f27c;
-	localparam	[255:0]	PY_2	= 256'h8b81e3e977597110c7cf2633435b2294b72642987defd3d4007e1cfc5df84541;
-
-		/* O = n * G */
-	localparam	[255:0]	K_3	= 256'hffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551;
-	localparam	[255:0]	PX_3	= 256'h0000000000000000000000000000000000000000000000000000000000000000;
-	localparam	[255:0]	PY_3	= 256'h0000000000000000000000000000000000000000000000000000000000000000;
-
-		/* H = 2 * G */
-	localparam	[255:0]	K_4	= 256'h0000000000000000000000000000000000000000000000000000000000000002;
-	localparam	[255:0]	PX_4	= 256'h7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978;
-	localparam	[255:0]	PY_4	= 256'h07775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1;
-		
-		/* G = (n + 1) * G */
-	localparam	[255:0]	K_5	= 256'hffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + 'd1;
-	localparam	[255:0]	PX_5	= 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296;
-	localparam	[255:0]	PY_5	= 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5;
-
-		/* H = (n + 2) * G */
-	localparam	[255:0]	K_6	= 256'hffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + 'd2;
-	localparam	[255:0]	PX_6	= 256'h7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978;
-	localparam	[255:0]	PY_6	= 256'h07775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1;
-				
-		
-		//
-		// Core Parameters
-		//
-	localparam	WORD_COUNTER_WIDTH	=  3;
-	localparam	OPERAND_NUM_WORDS		=  8;
-	
-
-		//
-		// Clock (100 MHz)
-		//
-	reg clk = 1'b0;
-	always #5 clk = ~clk;
-
-	
-		//
-		// Inputs, Outputs
-		//
-	reg	rst_n;
-	reg	ena;
-	wire	rdy;
-
-	
-		//
-		// Buffers (K, PX, PY)
-		//
-	wire	[WORD_COUNTER_WIDTH-1:0]	core_k_addr;
-	wire	[WORD_COUNTER_WIDTH-1:0]	core_px_addr;
-	wire	[WORD_COUNTER_WIDTH-1:0]	core_py_addr;
-	
-	wire										core_px_wren;
-	wire										core_py_wren;
-	
-	wire	[                32-1:0]	core_k_data;
-	wire	[                32-1:0]	core_px_data;
-	wire	[                32-1:0]	core_py_data;
-	
-	reg	[WORD_COUNTER_WIDTH-1:0]	tb_k_addr;
-	reg	[WORD_COUNTER_WIDTH-1:0]	tb_pxy_addr;
-	
-	reg										tb_k_wren;
-	
-	reg	[                  31:0]	tb_k_data;
-	wire	[                  31:0]	tb_px_data;
-	wire	[                  31:0]	tb_py_data;
-	
-	bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-	bram_k
-	(	.clk(clk),
-		.a_addr(tb_k_addr), .a_wr(tb_k_wren), .a_in(tb_k_data), .a_out(),
-		.b_addr(core_k_addr), .b_out(core_k_data)
-	);
-	
-	bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-	bram_px
-	(	.clk(clk),
-		.a_addr(core_px_addr), .a_wr(core_px_wren), .a_in(core_px_data), .a_out(),
-		.b_addr(tb_pxy_addr), .b_out(tb_px_data)
-	);
-	
-	bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-	bram_py
-	(	.clk(clk),
-		.a_addr(core_py_addr), .a_wr(core_py_wren), .a_in(core_py_data), .a_out(),
-		.b_addr(tb_pxy_addr), .b_out(tb_py_data)
-	);
-	
-	
-		//
-		// UUT
-		//
-	curve_mul_256 uut
-	(
-		.clk			(clk),
-		.rst_n		(rst_n),
-		
-		.ena			(ena),
-		.rdy			(rdy),
-		
-		.k_addr		(core_k_addr),
-		.rx_addr		(core_px_addr),
-		.ry_addr		(core_py_addr),
-		
-		.rx_wren		(core_px_wren),
-		.ry_wren		(core_py_wren),
-		
-		.k_din		(core_k_data),
-		
-		.rx_dout		(core_px_data),
-		.ry_dout		(core_py_data)
-	);
-		
-		
-		//
-		// Testbench Routine
-		//
-	reg ok = 1;
-	initial begin
-		
-			/* initialize control inputs */
-		rst_n		= 0;
-		ena		= 0;
-		
-			/* wait for some time */
-		#200;
-		
-			/* de-assert reset */
-		rst_n		= 1;
-		
-			/* wait for some time */
-		#100;		
-		
-			/* run tests */
-		//test_curve_multiplier(K_1, PX_1, PY_1);
-		//test_curve_multiplier(K_2, PX_2, PY_2);
-		//test_curve_multiplier(K_3, PX_3, PY_3);
-		//test_curve_multiplier(K_4, PX_4, PY_4);
-		//test_curve_multiplier(K_5, PX_5, PY_5);
-		test_curve_multiplier(K_6, PX_6, PY_6);
-		
-			/* print result */
-		if (ok)	$display("tb_curve_multiplier_256: SUCCESS");
-		else		$display("tb_curve_multiplier_256: FAILURE");
-		//
-		//$finish;
-		//
-	end
-	
-	
-		//
-		// Test Task
-		//	
-	reg		p_ok;
-	
-	integer	w;
-
-	task test_curve_multiplier;
-	
-		input	[255:0]	k;
-		input	[255:0]	px;
-		input	[255:0]	py;
-		
-		reg	[255:0]	k_shreg;
-		reg	[255:0]	px_shreg;
-		reg	[255:0]	py_shreg;
-		
-		begin
-		
-				/* start filling memories */
-			tb_k_wren = 1;
-			
-				/* initialize shift registers */
-			k_shreg = k;
-			
-				/* write all the words */
-			for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-				
-					/* set addresses */
-				tb_k_addr = w[WORD_COUNTER_WIDTH-1:0];
-				
-					/* set data words */
-				tb_k_data	= k_shreg[31:0];
-				
-					/* shift inputs */
-				k_shreg = {{32{1'bX}}, k_shreg[255:32]};
-				
-					/* wait for 1 clock tick */
-				#10;
-				
-			end
-			
-				/* wipe addresses */
-			tb_k_addr = {WORD_COUNTER_WIDTH{1'bX}};
-			
-				/* wipe data words */
-			tb_k_data = {32{1'bX}};
-			
-				/* stop filling memories */
-			tb_k_wren = 0;
-			
-				/* start operation */
-			ena = 1;
-			
-				/* clear flag */
-			#10 ena = 0;
-			
-				/* wait for operation to complete */
-			while (!rdy) #10;
-			
-				/* read result */
-			for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-				
-					/* set address */
-				tb_pxy_addr = w[WORD_COUNTER_WIDTH-1:0];
-				
-					/* wait for 1 clock tick */
-				#10;
-				
-					/* store data word */
-				px_shreg = {tb_px_data, px_shreg[255:32]};
-				py_shreg = {tb_py_data, py_shreg[255:32]};
-
-			end
-			
-				/* compare */
-			p_ok =	(px_shreg == px) &&
-						(py_shreg == py);
-
-				/* display results */
-			$display("test_curve_multiplier(): %s", p_ok ? "OK" : "ERROR");
-			
-				/* update global flag */
-			ok = ok && p_ok;
-		
-		end
-		
-	endtask
-	
+        //
+        // Test Vectors
+        //
+    `include "ecdsa256_test_vector_nsa.vh"
+    `include "ecdsa_test_vector_randomized.vh"
+
+
+        //
+        // Core Parameters
+        //
+    localparam WORD_COUNTER_WIDTH = 3;
+    localparam OPERAND_NUM_WORDS  = 8;
+
+
+       //
+       // P-256 Domain Parameters
+       //
+    localparam ECDSA_P256_N =
+        {32'hffffffff, 32'h00000000, 32'hffffffff, 32'hffffffff,
+         32'hbce6faad, 32'ha7179e84, 32'hf3b9cac2, 32'hfc632551};
+
+    localparam ECDSA_P256_GX =
+        {32'h6b17d1f2, 32'he12c4247, 32'hf8bce6e5, 32'h63a440f2,
+         32'h77037d81, 32'h2deb33a0, 32'hf4a13945, 32'hd898c296};
+
+    localparam ECDSA_P256_GY =
+        {32'h4fe342e2, 32'hfe1a7f9b, 32'h8ee7eb4a, 32'h7c0f9e16,
+         32'h2bce3357, 32'h6b315ece, 32'hcbb64068, 32'h37bf51f5};
+
+    localparam ECDSA_P256_HX =
+        {32'h7cf27b18, 32'h8d034f7e, 32'h8a523803, 32'h04b51ac3,
+         32'hc08969e2, 32'h77f21b35, 32'ha60b48fc, 32'h47669978};
+    
+    localparam ECDSA_P256_HY =
+        {32'h07775510, 32'hdb8ed040, 32'h293d9ac6, 32'h9f7430db,
+         32'hba7dade6, 32'h3ce98229, 32'h9e04b79d, 32'h227873d1};
+
+
+        //
+        // Clock (100 MHz)
+        //
+    reg clk = 1'b0;
+    always #5 clk = ~clk;
+
+
+        //
+        // Inputs, Outputs
+        //
+    reg  rst_n;
+    reg  ena;
+    wire rdy;
+
+
+        //
+        // Buffers (K, PX, PY)
+        //
+    wire [WORD_COUNTER_WIDTH-1:0] core_k_addr;
+    wire [WORD_COUNTER_WIDTH-1:0] core_pxy_addr;
+
+    wire                          core_px_wren;
+    wire                          core_py_wren;
+
+    wire [                32-1:0] core_k_data;
+    wire [                32-1:0] core_pxy_data;
+
+    reg  [WORD_COUNTER_WIDTH-1:0] tb_k_addr;
+    reg  [WORD_COUNTER_WIDTH-1:0] tb_pxy_addr;
+
+    reg                           tb_k_wren;
+
+    reg  [                  31:0] tb_k_data;
+    wire [                  31:0] tb_px_data;
+    wire [                  31:0] tb_py_data;
+
+    bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
+    bram_k
+    (   .clk(clk),
+        .a_addr(tb_k_addr), .a_wr(tb_k_wren), .a_in(tb_k_data), .a_out(),
+        .b_addr(core_k_addr), .b_out(core_k_data)
+    );
+
+    bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
+    bram_px
+    (   .clk(clk),
+        .a_addr(core_pxy_addr), .a_wr(core_px_wren), .a_in(core_pxy_data), .a_out(),
+        .b_addr(tb_pxy_addr), .b_out(tb_px_data)
+    );
+
+    bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
+    bram_py
+    (   .clk(clk),
+        .a_addr(core_pxy_addr), .a_wr(core_py_wren), .a_in(core_pxy_data), .a_out(),
+        .b_addr(tb_pxy_addr), .b_out(tb_py_data)
+    );
+
+
+        //
+        // UUT
+        //
+    ecdsa256_base_point_multiplier uut
+    (
+        .clk        (clk),
+        .rst_n      (rst_n),
+
+        .ena        (ena),
+        .rdy        (rdy),
+
+        .k_addr     (core_k_addr),
+        .rxy_addr   (core_pxy_addr),
+
+        .rx_wren    (core_px_wren),
+        .ry_wren    (core_py_wren),
+
+        .k_din      (core_k_data),
+
+        .rxy_dout   (core_pxy_data)
+    );
+
+
+        //
+        // Testbench Routine
+        //
+    reg ok = 1;
+    initial begin
+
+            /* initialize control inputs */
+        rst_n = 0;
+        ena   = 0;
+        
+            /* wait for some time */
+        #200;
+        
+            /* de-assert reset */
+        rst_n = 1;
+        
+            /* wait for some time */
+        #100;
+        
+            /* run tests */
+        $display("1. Q1 = d1 * G...");
+        test_curve_multiplier(ECDSA_P256_D_NSA, ECDSA_P256_QX_NSA, ECDSA_P256_QY_NSA);
+        
+        $display("2. R = k * G...");
+        test_curve_multiplier(ECDSA_P256_K_NSA, ECDSA_P256_RX_NSA, ECDSA_P256_RY_NSA);
+        
+        $display("3. Q2 = d2 * G...");
+        test_curve_multiplier(ECDSA_P256_D_RANDOM, ECDSA_P256_QX_RANDOM, ECDSA_P256_QY_RANDOM);
+
+        $display("4. O = n * G...");
+        test_curve_multiplier(ECDSA_P256_N, 256'd0, 256'd0);
+
+        $display("5. G = (n + 1) * G...");
+        test_curve_multiplier(ECDSA_P256_N + 256'd1, ECDSA_P256_GX, ECDSA_P256_GY);
+
+        $display("6. H = 2 * G...");
+        test_curve_multiplier(256'd2, ECDSA_P256_HX, ECDSA_P256_HY);
+
+        $display("7. H = (n + 2) * G...");
+        test_curve_multiplier(ECDSA_P256_N + 256'd2, ECDSA_P256_HX, ECDSA_P256_HY);
+
+            /* print result */
+        if (ok) $display("tb_curve_multiplier_256: SUCCESS");
+        else    $display("tb_curve_multiplier_256: FAILURE");
+
+        //$finish;
+
+    end
+
+
+        //
+        // Test Task
+        //
+    reg p_ok;
+
+    integer w;
+
+    task test_curve_multiplier;
+    
+        input [255:0] k;
+        input [255:0] px;
+        input [255:0] py;
+
+        reg [255:0] k_shreg;
+        reg [255:0] px_shreg;
+        reg [255:0] py_shreg;
+
+        begin
+        
+                /* start filling memories */
+            tb_k_wren = 1;
+
+                /* initialize shift registers */
+            k_shreg = k;
+
+                /* write all the words */
+            for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
+
+                    /* set addresses */
+                tb_k_addr = w[WORD_COUNTER_WIDTH-1:0];
+
+                    /* set data words */
+                tb_k_data   = k_shreg[31:0];
+
+                    /* shift inputs */
+                k_shreg = {{32{1'bX}}, k_shreg[255:32]};
+
+                    /* wait for 1 clock tick */
+                #10;
+
+            end
+
+                /* wipe addresses */
+            tb_k_addr = {WORD_COUNTER_WIDTH{1'bX}};
+
+                /* wipe data words */
+            tb_k_data = {32{1'bX}};
+
+                /* stop filling memories */
+            tb_k_wren = 0;
+
+                /* start operation */
+            ena = 1;
+
+                /* clear flag */
+            #10 ena = 0;
+
+                /* wait for operation to complete */
+            while (!rdy) #10;
+
+                /* read result */
+            for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
+
+                    /* set address */
+                tb_pxy_addr = w[WORD_COUNTER_WIDTH-1:0];
+
+                    /* wait for 1 clock tick */
+                #10;
+
+                    /* store data word */
+                px_shreg = {tb_px_data, px_shreg[255:32]};
+                py_shreg = {tb_py_data, py_shreg[255:32]};
+
+            end
+
+                /* compare */
+            p_ok = (px_shreg === px) &&
+                   (py_shreg === py);
+
+                /* display results */
+            if (p_ok) $display("test_curve_multiplier(): OK");
+            else begin
+                $display("test_curve_multiplier(): ERROR");
+                $display("ref_px  == %x", px);
+                $display("calc_px == %x", px_shreg);
+                $display("ref_py  == %x", py);
+                $display("calc_py == %x", py_shreg);
+            end
+
+                /* update global flag */
+            ok = ok && p_ok;
+        
+        end
+
+    endtask
+
 endmodule
 
 
diff --git a/bench/tb_lowlevel_adder32.v b/bench/tb_lowlevel_adder32.v
deleted file mode 100644
index 70fbb15..0000000
--- a/bench/tb_lowlevel_adder32.v
+++ /dev/null
@@ -1,175 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_lowlevel_adder32.v
-// -----------------------------------------------------------------------------
-// Testbench for 32-bit adder.
-//
-// 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.
-//
-//------------------------------------------------------------------------------
-
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-
-module tb_lowlevel_adder32;
-
-   //
-   // Inputs
-   //
-   reg				clk;
-   reg [31: 0] 			a;
-   reg [31: 0] 			b;
-   reg				c_in;
-
-   //
-   // Outputs
-   //
-   wire [31: 0] 		s;
-   wire				c_out;
-
-   //
-   // Test Vectors {a, b, c_in}
-   //
-   wire [64: 0] 		vec_0		= {32'h00000000, 32'h00000000, 1'b0};	// all zeroes, no carry
-   wire [64: 0] 		vec_1		= {32'h00000000, 32'h00000000, 1'b1};	// all zeroes with carry
-   wire [64: 0] 		vec_2		= {32'h00000000, 32'hFFFFFFFF, 1'b0};	// zeroes and ones, no carry
-   wire [64: 0] 		vec_3		= {32'h00000000, 32'hFFFFFFFF, 1'b1};	// zeroes and ones with carry
-   wire [64: 0] 		vec_4		= {32'hFFFFFFFF, 32'h00000000, 1'b0};	// ones and zeroes, no carry
-   wire [64: 0] 		vec_5		= {32'hFFFFFFFF, 32'h00000000, 1'b1};	// ones and zeroes with carry
-   wire [64: 0] 		vec_6		= {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b0};	// all ones, no carry
-   wire [64: 0] 		vec_7		= {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b1};	// all ones with carry
-
-   wire [64: 0] 		vec_8		= {32'hd898c296, 32'h37bf51f5, 1'b0};	// random values, no carry
-   wire [64: 0] 		vec_9		= {32'hf4a13945, 32'hcbb64068, 1'b0};	// random values, no carry
-   wire [64: 0] 		vec_10	= {32'h2deb33a0, 32'h6b315ece, 1'b0};	// random values, no carry
-   wire [64: 0] 		vec_11	= {32'h77037d81, 32'h2bce3357, 1'b0};	// random values, no carry
-   wire [64: 0] 		vec_12	= {32'h63a440f2, 32'h7c0f9e16, 1'b1};	// random values with carry
-   wire [64: 0] 		vec_13	= {32'hf8bce6e5, 32'h8ee7eb4a, 1'b1};	// random values with carry
-   wire [64: 0] 		vec_14	= {32'he12c4247, 32'hfe1a7f9b, 1'b1};	// random values with carry
-   wire [64: 0] 		vec_15	= {32'h6b17d1f2, 32'h4fe342e2, 1'b1};	// random values with carry
-
-
-   //
-   // UUT
-   //
-   adder32_wrapper uut
-     (
-      .clk		(clk),
-      .a			(a),
-      .b			(b),
-      .s			(s),
-      .c_in		(c_in),
-      .c_out	(c_out)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 				ok = 1;
-   initial begin
-      //
-      clk = 0;
-      //
-      #100;
-      //
-      test_adder32(vec_0);
-      test_adder32(vec_1);
-      test_adder32(vec_2);
-      test_adder32(vec_3);
-      test_adder32(vec_4);
-      test_adder32(vec_5);
-      test_adder32(vec_6);
-      test_adder32(vec_7);
-      //
-      test_adder32(vec_8);
-      test_adder32(vec_9);
-      test_adder32(vec_10);
-      test_adder32(vec_11);
-      test_adder32(vec_12);
-      test_adder32(vec_13);
-      test_adder32(vec_14);
-      test_adder32(vec_15);
-      //
-      if (ok)	$display("tb_lowlevel_adder32: SUCCESS");
-      else	$display("tb_lowlevel_adder32: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Routine
-   //
-   reg	[31: 0]	ss;		// reference value of sum
-   reg 		cc;		// reference value of carry
-   reg 		ss_ok;	// result matches reference value
-
-   task test_adder32;
-
-      input	[64: 0] vec;
-
-      begin
-
-	 /* break down test vector */
-	 a		= vec[64:33];
-	 b		= vec[32: 1];
-	 c_in	= vec[ 0: 0];
-
-	 /* calculate reference values */
-	 {cc, ss} = {1'b0, a} + {1'b0, b} + {32'd0, c_in};
-
-	 /* send one clock tick */
-	 #10 clk = 1;
-	 #10 clk = 0;
-
-	 /* check outputs */
-	 ss_ok = (s == ss) && (c_out == cc);
-
-	 /* display results */
-	 $display("test_adder32(): 0x%08X + 0x%08X + %01d = {%01d, 0x%08X} [%0s]", a, b, c_in, c_out, s, ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && ss_ok;
-
-      end
-
-   endtask
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_lowlevel_adder47.v b/bench/tb_lowlevel_adder47.v
deleted file mode 100644
index 663e8f9..0000000
--- a/bench/tb_lowlevel_adder47.v
+++ /dev/null
@@ -1,151 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_lowlevel_adder47.v
-// -----------------------------------------------------------------------------
-// Testbench for 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.
-//
-//------------------------------------------------------------------------------
-
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-
-module tb_lowlevel_adder47;
-
-   //
-   // Inputs
-   //
-   reg				clk;
-   reg [46: 0] 			a;
-   reg [46: 0] 			b;
-
-   //
-   // Outputs
-   //
-   wire [46: 0] 		s;
-
-   //
-   // Test Vectors {a, b}
-   //
-   wire [93: 0] 		vec_0		= {47'h2a87ca22be8b, 47'h05378eb1c71e};
-   wire [93: 0] 		vec_1		= {47'h7320ad746e1d, 47'h3b628ba79b98};
-   wire [93: 0] 		vec_2		= {47'h59f741e08254, 47'h2a385502f25d};
-   wire [93: 0] 		vec_3		= {47'h3f55296c3a54, 47'h5e3872760ab7};
-   wire [93: 0] 		vec_4		= {47'h3617de4a9626, 47'h2c6f5d9e98bf};
-   wire [93: 0] 		vec_5		= {47'h1292dc29f8f4, 47'h1dbd289a147c};
-   wire [93: 0] 		vec_6		= {47'h69da3113b5f0, 47'h38c00a60b1ce};
-   wire [93: 0] 		vec_7		= {47'h1d7e819d7a43, 47'h1d7c90ea0e5f};
-
-   //
-   // UUT
-   //
-   adder47_wrapper uut
-     (
-      .clk		(clk),
-      .a		(a),
-      .b		(b),
-      .s		(s)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 			ok = 1;
-   initial begin
-      //
-      clk = 0;
-      //
-      #100;
-      //
-      test_adder47(vec_0);
-      test_adder47(vec_1);
-      test_adder47(vec_2);
-      test_adder47(vec_3);
-      test_adder47(vec_4);
-      test_adder47(vec_5);
-      test_adder47(vec_6);
-      test_adder47(vec_7);
-      //
-      if (ok)	$display("tb_lowlevel_adder47: SUCCESS");
-      else	$display("tb_lowlevel_adder47: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Routine
-   //
-   reg	[46: 0]	ss;		// reference value of sum
-   reg 		cc;		// reference value of carry
-   reg 		ss_ok;	// result matches reference value
-
-   task test_adder47;
-
-      input	[93: 0] vec;
-
-      begin
-
-	 /* break down test vector */
-	 a		= vec[93:47];
-	 b		= vec[46: 0];
-
-	 /* calculate reference values */
-	 ss = a + b;
-
-	 /* send one clock tick */
-	 #10 clk = 1;
-	 #10 clk = 0;
-
-	 /* check outputs */
-	 ss_ok = (s == ss);
-
-	 /* display results */
-	 $display("test_adder47(): %s", ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && ss_ok;
-
-      end
-
-   endtask
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_lowlevel_subtractor32.v b/bench/tb_lowlevel_subtractor32.v
deleted file mode 100644
index fd96000..0000000
--- a/bench/tb_lowlevel_subtractor32.v
+++ /dev/null
@@ -1,174 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_lowlevel_subtractor32.v
-// -----------------------------------------------------------------------------
-// Testbench for 32-bit subtractor.
-//
-// 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.
-//
-//------------------------------------------------------------------------------
-
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_lowlevel_subtractor32;
-
-   //
-   // Inputs
-   //
-   reg				clk;
-   reg [31: 0] 			a;
-   reg [31: 0] 			b;
-   reg				b_in;
-
-   //
-   // Outputs
-   //
-   wire [31: 0] 		d;
-   wire				b_out;
-
-   //
-   // Test Vectors {a, b, b_in}
-   //
-   wire [64: 0] 		vec_0		= {32'h00000000, 32'h00000000, 1'b0};	// all zeroes, no borrow
-   wire [64: 0] 		vec_1		= {32'h00000000, 32'h00000000, 1'b1};	// all zeroes with borrow
-   wire [64: 0] 		vec_2		= {32'h00000000, 32'hFFFFFFFF, 1'b0};	// zeroes and ones, no borrow
-   wire [64: 0] 		vec_3		= {32'h00000000, 32'hFFFFFFFF, 1'b1};	// zeroes and ones with borrow
-   wire [64: 0] 		vec_4		= {32'hFFFFFFFF, 32'h00000000, 1'b0};	// ones and zeroes, no borrow
-   wire [64: 0] 		vec_5		= {32'hFFFFFFFF, 32'h00000000, 1'b1};	// ones and zeroes with borrow
-   wire [64: 0] 		vec_6		= {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b0};	// all ones, no borrow
-   wire [64: 0] 		vec_7		= {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b1};	// all ones with borrow
-
-   wire [64: 0] 		vec_8		= {32'hd898c296, 32'h37bf51f5, 1'b0};	// random values, no borrow
-   wire [64: 0] 		vec_9		= {32'hf4a13945, 32'hcbb64068, 1'b0};	// random values, no borrow
-   wire [64: 0] 		vec_10	= {32'h2deb33a0, 32'h6b315ece, 1'b0};	// random values, no borrow
-   wire [64: 0] 		vec_11	= {32'h77037d81, 32'h2bce3357, 1'b0};	// random values, no borrow
-   wire [64: 0] 		vec_12	= {32'h63a440f2, 32'h7c0f9e16, 1'b1};	// random values with borrow
-   wire [64: 0] 		vec_13	= {32'hf8bce6e5, 32'h8ee7eb4a, 1'b1};	// random values with borrow
-   wire [64: 0] 		vec_14	= {32'he12c4247, 32'hfe1a7f9b, 1'b1};	// random values with borrow
-   wire [64: 0] 		vec_15	= {32'h6b17d1f2, 32'h4fe342e2, 1'b1};	// random values with borrow
-
-
-   //
-   // UUT
-   //
-   subtractor32_wrapper uut
-     (
-      .clk		(clk),
-      .a		(a),
-      .b		(b),
-      .d		(d),
-      .b_in		(b_in),
-      .b_out		(b_out)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 			ok = 1;
-   initial begin
-      //
-      clk = 0;
-      //
-      #100;
-      //
-      test_subtractor32(vec_0);
-      test_subtractor32(vec_1);
-      test_subtractor32(vec_2);
-      test_subtractor32(vec_3);
-      test_subtractor32(vec_4);
-      test_subtractor32(vec_5);
-      test_subtractor32(vec_6);
-      test_subtractor32(vec_7);
-      //
-      test_subtractor32(vec_8);
-      test_subtractor32(vec_9);
-      test_subtractor32(vec_10);
-      test_subtractor32(vec_11);
-      test_subtractor32(vec_12);
-      test_subtractor32(vec_13);
-      test_subtractor32(vec_14);
-      test_subtractor32(vec_15);
-      //
-      if (ok)	$display("tb_lowlevel_subtractor32: SUCCESS");
-      else	$display("tb_lowlevel_subtractor32: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Routine
-   //
-   reg	[31: 0]	dd;		// reference value of difference
-   reg 		bb;		// reference value of borrow
-   reg 		dd_ok;	// result matches reference value
-
-   task test_subtractor32;
-
-      input	[64: 0] vec;
-
-      begin
-
-	 /* break down test vector */
-	 a		= vec[64:33];
-	 b		= vec[32: 1];
-	 b_in	= vec[ 0: 0];
-
-	 /* calculate reference values */
-	 {bb, dd} = {1'b0, a} - {1'b0, b} - {32'd0, b_in};
-
-	 /* send one clock tick */
-	 #10 clk = 1;
-	 #10 clk = 0;
-
-	 /* check outputs */
-	 dd_ok = (d == dd) && (b_out == bb);
-
-	 /* display results */
-	 $display("test_subtractor32(): 0x%08X - (0x%08X + %01d) = {%01d, 0x%08X} [%0s]", a, b, b_in, b_out, d, dd_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && dd_ok;
-
-      end
-
-   endtask
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_modular_adder.v b/bench/tb_modular_adder.v
deleted file mode 100644
index 713ff22..0000000
--- a/bench/tb_modular_adder.v
+++ /dev/null
@@ -1,357 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_modular_adder_256.v
-// -----------------------------------------------------------------------------
-// Testbench for modular multi-word 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.
-//
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_modular_adder_256;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[255:0]	N	= 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff;
-
-   localparam	[255:0]	X_1	= 256'h1ddbd0769df27bab1e234019dad09dccce1e87e2193b417ffa1a3465d7439ecd;
-   localparam	[255:0]	Y_1	= 256'h1f67cdc34bac91a072945d212f0a03442fc4855788583ecb7b2e375ad3848210;
-
-   localparam	[255:0]	X_2	= 256'hff563f653b1392a6fa6b0295a280f7a904a11e22d8ae468e220301d8ac232fcf;
-   localparam	[255:0]	Y_2	= 256'hf6f53c4b57b25453b68e923fb118e4f753d74af01fc58476dd15a80933453899;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  3;
-   localparam	OPERAND_NUM_WORDS	=  8;
-
-
-   //
-   // Clock (100 MHz)
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-
-   //
-   // Buffers (X, Y, N)
-   //
-   wire [WORD_COUNTER_WIDTH-1:0] core_xy_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_n_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_s_addr;
-   wire 			 core_s_wren;
-
-   wire [                  31:0] core_x_data;
-   wire [                  31:0] core_y_data;
-   wire [                  31:0] core_n_data;
-   wire [                  31:0] core_s_data;
-
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_xyn_addr;
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_s_addr;
-   reg 				 tb_xyn_wren;
-
-   reg [                  31:0]  tb_x_data;
-   reg [                  31:0]  tb_y_data;
-   reg [                  31:0]  tb_n_data;
-   wire [                  31:0] tb_s_data;
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_x
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_x_data),
-      .a_out	(),
-
-      .b_addr	(core_xy_addr),
-      .b_out	(core_x_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_y
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_y_data),
-      .a_out	(),
-
-      .b_addr	(core_xy_addr),
-      .b_out	(core_y_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_n
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_n_data),
-      .a_out	(),
-
-      .b_addr	(core_n_addr),
-      .b_out	(core_n_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_s
-     (
-      .clk		(clk),
-
-      .a_addr	(core_s_addr),
-      .a_wr		(core_s_wren),
-      .a_in		(core_s_data),
-      .a_out	(),
-
-      .b_addr	(tb_s_addr),
-      .b_out	(tb_s_data)
-      );
-
-
-   //
-   // UUT
-   //
-   modular_adder #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-      )
-   uut
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(ena),
-      .rdy			(rdy),
-
-      .ab_addr		(core_xy_addr),
-      .n_addr		(core_n_addr),
-      .s_addr		(core_s_addr),
-      .s_wren		(core_s_wren),
-
-      .a_din		(core_x_data),
-      .b_din		(core_y_data),
-      .n_din		(core_n_data),
-      .s_dout		(core_s_data)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 				 ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n			= 0;
-      ena			= 0;
-
-      tb_xyn_wren	= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n		= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_modular_adder(X_1, Y_1, N);
-      test_modular_adder(X_2, Y_2, N);
-      test_modular_adder(Y_1, X_1, N);
-      test_modular_adder(Y_2, X_2, N);
-
-      test_modular_adder(X_1, X_2, N);
-      test_modular_adder(X_2, X_1, N);
-      test_modular_adder(Y_1, Y_2, N);
-      test_modular_adder(Y_2, Y_1, N);
-
-      test_modular_adder(X_1, Y_2, N);
-      test_modular_adder(Y_2, X_1, N);
-      test_modular_adder(X_2, Y_1, N);
-      test_modular_adder(Y_1, X_2, N);
-
-      /* print result */
-      if (ok)	$display("tb_modular_adder_256: SUCCESS");
-      else	$display("tb_modular_adder_256: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg	[256:0]	s;
-   wire [255:0] s_dummy = s[255:0];
-   reg 		s_ok;
-
-   integer 	w;
-
-   reg [255:0] 	x_shreg;
-   reg [255:0] 	y_shreg;
-   reg [255:0] 	n_shreg;
-   reg [255:0] 	s_shreg;
-
-   task test_modular_adder;
-
-      input	[255:0]	x;
-      input [255:0] 	y;
-      input [255:0] 	n;
-
-      begin
-
-	 /* start filling memories */
-	 tb_xyn_wren	= 1;
-
-	 /* initialize shift registers */
-	 x_shreg = x;
-	 y_shreg = y;
-	 n_shreg = n;
-
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set addresses */
-	    tb_xyn_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* set data words */
-	    tb_x_data	= x_shreg[31:0];
-	    tb_y_data	= y_shreg[31:0];
-	    tb_n_data	= n_shreg[31:0];
-
-	    /* shift inputs */
-	    x_shreg = {{32{1'bX}}, x_shreg[255:32]};
-	    y_shreg = {{32{1'bX}}, y_shreg[255:32]};
-	    n_shreg = {{32{1'bX}}, n_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_xyn_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-
-	 /* wipe data words */
-	 tb_x_data	= {32{1'bX}};
-	 tb_y_data	= {32{1'bX}};
-	 tb_n_data	= {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_xyn_wren	= 0;
-
-	 /* calculate reference value */
-	 s = {1'b0, x} + {1'b0, y};
-	 if (s >= {1'b0, n})
-	   s = s - {1'b0, n};
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* read result */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set address */
-	    tb_s_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	    /* store data word */
-	    s_shreg = {tb_s_data, s_shreg[255:32]};
-
-	 end
-
-	 /* compare */
-	 s_ok = (s_shreg == s[255:0]);
-
-	 /* display results */
-	 $display("test_modular_adder(): %s", s_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && s_ok;
-
-      end
-
-   endtask
-
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_modular_invertor.v b/bench/tb_modular_invertor.v
deleted file mode 100644
index 24f6db1..0000000
--- a/bench/tb_modular_invertor.v
+++ /dev/null
@@ -1,225 +0,0 @@
-`timescale 1ns / 1ps
-
-module tb_modular_invertor;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[255:0]	Q		= 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff;
-
-   localparam	[255:0]	A_1 	= 256'hd3e73ccd63a5b10da308c615bb9ebd3f76e2c5fccc256fd9f629dcc956bf2382;
-   localparam	[255:0]	A1_1	= 256'h93fb26d5d199bbb7232a4b7c98e97ba9bb7530d304b5f07736ea4027bbb57ecd;
-
-   localparam	[255:0]	A_2 	= 256'h57b6c628a5c4e870740b2517975ace2216acbe094ac54568b53212ef45e69d22;
-   localparam	[255:0]	A1_2	= 256'hcd2af4766642d7d2f3f3f67d92c575c496772ef7d55c75eb46bd07e8d5f9a4aa;
-
-
-   //
-   // Clock
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-
-   //
-   // Buffers (A, A1, Q)
-   //
-   wire [ 2: 0] core_a_addr;
-   wire [ 2: 0] core_q_addr;
-   wire [ 2: 0] core_a1_addr;
-   wire 	core_a1_wren;
-
-   wire [31: 0] core_a_data;
-   wire [31: 0] core_q_data;
-   wire [31: 0] core_a1_data;
-
-   reg [ 2: 0] 	tb_aq_addr;
-   reg 		tb_aq_wren;
-   reg [ 2: 0] 	tb_a1_addr;
-
-   reg [31: 0] 	tb_a_data;
-   reg [31: 0] 	tb_q_data;
-   wire [31: 0] tb_a1_data;
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_a
-     (	.clk(clk),
-	.a_addr(tb_aq_addr), .a_wr(tb_aq_wren), .a_in(tb_a_data), .a_out(),
-	.b_addr(core_a_addr), .b_out(core_a_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_q
-     (	.clk(clk),
-	.a_addr(tb_aq_addr), .a_wr(tb_aq_wren), .a_in(tb_q_data), .a_out(),
-	.b_addr(core_q_addr), .b_out(core_q_data)
-	);
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_a1
-     (	.clk(clk),
-	.a_addr(core_a1_addr), .a_wr(core_a1_wren), .a_in(core_a1_data), .a_out(),
-	.b_addr(tb_a1_addr), .b_out(tb_a1_data)
-	);
-
-
-   //
-   // UUT
-   //
-   modular_invertor #
-     (
-      .MAX_OPERAND_WIDTH	(256)
-      )
-   uut
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(ena),
-      .rdy		(rdy),
-
-      .a_addr	(core_a_addr),
-      .q_addr	(core_q_addr),
-      .a1_addr	(core_a1_addr),
-      .a1_wren	(core_a1_wren),
-
-      .a_din	(core_a_data),
-      .q_din	(core_q_data),
-      .a1_dout	(core_a1_data)
-      );
-
-   //
-   // Testbench Routine
-   //
-   reg 		ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n		= 0;
-      ena		= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n		= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_modular_invertor(A_1, A1_1, Q);
-      test_modular_invertor(A_2, A1_2, Q);
-
-      /* print result */
-      if (ok)	$display("tb_modular_invertor: SUCCESS");
-      else	$display("tb_modular_invertor: FAILURE");
-      //
-      //$finish;
-      //
-
-   end
-
-
-   //
-   // Test Task
-   //
-   reg		a1_ok;
-
-   integer	w;
-
-   task test_modular_invertor;
-
-      input	[255:0]	a;
-      input [255:0] 	a1;
-      input [255:0] 	q;
-
-      reg [255:0] 	a_shreg;
-      reg [255:0] 	a1_shreg;
-      reg [255:0] 	q_shreg;
-
-      begin
-
-	 /* start filling memories */
-	 tb_aq_wren = 1;
-
-	 /* initialize shift registers */
-	 a_shreg = a;
-	 q_shreg = q;
-
-	 /* write all the words */
-	 for (w=0; w<8; w=w+1) begin
-
-	    /* set addresses */
-	    tb_aq_addr = w[2:0];
-
-	    /* set data words */
-	    tb_a_data	= a_shreg[31:0];
-	    tb_q_data	= q_shreg[31:0];
-
-	    /* shift inputs */
-	    a_shreg = {{32{1'bX}}, a_shreg[255:32]};
-	    q_shreg = {{32{1'bX}}, q_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_aq_addr = {3{1'bX}};
-
-	 /* wipe data words */
-	 tb_a_data = {32{1'bX}};
-	 tb_q_data = {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_aq_wren = 0;
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* read result */
-	 for (w=0; w<8; w=w+1) begin
-
-	    /* set address */
-	    tb_a1_addr = w[2:0];
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	    /* store data word */
-	    a1_shreg = {tb_a1_data, a1_shreg[255:32]};
-
-	 end
-
-	 /* compare */
-	 a1_ok =	(a1_shreg == a1);
-
-	 /* display results */
-	 $display("test_modular_invertor(): %s", a1_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && a1_ok;
-
-      end
-
-   endtask
-
-
-endmodule
diff --git a/bench/tb_modular_multiplier_256.v b/bench/tb_modular_multiplier_256.v
deleted file mode 100644
index 676a183..0000000
--- a/bench/tb_modular_multiplier_256.v
+++ /dev/null
@@ -1,366 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_modular_multiplier_256.v
-// -----------------------------------------------------------------------------
-// Testbench for modular multi-word multiplier.
-//
-// 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.
-//
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_modular_multiplier_256;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[255:0]	N	= 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff;
-
-   localparam	[255:0]	X_1	= 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296;
-   localparam	[255:0]	Y_1	= 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5;
-   localparam	[255:0]	P_1	= 256'h823cd15f6dd3c71933565064513a6b2bd183e554c6a08622f713ebbbface98be;
-
-   localparam	[255:0]	X_2	= 256'h29d05c193da77b710e86323538b77e1b11f904fea42998be16bd8d744ece7ad0;
-   localparam	[255:0]	Y_2	= 256'hb01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae07;
-   localparam	[255:0]	P_2	= 256'h76b2571d1d009ab0e7d1cc086c7d3648f08755b2e2585e780d11f053b06fb6ec;
-
-   localparam	[255:0]	X_3	= 256'h8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8;
-   localparam	[255:0]	Y_3	= 256'hd8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9;
-   localparam	[255:0]	P_3	= 256'h944fea6a4fac7ae475a6bb211db4bbd394bd9b3ee9a038f6c17125a00b3a5375;
-
-   localparam	[255:0]	X_4	= 256'h7214bc9647160bbd39ff2f80533f5dc6ddd70ddf86bb815661e805d5d4e6f27c;
-   localparam	[255:0]	Y_4	= 256'h8b81e3e977597110c7cf2633435b2294b72642987defd3d4007e1cfc5df84541;
-   localparam	[255:0]	P_4	= 256'h78d3e33c81ab9c652679363c76df004ea6f9a9e3a242a0fb71a4e8fdf41ab519;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  3;
-   localparam	OPERAND_NUM_WORDS	=  8;
-
-
-   //
-   // Clock (100 MHz)
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-
-   //
-   // Buffers (X, Y, N, P)
-   //
-   wire [WORD_COUNTER_WIDTH-1:0] core_x_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_y_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_n_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_p_addr;
-
-   wire 			 core_p_wren;
-
-   wire [                  31:0] core_x_data;
-   wire [                  31:0] core_y_data;
-   wire [                  31:0] core_n_data;
-   wire [                  31:0] core_p_data;
-
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_xyn_addr;
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_p_addr;
-
-   reg 				 tb_xyn_wren;
-
-   reg [                  31:0]  tb_x_data;
-   reg [                  31:0]  tb_y_data;
-   reg [                  31:0]  tb_n_data;
-   wire [                  31:0] tb_p_data;
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_x
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_x_data),
-      .a_out	(),
-
-      .b_addr	(core_x_addr),
-      .b_out	(core_x_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_y
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_y_data),
-      .a_out	(),
-
-      .b_addr	(core_y_addr),
-      .b_out	(core_y_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_n
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_n_data),
-      .a_out	(),
-
-      .b_addr	(core_n_addr),
-      .b_out	(core_n_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_s
-     (
-      .clk		(clk),
-
-      .a_addr	(core_p_addr),
-      .a_wr		(core_p_wren),
-      .a_in		(core_p_data),
-      .a_out	(),
-
-      .b_addr	(tb_p_addr),
-      .b_out	(tb_p_data)
-      );
-
-
-   //
-   // UUT
-   //
-   modular_multiplier_256 uut
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(ena),
-      .rdy		(rdy),
-
-      .a_addr	(core_x_addr),
-      .b_addr	(core_y_addr),
-      .n_addr	(core_n_addr),
-      .p_addr	(core_p_addr),
-      .p_wren	(core_p_wren),
-
-      .a_din	(core_x_data),
-      .b_din	(core_y_data),
-      .n_din	(core_n_data),
-      .p_dout	(core_p_data)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 				 ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n				= 0;
-      ena				= 0;
-
-      tb_xyn_wren		= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n				= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_modular_multiplier(X_1, Y_1, N, P_1);
-      test_modular_multiplier(X_2, Y_2, N, P_2);
-      test_modular_multiplier(X_3, Y_3, N, P_3);
-      test_modular_multiplier(X_4, Y_4, N, P_4);
-
-      /* print result */
-      if (ok)	$display("tb_modular_multiplier_256: SUCCESS");
-      else	$display("tb_modular_multiplier_256: FAILURE");
-      //
-      //$finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg	[255:0]	p;
-   reg 		p_ok;
-
-   integer 	w;
-
-   reg [511:0] 	pp_full;
-   reg [255:0] 	pp_ref;
-
-   task test_modular_multiplier;
-
-      input	[255:0] x;
-      input [255:0] 	y;
-      input [255:0] 	n;
-      input [255:0] 	pp;
-
-      reg [255:0] 	x_shreg;
-      reg [255:0] 	y_shreg;
-      reg [255:0] 	n_shreg;
-      reg [255:0] 	p_shreg;
-
-      begin
-
-	 /* start filling memories */
-	 tb_xyn_wren	= 1;
-
-	 /* initialize shift registers */
-	 x_shreg = x;
-	 y_shreg = y;
-	 n_shreg = n;
-
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set addresses */
-	    tb_xyn_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* set data words */
-	    tb_x_data	= x_shreg[31:0];
-	    tb_y_data	= y_shreg[31:0];
-	    tb_n_data	= n_shreg[31:0];
-
-	    /* shift inputs */
-	    x_shreg = {{32{1'bX}}, x_shreg[255:32]};
-	    y_shreg = {{32{1'bX}}, y_shreg[255:32]};
-	    n_shreg = {{32{1'bX}}, n_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_xyn_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-
-	 /* wipe data words */
-	 tb_x_data	= {32{1'bX}};
-	 tb_y_data	= {32{1'bX}};
-	 tb_n_data	= {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_xyn_wren	= 0;
-
-	 /* calculate reference value */
-	 pp_full = {{256{1'b0}}, x} * {{256{1'b0}}, y};
-	 pp_ref = pp_full % {{256{1'b0}}, n};
-
-	 /* compare reference value against hard-coded one */
-	 if (pp_ref != pp) begin
-	    $display("ERROR: pp_ref != pp");
-	    $finish;
-	 end
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* read result */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set address */
-	    tb_p_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	    /* store data word */
-	    p_shreg = {tb_p_data, p_shreg[255:32]};
-
-	 end
-
-	 /* compare */
-	 p_ok = (p_shreg == pp);
-
-	 /* display results */
-	 $display("test_modular_multiplier_256(): %s", p_ok ? "OK" : "ERROR");
-
-	 /* update flag */
-	 ok = ok && p_ok;
-
-      end
-
-   endtask
-
-
-
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_modular_subtractor.v b/bench/tb_modular_subtractor.v
deleted file mode 100644
index 6cf0e01..0000000
--- a/bench/tb_modular_subtractor.v
+++ /dev/null
@@ -1,356 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_modular_subtractor_256.v
-// -----------------------------------------------------------------------------
-// Testbench for modular multi-word 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.
-//
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_modular_subtractor_256;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[255:0]	N	= 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff;
-
-   localparam	[255:0]	X_1	= 256'h1ddbd0769df27bab1e234019dad09dccce1e87e2193b417ffa1a3465d7439ecd;
-   localparam	[255:0]	Y_1	= 256'h1f67cdc34bac91a072945d212f0a03442fc4855788583ecb7b2e375ad3848210;
-
-   localparam	[255:0]	X_2	= 256'hff563f653b1392a6fa6b0295a280f7a904a11e22d8ae468e220301d8ac232fcf;
-   localparam	[255:0]	Y_2	= 256'hf6f53c4b57b25453b68e923fb118e4f753d74af01fc58476dd15a80933453899;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  3;
-   localparam	OPERAND_NUM_WORDS	=  8;
-
-
-   //
-   // Clock (100 MHz)
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-
-   //
-   // Buffers (X, Y, N)
-   //
-   wire [WORD_COUNTER_WIDTH-1:0] core_xy_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_n_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_d_addr;
-   wire 			 core_d_wren;
-
-   wire [                  31:0] core_x_data;
-   wire [                  31:0] core_y_data;
-   wire [                  31:0] core_n_data;
-   wire [                  31:0] core_d_data;
-
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_xyn_addr;
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_d_addr;
-   reg 				 tb_xyn_wren;
-
-   reg [                  31:0]  tb_x_data;
-   reg [                  31:0]  tb_y_data;
-   reg [                  31:0]  tb_n_data;
-   wire [                  31:0] tb_d_data;
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_x
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_x_data),
-      .a_out	(),
-
-      .b_addr	(core_xy_addr),
-      .b_out	(core_x_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_y
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_y_data),
-      .a_out	(),
-
-      .b_addr	(core_xy_addr),
-      .b_out	(core_y_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_n
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xyn_addr),
-      .a_wr		(tb_xyn_wren),
-      .a_in		(tb_n_data),
-      .a_out	(),
-
-      .b_addr	(core_n_addr),
-      .b_out	(core_n_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_s
-     (
-      .clk		(clk),
-
-      .a_addr	(core_d_addr),
-      .a_wr		(core_d_wren),
-      .a_in		(core_d_data),
-      .a_out	(),
-
-      .b_addr	(tb_d_addr),
-      .b_out	(tb_d_data)
-      );
-
-
-   //
-   // UUT
-   //
-   modular_subtractor #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-      )
-   uut
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(ena),
-      .rdy			(rdy),
-
-      .ab_addr		(core_xy_addr),
-      .n_addr		(core_n_addr),
-      .d_addr		(core_d_addr),
-      .d_wren		(core_d_wren),
-
-      .a_din		(core_x_data),
-      .b_din		(core_y_data),
-      .n_din		(core_n_data),
-      .d_dout		(core_d_data)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 				 ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n			= 0;
-      ena			= 0;
-
-      tb_xyn_wren	= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n		= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_modular_subtractor(X_1, Y_1, N);
-      test_modular_subtractor(X_2, Y_2, N);
-      test_modular_subtractor(Y_1, X_1, N);
-      test_modular_subtractor(Y_2, X_2, N);
-
-      test_modular_subtractor(X_1, X_2, N);
-      test_modular_subtractor(X_2, X_1, N);
-      test_modular_subtractor(Y_1, Y_2, N);
-      test_modular_subtractor(Y_2, Y_1, N);
-
-      test_modular_subtractor(X_1, Y_2, N);
-      test_modular_subtractor(Y_2, X_1, N);
-      test_modular_subtractor(X_2, Y_1, N);
-      test_modular_subtractor(Y_1, X_2, N);
-
-      /* print result */
-      if (ok)	$display("tb_modular_subtractor_256: SUCCESS");
-      else	$display("tb_modular_subtractor_256: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg	[256:0]	d;
-   wire [255:0] d_dummy = d[255:0];
-   reg 		d_ok;
-
-   integer 	w;
-
-   reg [255:0] 	x_shreg;
-   reg [255:0] 	y_shreg;
-   reg [255:0] 	n_shreg;
-   reg [255:0] 	d_shreg;
-
-   task test_modular_subtractor;
-
-      input	[255:0]	x;
-      input [255:0] 	y;
-      input [255:0] 	n;
-
-      begin
-
-	 /* start filling memories */
-	 tb_xyn_wren	= 1;
-
-	 /* initialize shift registers */
-	 x_shreg = x;
-	 y_shreg = y;
-	 n_shreg = n;
-
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set addresses */
-	    tb_xyn_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* set data words */
-	    tb_x_data	= x_shreg[31:0];
-	    tb_y_data	= y_shreg[31:0];
-	    tb_n_data	= n_shreg[31:0];
-
-	    /* shift inputs */
-	    x_shreg = {{32{1'bX}}, x_shreg[255:32]};
-	    y_shreg = {{32{1'bX}}, y_shreg[255:32]};
-	    n_shreg = {{32{1'bX}}, n_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_xyn_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-
-	 /* wipe data words */
-	 tb_x_data	= {32{1'bX}};
-	 tb_y_data	= {32{1'bX}};
-	 tb_n_data	= {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_xyn_wren	= 0;
-
-	 /* calculate reference value */
-	 d = {1'b0, (x < y) ? n : {256{1'b0}}};
-	 d = d + {1'b0, x} - {1'b0, y};
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* read result */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set address */
-	    tb_d_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	    /* store data word */
-	    d_shreg = {tb_d_data, d_shreg[255:32]};
-
-	 end
-
-	 /* compare */
-	 d_ok = (d_shreg == d[255:0]);
-
-	 /* display results */
-	 $display("test_modular_subtractor(): %s", d_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && d_ok;
-
-      end
-
-   endtask
-
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_mw_comparator.v b/bench/tb_mw_comparator.v
deleted file mode 100644
index ed830a8..0000000
--- a/bench/tb_mw_comparator.v
+++ /dev/null
@@ -1,322 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_mw_comparator.v
-// -----------------------------------------------------------------------------
-// Testbench for multi-word comparator.
-//
-// 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.
-//
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_mw_comparator;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[383:0]	A_0	= 384'hBDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F76;
-
-   localparam	[383:0]	A_1	= 384'hBDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F75;
-   localparam	[383:0]	A_2	= 384'hBDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F77;
-
-   localparam	[383:0]	A_3	= 384'hBDC7B53C_616B13B5_77622510_75BA95FC_375D568B_79E730D4_18A9143C_18905F76;
-   localparam	[383:0]	A_4	= 384'hBDC7B53C_616B13B5_77622510_75BA95FC_575D568B_79E730D4_18A9143C_18905F76;
-
-   localparam	[383:0]	A_5	= 384'hBDC7B53C_616B13B5_77622510_75BA95FB_475D568B_79E730D4_18A9143C_18905F76;
-   localparam	[383:0]	A_6	= 384'hBDC7B53C_616B13B5_77622510_75BA95FD_475D568B_79E730D4_18A9143C_18905F76;
-
-   localparam	[383:0]	A_7	= 384'hADC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F76;
-   localparam	[383:0]	A_8	= 384'hCDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F76;
-
-   localparam	[383:0]	B_0	= 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E5;
-
-   localparam	[383:0]	B_1	= 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E4;
-   localparam	[383:0]	B_2	= 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E6;
-
-   localparam	[383:0]	B_3	= 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_9D784F98_850046D4_10DDD64D_F6BB32E5;
-   localparam	[383:0]	B_4	= 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_BD784F98_850046D4_10DDD64D_F6BB32E5;
-
-   localparam	[383:0]	B_5	= 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3BF_AD784F98_850046D4_10DDD64D_F6BB32E5;
-   localparam	[383:0]	B_6	= 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C1_AD784F98_850046D4_10DDD64D_F6BB32E5;
-
-   localparam	[383:0]	B_7	= 384'h248A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E5;
-   localparam	[383:0]	B_8	= 384'h448A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E5;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  3;
-   parameter	OPERAND_NUM_WORDS	=  8;
-
-
-   //
-   // Clock (100 MHz)
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-   wire	core_cmp_l;
-   wire	core_cmp_e;
-   wire	core_cmp_g;
-
-
-   //
-   // Buffers (X, Y)
-   //
-   wire [WORD_COUNTER_WIDTH-1:0] core_xy_addr;
-
-   wire [                32-1:0] core_x_data;
-   wire [                32-1:0] core_y_data;
-
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_xy_addr;
-   reg 				 tb_xy_wren;
-
-   reg [                32-1:0]  tb_x_data;
-   reg [                32-1:0]  tb_y_data;
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_x
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xy_addr),
-      .a_wr		(tb_xy_wren),
-      .a_in		(tb_x_data),
-      .a_out	(),
-
-      .b_addr	(core_xy_addr),
-      .b_out	(core_x_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_y
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_xy_addr),
-      .a_wr		(tb_xy_wren),
-      .a_in		(tb_y_data),
-      .a_out	(),
-
-      .b_addr	(core_xy_addr),
-      .b_out	(core_y_data)
-      );
-
-
-   //
-   // UUT
-   //
-   mw_comparator #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-      )
-   uut
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(ena),
-      .rdy		(rdy),
-
-      .xy_addr	(core_xy_addr),
-      .x_din	(core_x_data),
-      .y_din	(core_y_data),
-
-      .cmp_l	(core_cmp_l),
-      .cmp_e	(core_cmp_e),
-      .cmp_g	(core_cmp_g)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 				 ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n		= 0;
-      ena		= 0;
-
-      tb_xy_wren	= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n		= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_mw_comparator(A_0, A_0);
-
-      test_mw_comparator(A_0, A_1);
-      test_mw_comparator(A_0, A_2);
-      test_mw_comparator(A_0, A_3);
-      test_mw_comparator(A_0, A_4);
-      test_mw_comparator(A_0, A_5);
-      test_mw_comparator(A_0, A_6);
-      test_mw_comparator(A_0, A_7);
-      test_mw_comparator(A_0, A_8);
-
-      test_mw_comparator(B_0, B_0);
-
-      test_mw_comparator(B_0, B_1);
-      test_mw_comparator(B_0, B_2);
-      test_mw_comparator(B_0, B_3);
-      test_mw_comparator(B_0, B_4);
-      test_mw_comparator(B_0, B_5);
-      test_mw_comparator(B_0, B_6);
-      test_mw_comparator(B_0, B_7);
-      test_mw_comparator(B_0, B_8);
-
-      /* print result */
-      if (ok)	$display("tb_mw_comparator: SUCCESS");
-      else	$display("tb_mw_comparator: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg	cmp_l;
-   reg	cmp_e;
-   reg	cmp_g;
-   reg	cmp_ok;
-
-   integer w;
-
-   task test_mw_comparator;
-
-      input [255:0]	x;
-      input [255:0] 	y;
-
-      reg [255:0] 	x_shreg;
-      reg [255:0] 	y_shreg;
-
-      begin
-
-	 /* start filling memories */
-	 tb_xy_wren	= 1;
-
-	 /* initialize shift registers */
-	 x_shreg = x;
-	 y_shreg = y;
-
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set addresses */
-	    tb_xy_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* set data words */
-	    tb_x_data	= x_shreg[31:0];
-	    tb_y_data	= y_shreg[31:0];
-
-	    /* shift inputs */
-	    x_shreg = {{32{1'bX}}, x_shreg[255:32]};
-	    y_shreg = {{32{1'bX}}, y_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_xy_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-
-	 /* wipe data words */
-	 tb_x_data	= {32{1'bX}};
-	 tb_y_data	= {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_xy_wren	= 0;
-
-	 /* calculate reference values */
-	 cmp_l = (x <  y) ? 1 : 0;
-	 cmp_e = (x == y) ? 1 : 0;
-	 cmp_g = (x >  y) ? 1 : 0;
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* compare */
-	 cmp_ok = (cmp_l == core_cmp_l) && (cmp_e == core_cmp_e) && (cmp_g == core_cmp_g);
-
-	 /* display results */
-	 $display("test_mw_comparator(): %s", cmp_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && cmp_ok;
-
-      end
-
-   endtask
-
-endmodule
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/bench/tb_mw_mover.v b/bench/tb_mw_mover.v
deleted file mode 100644
index 08bdb9e..0000000
--- a/bench/tb_mw_mover.v
+++ /dev/null
@@ -1,282 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_modular_mover.v
-// -----------------------------------------------------------------------------
-// Testbench for multi-word data mover.
-//
-// 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.
-//
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
-module tb_mw_mover;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[255:0]	X_1	= 256'h1ddbd0769df27bab1e234019dad09dccce1e87e2193b417ffa1a3465d7439ecd;
-   localparam	[255:0]	X_2	= 256'h1f67cdc34bac91a072945d212f0a03442fc4855788583ecb7b2e375ad3848210;
-   localparam	[255:0]	X_3	= 256'hff563f653b1392a6fa6b0295a280f7a904a11e22d8ae468e220301d8ac232fcf;
-   localparam	[255:0]	X_4	= 256'hf6f53c4b57b25453b68e923fb118e4f753d74af01fc58476dd15a80933453899;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  3;
-   localparam	OPERAND_NUM_WORDS	=  8;
-
-
-   //
-   // Clock (100 MHz)
-   //
-   reg clk = 1'b0;
-   always #5 clk = ~clk;
-
-
-   //
-   // Inputs, Outputs
-   //
-   reg rst_n;
-   reg ena;
-   wire rdy;
-
-
-   //
-   // Buffers (X, Y)
-   //
-   wire [WORD_COUNTER_WIDTH-1:0] core_x_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] core_y_addr;
-   wire 			 core_y_wren;
-
-   wire [                32-1:0] core_x_data;
-   wire [                32-1:0] core_y_data;
-
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_x_addr;
-   reg [WORD_COUNTER_WIDTH-1:0]  tb_y_addr;
-   reg 				 tb_x_wren;
-
-   reg [                32-1:0]  tb_x_data;
-   wire [                32-1:0] tb_y_data;
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_x
-     (
-      .clk		(clk),
-
-      .a_addr	(tb_x_addr),
-      .a_wr		(tb_x_wren),
-      .a_in		(tb_x_data),
-      .a_out	(),
-
-      .b_addr	(core_x_addr),
-      .b_out	(core_x_data)
-      );
-
-   bram_1rw_1ro_readfirst #
-     (
-      .MEM_WIDTH			(32),
-      .MEM_ADDR_BITS		(WORD_COUNTER_WIDTH)
-      )
-   bram_d
-     (
-      .clk		(clk),
-
-      .a_addr	(core_y_addr),
-      .a_wr		(core_y_wren),
-      .a_in		(core_y_data),
-      .a_out	(),
-
-      .b_addr	(tb_y_addr),
-      .b_out	(tb_y_data)
-      );
-
-
-   //
-   // UUT
-   //
-   mw_mover #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-      )
-   uut
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(ena),
-      .rdy			(rdy),
-
-      .x_addr		(core_x_addr),
-      .y_addr		(core_y_addr),
-      .y_wren		(core_y_wren),
-
-      .x_din		(core_x_data),
-      .y_dout		(core_y_data)
-      );
-
-
-   //
-   // Testbench Routine
-   //
-   reg 				 ok = 1;
-   initial begin
-
-      /* initialize control inputs */
-      rst_n			= 0;
-      ena			= 0;
-
-      tb_x_wren	= 0;
-
-      /* wait for some time */
-      #200;
-
-      /* de-assert reset */
-      rst_n		= 1;
-
-      /* wait for some time */
-      #100;
-
-      /* run tests */
-      test_modular_mover(X_1);
-      test_modular_mover(X_2);
-      test_modular_mover(X_3);
-      test_modular_mover(X_4);
-
-      /* print result */
-      if (ok)	$display("tb_modular_mover: SUCCESS");
-      else	$display("tb_modular_mover: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg	[255:0]	y;
-   reg 		y_ok;
-
-   integer 	w;
-
-   reg [255:0] 	x_shreg;
-   reg [255:0] 	y_shreg;
-
-   task test_modular_mover;
-
-      input	[255:0]	x;
-
-      begin
-
-	 /* start filling memories */
-	 tb_x_wren	= 1;
-
-	 /* initialize shift registers */
-	 x_shreg = x;
-
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set addresses */
-	    tb_x_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* set data words */
-	    tb_x_data	= x_shreg[31:0];
-
-	    /* shift inputs */
-	    x_shreg = {{32{1'bX}}, x_shreg[255:32]};
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	 end
-
-	 /* wipe addresses */
-	 tb_x_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-
-	 /* wipe data words */
-	 tb_x_data	= {32{1'bX}};
-
-	 /* stop filling memories */
-	 tb_x_wren	= 0;
-
-	 /* start operation */
-	 ena = 1;
-
-	 /* clear flag */
-	 #10 ena = 0;
-
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
-
-	 /* read result */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
-
-	    /* set address */
-	    tb_y_addr	= w[WORD_COUNTER_WIDTH-1:0];
-
-	    /* wait for 1 clock tick */
-	    #10;
-
-	    /* store data word */
-	    y_shreg = {tb_y_data, y_shreg[255:32]};
-
-	 end
-
-	 /* compare */
-	 y_ok = (y_shreg == x);
-
-	 /* display results */
-	 $display("test_modular_mover(): %s", y_ok ? "OK" : "ERROR");
-
-	 /* update global flag */
-	 ok = ok && y_ok;
-
-      end
-
-   endtask
-
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/rtl/curve/curve_dbl_add_256.v b/rtl/curve/curve_dbl_add_256.v
deleted file mode 100644
index 1fb1bea..0000000
--- a/rtl/curve/curve_dbl_add_256.v
+++ /dev/null
@@ -1,893 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// curve_dbl_add_256.v
-// -----------------------------------------------------------------------------
-// Elliptic curve point adder and doubler.
-//
-// 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 curve_dbl_add_256
-  (
-   clk, rst_n,
-   ena, rdy,
-   uop_addr, uop,
-   px_addr, py_addr, pz_addr, rx_addr, ry_addr, rz_addr, q_addr, v_addr,
-   rx_wren, ry_wren, rz_wren,
-   px_din, py_din, pz_din,
-   rx_din, ry_din, rz_din,
-   rx_dout, ry_dout, rz_dout, q_din, v_din
-   );
-
-
-   //
-   // Microcode
-   //
-`include "../../../../math/ecdsalib/rtl/curve/uop_ecdsa.v"
-
-
-   //
-   // Constants
-   //
-   localparam	WORD_COUNTER_WIDTH	= 3;	// 0 .. 7
-   localparam	OPERAND_NUM_WORDS	= 8;	// 8 * 32 = 256
-
-
-   //
-   // 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	reg [ 6-1: 0] 	uop_addr;
-   input	wire [20-1: 0]	uop;
-
-   output	reg [WORD_COUNTER_WIDTH-1:0] px_addr;
-   output	reg [WORD_COUNTER_WIDTH-1:0] py_addr;
-   output	reg [WORD_COUNTER_WIDTH-1:0] pz_addr;
-   output	reg [WORD_COUNTER_WIDTH-1:0] rx_addr;
-   output	reg [WORD_COUNTER_WIDTH-1:0] ry_addr;
-   output	reg [WORD_COUNTER_WIDTH-1:0] rz_addr;
-   output	reg [WORD_COUNTER_WIDTH-1:0] v_addr;
-   output	wire [WORD_COUNTER_WIDTH-1:0] q_addr;
-
-   output	wire 			      rx_wren;
-   output	wire 			      ry_wren;
-   output	wire 			      rz_wren;
-
-   input		wire [                32-1:0] px_din;
-   input		wire [                32-1:0] py_din;
-   input		wire [                32-1:0] pz_din;
-   input		wire [                32-1:0] rx_din;
-   input		wire [                32-1:0] ry_din;
-   input		wire [                32-1:0] rz_din;
-   output	wire [                32-1:0] 	      rx_dout;
-   output	wire [                32-1:0] 	      ry_dout;
-   output	wire [                32-1:0] 	      rz_dout;
-   input		wire [                32-1:0] q_din;
-   input		wire [                32-1:0] v_din;
-
-
-   //
-   // Microcode
-   //
-   wire [ 4: 0] 				      uop_opcode	= uop[19:15];
-   wire [ 4: 0] 				      uop_src_a	= uop[14:10];
-   wire [ 4: 0] 				      uop_src_b	= uop[ 9: 5];
-   wire [ 2: 0] 				      uop_dst		= uop[ 4: 2];
-   wire [ 1: 0] 				      uop_exec		= uop[ 1: 0];
-
-
-   //
-   // Multi-Word Comparator
-   //
-   wire 					      mw_cmp_ena;
-   wire 					      mw_cmp_rdy;
-
-   wire 					      mw_cmp_out_l;
-   wire 					      mw_cmp_out_e;
-   wire 					      mw_cmp_out_g;
-
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mw_cmp_addr_xy;
-
-   wire [                32-1:0] 		      mw_cmp_din_x;
-   wire [                32-1:0] 		      mw_cmp_din_y;
-
-   // flags
-   reg 						      flag_pz_is_zero;
-   reg 						      flag_t1_is_zero;
-   reg 						      flag_t2_is_zero;
-
-   mw_comparator #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-      )
-   mw_comparator_inst
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(mw_cmp_ena),
-      .rdy			(mw_cmp_rdy),
-
-      .xy_addr		(mw_cmp_addr_xy),
-      .x_din		(mw_cmp_din_x),
-      .y_din		(mw_cmp_din_y),
-
-      .cmp_l		(mw_cmp_out_l),
-      .cmp_e		(mw_cmp_out_e),
-      .cmp_g		(mw_cmp_out_g)
-      );
-
-
-   //
-   // Modular Adder
-   //
-   wire 					      mod_add_ena;
-   wire 					      mod_add_rdy;
-
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_add_addr_ab;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_add_addr_n;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_add_addr_s;
-   wire 					      mod_add_wren_s;
-
-   wire [                32-1:0] 		      mod_add_din_a;
-   wire [                32-1:0] 		      mod_add_din_b;
-   wire [                32-1:0] 		      mod_add_din_n;
-   wire [                32-1:0] 		      mod_add_dout_s;
-
-   assign mod_add_din_n = q_din;
-
-   modular_adder #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-      )
-   modular_adder_inst
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(mod_add_ena),
-      .rdy			(mod_add_rdy),
-
-      .ab_addr		(mod_add_addr_ab),
-      .n_addr		(mod_add_addr_n),
-      .s_addr		(mod_add_addr_s),
-      .s_wren		(mod_add_wren_s),
-
-      .a_din		(mod_add_din_a),
-      .b_din		(mod_add_din_b),
-      .n_din		(mod_add_din_n),
-      .s_dout		(mod_add_dout_s)
-      );
-
-
-   //
-   // Modular Subtractor
-   //
-   wire 					      mod_sub_ena;
-   wire 					      mod_sub_rdy;
-
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_sub_addr_ab;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_sub_addr_n;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_sub_addr_d;
-   wire 					      mod_sub_wren_d;
-
-   wire [                32-1:0] 		      mod_sub_din_a;
-   wire [                32-1:0] 		      mod_sub_din_b;
-   wire [                32-1:0] 		      mod_sub_din_n;
-   wire [                32-1:0] 		      mod_sub_dout_d;
-
-   assign mod_sub_din_n = q_din;
-
-   modular_subtractor #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-      )
-   modular_subtractor_inst
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(mod_sub_ena),
-      .rdy			(mod_sub_rdy),
-
-      .ab_addr		(mod_sub_addr_ab),
-      .n_addr		(mod_sub_addr_n),
-      .d_addr		(mod_sub_addr_d),
-      .d_wren		(mod_sub_wren_d),
-
-      .a_din		(mod_sub_din_a),
-      .b_din		(mod_sub_din_b),
-      .n_din		(mod_sub_din_n),
-      .d_dout		(mod_sub_dout_d)
-      );
-
-
-   //
-   // Modular Multiplier
-   //
-   wire 					      mod_mul_ena;
-   wire 					      mod_mul_rdy;
-
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_mul_addr_a;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_mul_addr_b;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_mul_addr_n;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mod_mul_addr_p;
-   wire 					      mod_mul_wren_p;
-
-   wire [                32-1:0] 		      mod_mul_din_a;
-   wire [                32-1:0] 		      mod_mul_din_b;
-   wire [                32-1:0] 		      mod_mul_din_n;
-   wire [                32-1:0] 		      mod_mul_dout_p;
-
-   assign mod_mul_din_n = q_din;
-
-   modular_multiplier_256 modular_multiplier_inst
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(mod_mul_ena),
-      .rdy		(mod_mul_rdy),
-
-      .a_addr	(mod_mul_addr_a),
-      .b_addr	(mod_mul_addr_b),
-      .n_addr	(mod_mul_addr_n),
-      .p_addr	(mod_mul_addr_p),
-      .p_wren	(mod_mul_wren_p),
-
-      .a_din	(mod_mul_din_a),
-      .b_din	(mod_mul_din_b),
-      .n_din	(mod_mul_din_n),
-      .p_dout	(mod_mul_dout_p)
-      );
-
-
-   //
-   // Multi-Word Data Mover
-   //
-   wire 					      mw_mov_ena;
-   wire 					      mw_mov_rdy;
-
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mw_mov_addr_x;
-   wire [WORD_COUNTER_WIDTH-1:0] 		      mw_mov_addr_y;
-   wire 					      mw_mov_wren_y;
-
-   wire [                32-1:0] 		      mw_mov_din_x;
-   wire [                32-1:0] 		      mw_mov_dout_y;
-
-   mw_mover #
-     (
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH),
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS)
-
-      )
-   mw_mover_inst
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(mw_mov_ena),
-      .rdy		(mw_mov_rdy),
-
-      .x_addr	(mw_mov_addr_x),
-      .y_addr	(mw_mov_addr_y),
-      .y_wren	(mw_mov_wren_y),
-
-      .x_din	(mw_mov_din_x),
-      .y_dout	(mw_mov_dout_y)
-      );
-
-
-   //
-   // ROMs
-   //
-   reg [WORD_COUNTER_WIDTH-1:0] 		      brom_one_addr;
-   //reg	[WORD_COUNTER_WIDTH-1:0]	brom_zero_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      brom_delta_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      brom_g_x_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      brom_g_y_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      brom_h_x_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      brom_h_y_addr;
-
-   wire [                32-1:0] 		      brom_one_dout;
-   wire [                32-1:0] 		      brom_zero_dout;
-   wire [                32-1:0] 		      brom_delta_dout;
-   wire [                32-1:0] 		      brom_g_x_dout;
-   wire [                32-1:0] 		      brom_g_y_dout;
-   wire [                32-1:0] 		      brom_h_x_dout;
-   wire [                32-1:0] 		      brom_h_y_dout;
-
-   (* ROM_STYLE="BLOCK" *) brom_p256_one brom_one_inst
-     (.clk(clk), .b_addr(brom_one_addr), .b_out(brom_one_dout));
-
-   brom_p256_zero brom_zero_inst
-     (.b_out(brom_zero_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p256_delta brom_delta_inst
-     (.clk(clk), .b_addr(brom_delta_addr), .b_out(brom_delta_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p256_g_x brom_g_x_inst
-     (.clk(clk), .b_addr(brom_g_x_addr), .b_out(brom_g_x_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p256_g_y brom_g_y_inst
-     (.clk(clk), .b_addr(brom_g_y_addr), .b_out(brom_g_y_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p256_h_x brom_h_x_inst
-     (.clk(clk), .b_addr(brom_h_x_addr), .b_out(brom_h_x_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p256_h_y brom_h_y_inst
-     (.clk(clk), .b_addr(brom_h_y_addr), .b_out(brom_h_y_dout));
-
-
-   //
-   // Temporary Variables
-   //
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t1_wr_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t2_wr_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t3_wr_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t4_wr_addr;
-
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t1_rd_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t2_rd_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t3_rd_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      bram_t4_rd_addr;
-
-   wire 					      bram_t1_wr_en;
-   wire 					      bram_t2_wr_en;
-   wire 					      bram_t3_wr_en;
-   wire 					      bram_t4_wr_en;
-
-   wire [                32-1:0] 		      bram_t1_wr_data;
-   wire [                32-1:0] 		      bram_t2_wr_data;
-   wire [                32-1:0] 		      bram_t3_wr_data;
-   wire [                32-1:0] 		      bram_t4_wr_data;
-
-   wire [                32-1:0] 		      bram_t1_rd_data;
-   wire [                32-1:0] 		      bram_t2_rd_data;
-   wire [                32-1:0] 		      bram_t3_rd_data;
-   wire [                32-1:0] 		      bram_t4_rd_data;
-
-   bram_1rw_1ro_readfirst #
-     (	.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)
-	)
-   bram_t1
-     (	.clk		(clk),
-	.a_addr(bram_t1_wr_addr), .a_wr(bram_t1_wr_en), .a_in(bram_t1_wr_data), .a_out(),
-	.b_addr(bram_t1_rd_addr),                                               .b_out(bram_t1_rd_data)
-	);
-
-   bram_1rw_1ro_readfirst #
-     (	.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)
-	)
-   bram_t2
-     (	.clk		(clk),
-	.a_addr(bram_t2_wr_addr), .a_wr(bram_t2_wr_en), .a_in(bram_t2_wr_data), .a_out(),
-	.b_addr(bram_t2_rd_addr),                                               .b_out(bram_t2_rd_data)
-	);
-
-   bram_1rw_1ro_readfirst #
-     (	.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)
-	)
-   bram_t3
-     (	.clk		(clk),
-	.a_addr(bram_t3_wr_addr), .a_wr(bram_t3_wr_en), .a_in(bram_t3_wr_data), .a_out(),
-	.b_addr(bram_t3_rd_addr),                                               .b_out(bram_t3_rd_data)
-	);
-
-   bram_1rw_1ro_readfirst #
-     (	.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)
-	)
-   bram_t4
-     (	.clk		(clk),
-	.a_addr(bram_t4_wr_addr), .a_wr(bram_t4_wr_en), .a_in(bram_t4_wr_data), .a_out(),
-	.b_addr(bram_t4_rd_addr),                                               .b_out(bram_t4_rd_data)
-	);
-
-
-   //
-   // uOP Trigger Logic
-   //
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *) reg uop_trig_fsm;
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *) reg uop_trig_cmp;
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *) reg uop_trig_mov;
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *) reg uop_trig_add;
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *) reg uop_trig_sub;
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *) reg uop_trig_mul;
-   
-    always @(posedge clk or negedge rst_n)
-        //
-        if (rst_n == 1'b0) begin
-            uop_trig_fsm <= 1'b0;
-            uop_trig_cmp <= 1'b0;
-            uop_trig_mov <= 1'b0;
-            uop_trig_add <= 1'b0;
-            uop_trig_sub <= 1'b0;
-            uop_trig_mul <= 1'b0;
-        end else begin
-            uop_trig_fsm <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0;
-            uop_trig_cmp <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0;
-            uop_trig_mov <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0;
-            uop_trig_add <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0;
-            uop_trig_sub <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0;
-            uop_trig_mul <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0;
-        end
-
-
-   //
-   // FSM
-   //
-   localparam	[ 1: 0]	FSM_STATE_STALL	= 2'b00;
-   localparam	[ 1: 0]	FSM_STATE_FETCH	= 2'b01;
-   localparam	[ 1: 0]	FSM_STATE_EXECUTE	= 2'b10;
-
-   reg [ 1: 0] 					      fsm_state		= FSM_STATE_STALL;
-   wire [ 1: 0] 				      fsm_state_next	= (uop_opcode == OPCODE_RDY) ? FSM_STATE_STALL : FSM_STATE_FETCH;
-
-
-    //
-    // FSM Transition Logic
-    //
-    reg 						      uop_done;
-
-    always @(posedge clk or negedge rst_n)
-        //
-        if (rst_n == 1'b0)      fsm_state <= FSM_STATE_STALL;
-        else case (fsm_state)
-            FSM_STATE_STALL:    fsm_state <= ena ? FSM_STATE_FETCH : FSM_STATE_STALL;
-            FSM_STATE_FETCH:    fsm_state <= FSM_STATE_EXECUTE;
-            FSM_STATE_EXECUTE:  fsm_state <= (!uop_trig_fsm && uop_done) ? fsm_state_next : FSM_STATE_EXECUTE;
-            default:            fsm_state <= FSM_STATE_STALL;
-        endcase
-
-
-   //
-   // uOP Address Increment Logic
-   //
-   always @(posedge clk)
-     //
-     if (fsm_state == FSM_STATE_STALL)
-       uop_addr <= 5'd0;
-     else if (fsm_state == FSM_STATE_EXECUTE)
-       if (!uop_trig_fsm && uop_done)
-	 uop_addr <= (uop_opcode == OPCODE_RDY) ? 5'd0 : uop_addr + 1'b1;
-
-
-   //
-   // uOP Completion Logic
-   //
-   always @(*)
-   //
-   case (uop_opcode)
-     OPCODE_CMP:	uop_done = mw_cmp_rdy;
-     OPCODE_MOV:	uop_done = mw_mov_rdy;
-     OPCODE_ADD:	uop_done = mod_add_rdy;
-     OPCODE_SUB:	uop_done = mod_sub_rdy;
-     OPCODE_MUL:	uop_done = mod_mul_rdy;
-     OPCODE_RDY:	uop_done = 1'b1;
-     default:		uop_done = 1'b0;
-   endcase
-
-
-    //
-    // Helper Modules Enable Logic
-    //
-    assign mw_cmp_ena    = uop_opcode[0] & uop_trig_cmp;
-    assign mw_mov_ena    = uop_opcode[1] & uop_trig_mov;
-    assign mod_add_ena   = uop_opcode[2] & uop_trig_add;
-    assign mod_sub_ena   = uop_opcode[3] & uop_trig_sub;
-    assign mod_mul_ena   = uop_opcode[4] & uop_trig_mul;
-
-
-   //
-   // uOP Source Value Decoding Logic
-   //
-   reg [31: 0] 					      uop_src_a_value;
-
-   always @(*)
-				   //
-     case (uop_src_a)
-       UOP_SRC_PX:		uop_src_a_value = px_din;
-       UOP_SRC_PY:		uop_src_a_value = py_din;
-       UOP_SRC_PZ:		uop_src_a_value = pz_din;
-
-       UOP_SRC_RX:		uop_src_a_value = rx_din;
-       UOP_SRC_RY:		uop_src_a_value = ry_din;
-       UOP_SRC_RZ:		uop_src_a_value = rz_din;
-
-       UOP_SRC_T1:		uop_src_a_value = bram_t1_rd_data;
-       UOP_SRC_T2:		uop_src_a_value = bram_t2_rd_data;
-       UOP_SRC_T3:		uop_src_a_value = bram_t3_rd_data;
-       UOP_SRC_T4:		uop_src_a_value = bram_t4_rd_data;
-
-       UOP_SRC_ONE:	uop_src_a_value = brom_one_dout;
-       UOP_SRC_ZERO:	uop_src_a_value = brom_zero_dout;
-       UOP_SRC_DELTA:	uop_src_a_value = brom_delta_dout;
-
-       UOP_SRC_G_X:	uop_src_a_value = brom_g_x_dout;
-       UOP_SRC_G_Y:	uop_src_a_value = brom_g_y_dout;
-
-       UOP_SRC_H_X:	uop_src_a_value = brom_h_x_dout;
-       UOP_SRC_H_Y:	uop_src_a_value = brom_h_y_dout;
-
-       UOP_SRC_V:		uop_src_a_value = v_din;
-
-       default:			uop_src_a_value = {32{1'bX}};
-     endcase
-
-
-   assign mw_cmp_din_x  = uop_src_a_value;
-   assign mw_mov_din_x  = uop_src_a_value;
-   assign mod_add_din_a = uop_src_a_value;
-   assign mod_sub_din_a = uop_src_a_value;
-   assign mod_mul_din_a = uop_src_a_value;
-
-   reg [31: 0] 					      uop_src_b_value;
-
-   always @(*)
-						  //
-     case (uop_src_b)
-       UOP_SRC_PX:		uop_src_b_value = px_din;
-       UOP_SRC_PY:		uop_src_b_value = py_din;
-       UOP_SRC_PZ:		uop_src_b_value = pz_din;
-
-       UOP_SRC_RX:		uop_src_b_value = rx_din;
-       UOP_SRC_RY:		uop_src_b_value = ry_din;
-       UOP_SRC_RZ:		uop_src_b_value = rz_din;
-
-       UOP_SRC_T1:		uop_src_b_value = bram_t1_rd_data;
-       UOP_SRC_T2:		uop_src_b_value = bram_t2_rd_data;
-       UOP_SRC_T3:		uop_src_b_value = bram_t3_rd_data;
-       UOP_SRC_T4:		uop_src_b_value = bram_t4_rd_data;
-
-       UOP_SRC_ONE:	uop_src_b_value = brom_one_dout;
-       UOP_SRC_ZERO:	uop_src_b_value = brom_zero_dout;
-       UOP_SRC_DELTA:	uop_src_b_value = brom_delta_dout;
-
-       UOP_SRC_G_X:	uop_src_b_value = brom_g_x_dout;
-       UOP_SRC_G_Y:	uop_src_b_value = brom_g_y_dout;
-
-       UOP_SRC_H_X:	uop_src_b_value = brom_h_x_dout;
-       UOP_SRC_H_Y:	uop_src_b_value = brom_h_y_dout;
-
-       UOP_SRC_V:		uop_src_b_value = v_din;
-
-       default:			uop_src_b_value = {32{1'bX}};
-     endcase
-
-   assign mw_cmp_din_y  = uop_src_b_value;
-   assign mod_add_din_b = uop_src_b_value;
-   assign mod_sub_din_b = uop_src_b_value;
-   assign mod_mul_din_b = uop_src_b_value;
-
-
-   //
-   // uOP Source & Destination Address Decoding Logic
-   //
-   reg [WORD_COUNTER_WIDTH-1:0] 		      uop_src_a_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      uop_src_b_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      uop_dst_addr;
-   reg [WORD_COUNTER_WIDTH-1:0] 		      uop_q_addr;
-
-   assign q_addr = uop_q_addr;
-
-   always @(*)
-						  //
-     case (uop_opcode)
-       //
-       OPCODE_CMP:	begin
-	  uop_src_a_addr = mw_cmp_addr_xy;
-	  uop_src_b_addr = mw_cmp_addr_xy;
-	  uop_dst_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-	  uop_q_addr		= {WORD_COUNTER_WIDTH{1'bX}};
-       end
-       //
-       OPCODE_MOV:	begin
-	  uop_src_a_addr = mw_mov_addr_x;
-	  uop_src_b_addr = {WORD_COUNTER_WIDTH{1'bX}};
-	  uop_dst_addr	= mw_mov_addr_y;
-	  uop_q_addr		= {WORD_COUNTER_WIDTH{1'bX}};
-       end
-       //
-       OPCODE_ADD:	begin
-	  uop_src_a_addr = mod_add_addr_ab;
-	  uop_src_b_addr = mod_add_addr_ab;
-	  uop_dst_addr	= mod_add_addr_s;
-	  uop_q_addr		= mod_add_addr_n;
-       end
-       //
-       OPCODE_SUB:	begin
-	  uop_src_a_addr = mod_sub_addr_ab;
-	  uop_src_b_addr = mod_sub_addr_ab;
-	  uop_dst_addr	= mod_sub_addr_d;
-	  uop_q_addr		= mod_sub_addr_n;
-       end
-       //
-       OPCODE_MUL:	begin
-	  uop_src_a_addr = mod_mul_addr_a;
-	  uop_src_b_addr = mod_mul_addr_b;
-	  uop_dst_addr	= mod_mul_addr_p;
-	  uop_q_addr		= mod_mul_addr_n;
-       end
-       //
-       default: begin
-	  uop_src_a_addr = {WORD_COUNTER_WIDTH{1'bX}};
-	  uop_src_b_addr = {WORD_COUNTER_WIDTH{1'bX}};
-	  uop_dst_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-	  uop_q_addr		= {WORD_COUNTER_WIDTH{1'bX}};
-       end
-       //
-     endcase
-
-
-   //
-   // uOP Conditional Execution Logic
-   //
-   reg	uop_exec_effective;
-
-   always @(*)
-			   //
-     case (uop_exec)
-       UOP_EXEC_ALWAYS:		uop_exec_effective = 1'b1;
-       UOP_EXEC_PZT1T2_0XX:	uop_exec_effective =  flag_pz_is_zero;
-       UOP_EXEC_PZT1T2_100:	uop_exec_effective = !flag_pz_is_zero && flag_t1_is_zero &&  flag_t2_is_zero;
-       UOP_EXEC_PZT1T2_101:	uop_exec_effective = !flag_pz_is_zero && flag_t1_is_zero && !flag_t2_is_zero;
-     endcase
-
-
-   //
-   // uOP Destination Store Logic
-   //
-   reg	uop_dst_wren;
-
-   always @(*)
-						     //
-     case (uop_opcode)
-       //
-       OPCODE_MOV:	uop_dst_wren = mw_mov_wren_y & uop_exec_effective;
-       OPCODE_ADD:	uop_dst_wren = mod_add_wren_s;
-       OPCODE_SUB:	uop_dst_wren = mod_sub_wren_d;
-       OPCODE_MUL:	uop_dst_wren = mod_mul_wren_p;
-       default:		uop_dst_wren = 1'b0;
-       //
-     endcase
-
-
-   always @(*) begin
-      //
-      //
-      //
-      if      (uop_src_a == UOP_SRC_PX) px_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_PX) px_addr = uop_src_b_addr;
-      else                              px_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_PY) py_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_PY) py_addr = uop_src_b_addr;
-      else                              py_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_PZ) pz_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_PZ) pz_addr = uop_src_b_addr;
-      else                              pz_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //
-      //
-      if      (uop_src_a == UOP_SRC_ONE)   brom_one_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_ONE)   brom_one_addr = uop_src_b_addr;
-      else                                 brom_one_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //if      (uop_src_a == UOP_SRC_ZERO)  brom_zero_addr = uop_src_a_addr;
-      //else if (uop_src_b == UOP_SRC_ZERO)  brom_zero_addr = uop_src_b_addr;
-      //else                                 brom_zero_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_DELTA) brom_delta_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_DELTA) brom_delta_addr = uop_src_b_addr;
-      else                                 brom_delta_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //
-      //
-      if      (uop_src_a == UOP_SRC_G_X) brom_g_x_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_G_X) brom_g_x_addr = uop_src_b_addr;
-      else                               brom_g_x_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_G_Y) brom_g_y_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_G_Y) brom_g_y_addr = uop_src_b_addr;
-      else                               brom_g_y_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //
-      //
-      if      (uop_src_a == UOP_SRC_H_X) brom_h_x_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_H_X) brom_h_x_addr = uop_src_b_addr;
-      else                               brom_h_x_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_H_Y) brom_h_y_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_H_Y) brom_h_y_addr = uop_src_b_addr;
-      else                               brom_h_y_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //
-      //
-      if      (uop_src_a == UOP_SRC_V) v_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_V) v_addr = uop_src_b_addr;
-      else                             v_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //
-      //
-      if      (uop_src_a == UOP_SRC_T1) bram_t1_rd_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_T1) bram_t1_rd_addr = uop_src_b_addr;
-      else                              bram_t1_rd_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_T2) bram_t2_rd_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_T2) bram_t2_rd_addr = uop_src_b_addr;
-      else                              bram_t2_rd_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_T3) bram_t3_rd_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_T3) bram_t3_rd_addr = uop_src_b_addr;
-      else                              bram_t3_rd_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if      (uop_src_a == UOP_SRC_T4) bram_t4_rd_addr = uop_src_a_addr;
-      else if (uop_src_b == UOP_SRC_T4) bram_t4_rd_addr = uop_src_b_addr;
-      else                              bram_t4_rd_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //
-      //
-      if (uop_dst == UOP_DST_T1) bram_t1_wr_addr = uop_dst_addr;
-      else                       bram_t1_wr_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if (uop_dst == UOP_DST_T2) bram_t2_wr_addr = uop_dst_addr;
-      else                       bram_t2_wr_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if (uop_dst == UOP_DST_T3) bram_t3_wr_addr = uop_dst_addr;
-      else                       bram_t3_wr_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      if (uop_dst == UOP_DST_T4) bram_t4_wr_addr = uop_dst_addr;
-      else                       bram_t4_wr_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      //
-      //
-      //
-      if ((uop_dst == UOP_DST_RX) && (uop_dst_wren))	rx_addr = uop_dst_addr;
-      else begin
-	 if      (uop_src_a == UOP_SRC_RX) 				rx_addr = uop_src_a_addr;
-	 else if (uop_src_b == UOP_SRC_RX) 				rx_addr = uop_src_b_addr;
-	 else                              				rx_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      end
-      //
-      if ((uop_dst == UOP_DST_RY) && (uop_dst_wren))	ry_addr = uop_dst_addr;
-      else begin
-	 if      (uop_src_a == UOP_SRC_RY) 				ry_addr = uop_src_a_addr;
-	 else if (uop_src_b == UOP_SRC_RY) 				ry_addr = uop_src_b_addr;
-	 else                              				ry_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      end
-      //
-      if ((uop_dst == UOP_DST_RZ) && (uop_dst_wren))	rz_addr = uop_dst_addr;
-      else begin
-	 if      (uop_src_a == UOP_SRC_RZ) 				rz_addr = uop_src_a_addr;
-	 else if (uop_src_b == UOP_SRC_RZ) 				rz_addr = uop_src_b_addr;
-	 else                              				rz_addr = {WORD_COUNTER_WIDTH{1'bX}};
-      end
-      //
-   end
-
-
-   assign rx_wren = uop_dst_wren && (uop_dst == UOP_DST_RX);
-   assign ry_wren = uop_dst_wren && (uop_dst == UOP_DST_RY);
-   assign rz_wren = uop_dst_wren && (uop_dst == UOP_DST_RZ);
-
-   assign bram_t1_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T1);
-   assign bram_t2_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T2);
-   assign bram_t3_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T3);
-   assign bram_t4_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T4);
-
-
-
-   //
-   // Destination Value Selector
-   //
-   reg	[31: 0]	uop_dst_value;
-
-   always @(*)
-			  //
-     case (uop_opcode)
-
-       OPCODE_MOV:	uop_dst_value = mw_mov_dout_y;
-       OPCODE_ADD:	uop_dst_value = mod_add_dout_s;
-       OPCODE_SUB:	uop_dst_value = mod_sub_dout_d;
-       OPCODE_MUL:	uop_dst_value = mod_mul_dout_p;
-
-       default:		uop_dst_value = {32{1'bX}};
-
-     endcase
-
-   assign rx_dout = uop_dst_value;
-   assign ry_dout = uop_dst_value;
-   assign rz_dout = uop_dst_value;
-
-   assign bram_t1_wr_data = uop_dst_value;
-   assign bram_t2_wr_data = uop_dst_value;
-   assign bram_t3_wr_data = uop_dst_value;
-   assign bram_t4_wr_data = uop_dst_value;
-
-
-        //
-        // Latch Comparison Flags
-        //
-    always @(posedge clk)
-    //
-        if (	(fsm_state  == FSM_STATE_EXECUTE) &&
-                (uop_opcode == OPCODE_CMP)        &&
-                (uop_done && !uop_trig_cmp) ) begin
-
-        if ( (uop_src_a == UOP_SRC_PZ) && (uop_src_b == UOP_SRC_ZERO) )
-            flag_pz_is_zero <= !mw_cmp_out_l && mw_cmp_out_e && !mw_cmp_out_g;
-
-        if ( (uop_src_a == UOP_SRC_T1) && (uop_src_b == UOP_SRC_ZERO) )
-            flag_t1_is_zero <= !mw_cmp_out_l && mw_cmp_out_e && !mw_cmp_out_g;
-
-        if ( (uop_src_a == UOP_SRC_T2) && (uop_src_b == UOP_SRC_ZERO) )
-            flag_t2_is_zero <= !mw_cmp_out_l && mw_cmp_out_e && !mw_cmp_out_g;
-
-    end
-
-
-    //
-    // Ready Flag Logic
-    //
-    reg rdy_reg = 1'b1;
-    assign rdy = rdy_reg;
-
-    always @(posedge clk or negedge rst_n)
-        //
-        if (rst_n == 1'b0) rdy_reg <= 1'b1;
-        else begin
-
-            /* clear flag */
-            if (fsm_state == FSM_STATE_STALL)
-                if (ena) rdy_reg <= 1'b0;
-
-            /* set flag */
-            if ((fsm_state == FSM_STATE_EXECUTE) && !uop_trig_fsm && uop_done)
-                if (uop_opcode == OPCODE_RDY) rdy_reg <= 1'b1;
-
-        end
-
-
-endmodule
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/rtl/curve/curve_mul_256.v b/rtl/curve/curve_mul_256.v
deleted file mode 100644
index 43e2c7b..0000000
--- a/rtl/curve/curve_mul_256.v
+++ /dev/null
@@ -1,719 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// curve_mul_256.v
-// -----------------------------------------------------------------------------
-// Elliptic curve point scalar multiplier.
-//
-// 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 curve_mul_256
-  (
-   clk, rst_n,
-   ena, rdy,
-   k_addr, rx_addr, ry_addr,
-   rx_wren, ry_wren,
-   k_din,
-   rx_dout, ry_dout
-   );
-
-
-   //
-   // Constants
-   //
-   localparam	WORD_COUNTER_WIDTH	= 3;	// 0 .. 7
-   localparam	OPERAND_NUM_WORDS	= 8;	// 8 * 32 = 256
-
-
-   //
-   // 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 [ 2: 0] 	k_addr;
-   output	wire [ 2: 0] 	rx_addr;
-   output	wire [ 2: 0] 	ry_addr;
-
-   output	wire 		rx_wren;
-   output	wire 		ry_wren;
-
-   input	wire [31: 0]	k_din;
-
-   output	wire [31: 0]	rx_dout;
-   output	wire [31: 0]	ry_dout;
-
-
-   //
-   // Temporary Variables
-   //
-   reg [ 2: 0] 			     bram_tx_wr_addr;
-   reg [ 2: 0] 			     bram_ty_wr_addr;
-   reg [ 2: 0] 			     bram_tz_wr_addr;
-
-   reg [ 2: 0] 			     bram_rx_wr_addr;
-   reg [ 2: 0] 			     bram_ry_wr_addr;
-   reg [ 2: 0] 			     bram_rz_wr_addr;
-   wire [ 2: 0] 		     bram_rz1_wr_addr;
-
-   reg [ 2: 0] 			     bram_tx_rd_addr;
-   reg [ 2: 0] 			     bram_ty_rd_addr;
-   reg [ 2: 0] 			     bram_tz_rd_addr;
-
-   reg [ 2: 0] 			     bram_rx_rd_addr;
-   reg [ 2: 0] 			     bram_ry_rd_addr;
-   reg [ 2: 0] 			     bram_rz_rd_addr;
-   wire [ 2: 0] 		     bram_rz1_rd_addr;
-
-   reg 				     bram_tx_wr_en;
-   reg 				     bram_ty_wr_en;
-   reg 				     bram_tz_wr_en;
-
-   reg 				     bram_rx_wr_en;
-   reg 				     bram_ry_wr_en;
-   reg 				     bram_rz_wr_en;
-   wire 			     bram_rz1_wr_en;
-
-   wire [31: 0] 		     bram_tx_rd_data;
-   wire [31: 0] 		     bram_ty_rd_data;
-   wire [31: 0] 		     bram_tz_rd_data;
-
-   wire [31: 0] 		     bram_rx_rd_data;
-   wire [31: 0] 		     bram_ry_rd_data;
-   wire [31: 0] 		     bram_rz_rd_data;
-   wire [31: 0] 		     bram_rz1_rd_data;
-
-   reg [31: 0] 			     bram_tx_wr_data_in;
-   reg [31: 0] 			     bram_ty_wr_data_in;
-   reg [31: 0] 			     bram_tz_wr_data_in;
-
-   reg [31: 0] 			     bram_rx_wr_data_in;
-   reg [31: 0] 			     bram_ry_wr_data_in;
-   reg [31: 0] 			     bram_rz_wr_data_in;
-   wire [31: 0] 		     bram_rz1_wr_data_in;
-
-   wire [31: 0] 		     bram_tx_wr_data_out;
-   wire [31: 0] 		     bram_ty_wr_data_out;
-   wire [31: 0] 		     bram_tz_wr_data_out;
-
-   wire [31: 0] 		     bram_rx_wr_data_out;
-   wire [31: 0] 		     bram_ry_wr_data_out;
-   wire [31: 0] 		     bram_rz_wr_data_out;
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_tx (.clk(clk),
-	    .a_addr(bram_tx_wr_addr), .a_wr(bram_tx_wr_en), .a_in(bram_tx_wr_data_in), .a_out(bram_tx_wr_data_out),
-	    .b_addr(bram_tx_rd_addr),                                                  .b_out(bram_tx_rd_data));
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_ty (.clk(clk),
-	    .a_addr(bram_ty_wr_addr), .a_wr(bram_ty_wr_en), .a_in(bram_ty_wr_data_in), .a_out(bram_ty_wr_data_out),
-	    .b_addr(bram_ty_rd_addr),                                                  .b_out(bram_ty_rd_data));
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_tz (.clk(clk),
-	    .a_addr(bram_tz_wr_addr), .a_wr(bram_tz_wr_en), .a_in(bram_tz_wr_data_in), .a_out(bram_tz_wr_data_out),
-	    .b_addr(bram_tz_rd_addr),                                                  .b_out(bram_tz_rd_data));
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_rx (.clk(clk),
-	    .a_addr(bram_rx_wr_addr), .a_wr(bram_rx_wr_en), .a_in(bram_rx_wr_data_in), .a_out(bram_rx_wr_data_out),
-	    .b_addr(bram_rx_rd_addr),                                                  .b_out(bram_rx_rd_data));
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_ry (.clk(clk),
-	    .a_addr(bram_ry_wr_addr), .a_wr(bram_ry_wr_en), .a_in(bram_ry_wr_data_in), .a_out(bram_ry_wr_data_out),
-	    .b_addr(bram_ry_rd_addr),                                                  .b_out(bram_ry_rd_data));
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_rz (.clk(clk),
-	    .a_addr(bram_rz_wr_addr), .a_wr(bram_rz_wr_en), .a_in(bram_rz_wr_data_in), .a_out(bram_rz_wr_data_out),
-	    .b_addr(bram_rz_rd_addr),                                                  .b_out(bram_rz_rd_data));
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
-   bram_rz1 (.clk(clk),
-	     .a_addr(bram_rz1_wr_addr), .a_wr(bram_rz1_wr_en), .a_in(bram_rz1_wr_data_in), .a_out(),
-	     .b_addr(bram_rz1_rd_addr),                                                    .b_out(bram_rz1_rd_data));
-
-
-   //
-   // FSM
-   //
-   localparam	[ 3: 0]	FSM_STATE_IDLE				= 4'd00;
-   localparam	[ 3: 0]	FSM_STATE_PREPARE_TRIG	= 4'd01;
-   localparam	[ 3: 0]	FSM_STATE_PREPARE_WAIT	= 4'd02;
-   localparam	[ 3: 0]	FSM_STATE_DOUBLE_TRIG	= 4'd03;
-   localparam	[ 3: 0]	FSM_STATE_DOUBLE_WAIT	= 4'd04;
-   localparam	[ 3: 0]	FSM_STATE_ADD_TRIG		= 4'd05;
-   localparam	[ 3: 0]	FSM_STATE_ADD_WAIT		= 4'd06;
-   localparam	[ 3: 0]	FSM_STATE_COPY_TRIG		= 4'd07;
-   localparam	[ 3: 0]	FSM_STATE_COPY_WAIT		= 4'd08;
-   localparam	[ 3: 0]	FSM_STATE_INVERT_TRIG	= 4'd09;
-   localparam	[ 3: 0]	FSM_STATE_INVERT_WAIT	= 4'd10;
-   localparam	[ 3: 0]	FSM_STATE_CONVERT_TRIG	= 4'd11;
-   localparam	[ 3: 0]	FSM_STATE_CONVERT_WAIT	= 4'd12;
-   localparam	[ 3: 0]	FSM_STATE_DONE				= 4'd13;
-
-   reg [3:0] 			     fsm_state = FSM_STATE_IDLE;
-
-
-   //
-   // Round Counter
-   //
-   reg [ 7: 0] 			     bit_counter;
-   wire [ 7: 0] 		     bit_counter_max = 8'd255;
-   wire [ 7: 0] 		     bit_counter_zero = 8'd0;
-   wire [ 7: 0] 		     bit_counter_next =
-				     (bit_counter < bit_counter_max) ? bit_counter + 1'b1 : bit_counter_zero;
-
-
-   //
-   // Round Completion
-   //
-   wire [ 3: 0] 		     fsm_state_round_next = (bit_counter < bit_counter_max) ?
-				     FSM_STATE_DOUBLE_TRIG : FSM_STATE_INVERT_TRIG;
-
-
-   //
-   // OP Trigger Logic
-   //
-   reg 				     op_trig;
-   wire 			     op_done;
-
-   always @(posedge clk or negedge rst_n)
-     //
-     if (rst_n == 1'b0)	op_trig <= 1'b0;
-     else						op_trig <=	(fsm_state == FSM_STATE_PREPARE_TRIG) ||
-								  (fsm_state == FSM_STATE_DOUBLE_TRIG) ||
-								  (fsm_state == FSM_STATE_ADD_TRIG) ||
-								  (fsm_state == FSM_STATE_CONVERT_TRIG);
-
-   //
-   // Microprograms
-   //
-   wire [ 5: 0] 		     op_rom_addr;
-   wire [19: 0] 		     op_rom_init_data;
-   wire [19: 0] 		     op_rom_dbl_data;
-   wire [19: 0] 		     op_rom_add_data;
-   wire [19: 0] 		     op_rom_conv_data;
-   reg [19: 0] 			     op_rom_mux_data;
-
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *)
-   uop_init_rom op_rom_init
-     (
-      .clk	(clk),
-      .addr	(op_rom_addr),
-      .data	(op_rom_init_data)
-      );
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *)
-   uop_dbl_rom op_rom_dbl
-     (
-      .clk	(clk),
-      .addr	(op_rom_addr),
-      .data	(op_rom_dbl_data)
-      );
-      
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *)
-   uop_add_rom op_rom_add
-     (
-      .clk	(clk),
-      .addr	(op_rom_addr),
-      .data	(op_rom_add_data)
-      );
-
-   (* EQUIVALENT_REGISTER_REMOVAL="NO" *)
-   uop_conv_rom op_rom_conv
-     (
-      .clk	(clk),
-      .addr	(op_rom_addr),
-      .data	(op_rom_conv_data)
-      );
-
-   always @(*)
-   //
-   case (fsm_state)
-     FSM_STATE_PREPARE_WAIT:	op_rom_mux_data = op_rom_init_data;
-     FSM_STATE_DOUBLE_WAIT:	op_rom_mux_data = op_rom_dbl_data;
-     FSM_STATE_ADD_WAIT:	op_rom_mux_data = op_rom_add_data;
-     FSM_STATE_CONVERT_WAIT:	op_rom_mux_data = op_rom_conv_data;
-     default:			op_rom_mux_data = {20{1'bX}};
-   endcase
-
-
-
-   //
-   // Modulus
-   //
-   reg [ 2: 0] 			     rom_q_addr;
-   wire [31: 0] 		     rom_q_data;
-
-   brom_p256_q rom_q
-     (
-      .clk	(clk),
-      .b_addr	(rom_q_addr),
-      .b_out	(rom_q_data)
-      );
-
-
-   //
-   // Worker
-   //
-   wire [ 2: 0] 		     worker_addr_px;
-   wire [ 2: 0] 		     worker_addr_py;
-   wire [ 2: 0] 		     worker_addr_pz;
-
-   wire [ 2: 0] 		     worker_addr_rx;
-   wire [ 2: 0] 		     worker_addr_ry;
-   wire [ 2: 0] 		     worker_addr_rz;
-
-   wire [ 2: 0] 		     worker_addr_q;
-
-   wire 			     worker_wren_rx;
-   wire 			     worker_wren_ry;
-   wire 			     worker_wren_rz;
-
-   reg [31: 0] 			     worker_din_px;
-   reg [31: 0] 			     worker_din_py;
-   reg [31: 0] 			     worker_din_pz;
-
-   reg [31: 0] 			     worker_din_rx;
-   reg [31: 0] 			     worker_din_ry;
-   reg [31: 0] 			     worker_din_rz;
-
-   wire [31: 0] 		     worker_dout_rx;
-   wire [31: 0] 		     worker_dout_ry;
-   wire [31: 0] 		     worker_dout_rz;
-
-   curve_dbl_add_256 worker
-     (
-      .clk		(clk),
-      .rst_n		(rst_n),
-
-      .ena		(op_trig),
-      .rdy		(op_done),
-
-      .uop_addr		(op_rom_addr),
-      .uop		(op_rom_mux_data),
-
-      .px_addr		(worker_addr_px),
-      .py_addr		(worker_addr_py),
-      .pz_addr		(worker_addr_pz),
-
-      .rx_addr		(worker_addr_rx),
-      .ry_addr		(worker_addr_ry),
-      .rz_addr		(worker_addr_rz),
-
-      .q_addr		(worker_addr_q),
-
-      .v_addr		(bram_rz1_rd_addr),
-
-      .rx_wren		(worker_wren_rx),
-      .ry_wren		(worker_wren_ry),
-      .rz_wren		(worker_wren_rz),
-
-      .px_din		(worker_din_px),
-      .py_din		(worker_din_py),
-      .pz_din		(worker_din_pz),
-
-      .rx_din		(worker_din_rx),
-      .ry_din		(worker_din_ry),
-      .rz_din		(worker_din_rz),
-
-      .rx_dout		(worker_dout_rx),
-      .ry_dout		(worker_dout_ry),
-      .rz_dout		(worker_dout_rz),
-
-      .q_din		(rom_q_data),
-
-      .v_din		(bram_rz1_rd_data)
-      );
-
-
-   //
-   // Mover
-   //
-   reg 				     move_trig;
-   wire 			     move_done;
-
-   wire [ 2: 0] 		     mover_addr_x;
-   wire [ 2: 0] 		     mover_addr_y;
-
-   wire 			     mover_wren_y;
-
-   always @(posedge clk or negedge rst_n)
-     //
-     if (rst_n == 1'b0)	move_trig <= 1'b0;
-     else						move_trig <= (fsm_state == FSM_STATE_COPY_TRIG);
-
-   mw_mover #
-     (
-      .WORD_COUNTER_WIDTH	(3),
-      .OPERAND_NUM_WORDS	(8)
-      )
-   mover
-     (
-      .clk		(clk),
-      .rst_n	(rst_n),
-
-      .ena		(move_trig),
-      .rdy		(move_done),
-
-      .x_addr	(mover_addr_x),
-      .y_addr	(mover_addr_y),
-      .y_wren	(mover_wren_y),
-
-      .x_din	({32{1'bX}}),
-      .y_dout	()
-      );
-
-
-   //
-   // Invertor
-   //
-   reg 				     invert_trig;
-   wire 			     invert_done;
-
-   wire [ 2: 0] 		     invertor_addr_a;
-   wire [ 2: 0] 		     invertor_addr_q;
-
-   always @(posedge clk or negedge rst_n)
-     //
-     if (rst_n == 1'b0)	invert_trig <= 1'b0;
-     else						invert_trig <= (fsm_state == FSM_STATE_INVERT_TRIG);
-
-   modular_invertor #
-     (
-      .MAX_OPERAND_WIDTH(256)
-      )
-   invertor
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(invert_trig),
-      .rdy			(invert_done),
-
-      .a_addr		(invertor_addr_a),
-      .q_addr		(invertor_addr_q),
-      .a1_addr		(bram_rz1_wr_addr),
-      .a1_wren		(bram_rz1_wr_en),
-
-      .a_din		(bram_rz_rd_data),
-      .q_din		(rom_q_data),
-      .a1_dout		(bram_rz1_wr_data_in)
-      );
-
-
-   //
-   // FSM Transition Logic
-   //
-   always @(posedge clk or negedge rst_n)
-     //
-     if (rst_n == 1'b0)			fsm_state <= FSM_STATE_IDLE;
-     else case (fsm_state)
-
-	    FSM_STATE_IDLE:		fsm_state <= ena ? FSM_STATE_PREPARE_TRIG : FSM_STATE_IDLE;
-
-	    FSM_STATE_PREPARE_TRIG:	fsm_state <= FSM_STATE_PREPARE_WAIT;
-	    FSM_STATE_PREPARE_WAIT:	fsm_state <= (!op_trig && op_done) ? FSM_STATE_DOUBLE_TRIG : FSM_STATE_PREPARE_WAIT;
-
-	    FSM_STATE_DOUBLE_TRIG:	fsm_state <= FSM_STATE_DOUBLE_WAIT;
-	    FSM_STATE_DOUBLE_WAIT:	fsm_state <= (!op_trig && op_done) ? FSM_STATE_ADD_TRIG : FSM_STATE_DOUBLE_WAIT;
-
-	    FSM_STATE_ADD_TRIG:		fsm_state <= FSM_STATE_ADD_WAIT;
-	    FSM_STATE_ADD_WAIT:		fsm_state <= (!op_trig && op_done) ? FSM_STATE_COPY_TRIG : FSM_STATE_ADD_WAIT;
-
-	    FSM_STATE_COPY_TRIG:	fsm_state <= FSM_STATE_COPY_WAIT;
-	    FSM_STATE_COPY_WAIT:	fsm_state <= (!move_trig && move_done) ? fsm_state_round_next : FSM_STATE_COPY_WAIT;
-
-	    FSM_STATE_INVERT_TRIG:	fsm_state <= FSM_STATE_INVERT_WAIT;
-	    FSM_STATE_INVERT_WAIT:	fsm_state <= (!invert_trig && invert_done) ? FSM_STATE_CONVERT_TRIG : FSM_STATE_INVERT_WAIT;
-
-	    FSM_STATE_CONVERT_TRIG:	fsm_state <= FSM_STATE_CONVERT_WAIT;
-	    FSM_STATE_CONVERT_WAIT:	fsm_state <= (!op_trig && op_done) ? FSM_STATE_DONE : FSM_STATE_CONVERT_WAIT;
-
-	    FSM_STATE_DONE:		fsm_state <= FSM_STATE_IDLE;
-
-	    default:			fsm_state <= FSM_STATE_IDLE;
-
-	  endcase
-
-
-   //
-   // Bit Counter Increment
-   //
-   always @(posedge clk) begin
-      //
-      if ((fsm_state == FSM_STATE_PREPARE_WAIT) && !op_trig && op_done)
-	bit_counter <= bit_counter_zero;
-      //
-      if ((fsm_state == FSM_STATE_COPY_WAIT) && !move_trig && move_done)
-	bit_counter <= bit_counter_next;
-      //
-   end
-
-
-   //
-   // K Latch Logic
-   //
-   reg	[ 2: 0]	k_addr_reg;
-   reg [31: 0] 	k_din_reg;
-
-   assign k_addr = k_addr_reg;
-
-   always @(posedge clk) begin
-      //
-      if (fsm_state == FSM_STATE_DOUBLE_TRIG)
-	k_addr_reg <= 3'd7 - bit_counter[7:5];
-      //
-      if (fsm_state == FSM_STATE_ADD_TRIG)
-	k_din_reg <= (bit_counter[4:0] == 5'd0) ? k_din : {k_din_reg[30:0], 1'bX};
-      //
-   end
-
-
-
-   //
-   // Copy Inhibit Logic
-   //
-   wire	move_inhibit = k_din_reg[31];
-
-   wire	copy_t2r_int = mover_wren_y & ~move_inhibit;
-
-
-   always @(*) begin
-      //
-      // Q
-      //
-      case (fsm_state)
-	FSM_STATE_DOUBLE_WAIT:	rom_q_addr = worker_addr_q;
-	FSM_STATE_ADD_WAIT:		rom_q_addr = worker_addr_q;
-	FSM_STATE_INVERT_WAIT:	rom_q_addr = invertor_addr_q;
-	FSM_STATE_CONVERT_WAIT:	rom_q_addr = worker_addr_q;
-	default:						rom_q_addr = worker_addr_q;
-      endcase
-
-      //
-      // R(X,Y,Z)
-      //
-      case (fsm_state)
-	//
-	FSM_STATE_PREPARE_WAIT: begin
-	   //
-	   bram_rx_rd_addr    <= {3{1'bX}};      bram_ry_rd_addr    <= {3{1'bX}};      bram_rz_rd_addr    <= {3{1'bX}};
-	   bram_rx_wr_addr    <= worker_addr_rx; bram_ry_wr_addr    <= worker_addr_ry; bram_rz_wr_addr    <= worker_addr_rz;
-	   bram_rx_wr_en      <= worker_wren_rx; bram_ry_wr_en      <= worker_wren_ry; bram_rz_wr_en      <= worker_wren_rz;
-	   bram_rx_wr_data_in <= worker_dout_rx; bram_ry_wr_data_in <= worker_dout_ry; bram_rz_wr_data_in <= worker_dout_rz;
-	   //
-	end
-	//
-	FSM_STATE_DOUBLE_WAIT: begin
-	   //
-	   bram_rx_rd_addr    <= worker_addr_px; bram_ry_rd_addr    <= worker_addr_py; bram_rz_rd_addr    <= worker_addr_pz;
-	   bram_rx_wr_addr    <= {3{1'bX}};      bram_ry_wr_addr    <= {3{1'bX}};      bram_rz_wr_addr    <= {3{1'bX}};
-	   bram_rx_wr_en      <= 1'b0;           bram_ry_wr_en      <= 1'b0;           bram_rz_wr_en      <= 1'b0;
-	   bram_rx_wr_data_in <= {32{1'bX}};     bram_ry_wr_data_in <= {32{1'bX}};     bram_rz_wr_data_in <= {32{1'bX}};
-	   //
-	end
-	//
-	FSM_STATE_ADD_WAIT: begin
-	   //
-	   bram_rx_rd_addr    <= {3{1'bX}};      bram_ry_rd_addr    <= {3{1'bX}};      bram_rz_rd_addr    <= {3{1'bX}};
-	   bram_rx_wr_addr    <= worker_addr_rx; bram_ry_wr_addr    <= worker_addr_ry; bram_rz_wr_addr    <= worker_addr_rz;
-	   bram_rx_wr_en      <= worker_wren_rx; bram_ry_wr_en      <= worker_wren_ry; bram_rz_wr_en      <= worker_wren_rz;
-	   bram_rx_wr_data_in <= worker_dout_rx; bram_ry_wr_data_in <= worker_dout_ry; bram_rz_wr_data_in <= worker_dout_rz;
-	   //
-	end
-	//
-	FSM_STATE_COPY_WAIT: begin
-	   //
-	   bram_rx_rd_addr    <= {3{1'bX}};       bram_ry_rd_addr    <= {3{1'bX}};       bram_rz_rd_addr    <= {3{1'bX}};
-	   bram_rx_wr_addr    <= mover_addr_y;    bram_ry_wr_addr    <= mover_addr_y;    bram_rz_wr_addr    <= mover_addr_y;
-	   bram_rx_wr_en      <= copy_t2r_int;    bram_ry_wr_en      <= copy_t2r_int;    bram_rz_wr_en      <= copy_t2r_int;
-	   bram_rx_wr_data_in <= bram_tx_rd_data; bram_ry_wr_data_in <= bram_ty_rd_data; bram_rz_wr_data_in <= bram_tz_rd_data;
-	   //
-	end
-	//
-	FSM_STATE_INVERT_WAIT: begin
-	   //
-	   bram_rx_rd_addr    <= {3{1'bX}};  bram_ry_rd_addr    <= {3{1'bX}};  bram_rz_rd_addr    <= invertor_addr_a;
-	   bram_rx_wr_addr    <= {3{1'bX}};  bram_ry_wr_addr    <= {3{1'bX}};  bram_rz_wr_addr    <= {3{1'bX}};
-	   bram_rx_wr_en      <= 1'b0;       bram_ry_wr_en      <= 1'b0;       bram_rz_wr_en      <= 1'b0;
-	   bram_rx_wr_data_in <= {32{1'bX}}; bram_ry_wr_data_in <= {32{1'bX}}; bram_rz_wr_data_in <= {32{1'bX}};
-	   //
-	end
-	//
-	FSM_STATE_CONVERT_WAIT: begin
-	   //
-	   bram_rx_rd_addr    <= worker_addr_px; bram_ry_rd_addr    <= worker_addr_py; bram_rz_rd_addr    <= worker_addr_pz;
-	   bram_rx_wr_addr    <= {3{1'bX}};      bram_ry_wr_addr    <= {3{1'bX}};      bram_rz_wr_addr    <= {3{1'bX}};
-	   bram_rx_wr_en      <= 1'b0;           bram_ry_wr_en      <= 1'b0;           bram_rz_wr_en      <= 1'b0;
-	   bram_rx_wr_data_in <= {32{1'bX}};     bram_ry_wr_data_in <= {32{1'bX}};     bram_rz_wr_data_in <= {32{1'bX}};
-	   //
-	end
-
-	//
-	default: begin
-	   //
-	   bram_rx_rd_addr    <= {3{1'bX}};  bram_ry_rd_addr    <= {3{1'bX}};  bram_rz_rd_addr    <= {3{1'bX}};
-	   bram_rx_wr_addr    <= {3{1'bX}};  bram_ry_wr_addr    <= {3{1'bX}};  bram_rz_wr_addr    <= {3{1'bX}};
-	   bram_rx_wr_en      <= 1'b0;       bram_ry_wr_en      <= 1'b0;       bram_rz_wr_en      <= 1'b0;
-	   bram_rx_wr_data_in <= {32{1'bX}}; bram_ry_wr_data_in <= {32{1'bX}}; bram_rz_wr_data_in <= {32{1'bX}};
-	   //
-	end
-	//
-      endcase
-      //
-      // T(X,Y,Z)
-      //
-      case (fsm_state)
-	//
-	FSM_STATE_DOUBLE_WAIT: begin
-	   //
-	   bram_tx_rd_addr    <= {3{1'bX}};      bram_ty_rd_addr    <= {3{1'bX}};      bram_tz_rd_addr    <= {3{1'bX}};
-	   bram_tx_wr_addr    <= worker_addr_rx; bram_ty_wr_addr    <= worker_addr_ry; bram_tz_wr_addr    <= worker_addr_rz;
-	   bram_tx_wr_en      <= worker_wren_rx; bram_ty_wr_en      <= worker_wren_ry; bram_tz_wr_en      <= worker_wren_rz;
-	   bram_tx_wr_data_in <= worker_dout_rx; bram_ty_wr_data_in <= worker_dout_ry; bram_tz_wr_data_in <= worker_dout_rz;
-	   //
-	end
-	//
-	FSM_STATE_ADD_WAIT: begin
-	   //
-	   bram_tx_rd_addr    <= worker_addr_px; bram_ty_rd_addr    <= worker_addr_py; bram_tz_rd_addr    <= worker_addr_pz;
-	   bram_tx_wr_addr    <= {3{1'bX}};      bram_ty_wr_addr    <= {3{1'bX}};      bram_tz_wr_addr    <= {3{1'bX}};
-	   bram_tx_wr_en      <= 1'b0;           bram_ty_wr_en      <= 1'b0;           bram_tz_wr_en      <= 1'b0;
-	   bram_tx_wr_data_in <= {32{1'bX}};     bram_ty_wr_data_in <= {32{1'bX}};     bram_tz_wr_data_in <= {32{1'bX}};
-	   //
-	end
-	//
-	FSM_STATE_COPY_WAIT: begin
-	   //
-	   bram_tx_rd_addr    <= mover_addr_x; bram_ty_rd_addr    <= mover_addr_x; bram_tz_rd_addr    <= mover_addr_x;
-	   bram_tx_wr_addr    <= {3{1'bX}};    bram_ty_wr_addr    <= {3{1'bX}};    bram_tz_wr_addr    <= {3{1'bX}};
-	   bram_tx_wr_en      <= 1'b0;         bram_ty_wr_en      <= 1'b0;         bram_tz_wr_en      <= 1'b0;
-	   bram_tx_wr_data_in <= {32{1'bX}};   bram_ty_wr_data_in <= {32{1'bX}};   bram_tz_wr_data_in <= {32{1'bX}};
-	   //
-	end
-
-	//
-	default: begin
-	   //
-	   bram_tx_rd_addr    <= {3{1'bX}};  bram_ty_rd_addr    <= {3{1'bX}};  bram_tz_rd_addr    <= {3{1'bX}};
-	   bram_tx_wr_addr    <= {3{1'bX}};  bram_ty_wr_addr    <= {3{1'bX}};  bram_tz_wr_addr    <= {3{1'bX}};
-	   bram_tx_wr_en      <= 1'b0;       bram_ty_wr_en      <= 1'b0;       bram_tz_wr_en      <= 1'b0;
-	   bram_tx_wr_data_in <= {32{1'bX}}; bram_ty_wr_data_in <= {32{1'bX}}; bram_tz_wr_data_in <= {32{1'bX}};
-	   //
-	end
-	//
-      endcase
-      //
-      // Worker
-      //
-      case (fsm_state)
-	//
-	FSM_STATE_DOUBLE_WAIT: begin
-	   //
-	   worker_din_px <= bram_rx_rd_data;     worker_din_py <= bram_ry_rd_data;     worker_din_pz <= bram_rz_rd_data;
-	   worker_din_rx <= bram_tx_wr_data_out; worker_din_ry <= bram_ty_wr_data_out; worker_din_rz <= bram_tz_wr_data_out;
-	   //
-	end
-	//
-	FSM_STATE_ADD_WAIT: begin
-	   //
-	   worker_din_px <= bram_tx_rd_data;     worker_din_py <= bram_ty_rd_data;     worker_din_pz <= bram_tz_rd_data;
-	   worker_din_rx <= bram_rx_wr_data_out; worker_din_ry <= bram_ry_wr_data_out; worker_din_rz <= bram_rz_wr_data_out;
-	   //
-	end
-	//
-	FSM_STATE_CONVERT_WAIT: begin
-	   //
-	   worker_din_px <= bram_rx_rd_data; worker_din_py <= bram_ry_rd_data; worker_din_pz <= bram_rz_rd_data;
-	   worker_din_rx <= {32{1'bX}};      worker_din_ry <= {32{1'bX}};      worker_din_rz <= {32{1'bX}};
-	   //
-	end
-	//
-	default: begin
-	   //
-	   worker_din_px <= {32{1'bX}}; worker_din_py <= {32{1'bX}}; worker_din_pz <= {32{1'bX}};
-	   worker_din_rx <= {32{1'bX}}; worker_din_ry <= {32{1'bX}}; worker_din_rz <= {32{1'bX}};
-	   //
-	end
-	//
-      endcase
-      //
-   end
-
-
-   //
-   // Output Mapping
-   //
-   assign	rx_wren = worker_wren_rx && (fsm_state == FSM_STATE_CONVERT_WAIT);
-   assign	ry_wren = worker_wren_ry && (fsm_state == FSM_STATE_CONVERT_WAIT);
-
-   assign	rx_dout = worker_dout_rx;
-   assign	ry_dout = worker_dout_ry;
-
-   assign	rx_addr = worker_addr_rx;
-   assign	ry_addr = worker_addr_ry;
-
-
-   //
-   // Ready Flag Logic
-   //
-   reg rdy_reg = 1'b1;
-   assign rdy = rdy_reg;
-
-   always @(posedge clk or negedge rst_n)
-
-     if (rst_n == 1'b0) rdy_reg <= 1'b1;
-     else begin
-
-	/* clear flag */
-	if ((fsm_state == FSM_STATE_IDLE) && ena)
-	  rdy_reg <= 1'b0;
-
-	/* set flag */
-	if (fsm_state == FSM_STATE_DONE)
-	  rdy_reg <= 1'b1;
-
-     end
-
-
-endmodule
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/rtl/curve/rom/brom_p256_delta.v b/rtl/curve/rom/brom_p256_delta.v
deleted file mode 100644
index 4637575..0000000
--- a/rtl/curve/rom/brom_p256_delta.v
+++ /dev/null
@@ -1,68 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_delta
-  (
-   input wire 		clk,
-   input wire [ 3-1:0] 	b_addr,
-   output wire [32-1:0] b_out
-   );
-
-
-   //
-   // Output Registers
-   //
-   reg [31:0] 		bram_reg_b;
-
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-   //
-   always @(posedge clk)
-     //
-     case (b_addr)
-       3'b000:	bram_reg_b <= 32'h00000000;
-       3'b001:	bram_reg_b <= 32'h00000000;
-       3'b010:	bram_reg_b <= 32'h80000000;
-       3'b011:	bram_reg_b <= 32'h00000000;
-       3'b100:	bram_reg_b <= 32'h00000000;
-       3'b101:	bram_reg_b <= 32'h80000000;
-       3'b110:	bram_reg_b <= 32'h80000000;
-       3'b111:	bram_reg_b <= 32'h7fffffff;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p256_g_x.v b/rtl/curve/rom/brom_p256_g_x.v
deleted file mode 100644
index 86aeafd..0000000
--- a/rtl/curve/rom/brom_p256_g_x.v
+++ /dev/null
@@ -1,68 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_g_x
-  (
-   input wire 		clk,
-   input wire [ 3-1:0] 	b_addr,
-   output wire [32-1:0] b_out
-   );
-
-
-   //
-   // Output Registers
-   //
-   reg [31:0] 		bram_reg_b;
-
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-   //
-   always @(posedge clk)
-     //
-     case (b_addr)
-       3'b000:	bram_reg_b <= 32'hd898c296;
-       3'b001:	bram_reg_b <= 32'hf4a13945;
-       3'b010:	bram_reg_b <= 32'h2deb33a0;
-       3'b011:	bram_reg_b <= 32'h77037d81;
-       3'b100:	bram_reg_b <= 32'h63a440f2;
-       3'b101:	bram_reg_b <= 32'hf8bce6e5;
-       3'b110:	bram_reg_b <= 32'he12c4247;
-       3'b111:	bram_reg_b <= 32'h6b17d1f2;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p256_g_y.v b/rtl/curve/rom/brom_p256_g_y.v
deleted file mode 100644
index 39f9116..0000000
--- a/rtl/curve/rom/brom_p256_g_y.v
+++ /dev/null
@@ -1,68 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_g_y
-  (
-   input wire 		clk,
-   input wire [ 3-1:0] 	b_addr,
-   output wire [32-1:0] b_out
-   );
-
-
-   //
-   // Output Registers
-   //
-   reg [31:0] 		bram_reg_b;
-
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-   //
-   always @(posedge clk)
-     //
-     case (b_addr)
-       3'b000:	bram_reg_b <= 32'h37bf51f5;
-       3'b001:	bram_reg_b <= 32'hcbb64068;
-       3'b010:	bram_reg_b <= 32'h6b315ece;
-       3'b011:	bram_reg_b <= 32'h2bce3357;
-       3'b100:	bram_reg_b <= 32'h7c0f9e16;
-       3'b101:	bram_reg_b <= 32'h8ee7eb4a;
-       3'b110:	bram_reg_b <= 32'hfe1a7f9b;
-       3'b111:	bram_reg_b <= 32'h4fe342e2;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p256_h_x.v b/rtl/curve/rom/brom_p256_h_x.v
deleted file mode 100644
index f426475..0000000
--- a/rtl/curve/rom/brom_p256_h_x.v
+++ /dev/null
@@ -1,68 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_h_x
-   (
-		input		wire				clk,
-		input		wire	[ 3-1:0]	b_addr,
-		output	wire	[32-1:0]	b_out
-    );
-
-
-   //
-   // Output Registers
-   //
-   reg [31:0] bram_reg_b;
-
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-	//
-	always @(posedge clk)
-		//
-		case (b_addr)
-			3'b000:	bram_reg_b <= 32'h47669978;
-			3'b001:	bram_reg_b <= 32'ha60b48fc;
-			3'b010:	bram_reg_b <= 32'h77f21b35;
-			3'b011:	bram_reg_b <= 32'hc08969e2;
-			3'b100:	bram_reg_b <= 32'h04b51ac3;
-			3'b101:	bram_reg_b <= 32'h8a523803;
-			3'b110:	bram_reg_b <= 32'h8d034f7e;
-			3'b111:	bram_reg_b <= 32'h7cf27b18;
-		endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p256_h_y.v b/rtl/curve/rom/brom_p256_h_y.v
deleted file mode 100644
index c75d0da..0000000
--- a/rtl/curve/rom/brom_p256_h_y.v
+++ /dev/null
@@ -1,68 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_h_y
-   (
-		input		wire				clk,
-		input		wire	[ 3-1:0]	b_addr,
-		output	wire	[32-1:0]	b_out
-    );
-
-
-   //
-   // Output Registers
-   //
-   reg [31:0] bram_reg_b;
-
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-	//
-	always @(posedge clk)
-		//
-		case (b_addr)
-			3'b000:	bram_reg_b <= 32'h227873d1;
-			3'b001:	bram_reg_b <= 32'h9e04b79d;
-			3'b010:	bram_reg_b <= 32'h3ce98229;
-			3'b011:	bram_reg_b <= 32'hba7dade6;
-			3'b100:	bram_reg_b <= 32'h9f7430db;
-			3'b101:	bram_reg_b <= 32'h293d9ac6;
-			3'b110:	bram_reg_b <= 32'hdb8ed040;
-			3'b111:	bram_reg_b <= 32'h07775510;
-		endcase
-		
-
-endmodule
diff --git a/rtl/curve/rom/brom_p256_one.v b/rtl/curve/rom/brom_p256_one.v
deleted file mode 100644
index 15e3746..0000000
--- a/rtl/curve/rom/brom_p256_one.v
+++ /dev/null
@@ -1,68 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_one
-  (
-   input wire 		clk,
-   input wire [ 3-1:0] 	b_addr,
-   output wire [32-1:0] b_out
-   );
-
-
-   //
-   // Output Registers
-   //
-   reg [31:0] 		bram_reg_b;
-
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-   //
-   always @(posedge clk)
-     //
-     case (b_addr)
-       3'b000:	bram_reg_b <= 32'h00000001;
-       3'b001:	bram_reg_b <= 32'h00000000;
-       3'b010:	bram_reg_b <= 32'h00000000;
-       3'b011:	bram_reg_b <= 32'h00000000;
-       3'b100:	bram_reg_b <= 32'h00000000;
-       3'b101:	bram_reg_b <= 32'h00000000;
-       3'b110:	bram_reg_b <= 32'h00000000;
-       3'b111:	bram_reg_b <= 32'h00000000;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p256_q.v b/rtl/curve/rom/brom_p256_q.v
deleted file mode 100644
index 101a524..0000000
--- a/rtl/curve/rom/brom_p256_q.v
+++ /dev/null
@@ -1,68 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_q
-  (
-   input wire 		clk,
-   input wire [ 3-1:0] 	b_addr,
-   output wire [32-1:0] b_out
-   );
-
-
-   //
-   // Output Registers
-   //
-   reg [31:0] 		bram_reg_b;
-
-   assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-   //
-   always @(posedge clk)
-     //
-     case (b_addr)
-       3'b000:	bram_reg_b <= 32'hffffffff;
-       3'b001:	bram_reg_b <= 32'hffffffff;
-       3'b010:	bram_reg_b <= 32'hffffffff;
-       3'b011:	bram_reg_b <= 32'h00000000;
-       3'b100:	bram_reg_b <= 32'h00000000;
-       3'b101:	bram_reg_b <= 32'h00000000;
-       3'b110:	bram_reg_b <= 32'h00000001;
-       3'b111:	bram_reg_b <= 32'hffffffff;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p256_zero.v b/rtl/curve/rom/brom_p256_zero.v
deleted file mode 100644
index 2672cf2..0000000
--- a/rtl/curve/rom/brom_p256_zero.v
+++ /dev/null
@@ -1,70 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 brom_p256_zero
-  (
-   //input		wire			clk,
-   //input		wire	[ 3-1:0]	b_addr,
-   output wire [32-1:0] b_out
-   );
-
-
-   assign b_out = {32{1'b0}};
-
-   //
-   // Output Registers
-   //
-   //reg [31:0] bram_reg_b;
-
-   //assign b_out = bram_reg_b;
-
-
-   //
-   // Read-Only Port B
-   //
-   //always @(posedge clk)
-   //
-   //case (b_addr)
-   //3'b000:	bram_reg_b <= 32'h00000000;
-   //3'b001:	bram_reg_b <= 32'h00000000;
-   //3'b010:	bram_reg_b <= 32'h00000000;
-   //3'b011:	bram_reg_b <= 32'h00000000;
-   //3'b100:	bram_reg_b <= 32'h00000000;
-   //3'b101:	bram_reg_b <= 32'h00000000;
-   //3'b110:	bram_reg_b <= 32'h00000000;
-   //3'b111:	bram_reg_b <= 32'h00000000;
-   //endcase
-
-
-endmodule
diff --git a/rtl/ecdsa256.v b/rtl/ecdsa256.v
deleted file mode 100644
index 11276a2..0000000
--- a/rtl/ecdsa256.v
+++ /dev/null
@@ -1,160 +0,0 @@
-//======================================================================
-//
-// Copyright (c) 2016, 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 ecdsa256
-  (
-   input wire 	      clk,
-   input wire 	      rst_n,
-
-   input wire 	      next,
-   output wire 	      valid,
-
-   input wire 	      bus_cs,
-   input wire 	      bus_we,
-   input wire [ 4:0]  bus_addr,
-   input wire [31:0]  bus_data_wr,
-   output wire [31:0] bus_data_rd
-   );
-
-
-   //
-   // Memory Banks
-   //
-   localparam [1:0] BUS_ADDR_BANK_K = 2'b00;
-   localparam [1:0] BUS_ADDR_BANK_X = 2'b01;
-   localparam [1:0] BUS_ADDR_BANK_Y = 2'b10;
-
-   wire [1:0] 	      bus_addr_upper = bus_addr[4:3];
-   wire [2:0] 	      bus_addr_lower = bus_addr[2:0];
-
-
-   //
-   // Memories
-   //
-
-   wire [31:0] 	      user_rw_k_bram_out;
-   wire [31:0] 	      user_ro_x_bram_out;
-   wire [31:0] 	      user_ro_y_bram_out;
-
-   wire [ 2:0] 	      core_ro_k_bram_addr;
-   wire [ 2:0] 	      core_rw_x_bram_addr;
-   wire [ 2:0] 	      core_rw_y_bram_addr;
-
-   wire 	      core_rw_x_bram_wren;
-   wire 	      core_rw_y_bram_wren;
-
-   wire [31:0] 	      core_ro_k_bram_dout;
-   wire [31:0] 	      core_rw_x_bram_din;
-   wire [31:0] 	      core_rw_y_bram_din;
-
-
-   bram_1rw_1ro_readfirst #
-     (	.MEM_WIDTH(32), .MEM_ADDR_BITS(3)
-	)
-   bram_k
-     (	.clk(clk),
-	.a_addr(bus_addr_lower), .a_out(user_rw_k_bram_out), .a_wr(bus_cs && bus_we && (bus_addr_upper == BUS_ADDR_BANK_K)), .a_in(bus_data_wr),
-	.b_addr(core_ro_k_bram_addr), .b_out(core_ro_k_bram_dout)
-	);
-
-   bram_1rw_1ro_readfirst #
-     (	.MEM_WIDTH(32), .MEM_ADDR_BITS(3)
-	)
-   bram_x
-     (	.clk(clk),
-	.a_addr(core_rw_x_bram_addr), .a_out(), .a_wr(core_rw_x_bram_wren), .a_in(core_rw_x_bram_din),
-	.b_addr(bus_addr_lower),      .b_out(user_ro_x_bram_out)
-	);
-
-   bram_1rw_1ro_readfirst #
-     (	.MEM_WIDTH(32), .MEM_ADDR_BITS(3)
-	)
-   bram_y
-     (	.clk(clk),
-	.a_addr(core_rw_y_bram_addr), .a_out(), .a_wr(core_rw_y_bram_wren), .a_in(core_rw_y_bram_din),
-	.b_addr(bus_addr_lower),      .b_out(user_ro_y_bram_out)
-	);
-
-
-   //
-   // Curve Base Point Multiplier
-   //
-   reg		next_dly;
-
-   always @(posedge clk) next_dly <= next;
-
-   wire		next_trig = next && !next_dly;
-
-   curve_mul_256 base_point_multiplier_p256
-     (
-      .clk	(clk),
-      .rst_n	(rst_n),
-
-      .ena	(next_trig),
-      .rdy	(valid),
-
-      .k_addr	(core_ro_k_bram_addr),
-      .rx_addr	(core_rw_x_bram_addr),
-      .ry_addr	(core_rw_y_bram_addr),
-
-      .rx_wren	(core_rw_x_bram_wren),
-      .ry_wren	(core_rw_y_bram_wren),
-
-      .k_din	(core_ro_k_bram_dout),
-      .rx_dout	(core_rw_x_bram_din),
-      .ry_dout	(core_rw_y_bram_din)
-      );
-
-   //
-   // Output Selector
-   //
-   reg [1:0] 	      bus_addr_upper_prev;
-   always @(posedge clk) bus_addr_upper_prev = bus_addr_upper;
-
-   reg [31: 0] 	      bus_data_rd_mux;
-   assign bus_data_rd = bus_data_rd_mux;
-
-   always @(*)
-     //
-     case (bus_addr_upper_prev)
-       //
-       BUS_ADDR_BANK_K: bus_data_rd_mux = user_rw_k_bram_out;
-       BUS_ADDR_BANK_X: bus_data_rd_mux = user_ro_x_bram_out;
-       BUS_ADDR_BANK_Y: bus_data_rd_mux = user_ro_y_bram_out;
-       //
-       default:         bus_data_rd_mux = {32{1'b0}};
-       //
-     endcase
-
-endmodule
diff --git a/rtl/ecdsa256_banks_array.v b/rtl/ecdsa256_banks_array.v
new file mode 100644
index 0000000..1172429
--- /dev/null
+++ b/rtl/ecdsa256_banks_array.v
@@ -0,0 +1,119 @@
+//------------------------------------------------------------------------------
+//
+// ecdsa256_banks_array.v
+// -----------------------------------------------------------------------------
+// ECDSA Operand Banks Array
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 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 ecdsa256_banks_array
+(
+    input           clk,
+    
+    input           banks,  // 0: LO -> HI, 1: HI -> LO
+    
+    input   [ 5:0]  src1_operand,
+    input   [ 5:0]  src2_operand,
+    input   [ 5:0]  dst_operand,
+    
+    input   [ 2:0]  src1_addr,
+    input   [ 2:0]  src2_addr,
+    input   [ 2:0]  dst_addr,
+    
+    input           dst_wren,
+    
+    output  [31:0]  src1_dout,
+    output  [31:0]  src2_dout,
+    
+    input   [31:0]  dst_din
+);
+
+
+    //
+    // Banks
+    //
+    wire [31:0] bank_lo1_dout;
+    wire [31:0] bank_lo2_dout;
+    wire [31:0] bank_hi1_dout;
+    wire [31:0] bank_hi2_dout;
+    
+    assign src1_dout = !banks ? bank_lo1_dout : bank_hi1_dout;
+    assign src2_dout = !banks ? bank_lo2_dout : bank_hi2_dout;
+    
+    ecdsa256_operand_bank bank_operand_lo1
+    (
+        .clk     (clk),
+        .a_addr  ({dst_operand, dst_addr}),
+        .a_wr    (dst_wren & banks),
+        .a_in    (dst_din),
+        .b_addr  ({src1_operand, src1_addr}),
+        .b_out   (bank_lo1_dout)
+        );
+    
+    ecdsa256_operand_bank bank_operand_lo2
+    (
+        .clk     (clk),
+        .a_addr  ({dst_operand, dst_addr}),
+        .a_wr    (dst_wren & banks),
+        .a_in    (dst_din),
+        .b_addr  ({src2_operand, src2_addr}),
+        .b_out   (bank_lo2_dout)
+    );
+
+    ecdsa256_operand_bank bank_operand_hi1
+    (
+        .clk     (clk),
+        .a_addr  ({dst_operand, dst_addr}),
+        .a_wr    (dst_wren & ~banks),
+        .a_in    (dst_din),
+        .b_addr  ({src1_operand, src1_addr}),
+        .b_out   (bank_hi1_dout)
+    );
+
+    ecdsa256_operand_bank bank_operand_hi2
+    (
+        .clk     (clk),
+        .a_addr  ({dst_operand, dst_addr}),
+        .a_wr    (dst_wren & ~banks),
+        .a_in    (dst_din),
+        .b_addr  ({src2_operand, src2_addr}),
+        .b_out   (bank_hi2_dout)
+    );
+
+    
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/rtl/ecdsa256_base_point_multiplier.v b/rtl/ecdsa256_base_point_multiplier.v
new file mode 100644
index 0000000..8664d0c
--- /dev/null
+++ b/rtl/ecdsa256_base_point_multiplier.v
@@ -0,0 +1,310 @@
+//------------------------------------------------------------------------------
+//
+// ecdsa256_base_point_multiplier.v
+// -----------------------------------------------------------------------------
+// ECDSA base point scalar multiplier.
+//
+// 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 ecdsa256_base_point_multiplier
+(
+    clk, rst_n,
+    ena, rdy,
+    k_addr, rxy_addr,
+    rx_wren, ry_wren,
+    k_din,
+    rxy_dout
+);
+
+
+    //
+    // Microcode Header
+    //
+`include "ecdsa_uop.vh"
+    
+
+    //
+    // Ports
+    //
+    input           clk;        // system clock
+    input           rst_n;      // active-low async reset
+
+    input           ena;        // enable input
+    output          rdy;        // ready output
+
+    output  [ 2:0]  k_addr;     //
+    output  [ 2:0]  rxy_addr;   //
+    output          rx_wren;    //
+    output          ry_wren;    //
+    input   [31:0]  k_din;      //
+    output  [31:0]  rxy_dout;   //
+
+
+    //
+    // FSM
+    //
+    localparam [4:0] FSM_STATE_IDLE                 = 5'd00;
+    localparam [4:0] FSM_STATE_PREPARE_TRIG         = 5'd01;
+    localparam [4:0] FSM_STATE_PREPARE_WAIT         = 5'd02;
+    localparam [4:0] FSM_STATE_CYCLE_DBL_TRIG       = 5'd03;
+    localparam [4:0] FSM_STATE_CYCLE_DBL_WAIT       = 5'd04;
+    localparam [4:0] FSM_STATE_CYCLE_ADD_TRIG       = 5'd05;
+    localparam [4:0] FSM_STATE_CYCLE_ADD_WAIT       = 5'd06;
+    localparam [4:0] FSM_STATE_CYCLE_ADD_EXTRA_TRIG = 5'd07;
+    localparam [4:0] FSM_STATE_CYCLE_ADD_EXTRA_WAIT = 5'd08;
+    localparam [4:0] FSM_STATE_AFTER_CYCLE_TRIG     = 5'd09;
+    localparam [4:0] FSM_STATE_AFTER_CYCLE_WAIT     = 5'd10;
+    localparam [4:0] FSM_STATE_INVERT_TRIG          = 5'd11;
+    localparam [4:0] FSM_STATE_INVERT_WAIT          = 5'd12;
+    localparam [4:0] FSM_STATE_CONVERT_TRIG         = 5'd13;
+    localparam [4:0] FSM_STATE_CONVERT_WAIT         = 5'd14;
+    localparam [4:0] FSM_STATE_CONVERT_EXTRA_TRIG   = 5'd15;
+    localparam [4:0] FSM_STATE_CONVERT_EXTRA_WAIT   = 5'd16;
+    localparam [4:0] FSM_STATE_DONE                 = 5'd17;
+
+    reg [4:0] fsm_state = FSM_STATE_IDLE;
+    reg [4:0] fsm_state_next;
+
+
+    //
+    // Round Counter
+    //
+    reg  [7:0] bit_counter;
+    wire [7:0] bit_counter_last = 8'hFF;    // 255
+    wire [7:0] bit_counter_zero = 8'h00;    // 0
+    wire [7:0] bit_counter_prev =
+        (bit_counter > bit_counter_zero) ? bit_counter - 1'b1 : bit_counter_last;
+
+    assign k_addr = bit_counter[7:5];
+
+
+    //
+    // Worker Trigger Logic
+    //
+    reg  worker_trig = 1'b0;
+    wire worker_done;
+
+    wire fsm_wait_done = !worker_trig && worker_done;
+
+    always @(posedge clk or negedge rst_n)
+        //
+        if (rst_n == 1'b0)                      worker_trig <= 1'b0;
+        else case (fsm_state)
+            FSM_STATE_PREPARE_TRIG,
+            FSM_STATE_CYCLE_DBL_TRIG,
+            FSM_STATE_CYCLE_ADD_TRIG,
+            FSM_STATE_CYCLE_ADD_EXTRA_TRIG,
+            FSM_STATE_AFTER_CYCLE_TRIG,
+            FSM_STATE_INVERT_TRIG,
+            FSM_STATE_CONVERT_TRIG,
+            FSM_STATE_CONVERT_EXTRA_TRIG:       worker_trig <= 1'b1;
+            default:                            worker_trig <= 1'b0;
+        endcase
+        
+        
+    //
+    // Round Counter Increment Logic
+    //
+    always @(posedge clk)
+        //
+        case (fsm_state_next)
+            FSM_STATE_PREPARE_TRIG:         bit_counter <= bit_counter_last;
+            FSM_STATE_AFTER_CYCLE_TRIG:     bit_counter <= bit_counter_prev;
+        endcase
+
+
+    //
+    // Final Cycle Detection Logic
+    //
+    wire [ 3: 0] fsm_state_after_cycle = (bit_counter == bit_counter_last) ?
+        FSM_STATE_INVERT_TRIG : FSM_STATE_CYCLE_DBL_TRIG;
+        
+
+    //
+    // K Latch
+    //
+    reg [31:0] k_din_shreg;
+    
+    wire [4:0] k_bit_index = bit_counter[4:0];
+    
+    always @(posedge clk)
+        //
+        if (fsm_state_next == FSM_STATE_CYCLE_DBL_TRIG)
+            //
+            if (k_bit_index == 5'd31) k_din_shreg <= k_din;
+            else                      k_din_shreg <= {k_din_shreg[30:0], ~k_din_shreg[31]};
+    
+
+    //
+    // Worker Flags
+    //
+    wire worker_flagz_sz;
+    wire worker_flagz_rz;
+    wire worker_flagz_e;
+    wire worker_flagz_f;
+    
+    wire [2:0] worker_flagz_cycle_add =
+        {worker_flagz_sz, worker_flagz_e,  worker_flagz_f};
+
+    wire worker_flagz_convert_extra =
+        worker_flagz_rz;
+
+    
+    //
+    // Worker Offset Logic
+    //
+    reg [UOP_ADDR_WIDTH-1:0] worker_offset;
+    
+    always @(posedge clk)
+        //
+        case (fsm_state)
+        
+            FSM_STATE_PREPARE_TRIG:         worker_offset <= UOP_OFFSET_PREPARE;
+            
+            FSM_STATE_CYCLE_DBL_TRIG:       worker_offset <= UOP_OFFSET_CYCLE_DOUBLE;
+            FSM_STATE_CYCLE_ADD_TRIG:       worker_offset <= UOP_OFFSET_CYCLE_ADD;
+            
+            FSM_STATE_CYCLE_ADD_EXTRA_TRIG:
+                // {sz, e, f}
+                casez(worker_flagz_cycle_add)
+                    3'b1??:                 worker_offset <= UOP_OFFSET_CYCLE_ADD_AT_INFINITY;
+                    3'b011:                 worker_offset <= UOP_OFFSET_CYCLE_ADD_SAME_X_SAME_Y;
+                    3'b010:                 worker_offset <= UOP_OFFSET_CYCLE_ADD_SAME_X;
+                    3'b00?:                 worker_offset <= UOP_OFFSET_CYCLE_ADD_REGULAR;
+                endcase
+                
+            FSM_STATE_AFTER_CYCLE_TRIG:     worker_offset <= k_din_shreg[31] ?
+                                            UOP_OFFSET_CYCLE_K1 : UOP_OFFSET_CYCLE_K0;
+                                            
+            FSM_STATE_INVERT_TRIG:          worker_offset <= UOP_OFFSET_INVERT;
+            FSM_STATE_CONVERT_TRIG:         worker_offset <= UOP_OFFSET_CONVERT;
+            
+            FSM_STATE_CONVERT_EXTRA_TRIG:   worker_offset <= worker_flagz_convert_extra ?
+                                            UOP_OFFSET_CONVERT_AT_INFINITY : UOP_OFFSET_CONVERT_REGULAR;
+            
+            default:                        worker_offset <= {UOP_ADDR_WIDTH{1'bX}};
+            
+        endcase
+            
+
+    //
+    // FSM Process
+    //
+    always @(posedge clk or negedge rst_n)
+        //
+        if (rst_n == 1'b0)  fsm_state <= FSM_STATE_IDLE;
+        else                fsm_state <= fsm_state_next;
+
+
+    //
+    // FSM Transition Logic
+    //
+    always @* begin
+        //
+        fsm_state_next = FSM_STATE_IDLE;
+        //
+        case (fsm_state)
+
+            FSM_STATE_IDLE:                 fsm_state_next = ena           ? FSM_STATE_PREPARE_TRIG         : FSM_STATE_IDLE;
+            
+            FSM_STATE_PREPARE_TRIG:         fsm_state_next =                 FSM_STATE_PREPARE_WAIT         ;
+            FSM_STATE_PREPARE_WAIT:         fsm_state_next = fsm_wait_done ? FSM_STATE_CYCLE_DBL_TRIG       : FSM_STATE_PREPARE_WAIT;
+            FSM_STATE_CYCLE_DBL_TRIG:       fsm_state_next =                 FSM_STATE_CYCLE_DBL_WAIT       ;
+            FSM_STATE_CYCLE_DBL_WAIT:       fsm_state_next = fsm_wait_done ? FSM_STATE_CYCLE_ADD_TRIG       : FSM_STATE_CYCLE_DBL_WAIT;
+            FSM_STATE_CYCLE_ADD_TRIG:       fsm_state_next =                 FSM_STATE_CYCLE_ADD_WAIT       ;
+            FSM_STATE_CYCLE_ADD_WAIT:       fsm_state_next = fsm_wait_done ? FSM_STATE_CYCLE_ADD_EXTRA_TRIG : FSM_STATE_CYCLE_ADD_WAIT;
+            FSM_STATE_CYCLE_ADD_EXTRA_TRIG: fsm_state_next =                 FSM_STATE_CYCLE_ADD_EXTRA_WAIT ;
+            FSM_STATE_CYCLE_ADD_EXTRA_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_AFTER_CYCLE_TRIG     : FSM_STATE_CYCLE_ADD_EXTRA_WAIT;
+            FSM_STATE_AFTER_CYCLE_TRIG:     fsm_state_next =                 FSM_STATE_AFTER_CYCLE_WAIT     ;
+            FSM_STATE_AFTER_CYCLE_WAIT:     fsm_state_next = fsm_wait_done ? fsm_state_after_cycle          : FSM_STATE_AFTER_CYCLE_WAIT;
+            FSM_STATE_INVERT_TRIG:          fsm_state_next =                 FSM_STATE_INVERT_WAIT          ;
+            FSM_STATE_INVERT_WAIT:          fsm_state_next = fsm_wait_done ? FSM_STATE_CONVERT_TRIG         : FSM_STATE_INVERT_WAIT;
+            FSM_STATE_CONVERT_TRIG:         fsm_state_next =                 FSM_STATE_CONVERT_WAIT         ;
+            FSM_STATE_CONVERT_WAIT:         fsm_state_next = fsm_wait_done ? FSM_STATE_CONVERT_EXTRA_TRIG   : FSM_STATE_CONVERT_WAIT;
+            FSM_STATE_CONVERT_EXTRA_TRIG:   fsm_state_next =                 FSM_STATE_CONVERT_EXTRA_WAIT   ;
+            FSM_STATE_CONVERT_EXTRA_WAIT:   fsm_state_next = fsm_wait_done ? FSM_STATE_DONE                 : FSM_STATE_CONVERT_EXTRA_WAIT;
+            FSM_STATE_DONE:                 fsm_state_next =                 FSM_STATE_IDLE                 ;
+
+        endcase
+        //
+    end
+
+
+    //
+    // Worker
+    //
+    wire worker_output_now = (fsm_state == FSM_STATE_CONVERT_EXTRA_WAIT);
+    
+    ecdsa256_uop_worker uop_worker
+    (
+        .clk            (clk),
+        .rst_n          (rst_n),
+          
+        .ena            (worker_trig),
+        .rdy            (worker_done),
+        .uop_offset     (worker_offset),
+        .output_now     (worker_output_now),
+          
+        .flagz_sz       (worker_flagz_sz),
+        .flagz_rz       (worker_flagz_rz),
+        .flagz_e        (worker_flagz_e),
+        .flagz_f        (worker_flagz_f),
+        
+        .xy_addr        (rxy_addr),
+        .xy_dout        (rxy_dout),
+        .x_wren         (rx_wren),
+        .y_wren         (ry_wren)
+    );
+
+
+    //
+    // Ready Flag Logic
+    //
+    reg rdy_reg = 1'b1;
+    assign rdy = rdy_reg;
+
+    always @(posedge clk or negedge rst_n)
+        //
+        if (rst_n == 1'b0)              rdy_reg <= 1'b1;
+        else case (fsm_state)
+            FSM_STATE_IDLE: if (ena)    rdy_reg <= 1'b0;
+            FSM_STATE_DONE:             rdy_reg <= 1'b1;
+        endcase
+        
+
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/rtl/ecdsa256_core_top.v b/rtl/ecdsa256_core_top.v
new file mode 100644
index 0000000..3ce4174
--- /dev/null
+++ b/rtl/ecdsa256_core_top.v
@@ -0,0 +1,150 @@
+//======================================================================
+//
+// Copyright (c) 2016, 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 ecdsa256_core_top
+(
+    input  wire        clk,
+    input  wire        rst_n,
+
+    input  wire        next,
+    output wire        valid,
+
+    input  wire        bus_cs,
+    input  wire        bus_we,
+    input  wire [ 4:0] bus_addr,
+    input  wire [31:0] bus_data_wr,
+    output wire [31:0] bus_data_rd
+);
+
+
+    //
+    // Memory Banks
+    //
+    localparam [1:0] BUS_ADDR_BANK_K = 2'b00;
+    localparam [1:0] BUS_ADDR_BANK_X = 2'b01;
+    localparam [1:0] BUS_ADDR_BANK_Y = 2'b10;
+
+    wire [1:0] bus_addr_upper = bus_addr[4:3];
+    wire [2:0] bus_addr_lower = bus_addr[2:0];
+
+
+    //
+    // Memories
+    //
+
+    wire [31:0] user_rw_k_bram_out;
+    wire [31:0] user_ro_x_bram_out;
+    wire [31:0] user_ro_y_bram_out;
+
+    wire [ 2:0] core_ro_k_bram_addr;
+    wire [ 2:0] core_rw_xy_bram_addr;
+
+    wire        core_rw_x_bram_wren;
+    wire        core_rw_y_bram_wren;
+
+    wire [31:0] core_ro_k_bram_dout;
+    wire [31:0] core_rw_xy_bram_din;
+
+    bram_1rw_1ro_readfirst #
+    (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
+    bram_k
+    (   .clk(clk),
+        .a_addr(bus_addr_lower), .a_out(user_rw_k_bram_out), .a_wr(bus_cs && bus_we && (bus_addr_upper == BUS_ADDR_BANK_K)), .a_in(bus_data_wr),
+        .b_addr(core_ro_k_bram_addr), .b_out(core_ro_k_bram_dout)
+    );
+    
+    bram_1rw_1ro_readfirst #
+    (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
+    bram_x
+    (   .clk(clk),
+    .a_addr(core_rw_xy_bram_addr), .a_out(), .a_wr(core_rw_x_bram_wren), .a_in(core_rw_xy_bram_din),
+    .b_addr(bus_addr_lower),      .b_out(user_ro_x_bram_out)
+    );
+    
+    bram_1rw_1ro_readfirst #
+    (.MEM_WIDTH(32), .MEM_ADDR_BITS(3))
+    bram_y
+    (   .clk(clk),
+        .a_addr(core_rw_xy_bram_addr), .a_out(), .a_wr(core_rw_y_bram_wren), .a_in(core_rw_xy_bram_din),
+        .b_addr(bus_addr_lower),      .b_out(user_ro_y_bram_out)
+    );
+
+
+    //
+    // Curve Base Point Multiplier
+    //
+    reg next_dly;
+    
+    always @(posedge clk) next_dly <= next;
+    
+    wire next_trig = next && !next_dly;
+    
+    ecdsa256_base_point_multiplier base_point_multiplier_p256
+    (
+        .clk        (clk),
+        .rst_n      (rst_n),
+    
+        .ena        (next_trig),
+        .rdy        (valid),
+    
+        .k_addr     (core_ro_k_bram_addr),
+        .rxy_addr   (core_rw_xy_bram_addr),
+    
+        .rx_wren    (core_rw_x_bram_wren),
+        .ry_wren    (core_rw_y_bram_wren),
+    
+        .k_din      (core_ro_k_bram_dout),
+        .rxy_dout   (core_rw_xy_bram_din)
+    );
+
+    //
+    // Output Selector
+    //
+    reg [1:0] bus_addr_upper_prev;
+    always @(posedge clk) bus_addr_upper_prev = bus_addr_upper;
+
+    reg [31:0] bus_data_rd_mux;
+    assign bus_data_rd = bus_data_rd_mux;
+
+    always @(*)
+        //
+        case (bus_addr_upper_prev)
+            //
+            BUS_ADDR_BANK_K: bus_data_rd_mux = user_rw_k_bram_out;
+            BUS_ADDR_BANK_X: bus_data_rd_mux = user_ro_x_bram_out;
+            BUS_ADDR_BANK_Y: bus_data_rd_mux = user_ro_y_bram_out;
+            //
+            default:         bus_data_rd_mux = {32{1'b0}};
+            //
+        endcase
+
+endmodule
diff --git a/rtl/ecdsa256_microcode_rom.v b/rtl/ecdsa256_microcode_rom.v
new file mode 100644
index 0000000..82321cb
--- /dev/null
+++ b/rtl/ecdsa256_microcode_rom.v
@@ -0,0 +1,424 @@
+//======================================================================
+//
+// 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.
+//
+//======================================================================
+
+module ecdsa256_microcode_rom
+(
+    input  wire 	                 clk,
+    input  wire [UOP_ADDR_WIDTH-1:0] addr,
+    output reg  [UOP_DATA_WIDTH-1:0] data
+);
+
+`include "ecdsa_uop.vh"
+
+    always @(posedge clk)
+        //
+        case (addr)
+
+            // PREPARE
+            9'd000: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RX};
+            9'd001: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd002: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CONST_ZERO, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RZ};
+            9'd003: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_DOUBLE
+            9'd004: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_CYCLE_Z2};
+            9'd005: data <= {UOP_OPCODE_SUB, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_RX, UOP_OPERAND_CYCLE_Z2, UOP_OPERAND_CYCLE_T1};
+            9'd006: data <= {UOP_OPCODE_ADD, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_RX, UOP_OPERAND_CYCLE_Z2, UOP_OPERAND_CYCLE_T2};
+            9'd007: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_T1, UOP_OPERAND_CYCLE_T2, UOP_OPERAND_CYCLE_T3};
+            9'd008: data <= {UOP_OPCODE_ADD, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_T3, UOP_OPERAND_CYCLE_T3, UOP_OPERAND_CYCLE_T4};
+            9'd009: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_T4, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_T4};
+            9'd010: data <= {UOP_OPCODE_ADD, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_T3, UOP_OPERAND_CYCLE_T4, UOP_OPERAND_CYCLE_A};
+            9'd011: data <= {UOP_OPCODE_ADD, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_RY, UOP_OPERAND_CYCLE_RY, UOP_OPERAND_CYCLE_B};
+            9'd012: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_B, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_CYCLE_SZ};
+            9'd013: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_B, UOP_OPERAND_CYCLE_B, UOP_OPERAND_CYCLE_C};
+            9'd014: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_C, UOP_OPERAND_CYCLE_RX, UOP_OPERAND_CYCLE_D};
+            9'd015: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_C, UOP_OPERAND_CYCLE_C, UOP_OPERAND_CYCLE_C2};
+            9'd016: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_C2, UOP_OPERAND_CONST_DELTA, UOP_OPERAND_CYCLE_C2_2};
+            9'd017: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_A, UOP_OPERAND_CYCLE_A, UOP_OPERAND_CYCLE_A2};
+            9'd018: data <= {UOP_OPCODE_ADD, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_D, UOP_OPERAND_CYCLE_D, UOP_OPERAND_CYCLE_T1};
+            9'd019: data <= {UOP_OPCODE_SUB, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_A2, UOP_OPERAND_CYCLE_T1, UOP_OPERAND_CYCLE_SX};
+            9'd020: data <= {UOP_OPCODE_SUB, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_D, UOP_OPERAND_CYCLE_SX, UOP_OPERAND_CYCLE_T1};
+            9'd021: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_T1, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_T1};
+            9'd022: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_A, UOP_OPERAND_CYCLE_T1, UOP_OPERAND_CYCLE_T2};
+            9'd023: data <= {UOP_OPCODE_SUB, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_T2, UOP_OPERAND_CYCLE_C2_2, UOP_OPERAND_CYCLE_SY};
+            9'd024: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_ADD
+            9'd025: data <= {UOP_OPCODE_CMPZ, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_SZ, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            9'd026: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_SZ, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_SZ};
+            9'd027: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_SZ, UOP_OPERAND_CYCLE_SZ, UOP_OPERAND_CYCLE_A};
+            9'd028: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_A, UOP_OPERAND_CYCLE_SZ, UOP_OPERAND_CYCLE_B};
+            9'd029: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_B, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_B};
+            9'd030: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_A, UOP_OPERAND_CONST_GX, UOP_OPERAND_CYCLE_C};
+            9'd031: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_B, UOP_OPERAND_CONST_GY, UOP_OPERAND_CYCLE_D};
+            9'd032: data <= {UOP_OPCODE_SUB, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_C, UOP_OPERAND_CYCLE_SX, UOP_OPERAND_CYCLE_E};
+            9'd033: data <= {UOP_OPCODE_SUB, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_D, UOP_OPERAND_CYCLE_SY, UOP_OPERAND_CYCLE_F};
+            9'd034: data <= {UOP_OPCODE_CMPZ, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_E, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            9'd035: data <= {UOP_OPCODE_CMPZ, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_F, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            9'd036: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_E, UOP_OPERAND_CYCLE_SZ, UOP_OPERAND_CYCLE_RZ};
+            9'd037: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_E, UOP_OPERAND_CYCLE_E, UOP_OPERAND_CYCLE_G};
+            9'd038: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_G, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_G};
+            9'd039: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_E, UOP_OPERAND_CYCLE_G, UOP_OPERAND_CYCLE_H};
+            9'd040: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_G, UOP_OPERAND_CYCLE_SX, UOP_OPERAND_CYCLE_J};
+            9'd041: data <= {UOP_OPCODE_ADD, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_J, UOP_OPERAND_CYCLE_J, UOP_OPERAND_CYCLE_T1};
+            9'd042: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_F, UOP_OPERAND_CYCLE_F, UOP_OPERAND_CYCLE_T2};
+            9'd043: data <= {UOP_OPCODE_SUB, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_T2, UOP_OPERAND_CYCLE_T1, UOP_OPERAND_CYCLE_T3};
+            9'd044: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_T3, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_T3};
+            9'd045: data <= {UOP_OPCODE_SUB, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_T3, UOP_OPERAND_CYCLE_H, UOP_OPERAND_CYCLE_RX};
+            9'd046: data <= {UOP_OPCODE_SUB, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_J, UOP_OPERAND_CYCLE_RX, UOP_OPERAND_CYCLE_T1};
+            9'd047: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_F, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_F};
+            9'd048: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_F, UOP_OPERAND_CYCLE_T1, UOP_OPERAND_CYCLE_T2};
+            9'd049: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_H, UOP_OPERAND_CYCLE_SY, UOP_OPERAND_CYCLE_T3};
+            9'd050: data <= {UOP_OPCODE_SUB, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_T2, UOP_OPERAND_CYCLE_T3, UOP_OPERAND_CYCLE_RY};
+            9'd051: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_RY, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd052: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_ADD_AT_INFINITY
+            9'd053: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_GX, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RX};
+            9'd054: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_GY, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd055: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RZ};
+            9'd056: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_ADD_SAME_X_SAME_Y
+            9'd057: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_HX, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RX};
+            9'd058: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_HY, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd059: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RZ};
+            9'd060: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_ADD_SAME_X
+            9'd061: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RX};
+            9'd062: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd063: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CONST_ZERO, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RZ};
+            9'd064: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_ADD_REGULAR
+            9'd065: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_T1};
+            9'd066: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ONE, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_T2};
+            9'd067: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CONST_ZERO, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_T3};
+            9'd068: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_K0
+            9'd069: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_SX, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RX};
+            9'd070: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_SY, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd071: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_SZ, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RZ};
+            9'd072: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CYCLE_K1
+            9'd073: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_RX, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_SX};
+            9'd074: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_RY, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_SY};
+            9'd075: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_SZ};
+            9'd076: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CONVERT
+            9'd077: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_A2, UOP_OPERAND_CYCLE_RX, UOP_OPERAND_CYCLE_SX};
+            9'd078: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_A3, UOP_OPERAND_CYCLE_RY, UOP_OPERAND_CYCLE_SY};
+            9'd079: data <= {UOP_OPCODE_CMPZ, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            9'd080: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CONVERT_AT_INFINITY
+            9'd081: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ZERO, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RX};
+            9'd082: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CONST_ZERO, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd083: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // CONVERT_REGULAR
+            9'd084: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_SX, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RX};
+            9'd085: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_SY, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RY};
+            9'd086: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+            // INVERT_P256
+            9'd087: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_DONTCARE, UOP_OPERAND_CYCLE_RZ};
+            9'd088: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_INVERT_R1};
+            9'd089: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_X2};
+            9'd090: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X2, UOP_OPERAND_DONTCARE, UOP_OPERAND_INVERT_X2};
+            9'd091: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X2, UOP_OPERAND_INVERT_X2, UOP_OPERAND_INVERT_R1};
+            9'd092: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_INVERT_X3};
+            9'd093: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X3, UOP_OPERAND_DONTCARE, UOP_OPERAND_INVERT_X3};
+            9'd094: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X3, UOP_OPERAND_INVERT_X3, UOP_OPERAND_INVERT_R1};
+            9'd095: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd096: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd097: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_X3, UOP_OPERAND_INVERT_X6};
+            9'd098: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X6, UOP_OPERAND_INVERT_X6, UOP_OPERAND_INVERT_R1};
+            9'd099: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd100: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd101: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd102: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd103: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd104: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X6, UOP_OPERAND_INVERT_X12};
+            9'd105: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_X12, UOP_OPERAND_INVERT_X12, UOP_OPERAND_INVERT_R1};
+            9'd106: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd107: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd108: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_X3, UOP_OPERAND_INVERT_X15};
+            9'd109: data <= {UOP_OPCODE_COPY, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_X15, UOP_OPERAND_DONTCARE, UOP_OPERAND_INVERT_X15};
+            9'd110: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_X15, UOP_OPERAND_INVERT_X15, UOP_OPERAND_INVERT_R1};
+            9'd111: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd112: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd113: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd114: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd115: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd116: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd117: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd118: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd119: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd120: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd121: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd122: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd123: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd124: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd125: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_X15, UOP_OPERAND_INVERT_X30};
+            9'd126: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_X30, UOP_OPERAND_INVERT_X30, UOP_OPERAND_INVERT_R1};
+            9'd127: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd128: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X2, UOP_OPERAND_INVERT_X32};
+            9'd129: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X32, UOP_OPERAND_DONTCARE, UOP_OPERAND_INVERT_X32};
+            9'd130: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X32, UOP_OPERAND_INVERT_X32, UOP_OPERAND_INVERT_R1};
+            9'd131: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd132: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd133: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd134: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd135: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd136: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd137: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd138: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd139: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd140: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd141: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd142: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd143: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd144: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd145: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd146: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd147: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd148: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd149: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd150: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd151: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd152: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd153: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd154: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd155: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd156: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd157: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd158: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd159: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd160: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd161: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd162: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_INVERT_R1};
+            9'd163: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd164: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd165: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd166: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd167: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd168: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd169: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd170: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd171: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd172: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd173: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd174: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd175: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd176: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd177: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd178: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd179: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd180: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd181: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd182: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd183: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd184: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd185: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd186: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd187: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd188: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd189: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd190: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd191: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd192: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd193: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd194: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd195: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd196: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd197: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd198: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd199: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd200: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd201: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd202: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd203: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd204: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd205: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd206: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd207: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd208: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd209: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd210: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd211: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd212: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd213: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd214: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd215: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd216: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd217: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd218: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd219: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd220: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd221: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd222: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd223: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd224: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd225: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd226: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd227: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd228: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd229: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd230: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd231: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd232: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd233: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd234: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd235: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd236: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd237: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd238: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd239: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd240: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd241: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd242: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd243: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd244: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd245: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd246: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd247: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd248: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd249: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd250: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd251: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd252: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd253: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd254: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd255: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd256: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd257: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd258: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd259: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd260: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd261: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd262: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd263: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd264: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd265: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd266: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd267: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd268: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd269: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd270: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd271: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd272: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd273: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd274: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd275: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd276: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd277: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd278: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd279: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd280: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd281: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd282: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd283: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd284: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd285: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd286: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd287: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd288: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd289: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd290: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd291: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_X32, UOP_OPERAND_INVERT_R2};
+            9'd292: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd293: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd294: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd295: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd296: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd297: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd298: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd299: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd300: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd301: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd302: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd303: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd304: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd305: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd306: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd307: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd308: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd309: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd310: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd311: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd312: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd313: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd314: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd315: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd316: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd317: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd318: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd319: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd320: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd321: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd322: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd323: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd324: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X32, UOP_OPERAND_INVERT_R1};
+            9'd325: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd326: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd327: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd328: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd329: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd330: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd331: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd332: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd333: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd334: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd335: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd336: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd337: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd338: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd339: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd340: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd341: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd342: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd343: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd344: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd345: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd346: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd347: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd348: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd349: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd350: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd351: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd352: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd353: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd354: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd355: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_X30, UOP_OPERAND_INVERT_R2};
+            9'd356: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd357: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd358: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_DONTCARE, UOP_OPERAND_INVERT_A2};
+            9'd359: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_A2, UOP_OPERAND_INVERT_A2, UOP_OPERAND_INVERT_R1};
+            9'd360: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_INVERT_A3};
+            9'd361: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+
+    endcase
+
+endmodule
diff --git a/rtl/ecdsa256_operand_bank.v b/rtl/ecdsa256_operand_bank.v
new file mode 100644
index 0000000..807927c
--- /dev/null
+++ b/rtl/ecdsa256_operand_bank.v
@@ -0,0 +1,160 @@
+//======================================================================
+//
+// 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.
+//
+//======================================================================
+
+module ecdsa256_operand_bank
+(
+    input               clk,
+
+    input   [ 9-1:0]    a_addr,
+    input               a_wr,
+    input   [32-1:0]    a_in,
+
+    input   [ 9-1:0]    b_addr,
+    output  [32-1:0]    b_out
+);
+
+
+    //
+    // BRAM
+    //
+    reg [31:0] bram[0:64*8-1];
+
+
+    //
+    // Initialization
+    //
+    initial begin
+        //
+        // CONST_ZERO 
+        //
+        bram[ 0*8 + 7] = 32'h00000000;
+        bram[ 0*8 + 6] = 32'h00000000;
+        bram[ 0*8 + 5] = 32'h00000000;
+        bram[ 0*8 + 4] = 32'h00000000;
+        bram[ 0*8 + 3] = 32'h00000000;
+        bram[ 0*8 + 2] = 32'h00000000;
+        bram[ 0*8 + 1] = 32'h00000000;
+        bram[ 0*8 + 0] = 32'h00000000;
+        //
+        // CONST_ONE
+        //
+        bram[ 1*8 + 7] = 32'h00000000;
+        bram[ 1*8 + 6] = 32'h00000000;
+        bram[ 1*8 + 5] = 32'h00000000;
+        bram[ 1*8 + 4] = 32'h00000000;
+        bram[ 1*8 + 3] = 32'h00000000;
+        bram[ 1*8 + 2] = 32'h00000000;
+        bram[ 1*8 + 1] = 32'h00000000;
+        bram[ 1*8 + 0] = 32'h00000001;
+        //
+        // CONST_DELTA
+        //
+        bram[ 2*8 + 7] = 32'h7fffffff;
+        bram[ 2*8 + 6] = 32'h80000000;
+        bram[ 2*8 + 5] = 32'h80000000;
+        bram[ 2*8 + 4] = 32'h00000000;
+        bram[ 2*8 + 3] = 32'h00000000;
+        bram[ 2*8 + 2] = 32'h80000000;
+        bram[ 2*8 + 1] = 32'h00000000;
+        bram[ 2*8 + 0] = 32'h00000000;
+        //
+        // G_X
+        //
+        bram[ 3*8 + 7] = 32'h6b17d1f2;
+        bram[ 3*8 + 6] = 32'he12c4247;
+        bram[ 3*8 + 5] = 32'hf8bce6e5;
+        bram[ 3*8 + 4] = 32'h63a440f2;
+        bram[ 3*8 + 3] = 32'h77037d81;
+        bram[ 3*8 + 2] = 32'h2deb33a0;
+        bram[ 3*8 + 1] = 32'hf4a13945;
+        bram[ 3*8 + 0] = 32'hd898c296;
+        //
+        // G_Y
+        //
+        bram[ 4*8 + 7] = 32'h4fe342e2;
+        bram[ 4*8 + 6] = 32'hfe1a7f9b;
+        bram[ 4*8 + 5] = 32'h8ee7eb4a;
+        bram[ 4*8 + 4] = 32'h7c0f9e16;
+        bram[ 4*8 + 3] = 32'h2bce3357;
+        bram[ 4*8 + 2] = 32'h6b315ece;
+        bram[ 4*8 + 1] = 32'hcbb64068;
+        bram[ 4*8 + 0] = 32'h37bf51f5;
+        //
+        // H_X
+        //
+        bram[ 5*8 + 7] = 32'h7cf27b18;
+        bram[ 5*8 + 6] = 32'h8d034f7e;
+        bram[ 5*8 + 5] = 32'h8a523803;
+        bram[ 5*8 + 4] = 32'h04b51ac3;
+        bram[ 5*8 + 3] = 32'hc08969e2;
+        bram[ 5*8 + 2] = 32'h77f21b35;
+        bram[ 5*8 + 1] = 32'ha60b48fc;
+        bram[ 5*8 + 0] = 32'h47669978;
+        //
+        // H_Y
+        //
+        bram[ 6*8 + 7] = 32'h07775510;
+        bram[ 6*8 + 6] = 32'hdb8ed040;
+        bram[ 6*8 + 5] = 32'h293d9ac6;
+        bram[ 6*8 + 4] = 32'h9f7430db;
+        bram[ 6*8 + 3] = 32'hba7dade6;
+        bram[ 6*8 + 2] = 32'h3ce98229;
+        bram[ 6*8 + 1] = 32'h9e04b79d;
+        bram[ 6*8 + 0] = 32'h227873d1;
+	end
+
+
+    //
+    // Output Register
+    //
+    reg [32-1:0] bram_reg_b;
+
+    assign b_out = bram_reg_b;
+
+
+    //
+    // Write Port A
+    //
+    always @(posedge clk)
+        //
+        if (a_wr) bram[a_addr] <= a_in;
+
+
+    //
+    // Read Port B
+    //
+    always @(posedge clk)
+        //
+        bram_reg_b <= bram[b_addr];
+
+
+endmodule
diff --git a/rtl/ecdsa256_uop_worker.v b/rtl/ecdsa256_uop_worker.v
new file mode 100644
index 0000000..a754796
--- /dev/null
+++ b/rtl/ecdsa256_uop_worker.v
@@ -0,0 +1,604 @@
+//------------------------------------------------------------------------------
+//
+// ecdsa256_uop_worker.v
+// -----------------------------------------------------------------------------
+// ECDSA uOP Worker for P-256
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 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 ecdsa256_uop_worker
+(
+    clk, rst_n,
+    ena, rdy,
+    uop_offset,
+    output_now,
+    flagz_sz, flagz_rz,
+    flagz_e,  flagz_f,
+    xy_addr, xy_dout, x_wren, y_wren
+);
+
+
+    //
+    // Microcode Header
+    //
+`include "ecdsa_uop.vh"
+
+
+    //
+    // Ports
+    //
+    input   clk;    // system clock
+    input   rst_n;  // active-low async reset
+
+    input   ena;    // enable input
+    output  rdy;    // ready output
+    
+    input [UOP_ADDR_WIDTH-1:0] uop_offset;  // starting offset
+    
+    input   output_now;     // produce output    
+
+    output  flagz_sz;   // SZ is zero
+    output  flagz_rz;   // RZ is zero
+    output  flagz_e;    // E is zero
+    output  flagz_f;    // F is zero
+
+    output  [ 2: 0] xy_addr;
+    output  [31: 0] xy_dout;
+    output          x_wren;
+    output          y_wren;
+    
+    
+    //
+    // Constants
+    //
+    localparam integer OPERAND_NUM_WORDS = 8;   // 256 bits -> 8 x 32-bit words
+    localparam integer WORD_COUNTER_WIDTH = 3;  // 0..7 -> 3 bits
+    
+
+    //
+    // FSM
+    //
+    localparam [1:0] FSM_STATE_IDLE     = 2'b00;
+    localparam [1:0] FSM_STATE_FETCH    = 2'b01;
+    localparam [1:0] FSM_STATE_DECODE   = 2'b10;
+    localparam [1:0] FSM_STATE_BUSY     = 2'b11;
+
+    reg  [1:0] fsm_state = FSM_STATE_IDLE;
+    reg  [1:0] fsm_state_next;
+
+  
+    //
+    // Microcode
+    //
+    reg  [UOP_ADDR_WIDTH-1:0] uop_addr;
+    wire [UOP_DATA_WIDTH-1:0] uop_data;
+    
+    wire [5:0] uop_data_opcode        = uop_data[1 + 3*6 +: 6];
+    wire       uop_data_banks         = uop_data[0 + 3*6 +: 1];
+    wire [5:0] uop_data_operand_src1  = uop_data[0 + 2*6 +: 6];
+    wire [5:0] uop_data_operand_src2  = uop_data[0 + 1*6 +: 6];
+    wire [5:0] uop_data_operand_dst   = uop_data[0 + 0*6 +: 6];
+    
+    wire uop_data_opcode_is_stop = uop_data_opcode[5];
+    wire uop_data_opcode_is_mul  = uop_data_opcode[4];
+    wire uop_data_opcode_is_sub  = uop_data_opcode[3];
+    wire uop_data_opcode_is_add  = uop_data_opcode[2];
+    wire uop_data_opcode_is_copy = uop_data_opcode[1];
+    wire uop_data_opcode_is_cmpz = uop_data_opcode[0];
+    
+    ecdsa256_microcode_rom microcode_rom
+    (
+        .clk    (clk),
+        .addr   (uop_addr),
+        .data   (uop_data)
+    );
+
+    
+    //
+    // Microcode Address Increment Logic
+    //
+    always @(posedge clk)
+        //
+        if (fsm_state_next == FSM_STATE_FETCH)
+            uop_addr <= (fsm_state == FSM_STATE_IDLE) ? uop_offset : uop_addr + 1'b1;
+
+
+    //
+    // Multi-Word Mover
+    //
+    reg  mw_mover_ena = 1'b0;
+    wire mw_mover_rdy;
+    
+    wire [WORD_COUNTER_WIDTH-1:0]   mw_mover_x_addr;
+    wire [WORD_COUNTER_WIDTH-1:0]   mw_mover_y_addr;
+    wire [                32-1:0]   mw_mover_x_din;
+    wire [                32-1:0]   mw_mover_y_dout;
+    wire                            mw_mover_y_wren;
+    
+    multiword_mover #
+    (
+        .WORD_COUNTER_WIDTH     (WORD_COUNTER_WIDTH),
+        .OPERAND_NUM_WORDS      (OPERAND_NUM_WORDS)
+    )
+    mw_mover_inst
+    (
+        .clk        (clk),
+        .rst_n      (rst_n),
+        .ena        (mw_mover_ena),
+        .rdy        (mw_mover_rdy),
+        .x_addr     (mw_mover_x_addr),
+        .y_addr     (mw_mover_y_addr),
+        .y_wren     (mw_mover_y_wren),
+        .x_din      (mw_mover_x_din),
+        .y_dout     (mw_mover_y_dout)
+    );
+
+
+    //
+    // Modular Multiplier
+    //
+    reg  mod_mul_ena = 1'b0;
+    wire mod_mul_rdy;
+    
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_mul_a_addr;
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_mul_b_addr;
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_mul_p_addr;
+    wire [                32-1:0]   mod_mul_a_din;
+    wire [                32-1:0]   mod_mul_b_din;
+    wire [                32-1:0]   mod_mul_p_dout;
+    wire                            mod_mul_p_wren;
+    
+    ecdsa256_modular_multiplier mod_mul_inst
+    (
+        .clk        (clk),
+        .rst_n      (rst_n),
+        .ena        (mod_mul_ena),
+        .rdy        (mod_mul_rdy),
+        .a_addr     (mod_mul_a_addr),
+        .b_addr     (mod_mul_b_addr),
+        .p_addr     (mod_mul_p_addr),
+        .p_wren     (mod_mul_p_wren),
+        .a_din      (mod_mul_a_din),
+        .b_din      (mod_mul_b_din),
+        .p_dout     (mod_mul_p_dout)
+    );    
+    
+    
+    //
+    // Modular Adder
+    //
+    reg  mod_add_ena = 1'b0;
+    wire mod_add_rdy;
+    
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_add_ab_addr;
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_add_n_addr;
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_add_s_addr;
+    wire [                32-1:0]   mod_add_a_din;
+    wire [                32-1:0]   mod_add_b_din;
+    wire [                32-1:0]   mod_add_n_din;
+    wire [                32-1:0]   mod_add_s_dout;
+    wire                            mod_add_s_wren;
+        
+    modular_adder #
+    (
+        .OPERAND_NUM_WORDS(OPERAND_NUM_WORDS),
+        .WORD_COUNTER_WIDTH(WORD_COUNTER_WIDTH)
+    )
+    mod_add_inst
+    (
+        .clk        (clk),
+        .rst_n      (rst_n),
+        .ena        (mod_add_ena),
+        .rdy        (mod_add_rdy),
+        .ab_addr    (mod_add_ab_addr),
+        .n_addr     (mod_add_n_addr),
+        .s_addr     (mod_add_s_addr),
+        .s_wren     (mod_add_s_wren),
+        .a_din      (mod_add_a_din),
+        .b_din      (mod_add_b_din),
+        .n_din      (mod_add_n_din),
+        .s_dout     (mod_add_s_dout)
+    );
+    
+    
+    //
+    // Modular Subtractor
+    //
+    reg  mod_sub_ena = 1'b0;
+    wire mod_sub_rdy;
+    
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_sub_ab_addr;
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_sub_n_addr;
+    wire [WORD_COUNTER_WIDTH-1:0]   mod_sub_d_addr;
+    wire [                32-1:0]   mod_sub_a_din;
+    wire [                32-1:0]   mod_sub_b_din;
+    wire [                32-1:0]   mod_sub_n_din;
+    wire [                32-1:0]   mod_sub_d_dout;
+    wire                            mod_sub_d_wren;
+        
+    modular_subtractor #
+    (
+        .OPERAND_NUM_WORDS(OPERAND_NUM_WORDS),
+        .WORD_COUNTER_WIDTH(WORD_COUNTER_WIDTH)
+    )
+    mod_sub_inst
+    (
+        .clk        (clk),
+        .rst_n      (rst_n),
+        .ena        (mod_sub_ena),
+        .rdy        (mod_sub_rdy),
+        .ab_addr    (mod_sub_ab_addr),
+        .n_addr     (mod_sub_n_addr),
+        .d_addr     (mod_sub_d_addr),
+        .d_wren     (mod_sub_d_wren),
+        .a_din      (mod_sub_a_din),
+        .b_din      (mod_sub_b_din),
+        .n_din      (mod_sub_n_din),
+        .d_dout     (mod_sub_d_dout)
+    );
+    
+    
+    //
+    // Modulus (two instances for better placement and routing)
+    //
+    ecdsa256_modulus_distmem modulus_add
+    (
+        .clk    (clk),
+        .b_addr (mod_add_n_addr),
+        .b_out  (mod_add_n_din)
+    );    
+
+    ecdsa256_modulus_distmem modulus_sub
+    (
+        .clk    (clk),
+        .b_addr (mod_sub_n_addr),
+        .b_out  (mod_sub_n_din)
+    );        
+
+    
+    //
+    // Multi-Word Comparator
+    //
+    reg  mw_comp_ena = 1'b0;
+    wire mw_comp_rdy;
+    
+    wire mw_comp_cmp_e;
+    
+    wire [WORD_COUNTER_WIDTH-1:0]   mw_comp_x_addr;
+    wire [                32-1:0]   mw_comp_x_din;
+    
+    multiword_comparator #
+    (
+        .WORD_COUNTER_WIDTH     (WORD_COUNTER_WIDTH),
+        .OPERAND_NUM_WORDS      (OPERAND_NUM_WORDS)    
+    )
+    mw_comp_inst
+    (
+        .clk        (clk),
+        .rst_n      (rst_n),
+        .ena        (mw_comp_ena),
+        .rdy        (mw_comp_rdy),
+        .xy_addr    (mw_comp_x_addr),
+        .x_din      (mw_comp_x_din),
+        .y_din      ({32{1'b0}}),
+        .cmp_l      (),
+        .cmp_e      (mw_comp_cmp_e),
+        .cmp_g      ()
+    );
+    
+    
+    //
+    // Comparison Flags
+    //
+    reg flagz_sz_reg;
+    reg flagz_rz_reg;
+    reg flagz_e_reg;
+    reg flagz_f_reg;
+    
+    assign flagz_sz = flagz_sz_reg; 
+    assign flagz_rz = flagz_rz_reg;
+    assign flagz_e  = flagz_e_reg;
+    assign flagz_f  = flagz_f_reg;
+    
+    reg mw_comp_rdy_dly = 1'b1;
+    
+    always @(posedge clk) mw_comp_rdy_dly <= mw_comp_rdy;
+
+    always @(posedge clk)
+        //
+        if (mw_comp_rdy && !mw_comp_rdy_dly)
+            //
+            case (uop_data_operand_src1)
+                UOP_OPERAND_CYCLE_SZ: flagz_sz_reg <= mw_comp_cmp_e;
+                UOP_OPERAND_CYCLE_RZ: flagz_rz_reg <= mw_comp_cmp_e;
+                UOP_OPERAND_CYCLE_E:  flagz_e_reg  <= mw_comp_cmp_e;
+                UOP_OPERAND_CYCLE_F:  flagz_f_reg  <= mw_comp_cmp_e;
+            endcase
+            
+    
+    
+    //
+    // uOP Trigger Logic
+    //
+    always @(posedge clk)
+        //
+        if (fsm_state == FSM_STATE_DECODE) begin
+            mw_comp_ena     <= uop_data_opcode_is_cmpz;
+            mw_mover_ena    <= uop_data_opcode_is_copy;
+            mod_mul_ena     <= uop_data_opcode_is_mul;
+            mod_add_ena     <= uop_data_opcode_is_add;
+            mod_sub_ena     <= uop_data_opcode_is_sub;
+        end else begin
+            mw_comp_ena     <= 1'b0;
+            mw_mover_ena    <= 1'b0;
+            mod_mul_ena     <= 1'b0;
+            mod_add_ena     <= 1'b0;
+            mod_sub_ena     <= 1'b0;
+        end
+
+    
+    //
+    // uOP Completion Detector
+    //
+    reg fsm_exit_from_busy;
+    
+    always @* begin
+        //
+        fsm_exit_from_busy = 0;
+        //
+        if (uop_data_opcode_is_cmpz)    fsm_exit_from_busy = ~mw_comp_ena  & mw_comp_rdy;
+        if (uop_data_opcode_is_copy)    fsm_exit_from_busy = ~mw_mover_ena & mw_mover_rdy;
+        if (uop_data_opcode_is_mul)     fsm_exit_from_busy = ~mod_mul_ena  & mod_mul_rdy;
+        if (uop_data_opcode_is_add)     fsm_exit_from_busy = ~mod_add_ena  & mod_add_rdy;
+        if (uop_data_opcode_is_sub)     fsm_exit_from_busy = ~mod_sub_ena  & mod_sub_rdy;
+        //
+    end
+
+        
+        //
+        // Banks
+        //
+    reg     [ 2:0]  banks_src1_addr;
+    reg     [ 2:0]  banks_src2_addr;
+    reg     [ 2:0]  banks_dst_addr;
+    
+    reg             banks_dst_wren;
+    
+    reg     [31:0]  banks_dst_din;
+
+    wire    [31:0]  banks_src1_dout;
+    wire    [31:0]  banks_src2_dout;    
+    
+    ecdsa256_banks_array banks_array
+    (
+        .clk            (clk),
+    
+        .banks          (uop_data_banks),
+    
+        .src1_operand   (uop_data_operand_src1),
+        .src2_operand   (uop_data_operand_src2),
+        .dst_operand    (uop_data_operand_dst),
+    
+        .src1_addr      (banks_src1_addr),
+        .src2_addr      (banks_src2_addr),
+        .dst_addr       (banks_dst_addr),
+    
+        .dst_wren       (banks_dst_wren),
+    
+        .src1_dout      (banks_src1_dout),
+        .src2_dout      (banks_src2_dout),
+    
+        .dst_din        (banks_dst_din)
+    );
+    
+    assign mw_comp_x_din    = banks_src1_dout;
+    assign mw_mover_x_din   = banks_src1_dout;
+    assign mod_mul_a_din    = banks_src1_dout;
+    assign mod_mul_b_din    = banks_src2_dout;
+    assign mod_add_a_din    = banks_src1_dout;
+    assign mod_add_b_din    = banks_src2_dout;
+    assign mod_sub_a_din    = banks_src1_dout;
+    assign mod_sub_b_din    = banks_src2_dout;
+    
+    always @*
+        //
+        case (uop_data_opcode)
+            //
+            UOP_OPCODE_CMPZ: begin
+                banks_src1_addr = mw_comp_x_addr;
+                banks_src2_addr = {3{1'bX}};
+                //
+                banks_dst_addr  = {3{1'bX}};
+                //
+                banks_dst_wren  = 1'b0;
+                //
+                banks_dst_din   = {32{1'bX}};
+            end
+            //
+            UOP_OPCODE_COPY: begin
+                //
+                banks_src1_addr = mw_mover_x_addr;
+                banks_src2_addr = {3{1'bX}};
+                //
+                banks_dst_addr  = mw_mover_y_addr;
+                //
+                banks_dst_wren  = mw_mover_y_wren;
+                //
+                banks_dst_din   = mw_mover_y_dout;
+                //
+            end
+            //
+            UOP_OPCODE_ADD: begin
+                //
+                banks_src1_addr = mod_add_ab_addr;
+                banks_src2_addr = mod_add_ab_addr;
+                //
+                banks_dst_addr  = mod_add_s_addr;
+                //
+                banks_dst_wren  = mod_add_s_wren;
+                //
+                banks_dst_din   = mod_add_s_dout;
+                //                
+            end
+            //
+            UOP_OPCODE_SUB: begin
+                //
+                banks_src1_addr = mod_sub_ab_addr;
+                banks_src2_addr = mod_sub_ab_addr;
+                //
+                banks_dst_addr  = mod_sub_d_addr;
+                //
+                banks_dst_wren  = mod_sub_d_wren;
+                //
+                banks_dst_din   = mod_sub_d_dout;
+                //                
+            end
+            //
+            UOP_OPCODE_MUL: begin
+                //
+                banks_src1_addr = mod_mul_a_addr;
+                banks_src2_addr = mod_mul_b_addr;
+                //
+                banks_dst_addr  = mod_mul_p_addr;
+                //
+                banks_dst_wren  = mod_mul_p_wren;
+                //
+                banks_dst_din   = mod_mul_p_dout;
+                //                
+            end
+            //
+            default: begin
+                //
+                banks_src1_addr = {3{1'bX}};
+                banks_src2_addr = {3{1'bX}};
+                //
+                banks_dst_addr  = {3{1'bX}};
+                //
+                banks_dst_wren  = 1'b0;
+                //
+                banks_dst_din   = {32{1'bX}};
+                //
+            end
+            //
+        endcase
+
+    
+    //
+    // FSM Process
+    //
+    always @(posedge clk or negedge rst_n)
+        //
+        if (rst_n == 1'b0)  fsm_state <= FSM_STATE_IDLE;
+        else                fsm_state <= fsm_state_next;
+    
+    
+    //
+    // FSM Transition Logic
+    //
+    always @* begin
+        //
+        fsm_state_next = FSM_STATE_IDLE;
+        //
+        case (fsm_state)
+            FSM_STATE_IDLE:     fsm_state_next = ena                     ? FSM_STATE_FETCH : FSM_STATE_IDLE;
+            FSM_STATE_FETCH:    fsm_state_next = FSM_STATE_DECODE;
+            FSM_STATE_DECODE:   fsm_state_next = uop_data_opcode_is_stop ? FSM_STATE_IDLE  : FSM_STATE_BUSY;
+            FSM_STATE_BUSY:     fsm_state_next = fsm_exit_from_busy      ? FSM_STATE_FETCH : FSM_STATE_BUSY;
+        endcase
+        //
+    end
+
+
+    //
+    // Ready Flag Logic
+    //
+    reg rdy_reg = 1'b1;
+    assign rdy = rdy_reg;
+
+    always @(posedge clk or negedge rst_n)
+        //
+        if (rst_n == 1'b0)      rdy_reg <= 1'b1;
+        else case (fsm_state)
+            FSM_STATE_IDLE:     rdy_reg <= ~ena;
+            FSM_STATE_DECODE:   rdy_reg <= uop_data_opcode_is_stop;
+        endcase
+
+
+    //
+    // Output Logic
+    //
+    reg [ 2: 0] xy_addr_reg = 3'b000;
+    reg [31: 0] xy_dout_reg = 32'h00000000;
+    reg         x_wren_reg  = 1'b0;
+    reg         y_wren_reg  = 1'b0;
+
+    assign xy_addr = xy_addr_reg;
+    assign xy_dout = xy_dout_reg;
+    assign x_wren  = x_wren_reg;
+    assign y_wren  = y_wren_reg;
+
+    reg xy_phase;   // 0 - x, 1 - y
+
+    always @(posedge clk)
+        //
+        if (output_now) begin
+        
+            if (ena)
+                xy_phase <= 1'b0;
+            else if (!mw_mover_ena && mw_mover_rdy && (fsm_state == FSM_STATE_BUSY))
+                xy_phase <= 1'b1;
+        
+        end 
+           
+
+    always @(posedge clk)
+        //
+        if (output_now && mw_mover_y_wren) xy_addr_reg <= mw_mover_y_addr;
+        else                               xy_addr_reg <= 3'b000;
+        
+    always @(posedge clk)
+        //
+        if (output_now && mw_mover_y_wren) xy_dout_reg <= mw_mover_y_dout;
+        else                               xy_dout_reg <= 32'h00000000;
+        
+    always @(posedge clk)
+            //
+            if (output_now && mw_mover_y_wren) {y_wren_reg, x_wren_reg} <= {xy_phase, ~xy_phase};
+            else                               {y_wren_reg, x_wren_reg} <= 2'b00;        
+
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/rtl/ecdsa256_wrapper.v b/rtl/ecdsa256_wrapper.v
index 1684599..2b1d781 100644
--- a/rtl/ecdsa256_wrapper.v
+++ b/rtl/ecdsa256_wrapper.v
@@ -1,6 +1,6 @@
 //======================================================================
 //
-// Copyright (c) 2016, NORDUnet A/S All rights reserved.
+// Copyright (c) 2016, 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
@@ -31,17 +31,17 @@
 //======================================================================
 
 module ecdsa256_wrapper
-  (
-   input wire 	       clk,
-   input wire 	       reset_n,
+(
+   input  wire        clk,
+   input  wire        reset_n,
 
-   input wire 	       cs,
-   input wire 	       we,
+   input  wire        cs,
+   input  wire        we,
 
-   input wire [5: 0]   address,
-   input wire [31: 0]  write_data,
-   output wire [31: 0] read_data
-   );
+   input  wire [ 5:0] address,
+   input  wire [31:0] write_data,
+   output wire [31:0] read_data
+);
 
 
    //
@@ -50,15 +50,15 @@ module ecdsa256_wrapper
    localparam ADDR_MSB_REGS = 1'b0;
    localparam ADDR_MSB_CORE = 1'b1;
 
-   wire [0:0] 	       addr_msb = address[5];
-   wire [4:0] 	       addr_lsb = address[4:0];
+   wire [0:0] addr_msb = address[5];
+   wire [4:0] addr_lsb = address[4:0];
 
 
    //
    // Output Mux
    //
-   wire [31: 0]        read_data_regs;
-   wire [31: 0]        read_data_core;
+   wire [31:0] read_data_regs;
+   wire [31:0] read_data_core;
 
 
    //
@@ -80,45 +80,45 @@ module ecdsa256_wrapper
 
    localparam CORE_NAME0        = 32'h65636473; // "ecds"
    localparam CORE_NAME1        = 32'h61323536; // "a256"
-   localparam CORE_VERSION      = 32'h302E3131; // "0.11"
+   localparam CORE_VERSION      = 32'h302E3230; // "0.20"
 
 
    //
    // Registers
    //
-   reg 		       reg_control;
-   reg [31:0] 	       reg_dummy;
+   reg        reg_control;
+   reg [31:0] reg_dummy;
 
 
    //
    // Wires
    //
-   wire 	       reg_status;
+   wire reg_status;
 
 
-   //
-   // ECDSA256
-   //
-   ecdsa256 ecdsa256_inst
-     (
-      .clk                      (clk),
-      .rst_n                    (reset_n),
+    //
+    // ECDSA256
+    //
+    ecdsa256_core_top ecdsa256_inst
+    (
+        .clk            (clk),
+        .rst_n          (reset_n),
 
-      .next                     (reg_control),
-      .valid                    (reg_status),
+        .next           (reg_control),
+        .valid          (reg_status),
 
-      .bus_cs                   (cs && (addr_msb == ADDR_MSB_CORE)),
-      .bus_we                   (we),
-      .bus_addr                 (addr_lsb),
-      .bus_data_wr              (write_data),
-      .bus_data_rd              (read_data_core)
-      );
+        .bus_cs         (cs && (addr_msb == ADDR_MSB_CORE)),
+        .bus_we         (we),
+        .bus_addr       (addr_lsb),
+        .bus_data_wr    (write_data),
+        .bus_data_rd    (read_data_core)
+    );
 
 
    //
    // Read Latch
    //
-   reg [31: 0] 	       tmp_read_data;
+   reg [31:0] tmp_read_data;
 
 
    //
@@ -139,7 +139,7 @@ module ecdsa256_wrapper
            case (addr_lsb)
              //
              ADDR_CONTROL: reg_control <= write_data[CONTROL_NEXT_BIT];
-	     ADDR_DUMMY:   reg_dummy   <= write_data;
+             ADDR_DUMMY:   reg_dummy   <= write_data;
              //
            endcase
            //
@@ -154,7 +154,7 @@ module ecdsa256_wrapper
              ADDR_VERSION:      tmp_read_data <= CORE_VERSION;
              ADDR_CONTROL:      tmp_read_data <= {{30{1'b0}}, reg_control, 1'b0};
              ADDR_STATUS:       tmp_read_data <= {{30{1'b0}}, reg_status,  1'b1};
-	     ADDR_DUMMY:        tmp_read_data <= reg_dummy;
+             ADDR_DUMMY:        tmp_read_data <= reg_dummy;
              //
              default:           tmp_read_data <= 32'h00000000;
              //
diff --git a/rtl/modular/modular_multiplier_256.v b/rtl/modular/modular_multiplier_256.v
deleted file mode 100644
index 2b35233..0000000
--- a/rtl/modular/modular_multiplier_256.v
+++ /dev/null
@@ -1,402 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// modular_multiplier_256.v
-// -----------------------------------------------------------------------------
-// Modular multiplier.
-//
-// 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 modular_multiplier_256
-  (
-   clk, rst_n,
-   ena, rdy,
-   a_addr, b_addr, n_addr, p_addr, p_wren,
-   a_din, b_din, n_din, p_dout
-   );
-
-
-   //
-   // Constants
-   //
-   localparam	OPERAND_NUM_WORDS				= 8;
-   localparam	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	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] 		a_addr;	// index of current A word
-   output	wire [WORD_COUNTER_WIDTH-1:0] 		b_addr;	// index of current B word
-   output	wire [WORD_COUNTER_WIDTH-1:0] 		n_addr;	// index of current N word
-   output	wire [WORD_COUNTER_WIDTH-1:0] 		p_addr;	// index of current P word
-   output	wire 					p_wren;	// store current P word now
-
-   input	wire [                  31:0] 		a_din;	// A
-   input	wire [                  31:0] 		b_din;	// B
-   input	wire [                  31:0] 		n_din;	// N (must be P-256!)
-   output	wire [                  31:0] 		p_dout;	// P = A * B mod N
-
-
-   //
-   // 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	FSM_SHREG_WIDTH	= (1 * OPERAND_NUM_WORDS + 1) + (2 * OPERAND_NUM_WORDS + 1) + (2 * OPERAND_NUM_WORDS + 2) + (0 * OPERAND_NUM_WORDS + 2) + 1;
-
-   reg [FSM_SHREG_WIDTH-1:0] 				fsm_shreg;
-
-   assign rdy = fsm_shreg[0];
-
-   wire [1 * OPERAND_NUM_WORDS-1:0] 			fsm_shreg_inc_index_a	= fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 1) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 0)];
-   wire [1 * OPERAND_NUM_WORDS-1:0] 			fsm_shreg_store_word_a	= fsm_shreg[FSM_SHREG_WIDTH - (0 * OPERAND_NUM_WORDS + 2) : FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 1)];
-   wire [2 * OPERAND_NUM_WORDS-1:0] 			fsm_shreg_inc_index_b	= fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 1) : FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 1)];
-   wire [2 * OPERAND_NUM_WORDS-2:0] 			fsm_shreg_store_si_msb	= fsm_shreg[FSM_SHREG_WIDTH - (1 * OPERAND_NUM_WORDS + 2) : FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 1)];
-   wire [0 * OPERAND_NUM_WORDS-0:0] 			fsm_shreg_store_si_lsb	= fsm_shreg[FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 2) : FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 2)];
-   wire [2 * OPERAND_NUM_WORDS-2:0] 			fsm_shreg_shift_si	= fsm_shreg[FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 3) : FSM_SHREG_WIDTH - (5 * OPERAND_NUM_WORDS + 1)];
-   wire [0 * OPERAND_NUM_WORDS-0:0] 			fsm_shreg_mask_cw1_sum	= fsm_shreg[FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 4) : FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 4)];
-   wire [2 * OPERAND_NUM_WORDS-1:0] 			fsm_shreg_store_c_word	= fsm_shreg[FSM_SHREG_WIDTH - (3 * OPERAND_NUM_WORDS + 5) : FSM_SHREG_WIDTH - (5 * OPERAND_NUM_WORDS + 4)];
-   wire [0 * OPERAND_NUM_WORDS-0:0] 			fsm_shreg_reduce_start	= fsm_shreg[FSM_SHREG_WIDTH - (5 * OPERAND_NUM_WORDS + 5) : FSM_SHREG_WIDTH - (5 * OPERAND_NUM_WORDS + 5)];
-   wire [0 * OPERAND_NUM_WORDS-0:0] 			fsm_shreg_reduce_stop	= fsm_shreg[FSM_SHREG_WIDTH - (5 * OPERAND_NUM_WORDS + 6) : FSM_SHREG_WIDTH - (5 * OPERAND_NUM_WORDS + 6)];
-
-   wire 						inc_index_a		= |fsm_shreg_inc_index_a;
-   wire 						store_word_a		= |fsm_shreg_store_word_a;
-   wire 						inc_index_b		= |fsm_shreg_inc_index_b;
-   wire 						clear_mac_ab		= |fsm_shreg_inc_index_b;
-   wire 						shift_wide_a		= |fsm_shreg_inc_index_b;
-   wire 						enable_mac_ab		= |fsm_shreg_inc_index_b;
-   wire 						store_si_msb		= |fsm_shreg_store_si_msb;
-   wire 						store_si_lsb		=  fsm_shreg_store_si_lsb;
-   wire 						shift_si		= |fsm_shreg_shift_si;
-   wire 						mask_cw1_sum		=  fsm_shreg_mask_cw1_sum;
-   wire 						store_c_word		= |fsm_shreg_store_c_word;
-   wire 						reduce_start		=  fsm_shreg_reduce_start;
-   wire 						reduce_stop		=  fsm_shreg_reduce_stop;
-
-
-   //
-   // FSM Logic
-   //
-   wire 						reduce_done;
-
-   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 if (!reduce_stop || reduce_done)
-	  fsm_shreg <= {1'b0, fsm_shreg[FSM_SHREG_WIDTH-1:1]};
-	//
-     end
-
-
-   //
-   // Word Index Increment Logic
-   //
-   reg	index_b_ff;
-
-   always @(posedge clk)
-     //
-     if (inc_index_b) index_b_ff <= ~index_b_ff;
-     else index_b_ff <= 1'b0;
-
-   always @(posedge clk)
-     //
-     if (rdy) begin
-	//
-	index_a		<= WORD_INDEX_ZERO;
-	index_b		<= WORD_INDEX_LAST;
-	//
-     end else begin
-	//
-	if (inc_index_a)		index_a	<= WORD_INDEX_NEXT_OR_ZERO(index_a);
-	if (inc_index_b && !index_b_ff)	index_b	<= WORD_INDEX_PREVIOUS_OR_LAST(index_b);
-	//
-     end
-
-
-   //
-   // Wide Operand Buffer
-   //
-   reg	[255:0]	buf_a_wide;
-
-   always @(posedge clk)
-     //
-     if (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 (shift_wide_a)
-       buf_a_wide <= {buf_a_wide[256-(16+1):0], buf_a_wide[256-16+:16]};
-
-
-   //
-   // Multiplier Array
-   //
-   wire 	mac_inhibit;	// control signal to pause all accumulators
-
-   wire [46: 0] mac[0:15];	// outputs of all accumulators
-   reg [15: 0] 	mac_clear;	// individual per-accumulator clear flag
-
-   assign mac_inhibit = ~enable_mac_ab;
-
-   always @(posedge clk)
-     //
-     if (!clear_mac_ab)
-       mac_clear <= {16{1'b1}};
-     else begin
-
-	if (mac_clear == {16{1'b1}})
-	  mac_clear <= {{14{1'b0}}, 1'b1, {1{1'b0}}};
-	else
-	  mac_clear <= (mac_clear[15] == 1'b0) ? {mac_clear[14:0], 1'b0} : {16{1'b1}};
-
-
-     end
-
-     //
-     // Array of parallel multipliers
-     //
-     genvar i;
-     generate for (i=0; i<16; i=i+1)
-       begin : gen_mac_array
-	  //
-	  mac16_wrapper mac16_inst
-		     (
-		      .clk		(clk),
-		      .ce		(~mac_inhibit),
-
-		      .clr		(mac_clear[i]),
-
-		      .a		(buf_a_wide[16*i+:16]),
-		      .b		(index_b_ff ? b_din[15:0] : b_din[31:16]),
-		      .s		(mac[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[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[i] : si_msb[47*(15-i)+:47];
-       end
-     endgenerate
-
-     always @(posedge clk) begin
-	//
-	if (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 (store_si_msb)
-	     si_msb <= si_msb_new;
-
-	   if (store_si_lsb)
-	     si_lsb <= si_lsb_new;
-	end
-
-     end
-
-
-     //
-     // Accumulators
-     //
-     wire	[46: 0]	add47_cw0_s;
-     wire	[46: 0]	add47_cw1_s;
-
-
-     //
-     // cw0, b, cw1, b
-     //
-     reg	[30: 0]	si_prev_dly;
-     reg	[15: 0]	si_next_dly;
-
-     always @(posedge clk)
-       //
-       if (shift_si)
-	 si_prev_dly <= si_lsb[93:63];
-       else
-	 si_prev_dly <= {31{1'b0}};
-
-       always @(posedge clk)
-	 //
-	 si_next_dly <= si_lsb[62:47];
-
-       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, mask_cw1_sum ? {16{1'b0}} : {1'b0, add47_cw1_s[46:32]}};
-
-       adder47_wrapper add47_cw0_inst
-	 (
-	  .clk	(clk),
-	  .a		(add47_cw0_a),
-	  .b		(add47_cw0_b),
-	  .s		(add47_cw0_s)
-	  );
-
-       adder47_wrapper add47_cw1_inst
-	 (
-	  .clk	(clk),
-	  .a		(add47_cw1_a),
-	  .b		(add47_cw1_b),
-	  .s		(add47_cw1_s)
-	  );
-
-
-
-       //
-       // Full-Size Product
-       //
-       reg	[WORD_COUNTER_WIDTH:0]	bram_c_addr;
-
-       wire	[WORD_COUNTER_WIDTH:0]	reduce_c_addr;
-       wire	[                31:0]	reduce_c_word;
-
-       always @(posedge clk)
-	 //
-	 if (store_c_word)
-	   bram_c_addr <= bram_c_addr + 1'b1;
-	 else
-	   bram_c_addr <= {2*WORD_COUNTER_WIDTH{1'b0}};
-
-	 bram_1rw_1ro_readfirst #
-	   (
-	    .MEM_WIDTH		(32),
-	    .MEM_ADDR_BITS	(WORD_COUNTER_WIDTH + 1)
-	    )
-	 bram_c_inst
-	   (
-	    .clk		(clk),
-
-	    .a_addr		(bram_c_addr),
-	    .a_wr		(store_c_word),
-	    .a_in		(add47_cw1_s[31:0]),
-	    .a_out		(),
-
-	    .b_addr		(reduce_c_addr),
-	    .b_out		(reduce_c_word)
-	    );
-
-
-	 //
-	 // Reduction Stage
-	 //
-	 modular_reductor_256 reduce_256_inst
-	   (
-	    .clk		(clk),
-	    .rst_n		(rst_n),
-
-	    .ena		(reduce_start),
-	    .rdy		(reduce_done),
-
-	    .x_addr		(reduce_c_addr),
-	    .n_addr		(n_addr),
-	    .p_addr		(p_addr),
-	    .p_wren		(p_wren),
-
-	    .x_din		(reduce_c_word),
-	    .n_din		(n_din),
-	    .p_dout		(p_dout)
-	    );
-
-
-	 endmodule
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/rtl/modular/modular_reductor_256.v b/rtl/modular/modular_reductor_256.v
deleted file mode 100644
index 6f31570..0000000
--- a/rtl/modular/modular_reductor_256.v
+++ /dev/null
@@ -1,692 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// modular_reductor_256.v
-// -----------------------------------------------------------------------------
-// Modular reductor.
-//
-// 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 modular_reductor_256
-  (
-   clk, rst_n,
-   ena, rdy,
-   x_addr, n_addr, p_addr, p_wren,
-   x_din, n_din, p_dout
-   );
-
-   //
-   // Constants
-   //
-   localparam	OPERAND_NUM_WORDS	= 8;
-   localparam	WORD_COUNTER_WIDTH	= 3;
-
-
-   //
-   // Handy Numbers
-   //
-   localparam	[WORD_COUNTER_WIDTH:0]	WORD_INDEX_ZERO	= 0;
-   localparam	[WORD_COUNTER_WIDTH:0]	WORD_INDEX_LAST	= 2 * OPERAND_NUM_WORDS - 1;
-
-
-   //
-   // Handy Functions
-   //
-   function	[WORD_COUNTER_WIDTH:0]	WORD_INDEX_PREVIOUS_OR_LAST;
-      input	[WORD_COUNTER_WIDTH: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		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-0:0] 		x_addr;	// index of current X word
-   output	wire [WORD_COUNTER_WIDTH-1:0] 		n_addr;	// index of current N word
-   output	wire [WORD_COUNTER_WIDTH-1:0] 		p_addr;	// index of current P word
-   output	wire 					p_wren;	// store current P word now
-
-   input		wire [                  31:0] 	x_din;	// X
-   input		wire [                  31:0] 	n_din;	// N (must be P-256!)
-   output	wire [                  31:0] 		p_dout;	// P = X mod N
-
-
-   //
-   // Word Indices
-   //
-   reg [WORD_COUNTER_WIDTH:0] 				index_x;
-
-
-   /* map registers to output ports */
-   assign x_addr	= index_x;
-
-
-   //
-   // FSM
-   //
-   localparam	FSM_SHREG_WIDTH	= (2 * OPERAND_NUM_WORDS + 1) + (5 * 2) + 1;
-
-   reg [FSM_SHREG_WIDTH-1:0] 				fsm_shreg;
-
-   assign rdy = fsm_shreg[0];
-
-   wire [2 * OPERAND_NUM_WORDS - 1:0] 			fsm_shreg_inc_index_x	= fsm_shreg[FSM_SHREG_WIDTH - 0*OPERAND_NUM_WORDS - 1 -: 2 * OPERAND_NUM_WORDS];
-   wire [2 * OPERAND_NUM_WORDS - 1:0] 			fsm_shreg_store_word_z	= fsm_shreg[FSM_SHREG_WIDTH - 0*OPERAND_NUM_WORDS - 2 -: 2 * OPERAND_NUM_WORDS];
-   wire [2 *                 5 - 1:0] 			fsm_shreg_reduce_stages	= fsm_shreg[                                        1 +: 2 *                 5];
-
-   wire [5-1:0] 					fsm_shreg_reduce_stage_start;
-   wire [5-1:0] 					fsm_shreg_reduce_stage_stop;
-
-   genvar 						s;
-   generate for (s=0; s<5; s=s+1)
-     begin : gen_fsm_shreg_reduce_stages
-	assign fsm_shreg_reduce_stage_start[5 - (s + 1)]	= fsm_shreg_reduce_stages[2 * (5 - s) - 1];
-	assign fsm_shreg_reduce_stage_stop[5 - (s + 1)]		= fsm_shreg_reduce_stages[2 * (5 - s) - 2];
-     end
-   endgenerate
-
-   wire inc_index_x	= |fsm_shreg_inc_index_x;
-   wire store_word_z	= |fsm_shreg_store_word_z;
-   wire reduce_start	= |fsm_shreg_reduce_stage_start;
-   wire reduce_stop	= |fsm_shreg_reduce_stage_stop;
-   wire store_p		=  fsm_shreg_reduce_stage_stop[0];
-
-
-   wire	reduce_adder0_done;
-   wire	reduce_adder1_done;
-   wire	reduce_subtractor_done;
-
-   wire	reduce_done_all = reduce_adder0_done & reduce_adder1_done & reduce_subtractor_done;
-
-   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 if (!reduce_stop || reduce_done_all)
-	  //
-	  fsm_shreg <= {1'b0, fsm_shreg[FSM_SHREG_WIDTH-1:1]};
-	//
-     end
-
-
-   //
-   // Word Index Increment Logic
-   //
-   always @(posedge clk)
-     //
-     if (rdy)
-       //
-       index_x <= WORD_INDEX_LAST;
-   //
-     else if (inc_index_x)
-       //
-       index_x	<= WORD_INDEX_PREVIOUS_OR_LAST(index_x);
-
-
-   //
-   // Look-up Table
-   //
-
-   //
-   // Take a look at the corresponding C model for more information
-   // on how exactly the math behind reduction works. The first step
-   // is to assemble nine 256-bit values ("z-words") from 32-bit parts
-   // of the full 512-bit product ("c-word"). The problem with z5 is
-   // that it contains c13 two times. This implementation scans from
-   // c15 to c0 and writes current part of c-word into corresponding
-   // parts of z-words. Since those 32-bit parts are stored in block
-   // memories, one source word can only be written to one location in
-   // every z-word at a time. The trick is to delay c13 and then write
-   // the delayed value at the corresponding location in z5 instead of
-   // the next c12. "z_save" flag is used to indicate that the current
-   // word should be delayed and written once again during the next cycle.
-   //
-
-   reg	[9*WORD_COUNTER_WIDTH-1:0]	z_addr;	//
-   reg [9                   -1:0] 	z_wren;	//
-   reg [9                   -1:0] 	z_mask;	// mask input to store zero word
-   reg [9                   -1:0] 	z_save;	// save previous word once again
-
-   always @(posedge clk)
-     //
-     if (inc_index_x)
-       //
-       case (index_x)
-	 //
-	 //                     s9     s8     s7     s6     s5     s4     s3     s2     s1
-	 //                     ||     ||     ||     ||     ||     ||     ||     ||     ||
-	 4'd00:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd00};
-	 4'd01:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd01};
-	 4'd02:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd02};
-	 4'd03:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd03};
-	 4'd04:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd04};
-	 4'd05:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd05};
-	 4'd06:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd06};
-	 4'd07:	z_addr <= {3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'dxx, 3'd07};
-	 4'd08:	z_addr <= {3'd02, 3'd03, 3'd04, 3'd06, 3'd07, 3'd00, 3'd00, 3'd00, 3'dxx};
-	 4'd09:	z_addr <= {3'd03, 3'd04, 3'd06, 3'd03, 3'd00, 3'd01, 3'd01, 3'd01, 3'dxx};
-	 4'd10:	z_addr <= {3'd04, 3'd05, 3'd05, 3'd07, 3'd01, 3'd02, 3'd02, 3'd02, 3'dxx};
-	 4'd11:	z_addr <= {3'd05, 3'd06, 3'd07, 3'd00, 3'd02, 3'd03, 3'd07, 3'd03, 3'dxx};
-	 4'd12:	z_addr <= {3'd06, 3'd07, 3'd00, 3'd01, 3'd06, 3'd04, 3'd03, 3'd04, 3'dxx};
-	 4'd13:	z_addr <= {3'd07, 3'd00, 3'd01, 3'd02, 3'd03, 3'd05, 3'd04, 3'd05, 3'dxx};
-	 4'd14:	z_addr <= {3'd00, 3'd01, 3'd02, 3'd04, 3'd04, 3'd06, 3'd05, 3'd06, 3'dxx};
-	 4'd15:	z_addr <= {3'd01, 3'd02, 3'd03, 3'd05, 3'd05, 3'd07, 3'd06, 3'd07, 3'dxx};
-	 //
-         default:	z_addr <= {9*WORD_COUNTER_WIDTH{1'bX}};
-	 //
-       endcase
-
-   always @(posedge clk)
-     //
-     case (index_x)
-       //
-       //                     9     8     7     6     5     4     3     2     1
-       //                     |     |     |     |     |     |     |     |     |
-       4'd00:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd01:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd02:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd03:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd04:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd05:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd06:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd07:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       4'd08:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       4'd09:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       4'd10:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       4'd11:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       4'd12:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       4'd13:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       4'd14:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       4'd15:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       //
-       default:	z_wren <= {9{1'b0}};
-       //
-     endcase
-
-   always @(posedge clk)
-     //
-     if (inc_index_x)
-       //
-       case (index_x)
-	 //
-	 //                     9     8     7     6     5     4     3     2     1
-	 //                     |     |     |     |     |     |     |     |     |
-	 4'd00:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd01:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd02:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd03:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd04:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd05:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd06:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd07:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd08:	z_mask <= {1'b1, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0};
-	 4'd09:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0};
-	 4'd10:	z_mask <= {1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0};
-	 4'd11:	z_mask <= {1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0};
-	 4'd12:	z_mask <= {1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0};
-	 4'd13:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0};
-	 4'd14:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd15:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 //
-         default:	z_mask <= {9{1'bX}};
-	 //
-       endcase
-
-   always @(posedge clk)
-     //
-     if (inc_index_x)
-       //
-       case (index_x)
-	 //
-	 //                     9     8     7     6     5     4     3     2     1
-	 //                     |     |     |     |     |     |     |     |     |
-	 4'd00:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd01:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd02:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd03:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd04:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd05:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd06:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd07:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd08:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd09:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd10:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd11:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd12:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd13:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd14:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 4'd15:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 //
-         default:	z_save <= {9{1'bX}};
-	 //
-       endcase
-
-
-   //
-   // Intermediate Numbers
-   //
-   reg [WORD_COUNTER_WIDTH-1:0] 	reduce_z_addr[1:9];
-   wire [                32-1:0] 	reduce_z_dout[1:9];
-
-   reg [31: 0] 				x_din_dly;
-   always @(posedge clk)
-     //
-     x_din_dly <= x_din;
-
-
-   genvar 				z;
-   generate for (z=1; z<=9; z=z+1)
-     //
-     begin : gen_z_bram
-	//
-	bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-	bram_c_inst
-		   (
-		    .clk		(clk),
-
-		    .a_addr	(z_addr[(z-1) * WORD_COUNTER_WIDTH +: WORD_COUNTER_WIDTH]),
-		    .a_wr		(z_wren[z-1] & store_word_z),
-		    .a_in		(z_mask[z-1] ? {32{1'b0}} : (z_save[z-1] ? x_din_dly : x_din)),
-		    .a_out	(),
-
-		    .b_addr	(reduce_z_addr[z]),
-		    .b_out	(reduce_z_dout[z])
-		    );
-	//
-     end
-      //
-   endgenerate
-
-
-
-
-   wire	[                32-1:0]	bram_sum0_wr_din;
-   wire [WORD_COUNTER_WIDTH-1:0] 	bram_sum0_wr_addr;
-   wire 				bram_sum0_wr_wren;
-
-   wire [                32-1:0] 	bram_sum1_wr_din;
-   wire [WORD_COUNTER_WIDTH-1:0] 	bram_sum1_wr_addr;
-   wire 				bram_sum1_wr_wren;
-
-   wire [                32-1:0] 	bram_diff_wr_din;
-   wire [WORD_COUNTER_WIDTH-1:0] 	bram_diff_wr_addr;
-   wire 				bram_diff_wr_wren;
-
-   wire [                32-1:0] 	bram_sum0_rd_dout;
-   reg [WORD_COUNTER_WIDTH-1:0] 	bram_sum0_rd_addr;
-
-   wire [                32-1:0] 	bram_sum1_rd_dout;
-   reg [WORD_COUNTER_WIDTH-1:0] 	bram_sum1_rd_addr;
-
-   wire [                32-1:0] 	bram_diff_rd_dout;
-   reg [WORD_COUNTER_WIDTH-1:0] 	bram_diff_rd_addr;
-
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_sum0_inst
-     (
-      .clk		(clk),
-
-      .a_addr	(bram_sum0_wr_addr),
-      .a_wr		(bram_sum0_wr_wren),
-      .a_in		(bram_sum0_wr_din),
-      .a_out	(),
-
-      .b_addr	(bram_sum0_rd_addr),
-      .b_out	(bram_sum0_rd_dout)
-      );
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_sum1_inst
-     (
-      .clk		(clk),
-
-      .a_addr	(bram_sum1_wr_addr),
-      .a_wr		(bram_sum1_wr_wren),
-      .a_in		(bram_sum1_wr_din),
-      .a_out	(),
-
-      .b_addr	(bram_sum1_rd_addr),
-      .b_out	(bram_sum1_rd_dout)
-      );
-
-   bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH))
-   bram_diff_inst
-     (
-      .clk		(clk),
-
-      .a_addr	(bram_diff_wr_addr),
-      .a_wr		(bram_diff_wr_wren),
-      .a_in		(bram_diff_wr_din),
-      .a_out	(),
-
-      .b_addr	(bram_diff_rd_addr),
-      .b_out	(bram_diff_rd_dout)
-      );
-
-
-   wire [WORD_COUNTER_WIDTH-1:0] 	adder0_ab_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] 	adder1_ab_addr;
-   wire [WORD_COUNTER_WIDTH-1:0] 	subtractor_ab_addr;
-
-   reg [                32-1:0] 	adder0_a_din;
-   reg [                32-1:0] 	adder0_b_din;
-
-   reg [                32-1:0] 	adder1_a_din;
-   reg [                32-1:0] 	adder1_b_din;
-
-   reg [                32-1:0] 	subtractor_a_din;
-   reg [                32-1:0] 	subtractor_b_din;
-
-   // n_addr - only 1 output, because all modules are in sync
-
-   modular_adder #
-     (
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS),
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH)
-      )
-   adder_inst0
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(reduce_start),
-      .rdy			(reduce_adder0_done),
-
-      .ab_addr		(adder0_ab_addr),
-      .n_addr		(),
-      .s_addr		(bram_sum0_wr_addr),
-      .s_wren		(bram_sum0_wr_wren),
-
-      .a_din		(adder0_a_din),
-      .b_din		(adder0_b_din),
-      .n_din		(n_din),
-      .s_dout		(bram_sum0_wr_din)
-      );
-
-   modular_adder #
-     (
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS),
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH)
-      )
-   adder_inst1
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(reduce_start),
-      .rdy			(reduce_adder1_done),
-
-      .ab_addr		(adder1_ab_addr),
-      .n_addr		(),
-      .s_addr		(bram_sum1_wr_addr),
-      .s_wren		(bram_sum1_wr_wren),
-
-      .a_din		(adder1_a_din),
-      .b_din		(adder1_b_din),
-      .n_din		(n_din),
-      .s_dout		(bram_sum1_wr_din)
-      );
-
-   modular_subtractor #
-     (
-      .OPERAND_NUM_WORDS	(OPERAND_NUM_WORDS),
-      .WORD_COUNTER_WIDTH	(WORD_COUNTER_WIDTH)
-      )
-   subtractor_inst
-     (
-      .clk			(clk),
-      .rst_n		(rst_n),
-
-      .ena			(reduce_start),
-      .rdy			(reduce_subtractor_done),
-
-      .ab_addr		(subtractor_ab_addr),
-      .n_addr		(n_addr),
-      .d_addr		(bram_diff_wr_addr),
-      .d_wren		(bram_diff_wr_wren),
-
-      .a_din		(subtractor_a_din),
-      .b_din		(subtractor_b_din),
-      .n_din		(n_din),
-      .d_dout		(bram_diff_wr_din)
-      );
-
-
-   //
-   // Address (Operand) Selector
-   //
-   always @(*)
-     //
-     case (fsm_shreg_reduce_stage_stop)
-       //
-       5'b10000: begin
-	  reduce_z_addr[1]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[2]	= adder0_ab_addr;
-	  reduce_z_addr[3]	= adder1_ab_addr;
-	  reduce_z_addr[4]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[5]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[6]	= subtractor_ab_addr;
-	  reduce_z_addr[7]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[8]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[9]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_sum0_rd_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_sum1_rd_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_diff_rd_addr = {WORD_COUNTER_WIDTH{1'bX}};
-       end
-       //
-       5'b01000: begin
-	  reduce_z_addr[1]	= adder0_ab_addr;
-	  reduce_z_addr[2]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[3]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[4]	= adder1_ab_addr;
-	  reduce_z_addr[5]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[6]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[7]	= subtractor_ab_addr;
-	  reduce_z_addr[8]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[9]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_sum0_rd_addr	= adder0_ab_addr;
-	  bram_sum1_rd_addr	= adder1_ab_addr;
-	  bram_diff_rd_addr = subtractor_ab_addr;
-       end
-       //
-       5'b00100: begin
-	  reduce_z_addr[1]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[2]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[3]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[4]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[5]	= adder0_ab_addr;
-	  reduce_z_addr[6]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[7]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[8]	= subtractor_ab_addr;
-	  reduce_z_addr[9]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_sum0_rd_addr	= adder0_ab_addr;
-	  bram_sum1_rd_addr	= adder1_ab_addr;
-	  bram_diff_rd_addr = subtractor_ab_addr;
-       end
-       //
-       5'b00010: begin
-	  reduce_z_addr[1]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[2]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[3]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[4]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[5]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[6]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[7]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[8]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[9]	= subtractor_ab_addr;
-	  bram_sum0_rd_addr	= adder0_ab_addr;
-	  bram_sum1_rd_addr	= adder0_ab_addr;
-	  bram_diff_rd_addr = subtractor_ab_addr;
-       end
-       //
-       5'b00001: begin
-	  reduce_z_addr[1]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[2]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[3]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[4]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[5]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[6]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[7]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[8]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[9]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_sum0_rd_addr	= adder0_ab_addr;
-	  bram_sum1_rd_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_diff_rd_addr = adder0_ab_addr;
-       end
-       //
-       default: begin
-	  reduce_z_addr[1]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[2]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[3]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[4]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[5]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[6]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[7]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[8]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[9]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_sum0_rd_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_sum1_rd_addr	= {WORD_COUNTER_WIDTH{1'bX}};
-	  bram_diff_rd_addr = {WORD_COUNTER_WIDTH{1'bX}};
-       end
-       //
-     endcase
-
-
-   //
-   // adder 0
-   //
-   always @(*) begin
-      //
-      case (fsm_shreg_reduce_stage_stop)
-	5'b10000:	adder0_a_din = reduce_z_dout[2];
-	5'b01000:	adder0_a_din = bram_sum0_rd_dout;
-	5'b00100:	adder0_a_din = bram_sum0_rd_dout;
-	5'b00010:	adder0_a_din = bram_sum0_rd_dout;
-	5'b00001:	adder0_a_din = bram_sum0_rd_dout;
-	default:		adder0_a_din = {32{1'bX}};
-      endcase
-      //
-      case (fsm_shreg_reduce_stage_stop)
-	5'b10000:	adder0_b_din = reduce_z_dout[2];
-	5'b01000:	adder0_b_din = reduce_z_dout[1];
-	5'b00100:	adder0_b_din = reduce_z_dout[5];
-	5'b00010:	adder0_b_din = bram_sum1_rd_dout;
-	5'b00001:	adder0_b_din = bram_diff_rd_dout;
-	default:		adder0_b_din = {32{1'bX}};
-      endcase
-      //
-   end
-
-   //
-   // adder 1
-   //
-   always @(*) begin
-      //
-      case (fsm_shreg_reduce_stage_stop)
-	5'b10000:	adder1_a_din = reduce_z_dout[3];
-	5'b01000:	adder1_a_din = bram_sum1_rd_dout;
-	5'b00100:	adder1_a_din = bram_sum1_rd_dout;
-	5'b00010:	adder1_a_din = {32{1'bX}};
-	5'b00001:	adder1_a_din = {32{1'bX}};
-	default:		adder1_a_din = {32{1'bX}};
-      endcase
-      //
-      case (fsm_shreg_reduce_stage_stop)
-	5'b10000:	adder1_b_din = reduce_z_dout[3];
-	5'b01000:	adder1_b_din = reduce_z_dout[4];
-	5'b00100:	adder1_b_din = {32{1'b0}};
-	5'b00010:	adder1_b_din = {32{1'bX}};
-	5'b00001:	adder1_b_din = {32{1'bX}};
-	default:		adder1_b_din = {32{1'bX}};
-      endcase
-      //
-   end
-
-
-   //
-   // subtractor
-   //
-   always @(*) begin
-      //
-      case (fsm_shreg_reduce_stage_stop)
-	5'b10000:	subtractor_a_din = {32{1'b0}};
-	5'b01000:	subtractor_a_din = bram_diff_rd_dout;
-	5'b00100:	subtractor_a_din = bram_diff_rd_dout;
-	5'b00010:	subtractor_a_din = bram_diff_rd_dout;
-	5'b00001:	subtractor_a_din = {32{1'bX}};
-	default:		subtractor_a_din = {32{1'bX}};
-      endcase
-      //
-      case (fsm_shreg_reduce_stage_stop)
-	5'b10000:	subtractor_b_din = reduce_z_dout[6];
-	5'b01000:	subtractor_b_din = reduce_z_dout[7];
-	5'b00100:	subtractor_b_din = reduce_z_dout[8];
-	5'b00010:	subtractor_b_din = reduce_z_dout[9];
-	5'b00001:	subtractor_b_din = {32{1'bX}};
-	default:		subtractor_b_din = {32{1'bX}};
-      endcase
-      //
-   end
-
-
-   //
-   // Address Mapping
-   //
-   assign p_addr	= bram_sum0_wr_addr;
-   assign p_wren	= bram_sum0_wr_wren & store_p;
-   assign p_dout	= bram_sum0_wr_din;
-
-
-endmodule
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/stm32_driver/ecdsa256_driver_sample.c b/stm32_driver/ecdsa256_driver_sample.c
index 1950491..35f1525 100644
--- a/stm32_driver/ecdsa256_driver_sample.c
+++ b/stm32_driver/ecdsa256_driver_sample.c
@@ -31,34 +31,44 @@
 // curve selection
 #define USE_CURVE			1
 
-#include "../../../user/shatov/ecdsa_fpga_model/ecdsa_model.h"
+#include "ecdsa_test_vector_nsa.h"
+#include "ecdsa_test_vector_randomized.h"
 
-#define BUF_NUM_WORDS		(OPERAND_WIDTH / (sizeof(uint32_t) << 3))	// 8
+#define bool uint32_t // very dirty hack, but works in this particular case
+#include "ecdsa_fpga_lowlevel.h"
+#include "ecdsa_fpga_multiword.h"
+#include "ecdsa_fpga_curve.h"
+#undef bool
+
+#define BUF_NUM_WORDS FPGA_OPERAND_NUM_WORDS
 
 //
 // test vectors
 //
-static const uint32_t p256_d[BUF_NUM_WORDS]  = ECDSA_D;
-static const uint32_t p256_qx[BUF_NUM_WORDS] = ECDSA_Q_X;
-static const uint32_t p256_qy[BUF_NUM_WORDS] = ECDSA_Q_Y;
+static const uint32_t p256_d_nsa[BUF_NUM_WORDS]  = ECDSA_P256_D_NSA_INIT;
+static const uint32_t p256_qx_nsa[BUF_NUM_WORDS] = ECDSA_P256_QX_NSA_INIT;
+static const uint32_t p256_qy_nsa[BUF_NUM_WORDS] = ECDSA_P256_QY_NSA_INIT;
+
+static const uint32_t p256_k_nsa[BUF_NUM_WORDS]  = ECDSA_P256_K_NSA_INIT;
+static const uint32_t p256_rx_nsa[BUF_NUM_WORDS] = ECDSA_P256_RX_NSA_INIT;
+static const uint32_t p256_ry_nsa[BUF_NUM_WORDS] = ECDSA_P256_RY_NSA_INIT;
 
-static const uint32_t p256_k[BUF_NUM_WORDS]  = ECDSA_K;
-static const uint32_t p256_rx[BUF_NUM_WORDS] = ECDSA_R_X;
-static const uint32_t p256_ry[BUF_NUM_WORDS] = ECDSA_R_Y;
+static const uint32_t p256_d_random[BUF_NUM_WORDS]  = ECDSA_P256_D_RANDOM_INIT;
+static const uint32_t p256_qx_random[BUF_NUM_WORDS] = ECDSA_P256_QX_RANDOM_INIT;
+static const uint32_t p256_qy_random[BUF_NUM_WORDS] = ECDSA_P256_QY_RANDOM_INIT;
 
-static const uint32_t p256_i[BUF_NUM_WORDS]  = ECDSA_ONE;
-static const uint32_t p256_gx[BUF_NUM_WORDS] = ECDSA_G_X;
-static const uint32_t p256_gy[BUF_NUM_WORDS] = ECDSA_G_Y;
 
-static const uint32_t p256_hx[BUF_NUM_WORDS] = ECDSA_H_X;
-static const uint32_t p256_hy[BUF_NUM_WORDS] = ECDSA_H_Y;
+static const uint32_t p256_gx[BUF_NUM_WORDS] = ECDSA_P256_GX_INIT;
+static const uint32_t p256_gy[BUF_NUM_WORDS] = ECDSA_P256_GY_INIT;
+static const uint32_t p256_hx[BUF_NUM_WORDS] = ECDSA_P256_HX_INIT;
+static const uint32_t p256_hy[BUF_NUM_WORDS] = ECDSA_P256_HY_INIT;
+static const uint32_t p256_n[BUF_NUM_WORDS]  = ECDSA_P256_N_INIT;
 
-static const uint32_t p256_z[BUF_NUM_WORDS]  = ECDSA_ZERO;
-static const uint32_t p256_n[BUF_NUM_WORDS]  = ECDSA_N;
+static uint32_t p256_zero[BUF_NUM_WORDS];
+static uint32_t p256_two [BUF_NUM_WORDS];
+static uint32_t p256_n1  [BUF_NUM_WORDS];
+static uint32_t p256_n2  [BUF_NUM_WORDS];
 
-static uint32_t p256_2[BUF_NUM_WORDS];	// 2
-static uint32_t p256_n1[BUF_NUM_WORDS];	// n + 1
-static uint32_t p256_n2[BUF_NUM_WORDS];	// n + 2
 
 //
 // prototypes
@@ -84,9 +94,11 @@ int main()
 
   uint32_t core_name0;
   uint32_t core_name1;
+	uint32_t core_version;
 
-  fmc_read_32(CORE_ADDR_NAME0, &core_name0);
-  fmc_read_32(CORE_ADDR_NAME1, &core_name1);
+  fmc_read_32(CORE_ADDR_NAME0,   &core_name0);
+  fmc_read_32(CORE_ADDR_NAME1,   &core_name1);
+	fmc_read_32(CORE_ADDR_VERSION, &core_version);
 
   // "ecds", "a256"
   if ((core_name0 != 0x65636473) || (core_name1 != 0x61323536)) {
@@ -98,15 +110,15 @@ int main()
 	// prepare more numbers
 	size_t w;
 	for (w=0; w<BUF_NUM_WORDS; w++)
-	{	p256_2[w]  = p256_z[w];	// p256_2 = p256_z = 0
-		p256_n1[w] = p256_n[w];	// p256_n1 = p256_n = N
-		p256_n2[w] = p256_n[w];	// p256_n2 = p256_n = N
+	{	p256_zero[w] = 0;
+		p256_two [w] = 0;
+		p256_n1  [w] = p256_n   [w];
+		p256_n2  [w] = p256_n   [w];
 	}
 	
-	p256_2[BUF_NUM_WORDS-1]  += 2;	// p256_2 = 2
-	p256_n1[BUF_NUM_WORDS-1] += 1;	// p256_n1 = N + 1
-	p256_n2[BUF_NUM_WORDS-1] += 2;	// p256_n2 = N + 2
-	
+	p256_two[BUF_NUM_WORDS-1] += 2;
+	p256_n1 [BUF_NUM_WORDS-1] += 1;
+	p256_n2 [BUF_NUM_WORDS-1] += 2;
 	
 	
   // repeat forever
@@ -114,15 +126,12 @@ int main()
     {
       ok = 1;
 			
-      ok = ok && test_p256_multiplier(p256_d, p256_qx, p256_qy);	/* Q = d * G */
-      ok = ok && test_p256_multiplier(p256_k, p256_rx, p256_ry);	/* R = k * G */
+      ok = ok && test_p256_multiplier(p256_d_nsa,    p256_qx_nsa,    p256_qy_nsa);	  /* Q = d * G */
+      ok = ok && test_p256_multiplier(p256_k_nsa,    p256_rx_nsa,    p256_ry_nsa);	  /* R = k * G */
+			ok = ok && test_p256_multiplier(p256_d_random, p256_qx_random, p256_qy_random);	/* Q = d * G */
 			
-      ok = ok && test_p256_multiplier(p256_z, p256_z,  p256_z);		/* O = 0 * G */
-      ok = ok && test_p256_multiplier(p256_i, p256_gx, p256_gy);	/* G = 1 * G */
-			
-      ok = ok && test_p256_multiplier(p256_n, p256_z,  p256_z);		/* O = n * G */
-
-      ok = ok && test_p256_multiplier(p256_n1, p256_gx, p256_gy);	/* G = (n + 1) * G */
+      ok = ok && test_p256_multiplier(p256_n,   p256_zero, p256_zero); /* O = n * G */
+      ok = ok && test_p256_multiplier(p256_n1,  p256_gx,   p256_gy);	 /* G = (n + 1) * G */
 			
 	//
 	// The following two vectors test the virtually never taken path in the curve point
@@ -136,8 +145,9 @@ int main()
 	// on the fly. Note that in practice one should never be multiplying by anything larger than (n-1),
 	// because both the secret key and the per-message (random) number must be from [1, n-1].
 	//
-	ok = ok && test_p256_multiplier(p256_2, p256_hx, p256_hy);	/* H = 2 * G */
-	ok = ok && test_p256_multiplier(p256_n2, p256_hx, p256_hy);	/* H = (n + 2) * G */			
+			ok = ok && test_p256_multiplier(p256_two, p256_hx,   p256_hy);	 /* H = 2 * G */
+      ok = ok && test_p256_multiplier(p256_n2,  p256_hx,   p256_hy);	 /* H = (n + 2) * G */
+
 			
       if (!ok) {
 				led_off(LED_GREEN);
@@ -163,14 +173,14 @@ int test_p256_multiplier(const uint32_t *k, const uint32_t *px, const uint32_t *
   // fill k
   for (i=0; i<BUF_NUM_WORDS; i++) {
     k_word = k[i];
-    fmc_write_32(CORE_ADDR_BUF_K + ((BUF_NUM_WORDS - (i + 1)) * sizeof(uint32_t)), &k_word);
+    fmc_write_32(CORE_ADDR_BUF_K + ((BUF_NUM_WORDS - (i + 1)) * sizeof(uint32_t)), k_word);
   }
 
   // clear 'next' control bit, then set 'next' control bit again to trigger new operation
   reg_control = 0;
-  fmc_write_32(CORE_ADDR_CONTROL, &reg_control);
+  fmc_write_32(CORE_ADDR_CONTROL, reg_control);
   reg_control = CORE_CONTROL_BIT_NEXT;
-  fmc_write_32(CORE_ADDR_CONTROL, &reg_control);
+  fmc_write_32(CORE_ADDR_CONTROL, reg_control);
 
   // wait for 'ready' status bit to be set
   num_cyc = 0;
@@ -207,6 +217,16 @@ void toggle_yellow_led(void)
 }
 
 
+//
+// systick
+//
+void SysTick_Handler(void)
+{
+    HAL_IncTick();
+    HAL_SYSTICK_IRQHandler();
+}
+
+
 //
 // 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