[Cryptech-Commits] [core/pkey/ecdsa384] branch master updated: Same changes as per the P-256 core.

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

The following commit(s) were added to refs/heads/master by this push:
     new 4abd3ef  Same changes as per the P-256 core.
4abd3ef is described below

commit 4abd3ef0466dfbfe4b08488125375bccdd581d6a
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Wed Dec 19 15:40:36 2018 +0300

    Same changes as per the P-256 core.
---
 bench/ecdsa384_test_vector_nsa.vh     |  31 ++
 bench/ecdsa_test_vector_randomized.vh |  29 ++
 bench/tb_curve_adder_384.v            | 426 ----------------
 bench/tb_curve_doubler_384.v          | 413 ----------------
 bench/tb_curve_multiplier_384.v       | 440 +++++++++--------
 bench/tb_modular_multiplier_384.v     | 366 --------------
 rtl/curve/curve_dbl_add_384.v         | 893 ----------------------------------
 rtl/curve/curve_mul_384.v             | 720 ---------------------------
 rtl/curve/rom/brom_p384_delta.v       |  72 ---
 rtl/curve/rom/brom_p384_g_x.v         |  72 ---
 rtl/curve/rom/brom_p384_g_y.v         |  72 ---
 rtl/curve/rom/brom_p384_h_x.v         |  72 ---
 rtl/curve/rom/brom_p384_h_y.v         |  71 ---
 rtl/curve/rom/brom_p384_one.v         |  72 ---
 rtl/curve/rom/brom_p384_q.v           |  72 ---
 rtl/curve/rom/brom_p384_zero.v        |  42 --
 rtl/ecdsa384.v                        | 160 ------
 rtl/ecdsa384_banks_array.v            | 118 +++++
 rtl/ecdsa384_base_point_multiplier.v  | 310 ++++++++++++
 rtl/ecdsa384_core_top.v               | 150 ++++++
 rtl/ecdsa384_microcode_rom.v          | 553 +++++++++++++++++++++
 rtl/ecdsa384_operand_bank.v           | 188 +++++++
 rtl/ecdsa384_uop_worker.v             | 604 +++++++++++++++++++++++
 rtl/ecdsa384_wrapper.v                |  72 +--
 rtl/modular/modular_multiplier_384.v  | 402 ---------------
 rtl/modular/modular_reductor_384.v    | 739 ----------------------------
 26 files changed, 2246 insertions(+), 4913 deletions(-)

diff --git a/bench/ecdsa384_test_vector_nsa.vh b/bench/ecdsa384_test_vector_nsa.vh
new file mode 100644
index 0000000..048c5a5
--- /dev/null
+++ b/bench/ecdsa384_test_vector_nsa.vh
@@ -0,0 +1,31 @@
+/* Values from "Suite B Implementer's Guide to FIPS 186-3 (ECDSA)" */
+
+localparam [383:0] ECDSA_P384_D_NSA =
+    {32'hc838b852, 32'h53ef8dc7, 32'h394fa580, 32'h8a518398,
+	 32'h1c7deef5, 32'ha69ba8f4, 32'hf2117ffe, 32'ha39cfcd9,
+	 32'h0e95f6cb, 32'hc854abac, 32'hab701d50, 32'hc1f3cf24};
+
+localparam [383:0] ECDSA_P384_QX_NSA =
+	{32'h1fbac8ee, 32'hbd0cbf35, 32'h640b39ef, 32'he0808dd7,
+	 32'h74debff2, 32'h0a2a329e, 32'h91713baf, 32'h7d7f3c3e,
+	 32'h81546d88, 32'h3730bee7, 32'he48678f8, 32'h57b02ca0};
+	 
+localparam [383:0] ECDSA_P384_QY_NSA =
+	{32'heb213103, 32'hbd68ce34, 32'h3365a8a4, 32'hc3d4555f,
+	 32'ha385f533, 32'h0203bdd7, 32'h6ffad1f3, 32'haffb9575,
+	 32'h1c132007, 32'he1b24035, 32'h3cb0a4cf, 32'h1693bdf9};
+	 
+localparam [383:0] ECDSA_P384_K_NSA =
+	{32'hdc6b4403, 32'h6989a196, 32'he39d1cda, 32'hc000812f,
+	 32'h4bdd8b2d, 32'hb41bb33a, 32'hf5137258, 32'h5ebd1db6,
+	 32'h3f0ce827, 32'h5aa1fd45, 32'he2d2a735, 32'hf8749359};
+
+localparam [383:0] ECDSA_P384_RX_NSA =
+	{32'ha0c27ec8, 32'h93092dea, 32'h1e1bd2cc, 32'hfed3cf94,
+	 32'h5c8134ed, 32'h0c9f8131, 32'h1a0f4a05, 32'h942db8db,
+	 32'hed8dd59f, 32'h267471d5, 32'h462aa14f, 32'he72de856};
+	 
+localparam [383:0] ECDSA_P384_RY_NSA =
+	{32'h85564940, 32'h9815bb91, 32'h424eaca5, 32'hfd76c973,
+	 32'h75d575d1, 32'h422ec53d, 32'h343bd33b, 32'h847fdf0c,
+	 32'h11569685, 32'hb528ab25, 32'h49301542, 32'h8d7cf72b};
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_384.v b/bench/tb_curve_adder_384.v
deleted file mode 100644
index 4fee4e1..0000000
--- a/bench/tb_curve_adder_384.v
+++ /dev/null
@@ -1,426 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_curve_adder_384.v
-// -----------------------------------------------------------------------------
-// Testbench for 384-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_384;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[383:0]	PX_1	= 384'h7d51764067faaac686ee307807af5544a93e13c540cac538c7853a590102fa5fe6cdcc7791e44b76ef21c57e21df37e5;
-   localparam	[383:0]	PY_1	= 384'h046ed01f219649209a4cfd43572d7bdd1f10f74d5be895a6c8da8e8edfc2601aaf7651e497b8688cf02ba5e1c7e77773;
-   localparam	[383:0]	PZ_1	= 384'h27c452f26af1ece2924446b574969fd102556bd28712ff4b3eb1044c5ec23e59f958793e10a510f0aef98c3b724df1d5;
-
-   localparam	[383:0]	RX_1	= 384'h238faca9e58d1fe1b59a24ba94ec6d9836fc360cb84e103715f1761554ff6a09b6d605a34f63ae0f995f59c162e7ff24;
-   localparam	[383:0]	RY_1	= 384'h63b7c7672a310f779a2047315523788d69b823d4e97e26c3b45201b0345a95de977024e97e8648215a637727d0f17747;
-   localparam	[383:0]	RZ_1	= 384'h394b5d916df6f9120c7771c750df3bc910998eb0a08daac1ca6e15ef70780fd48bf794d06f9cbe9568a2dbf4362dda86;
-
-
-   localparam	[383:0]	PX_2	= 384'h8418363a2fe99e888abba4df9e4a0e55452b9e968454ffadc96b4fb8072174109755c564a7be3c2f860652315d635f56;
-   localparam	[383:0]	PY_2	= 384'h2bef570ce39347040330df4ac581fcc7d9dd9deb286bd80f05257d90d6560f1b5381009a3a6f0acc1ea30a5e7cc7d8b8;
-   localparam	[383:0]	PZ_2	= 384'h86a8b840bd52d4dc58e9e4323fd4b40ea9b262a8cb45f7e95f5407b7e5eacc16fe4ce70125f20b76b37900af12cbf909;
-
-   localparam	[383:0]	RX_2	= 384'h7de41f9c2d48cd65d2cd1288c4fcdcd5bfe37575b23b8784e6091917a1c92c264a1105ce3c4ab88ca53947f35610f671;
-   localparam	[383:0]	RY_2	= 384'h419decfcef28d06a824595bbcb86ff56aebe48a33ceb80f0a256b90aee8214d0d879454842457d49e00a2330cc0ccb57;
-   localparam	[383:0]	RZ_2	= 384'h63843f81a3427e4dea2e3e150c16d26a4aa2af4d8037a1012e0490babdfa55606e5cea5e183cc147f2c1b377748ae58b;
-
-
-   localparam	[383:0]	PX_3	= 384'hd95cd4004f9417b3bea71ac087da4849841c4fbb41b500736773f41f241414024d0025e1a4337e5b24b1fe2ba2e51a83;
-   localparam	[383:0]	PY_3	= 384'h53650c78f3347a07248d6f6452dd80f5e373c7eddc810c6123c912b55da1a297e147e834547d1af4938fc139e71958f7;
-   localparam	[383:0]	PZ_3	= 384'hfbcfa387106d61d1e1e5f660206189f13e0861b3eb2e880b200cae1878b8b47bd5b727b2825a5f395025bf42a571093b;
-
-   localparam	[383:0]	RX_3	= 384'hf94e9fb67d6bac22276bb4fb4f965419f1907078236dd8520ff416e8525933055795c496d344a2e1cce480557dde88f4;
-   localparam	[383:0]	RY_3	= 384'h3feb5bc25c380ead1a149ab2f5e3ac4cfeaa5d91bd66dda0f29d6e02520ea8583bb3ab744fb826c18981f7bac03a0886;
-   localparam	[383:0]	RZ_3	= 384'hbc364ce11866cdeb1abdbc34b633e54fbb000090134600cb6dbff71f69e3d24843e40af30c07444530b53acb89eef49b;
-
-
-   localparam	[383:0]	PX_4	= 384'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-   localparam	[383:0]	PY_4	= 384'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-   localparam	[383:0]	PZ_4	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
-
-   localparam	[383:0]	RX_4	= 384'haa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7; // G.x
-   localparam	[383:0]	RY_4	= 384'h3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f; // G.y
-   localparam	[383:0]	RZ_4	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
-
-
-   localparam	[383:0]	PX_5	= 384'haa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7; // G.x
-   localparam	[383:0]	PY_5	= 384'h3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f; // G.y
-   localparam	[383:0]	PZ_5	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[383:0]	RX_5	= 384'haaf06bba82e9f590e29c71c219bea51723c5893ae8b0c8cf4c117c3efb57ab8d55fa1b428155ad278b5743911b13ea8a; // H.x
-   localparam	[383:0]	RY_5	= 384'hc9e821b569d9d390a26167406d6d23d6070be242d765eb831625ceec4a0f473ef59f4e30e2817e6285bce2846f15f19d; // H.y
-   localparam	[383:0]	RZ_5	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
-
-
-   localparam	[383:0]	PX_6	= 384'haa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7; // G.x
-   localparam	[383:0]	PY_6	= 384'h3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f; // G.y
-   localparam	[383:0]	PZ_6	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[383:0]	RX_6	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;	//
-   localparam	[383:0]	RY_6	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;	// O
-   localparam	[383:0]	RZ_6	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;	//
-
-
-   localparam	[383:0]	Q	= 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  4;
-   localparam	OPERAND_NUM_WORDS	= 12;
-
-
-   //
-   // 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_384 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_384: SUCCESS");
-      else	$display("tb_curve_adder_384: FAILURE");
-      //
-      $finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg		t_ok;
-
-   integer	w;
-
-   task test_curve_adder;
-
-      input	[383:0]	px;
-      input [383:0] 	py;
-      input [383:0] 	pz;
-
-      input [383:0] 	rx;
-      input [383:0] 	ry;
-      input [383:0] 	rz;
-
-      reg [383:0] 	px_shreg;
-      reg [383:0] 	py_shreg;
-      reg [383:0] 	pz_shreg;
-
-      reg [383:0] 	rx_shreg;
-      reg [383:0] 	ry_shreg;
-      reg [383:0] 	rz_shreg;
-
-      reg [383: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[383:32]};
-	    py_shreg = {{32{1'bX}}, py_shreg[383:32]};
-	    pz_shreg = {{32{1'bX}}, pz_shreg[383:32]};
-	    q_shreg  = {{32{1'bX}}, q_shreg[383: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[383:32]};
-	    ry_shreg = {tb_ry_data, ry_shreg[383:32]};
-	    rz_shreg = {tb_rz_data, rz_shreg[383: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_384.v b/bench/tb_curve_doubler_384.v
deleted file mode 100644
index 54a9914..0000000
--- a/bench/tb_curve_doubler_384.v
+++ /dev/null
@@ -1,413 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_curve_doubler_384.v
-// -----------------------------------------------------------------------------
-// Testbench for 384-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_384;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[383:0]	PX_1	= 384'haa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7;
-   localparam	[383:0]	PY_1	= 384'h3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f;
-   localparam	[383:0]	PZ_1	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
-
-   localparam	[383:0]	RX_1	= 384'he50dbe0981ef5f4f52eebd29e34e6d18d279318fe6b5d5616c54c93ea906c671b223d61ab7ba23cd59ab4f6ec5e40b94;
-   localparam	[383:0]	RY_1	= 384'h5b939b5a52ac7ebed90b8c1a809fb3a5c068b421b9e0a16208c2e53b1fe41e8373333e360ad2205e9dd63d29f1e0757a;
-   localparam	[383:0]	RZ_1	= 384'h6c2fbc952c4c58debb3d317f2525b853f1e83b7a513428f9d3b462276be1718014c1639c3afd033af4863af921d41cbe;
-
-
-   localparam	[383:0]	PX_2	= 384'heea14dc6c53e682b16c979fcbf2b39c0f5c43efa5b412f3e9bec8251a5ff9e243f46c6ba91a1604abdd5028b56e60334;
-   localparam	[383:0]	PY_2	= 384'h7ff6e6e9ed8da4aea5baa06d3a9583b6a3f206e935566659cd2025202a9e2a62e0c44e603f3a4304bfa974470f53f646;
-   localparam	[383:0]	PZ_2	= 384'hcb16156bf82550274e39900f2ed4359794160a166257ae2c71c6503c129b6ce92f31277387aa1c538e7702e3658a883d;
-
-   localparam	[383:0]	RX_2	= 384'h9455050d6d00285ae2cd25c95372b30d321fb31899f7b0e6f3b4dd557d3465edbc500cc403b076c7534a07a48d87824d;
-   localparam	[383:0]	RY_2	= 384'hd0cc7a7eb6fbe9cd962efa82f89b701fbd1f8a3579066feda96c9124ee3ef2764d923a2c0039e06865442dbf3ed460ae;
-   localparam	[383:0]	RZ_2	= 384'h473d297a1e5ed8b7afd51a27d5d933ab4555414ef75e1104c1fb56ba9b110f5d0d63a79e8e12edc4432c37663cc828f2;
-
-
-   localparam	[383:0]	PX_3	= 384'h4af343df7a804f6b345562a471c4cea419f5e87086eaba95b7a7fa43aeb24a357d22047eea55c529fcdfb44ea80d3aab;
-   localparam	[383:0]	PY_3	= 384'hfa3e2ceb637c90fde564039da3e256456a8d0995c2f69846bf3e22f2f0760a2df00f2df2f79ce2484ed5b26124d733f1;
-   localparam	[383:0]	PZ_3	= 384'hdf144e3659137591d09ba17e7045f74c477e4f27e0f6c602f11306def2abeae08aee53fa40e3ca3b3ca52f9eaae47720;
-
-   localparam	[383:0]	RX_3	= 384'h9e2aad0ad19c585e03af779d1205a3a98bf7d367c0c829f741161983dc0d24d222d5d9c2ae39399ff40d4974df22ce4d;
-   localparam	[383:0]	RY_3	= 384'he0e40da86ae320396c813bb891f31f3d59be8c4957c602b56b5aa976e47d128127625b1ce7470fa33ed9e57eca5a268d;
-   localparam	[383:0]	RZ_3	= 384'h836e9d9117ba665abbee7063599a8631cd42f685a8bc29b05895c2928c19f640a065cfd2cc5b0d607ea52e388be513cf;
-
-
-   localparam	[383:0]	PX_4	= 384'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-   localparam	[383:0]	PY_4	= 384'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-   localparam	[383:0]	PZ_4	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
-
-   localparam	[383:0]	RX_4	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
-   localparam	[383:0]	RY_4	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
-   localparam	[383:0]	RZ_4	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
-
-
-   localparam	[383:0]	Q	= 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff;
-
-
-
-   //
-   // TODO: Test special cases!
-   //
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  4;
-   localparam	OPERAND_NUM_WORDS	= 12;
-
-
-   //
-   // 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_384 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_384: SUCCESS");
-      else	$display("tb_curve_doubler_384: FAILURE");
-      //
-      //		$finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg		t_ok;
-
-   integer	w;
-
-   task test_curve_doubler;
-
-      input	[383:0]	px;
-      input [383:0] 	py;
-      input [383:0] 	pz;
-
-      input [383:0] 	rx;
-      input [383:0] 	ry;
-      input [383:0] 	rz;
-
-      reg [383:0] 	px_shreg;
-      reg [383:0] 	py_shreg;
-      reg [383:0] 	pz_shreg;
-
-      reg [383:0] 	rx_shreg;
-      reg [383:0] 	ry_shreg;
-      reg [383:0] 	rz_shreg;
-
-      reg [383: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[383:32]};
-	    py_shreg = {{32{1'bX}}, py_shreg[383:32]};
-	    pz_shreg = {{32{1'bX}}, pz_shreg[383:32]};
-	    q_shreg  = {{32{1'bX}}, q_shreg[383: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[383:32]};
-	    ry_shreg = {tb_ry_data, ry_shreg[383:32]};
-	    rz_shreg = {tb_rz_data, rz_shreg[383: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_384.v b/bench/tb_curve_multiplier_384.v
index 163f39f..ad78677 100644
--- a/bench/tb_curve_multiplier_384.v
+++ b/bench/tb_curve_multiplier_384.v
@@ -2,11 +2,11 @@
 //
 // tb_curve_multiplier_384.v
 // -----------------------------------------------------------------------------
-// Testbench for 384-bit curve point scalar multiplier.
+// Testbench for 384-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,264 +36,278 @@
 //
 //------------------------------------------------------------------------------
 
-//------------------------------------------------------------------------------
-`timescale 1ns / 1ps
-//------------------------------------------------------------------------------
-
 module tb_curve_multiplier_384;
 
 
-   //
-   // Test Vectors
-   //
-
-		/* Q = d * G */
-   localparam	[383:0]	K_1	= 384'hc838b85253ef8dc7394fa5808a5183981c7deef5a69ba8f4f2117ffea39cfcd90e95f6cbc854abacab701d50c1f3cf24;
-   localparam	[383:0]	PX_1	= 384'h1fbac8eebd0cbf35640b39efe0808dd774debff20a2a329e91713baf7d7f3c3e81546d883730bee7e48678f857b02ca0;
-   localparam	[383:0]	PY_1	= 384'heb213103bd68ce343365a8a4c3d4555fa385f5330203bdd76ffad1f3affb95751c132007e1b240353cb0a4cf1693bdf9;
-
-		/* R = k * G */
-   localparam	[383:0]	K_2	= 384'hdc6b44036989a196e39d1cdac000812f4bdd8b2db41bb33af51372585ebd1db63f0ce8275aa1fd45e2d2a735f8749359;
-   localparam	[383:0]	PX_2	= 384'ha0c27ec893092dea1e1bd2ccfed3cf945c8134ed0c9f81311a0f4a05942db8dbed8dd59f267471d5462aa14fe72de856;
-   localparam	[383:0]	PY_2	= 384'h855649409815bb91424eaca5fd76c97375d575d1422ec53d343bd33b847fdf0c11569685b528ab25493015428d7cf72b;
-
-		/* O = n * G */
-   localparam	[383:0]	K_3	= 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973;
-   localparam	[383:0]	PX_3	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
-   localparam	[383:0]	PY_3	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
-		
-		/* H = 2 * G */
-	localparam	[383:0]	K_4	= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002;
-	localparam	[383:0]	PX_4	= 384'h08d999057ba3d2d969260045c55b97f089025959a6f434d651d207d19fb96e9e4fe0e86ebe0e64f85b96a9c75295df61;
-	localparam	[383:0]	PY_4	= 384'h8e80f1fa5b1b3cedb7bfe8dffd6dba74b275d875bc6cc43e904e505f256ab4255ffd43e94d39e22d61501e700a940e80;
-		
-		/* G = (n + 1) * G */
-	localparam	[383:0]	K_5	= 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 + 'd1;
-	localparam	[383:0]	PX_5	= 384'haa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7;
-	localparam	[383:0]	PY_5	= 384'h3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f;
-
-		/* H = (n + 2) * G */
-	localparam	[383:0]	K_6	= 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 + 'd2;
-	localparam	[383:0]	PX_6	= 384'h08d999057ba3d2d969260045c55b97f089025959a6f434d651d207d19fb96e9e4fe0e86ebe0e64f85b96a9c75295df61;
-	localparam	[383:0]	PY_6	= 384'h8e80f1fa5b1b3cedb7bfe8dffd6dba74b275d875bc6cc43e904e505f256ab4255ffd43e94d39e22d61501e700a940e80;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  4;
-   localparam	OPERAND_NUM_WORDS	= 12;
-
-
-   //
-   // 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_384 uut
-     (
-      .clk		(clk),
-      .rst_n		(rst_n),
+        //
+        // Test Vectors
+        //
+    `include "ecdsa384_test_vector_nsa.vh"
+    `include "ecdsa_test_vector_randomized.vh"
+
+
+        //
+        // Core Parameters
+        //
+    localparam WORD_COUNTER_WIDTH =  4;
+    localparam OPERAND_NUM_WORDS  = 12;
 
-      .ena		(ena),
-      .rdy		(rdy),
 
-      .k_addr		(core_k_addr),
-      .rx_addr		(core_px_addr),
-      .ry_addr		(core_py_addr),
+       //
+       // P-384 Domain Parameters
+       //
+    localparam ECDSA_P384_N =
+        {32'hffffffff, 32'hffffffff, 32'hffffffff, 32'hffffffff,
+         32'hffffffff, 32'hffffffff, 32'hc7634d81, 32'hf4372ddf,
+         32'h581a0db2, 32'h48b0a77a, 32'hecec196a, 32'hccc52973};
+
+    localparam ECDSA_P384_GX =
+        {32'haa87ca22, 32'hbe8b0537, 32'h8eb1c71e, 32'hf320ad74,
+         32'h6e1d3b62, 32'h8ba79b98, 32'h59f741e0, 32'h82542a38,
+         32'h5502f25d, 32'hbf55296c, 32'h3a545e38, 32'h72760ab7};
 
-      .rx_wren		(core_px_wren),
-      .ry_wren		(core_py_wren),
+    localparam ECDSA_P384_GY =
+        {32'h3617de4a, 32'h96262c6f, 32'h5d9e98bf, 32'h9292dc29,
+         32'hf8f41dbd, 32'h289a147c, 32'he9da3113, 32'hb5f0b8c0,
+         32'h0a60b1ce, 32'h1d7e819d, 32'h7a431d7c, 32'h90ea0e5f};
 
-      .k_din		(core_k_data),
+    localparam ECDSA_P384_HX =
+        {32'h08d99905, 32'h7ba3d2d9, 32'h69260045, 32'hc55b97f0,
+         32'h89025959, 32'ha6f434d6, 32'h51d207d1, 32'h9fb96e9e,
+        32'h4fe0e86e, 32'hbe0e64f8, 32'h5b96a9c7, 32'h5295df61};
 
-      .rx_dout		(core_px_data),
-      .ry_dout		(core_py_data)
-      );
+    localparam ECDSA_P384_HY =
+        {32'h8e80f1fa, 32'h5b1b3ced, 32'hb7bfe8df, 32'hfd6dba74,
+         32'hb275d875, 32'hbc6cc43e, 32'h904e505f, 32'h256ab425,
+         32'h5ffd43e9, 32'h4d39e22d, 32'h61501e70, 32'h0a940e80};
+
+
+        //
+        // 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
+        //
+    ecdsa384_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;
+        //
+        // Testbench Routine
+        //
+    reg ok = 1;
+    initial begin
 
-      /* wait for some time */
-      #200;
+            /* 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_P384_D_NSA, ECDSA_P384_QX_NSA, ECDSA_P384_QY_NSA);
+        
+        $display("2. R = k * G...");
+        test_curve_multiplier(ECDSA_P384_K_NSA, ECDSA_P384_RX_NSA, ECDSA_P384_RY_NSA);
+        
+        $display("3. Q2 = d2 * G...");
+        test_curve_multiplier(ECDSA_P384_D_RANDOM, ECDSA_P384_QX_RANDOM, ECDSA_P384_QY_RANDOM);
 
-      /* de-assert reset */
-      rst_n		= 1;
+        $display("4. O = n * G...");
+        test_curve_multiplier(ECDSA_P384_N, 384'd0, 384'd0);
 
-      /* wait for some time */
-      #100;
+        $display("5. G = (n + 1) * G...");
+        test_curve_multiplier(ECDSA_P384_N + 384'd1, ECDSA_P384_GX, ECDSA_P384_GY);
 
-      /* 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);
+        $display("6. H = 2 * G...");
+        test_curve_multiplier(384'd2, ECDSA_P384_HX, ECDSA_P384_HY);
 
-      /* print result */
-      if (ok)	$display("tb_curve_multiplier_384: SUCCESS");
-      else	$display("tb_curve_multiplier_384: FAILURE");
-      //
-      //$finish;
-      //
-   end
+        $display("7. H = (n + 2) * G...");
+        test_curve_multiplier(ECDSA_P384_N + 384'd2, ECDSA_P384_HX, ECDSA_P384_HY);
 
+            /* print result */
+        if (ok) $display("tb_curve_multiplier_384: SUCCESS");
+        else    $display("tb_curve_multiplier_384: FAILURE");
 
-   //
-   // Test Task
-   //
-   reg		p_ok;
+        //$finish;
 
-   integer	w;
+    end
 
-   task test_curve_multiplier;
 
-      input [383:0]	k;
-      input [383:0] 	px;
-      input [383:0] 	py;
+        //
+        // Test Task
+        //
+    reg p_ok;
 
-      reg [383:0] 	k_shreg;
-      reg [383:0] 	px_shreg;
-      reg [383:0] 	py_shreg;
+    integer w;
 
-      begin
+    task test_curve_multiplier;
+    
+        input [383:0] k;
+        input [383:0] px;
+        input [383:0] py;
 
-	 /* start filling memories */
-	 tb_k_wren = 1;
+        reg [383:0] k_shreg;
+        reg [383:0] px_shreg;
+        reg [383:0] py_shreg;
 
-	 /* initialize shift registers */
-	 k_shreg = k;
+        begin
+        
+                /* start filling memories */
+            tb_k_wren = 1;
 
-	 /* write all the words */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
+                /* initialize shift registers */
+            k_shreg = k;
 
-	    /* set addresses */
-	    tb_k_addr = w[WORD_COUNTER_WIDTH-1:0];
+                /* write all the words */
+            for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
 
-	    /* set data words */
-	    tb_k_data	= k_shreg[31:0];
+                    /* set addresses */
+                tb_k_addr = w[WORD_COUNTER_WIDTH-1:0];
 
-	    /* shift inputs */
-	    k_shreg = {{32{1'bX}}, k_shreg[383:32]};
+                    /* set data words */
+                tb_k_data   = k_shreg[31:0];
 
-	    /* wait for 1 clock tick */
-	    #10;
+                    /* shift inputs */
+                k_shreg = {{32{1'bX}}, k_shreg[383:32]};
 
-	 end
+                    /* wait for 1 clock tick */
+                #10;
 
-	 /* wipe addresses */
-	 tb_k_addr = {WORD_COUNTER_WIDTH{1'bX}};
+            end
 
-	 /* wipe data words */
-	 tb_k_data = {32{1'bX}};
+                /* wipe addresses */
+            tb_k_addr = {WORD_COUNTER_WIDTH{1'bX}};
 
-	 /* stop filling memories */
-	 tb_k_wren = 0;
+                /* wipe data words */
+            tb_k_data = {32{1'bX}};
 
-	 /* start operation */
-	 ena = 1;
+                /* stop filling memories */
+            tb_k_wren = 0;
 
-	 /* clear flag */
-	 #10 ena = 0;
+                /* start operation */
+            ena = 1;
 
-	 /* wait for operation to complete */
-	 while (!rdy) #10;
+                /* clear flag */
+            #10 ena = 0;
 
-	 /* read result */
-	 for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
+                /* wait for operation to complete */
+            while (!rdy) #10;
 
-	    /* set address */
-	    tb_pxy_addr = w[WORD_COUNTER_WIDTH-1:0];
+                /* read result */
+            for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
 
-	    /* wait for 1 clock tick */
-	    #10;
+                    /* set address */
+                tb_pxy_addr = w[WORD_COUNTER_WIDTH-1:0];
 
-	    /* store data word */
-	    px_shreg = {tb_px_data, px_shreg[383:32]};
-	    py_shreg = {tb_py_data, py_shreg[383:32]};
+                    /* wait for 1 clock tick */
+                #10;
 
-	 end
+                    /* store data word */
+                px_shreg = {tb_px_data, px_shreg[383:32]};
+                py_shreg = {tb_py_data, py_shreg[383:32]};
 
-	 /* compare */
-	 p_ok =	(px_shreg == px) &&
-	       (py_shreg == py);
+            end
 
-	 /* display results */
-	 $display("test_curve_multiplier(): %s", p_ok ? "OK" : "ERROR");
+                /* compare */
+            p_ok = (px_shreg === px) &&
+                   (py_shreg === py);
 
-	 /* update global flag */
-	 ok = ok && p_ok;
+                /* 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
 
-      end
+                /* update global flag */
+            ok = ok && p_ok;
+        
+        end
 
-   endtask
+    endtask
 
 endmodule
 
diff --git a/bench/tb_modular_multiplier_384.v b/bench/tb_modular_multiplier_384.v
deleted file mode 100644
index a5825d8..0000000
--- a/bench/tb_modular_multiplier_384.v
+++ /dev/null
@@ -1,366 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// tb_modular_multiplier_384.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_384;
-
-
-   //
-   // Test Vectors
-   //
-   localparam	[383:0]	N	= 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff;
-
-   localparam	[383:0]	X_1	= 384'haa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7;
-   localparam	[383:0]	Y_1	= 384'h3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f;
-   localparam	[383:0]	P_1	= 384'h332e559389c970313cb29c4b55af5783821971a99c250daf84dc5d3cc441cb0a482e90de9d3ccd96b3c8c48b2ad3f025;
-
-   localparam	[383:0]	X_2	= 384'haaf06bba82e9f590e29c71c219bea51723c5893ae8b0c8cf4c117c3efb57ab8d55fa1b428155ad278b5743911b13ea8a;
-   localparam	[383:0]	Y_2	= 384'hc9e821b569d9d390a26167406d6d23d6070be242d765eb831625ceec4a0f473ef59f4e30e2817e6285bce2846f15f19d;
-   localparam	[383:0]	P_2	= 384'haa1a9db70fba0a4c034777cdcd93e8bd6e9afa1171d43bdea0a16c32da20e7ebccb2fac9676f9d67a31e6f4f69e876e5;
-
-   localparam	[383:0]	X_3	= 384'h1fbac8eebd0cbf35640b39efe0808dd774debff20a2a329e91713baf7d7f3c3e81546d883730bee7e48678f857b02ca0;
-   localparam	[383:0]	Y_3	= 384'heb213103bd68ce343365a8a4c3d4555fa385f5330203bdd76ffad1f3affb95751c132007e1b240353cb0a4cf1693bdf9;
-   localparam	[383:0]	P_3	= 384'h80f70000040a44b05f3752b7d5338f87e409b868f032911bda888451c13097039d66d9e7b0e3e799b9dd613d2524b7af;
-
-   localparam	[383:0]	X_4	= 384'ha0c27ec893092dea1e1bd2ccfed3cf945c8134ed0c9f81311a0f4a05942db8dbed8dd59f267471d5462aa14fe72de856;
-   localparam	[383:0]	Y_4	= 384'h855649409815bb91424eaca5fd76c97375d575d1422ec53d343bd33b847fdf0c11569685b528ab25493015428d7cf72b;
-   localparam	[383:0]	P_4	= 384'h548e8456d5b3c36557a59914af514739a92908e59ddde731b8746891ad26199de955789e7cc34bfe966e3471c2684969;
-
-
-   //
-   // Core Parameters
-   //
-   localparam	WORD_COUNTER_WIDTH	=  4;
-   localparam	OPERAND_NUM_WORDS	= 12;
-
-
-   //
-   // 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_384 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_384(X_1, Y_1, N, P_1);
-      test_modular_multiplier_384(X_2, Y_2, N, P_2);
-      test_modular_multiplier_384(X_3, Y_3, N, P_3);
-      test_modular_multiplier_384(X_4, Y_4, N, P_4);
-
-      /* print result */
-      if (ok)	$display("tb_modular_multiplier_384: SUCCESS");
-      else	$display("tb_modular_multiplier_384: FAILURE");
-      //
-      //$finish;
-      //
-   end
-
-
-   //
-   // Test Task
-   //
-   reg	[383:0]	p;
-   reg 		p_ok;
-
-   integer 	w;
-
-   reg [767:0] 	pp_full;
-   reg [383:0] 	pp_ref;
-
-   task test_modular_multiplier_384;
-
-      input	[383:0] x;
-      input [383:0] 	y;
-      input [383:0] 	n;
-      input [383:0] 	pp;
-
-      reg [383:0] 	x_shreg;
-      reg [383:0] 	y_shreg;
-      reg [383:0] 	n_shreg;
-      reg [383: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[383:32]};
-	    y_shreg = {{32{1'bX}}, y_shreg[383:32]};
-	    n_shreg = {{32{1'bX}}, n_shreg[383: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 = {{384{1'b0}}, x} * {{384{1'b0}}, y};
-	 pp_ref = pp_full % {{384{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[383:32]};
-
-	 end
-
-	 /* compare */
-	 p_ok = (p_shreg == pp);
-
-	 /* display results */
-	 $display("test_modular_multiplier_384(): %s", p_ok ? "OK" : "ERROR");
-
-	 /* update flag */
-	 ok = ok && p_ok;
-
-      end
-
-   endtask
-
-
-
-
-endmodule
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
diff --git a/rtl/curve/curve_dbl_add_384.v b/rtl/curve/curve_dbl_add_384.v
deleted file mode 100644
index cc983f3..0000000
--- a/rtl/curve/curve_dbl_add_384.v
+++ /dev/null
@@ -1,893 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// curve_dbl_add_384.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_384
-  (
-   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	=  4;	// 0 .. 11
-   localparam	OPERAND_NUM_WORDS	= 12;	// 12 * 32 = 384
-
-
-   //
-   // 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_384 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_p384_one brom_one_inst
-     (.clk(clk), .b_addr(brom_one_addr), .b_out(brom_one_dout));
-
-   brom_p384_zero brom_zero_inst
-     (.b_out(brom_zero_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p384_delta brom_delta_inst
-     (.clk(clk), .b_addr(brom_delta_addr), .b_out(brom_delta_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p384_g_x brom_g_x_inst
-     (.clk(clk), .b_addr(brom_g_x_addr), .b_out(brom_g_x_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p384_g_y brom_g_y_inst
-     (.clk(clk), .b_addr(brom_g_y_addr), .b_out(brom_g_y_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p384_h_x brom_h_x_inst
-     (.clk(clk), .b_addr(brom_h_x_addr), .b_out(brom_h_x_dout));
-
-   (* ROM_STYLE="BLOCK" *) brom_p384_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_384.v b/rtl/curve/curve_mul_384.v
deleted file mode 100644
index e9a531a..0000000
--- a/rtl/curve/curve_mul_384.v
+++ /dev/null
@@ -1,720 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// curve_mul_384.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_384
-  (
-   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	=  4;	// 0 .. 11
-   localparam	OPERAND_NUM_WORDS	= 12;	// 12 * 32 = 384
-
-
-   //
-   // 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 [ 3: 0] 	k_addr;
-   output	wire [ 3: 0] 	rx_addr;
-   output	wire [ 3: 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 [ 3: 0]		bram_tx_wr_addr;
-   reg [ 3: 0]		bram_ty_wr_addr;
-   reg [ 3: 0]		bram_tz_wr_addr;
-
-   reg [ 3: 0]		bram_rx_wr_addr;
-   reg [ 3: 0]		bram_ry_wr_addr;
-   reg [ 3: 0]		bram_rz_wr_addr;
-   wire [ 3: 0] 	bram_rz1_wr_addr;
-
-   reg [ 3: 0] 		bram_tx_rd_addr;
-   reg [ 3: 0] 		bram_ty_rd_addr;
-   reg [ 3: 0] 		bram_tz_rd_addr;
-
-   reg [ 3: 0] 		bram_rx_rd_addr;
-   reg [ 3: 0] 		bram_ry_rd_addr;
-   reg [ 3: 0] 		bram_rz_rd_addr;
-   wire [ 3: 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(4))
-   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(4))
-   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(4))
-   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(4))
-   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(4))
-   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(4))
-   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(4))
-   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 [ 8: 0] 			     bit_counter;
-   wire [ 8: 0] 		     bit_counter_max = 9'd383;
-   wire [ 8: 0] 		     bit_counter_zero = 9'd0;
-   wire [ 8: 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 [ 3: 0]			rom_q_addr;
-   wire [31: 0]			rom_q_data;
-
-   brom_p384_q rom_q
-     (
-      .clk	(clk),
-      .b_addr	(rom_q_addr),
-      .b_out	(rom_q_data)
-      );
-
-
-   //
-   // Worker
-   //
-   wire [ 3: 0] 		     worker_addr_px;
-   wire [ 3: 0] 		     worker_addr_py;
-   wire [ 3: 0] 		     worker_addr_pz;
-
-   wire [ 3: 0] 		     worker_addr_rx;
-   wire [ 3: 0] 		     worker_addr_ry;
-   wire [ 3: 0] 		     worker_addr_rz;
-
-   wire [ 3: 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_384 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 [ 3: 0] 		     mover_addr_x;
-   wire [ 3: 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	(4),
-      .OPERAND_NUM_WORDS	(12)
-      )
-   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 [ 3: 0] 		     invertor_addr_a;
-   wire [ 3: 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(384)
-      )
-   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	[ 3: 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 <= 4'd11 - bit_counter[8: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    <= {4{1'bX}};      bram_ry_rd_addr    <= {4{1'bX}};      bram_rz_rd_addr    <= {4{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    <= {4{1'bX}};      bram_ry_wr_addr    <= {4{1'bX}};      bram_rz_wr_addr    <= {4{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    <= {4{1'bX}};      bram_ry_rd_addr    <= {4{1'bX}};      bram_rz_rd_addr    <= {4{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    <= {4{1'bX}};       bram_ry_rd_addr    <= {4{1'bX}};       bram_rz_rd_addr    <= {4{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    <= {4{1'bX}};  bram_ry_rd_addr    <= {4{1'bX}};  bram_rz_rd_addr    <= invertor_addr_a;
-	   bram_rx_wr_addr    <= {4{1'bX}};  bram_ry_wr_addr    <= {4{1'bX}};  bram_rz_wr_addr    <= {4{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    <= {4{1'bX}};      bram_ry_wr_addr    <= {4{1'bX}};      bram_rz_wr_addr    <= {4{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    <= {4{1'bX}};  bram_ry_rd_addr    <= {4{1'bX}};  bram_rz_rd_addr    <= {4{1'bX}};
-	   bram_rx_wr_addr    <= {4{1'bX}};  bram_ry_wr_addr    <= {4{1'bX}};  bram_rz_wr_addr    <= {4{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    <= {4{1'bX}};      bram_ty_rd_addr    <= {4{1'bX}};      bram_tz_rd_addr    <= {4{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    <= {4{1'bX}};      bram_ty_wr_addr    <= {4{1'bX}};      bram_tz_wr_addr    <= {4{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    <= {4{1'bX}};    bram_ty_wr_addr    <= {4{1'bX}};    bram_tz_wr_addr    <= {4{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    <= {4{1'bX}};  bram_ty_rd_addr    <= {4{1'bX}};  bram_tz_rd_addr    <= {4{1'bX}};
-	   bram_tx_wr_addr    <= {4{1'bX}};  bram_ty_wr_addr    <= {4{1'bX}};  bram_tz_wr_addr    <= {4{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_p384_delta.v b/rtl/curve/rom/brom_p384_delta.v
deleted file mode 100644
index 165b3d9..0000000
--- a/rtl/curve/rom/brom_p384_delta.v
+++ /dev/null
@@ -1,72 +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_p384_delta
-  (
-   input wire 		clk,
-   input wire [ 4-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)
-       4'b0000:	bram_reg_b <= 32'h80000000;
-       4'b0001:	bram_reg_b <= 32'h00000000;
-       4'b0010:	bram_reg_b <= 32'h80000000;
-       4'b0011:	bram_reg_b <= 32'h7fffffff;
-       4'b0100:	bram_reg_b <= 32'hffffffff;
-       4'b0101:	bram_reg_b <= 32'hffffffff;
-       4'b0110:	bram_reg_b <= 32'hffffffff;
-       4'b0111:	bram_reg_b <= 32'hffffffff;
-       4'b1000:	bram_reg_b <= 32'hffffffff;
-       4'b1001:	bram_reg_b <= 32'hffffffff;
-       4'b1010:	bram_reg_b <= 32'hffffffff;
-       4'b1011:	bram_reg_b <= 32'h7fffffff;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p384_g_x.v b/rtl/curve/rom/brom_p384_g_x.v
deleted file mode 100644
index 614c7fe..0000000
--- a/rtl/curve/rom/brom_p384_g_x.v
+++ /dev/null
@@ -1,72 +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_p384_g_x
-  (
-   input wire 		clk,
-   input wire [ 4-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)
-       4'b0000:	bram_reg_b <= 32'h72760ab7;
-       4'b0001:	bram_reg_b <= 32'h3a545e38;
-       4'b0010:	bram_reg_b <= 32'hbf55296c;
-       4'b0011:	bram_reg_b <= 32'h5502f25d;
-       4'b0100:	bram_reg_b <= 32'h82542a38;
-       4'b0101:	bram_reg_b <= 32'h59f741e0;
-       4'b0110:	bram_reg_b <= 32'h8ba79b98;
-       4'b0111:	bram_reg_b <= 32'h6e1d3b62;
-       4'b1000:	bram_reg_b <= 32'hf320ad74;
-       4'b1001:	bram_reg_b <= 32'h8eb1c71e;
-       4'b1010:	bram_reg_b <= 32'hbe8b0537;
-       4'b1011:	bram_reg_b <= 32'haa87ca22;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p384_g_y.v b/rtl/curve/rom/brom_p384_g_y.v
deleted file mode 100644
index e64d9aa..0000000
--- a/rtl/curve/rom/brom_p384_g_y.v
+++ /dev/null
@@ -1,72 +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_p384_g_y
-  (
-   input wire 		clk,
-   input wire [ 4-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)
-       4'b0000:	bram_reg_b <= 32'h90ea0e5f;
-       3'b0001:	bram_reg_b <= 32'h7a431d7c;
-       4'b0010:	bram_reg_b <= 32'h1d7e819d;
-       4'b0011:	bram_reg_b <= 32'h0a60b1ce;
-       4'b0100:	bram_reg_b <= 32'hb5f0b8c0;
-       4'b0101:	bram_reg_b <= 32'he9da3113;
-       4'b0110:	bram_reg_b <= 32'h289a147c;
-       4'b0111:	bram_reg_b <= 32'hf8f41dbd;
-       4'b1000:	bram_reg_b <= 32'h9292dc29;
-       4'b1001:	bram_reg_b <= 32'h5d9e98bf;
-       4'b1010:	bram_reg_b <= 32'h96262c6f;
-       4'b1011:	bram_reg_b <= 32'h3617de4a;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p384_h_x.v b/rtl/curve/rom/brom_p384_h_x.v
deleted file mode 100644
index 5fef79a..0000000
--- a/rtl/curve/rom/brom_p384_h_x.v
+++ /dev/null
@@ -1,72 +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_p384_h_x
-  (
-   input wire 		clk,
-   input wire [ 4-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)
-       4'b0000:	bram_reg_b <= 32'h5295df61;
-       4'b0001:	bram_reg_b <= 32'h5b96a9c7;
-       4'b0010:	bram_reg_b <= 32'hbe0e64f8;
-       4'b0011:	bram_reg_b <= 32'h4fe0e86e;
-       4'b0100:	bram_reg_b <= 32'h9fb96e9e;
-       4'b0101:	bram_reg_b <= 32'h51d207d1;
-       4'b0110:	bram_reg_b <= 32'ha6f434d6;
-       4'b0111:	bram_reg_b <= 32'h89025959;
-       4'b1000:	bram_reg_b <= 32'hc55b97f0;
-       4'b1001:	bram_reg_b <= 32'h69260045;
-       4'b1010:	bram_reg_b <= 32'h7ba3d2d9;
-       4'b1011:	bram_reg_b <= 32'h08d99905;
-     endcase
-	  
-
-endmodule
diff --git a/rtl/curve/rom/brom_p384_h_y.v b/rtl/curve/rom/brom_p384_h_y.v
deleted file mode 100644
index f56efc5..0000000
--- a/rtl/curve/rom/brom_p384_h_y.v
+++ /dev/null
@@ -1,71 +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_p384_h_y
-  (
-   input wire 		clk,
-   input wire [ 4-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)
-       4'b0000:	bram_reg_b <= 32'h0a940e80;
-       4'b0001:	bram_reg_b <= 32'h61501e70;
-       4'b0010:	bram_reg_b <= 32'h4d39e22d;
-       4'b0011:	bram_reg_b <= 32'h5ffd43e9;
-       4'b0100:	bram_reg_b <= 32'h256ab425;
-       4'b0101:	bram_reg_b <= 32'h904e505f;
-       4'b0110:	bram_reg_b <= 32'hbc6cc43e;
-       4'b0111:	bram_reg_b <= 32'hb275d875;
-       4'b1000:	bram_reg_b <= 32'hfd6dba74;
-       4'b1001:	bram_reg_b <= 32'hb7bfe8df;
-       4'b1010:	bram_reg_b <= 32'h5b1b3ced;
-       4'b1011:	bram_reg_b <= 32'h8e80f1fa;
-     endcase
-
-endmodule
diff --git a/rtl/curve/rom/brom_p384_one.v b/rtl/curve/rom/brom_p384_one.v
deleted file mode 100644
index c8ec6c3..0000000
--- a/rtl/curve/rom/brom_p384_one.v
+++ /dev/null
@@ -1,72 +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_p384_one
-  (
-   input wire 		clk,
-   input wire [ 4-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)
-       4'b0000:	bram_reg_b <= 32'h00000001;
-       4'b0001:	bram_reg_b <= 32'h00000000;
-       4'b0010:	bram_reg_b <= 32'h00000000;
-       4'b0011:	bram_reg_b <= 32'h00000000;
-       4'b0100:	bram_reg_b <= 32'h00000000;
-       4'b0101:	bram_reg_b <= 32'h00000000;
-       4'b0110:	bram_reg_b <= 32'h00000000;
-       4'b0111:	bram_reg_b <= 32'h00000000;
-       4'b1000:	bram_reg_b <= 32'h00000000;
-       4'b1001:	bram_reg_b <= 32'h00000000;
-       4'b1010:	bram_reg_b <= 32'h00000000;
-       4'b1011:	bram_reg_b <= 32'h00000000;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p384_q.v b/rtl/curve/rom/brom_p384_q.v
deleted file mode 100644
index 7571305..0000000
--- a/rtl/curve/rom/brom_p384_q.v
+++ /dev/null
@@ -1,72 +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_p384_q
-  (
-   input wire 		clk,
-   input wire [ 4-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)
-       4'b0000:	bram_reg_b <= 32'hffffffff;
-       4'b0001:	bram_reg_b <= 32'h00000000;
-       4'b0010:	bram_reg_b <= 32'h00000000;
-       4'b0011:	bram_reg_b <= 32'hffffffff;
-       4'b0100:	bram_reg_b <= 32'hfffffffe;
-       4'b0101:	bram_reg_b <= 32'hffffffff;
-       4'b0110:	bram_reg_b <= 32'hffffffff;
-       4'b0111:	bram_reg_b <= 32'hffffffff;
-       4'b1000:	bram_reg_b <= 32'hffffffff;
-       4'b1001:	bram_reg_b <= 32'hffffffff;
-       4'b1010:	bram_reg_b <= 32'hffffffff;
-       4'b1011:	bram_reg_b <= 32'hffffffff;
-     endcase
-
-
-endmodule
diff --git a/rtl/curve/rom/brom_p384_zero.v b/rtl/curve/rom/brom_p384_zero.v
deleted file mode 100644
index efac8e8..0000000
--- a/rtl/curve/rom/brom_p384_zero.v
+++ /dev/null
@@ -1,42 +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_p384_zero
-  (
-   output wire [32-1:0] b_out
-   );
-
-   assign b_out = {32{1'b0}};
-
-endmodule
diff --git a/rtl/ecdsa384.v b/rtl/ecdsa384.v
deleted file mode 100644
index 7a63c9e..0000000
--- a/rtl/ecdsa384.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 ecdsa384
-  (
-   input wire 	      clk,
-   input wire 	      rst_n,
-
-   input wire 	      next,
-   output wire 	      valid,
-
-   input wire 	      bus_cs,
-   input wire 	      bus_we,
-   input wire [ 5: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[5:4];
-   wire [3:0] 	      bus_addr_lower = bus_addr[3: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 [ 3:0] 	      core_ro_k_bram_addr;
-   wire [ 3:0] 	      core_rw_x_bram_addr;
-   wire [ 3: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(4)
-	)
-   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(4)
-	)
-   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(4)
-	)
-   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_384 base_point_multiplier_p384
-     (
-      .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/ecdsa384_banks_array.v b/rtl/ecdsa384_banks_array.v
new file mode 100644
index 0000000..4b61dca
--- /dev/null
+++ b/rtl/ecdsa384_banks_array.v
@@ -0,0 +1,118 @@
+//------------------------------------------------------------------------------
+//
+// ecdsa384_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 ecdsa384_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   [ 3:0]  src1_addr,
+    input   [ 3:0]  src2_addr,
+    input   [ 3: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;
+    
+    ecdsa384_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)
+    );
+    
+    ecdsa384_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)
+    );
+
+    ecdsa384_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)
+    );
+
+    ecdsa384_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/ecdsa384_base_point_multiplier.v b/rtl/ecdsa384_base_point_multiplier.v
new file mode 100644
index 0000000..dc8d976
--- /dev/null
+++ b/rtl/ecdsa384_base_point_multiplier.v
@@ -0,0 +1,310 @@
+//------------------------------------------------------------------------------
+//
+// ecdsa384_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 ecdsa384_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  [ 3:0]  k_addr;     //
+    output  [ 3: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  [8:0] bit_counter;
+    wire [8:0] bit_counter_last = 9'h17F;    // 384
+    wire [8:0] bit_counter_zero = 9'h000;    // 0
+    wire [8:0] bit_counter_prev =
+        (bit_counter > bit_counter_zero) ? bit_counter - 1'b1 : bit_counter_last;
+
+    assign k_addr = bit_counter[8: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);
+    
+    ecdsa384_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/ecdsa384_core_top.v b/rtl/ecdsa384_core_top.v
new file mode 100644
index 0000000..2dc800e
--- /dev/null
+++ b/rtl/ecdsa384_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 ecdsa384_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 [ 5: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[5:4];
+    wire [3:0] bus_addr_lower = bus_addr[3: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 [ 3:0] core_ro_k_bram_addr;
+    wire [ 3: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(4))
+    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(4))
+    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(4))
+    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;
+    
+    ecdsa384_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/ecdsa384_microcode_rom.v b/rtl/ecdsa384_microcode_rom.v
new file mode 100644
index 0000000..137d1dc
--- /dev/null
+++ b/rtl/ecdsa384_microcode_rom.v
@@ -0,0 +1,553 @@
+//======================================================================
+//
+// 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 ecdsa384_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_P384
+            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_R2, UOP_OPERAND_INVERT_R1};
+            9'd129: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd130: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd131: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd132: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd133: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd134: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd135: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd136: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd137: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd138: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd139: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd140: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd141: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd142: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd143: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd144: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd145: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd146: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd147: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd148: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd149: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd150: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd151: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd152: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd153: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd154: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd155: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd156: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X30, UOP_OPERAND_INVERT_X60};
+            9'd157: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_X60, UOP_OPERAND_INVERT_X60, UOP_OPERAND_INVERT_R1};
+            9'd158: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd159: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd160: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd161: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd162: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd163: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd164: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd165: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd166: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd167: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd168: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd169: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd170: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd171: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd172: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd173: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd174: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd175: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd176: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd177: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd178: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd179: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd180: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd181: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd182: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd183: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd184: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd185: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd186: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd187: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd188: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd189: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd190: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd191: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd192: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd193: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd194: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd195: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd196: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd197: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd198: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd199: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd200: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd201: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd202: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd203: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd204: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd205: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd206: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd207: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd208: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd209: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd210: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd211: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd212: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd213: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd214: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd215: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd216: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd217: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X60, UOP_OPERAND_INVERT_X120};
+            9'd218: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_X120, UOP_OPERAND_INVERT_X120, UOP_OPERAND_INVERT_R1};
+            9'd219: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd220: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd221: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd222: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd223: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd224: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd225: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd226: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd227: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd228: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd229: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd230: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd231: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd232: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd233: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd234: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd235: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd236: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd237: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd238: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd239: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd240: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd241: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd242: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd243: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd244: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd245: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd246: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd247: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd248: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd249: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd250: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd251: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd252: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd253: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd254: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd255: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd256: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd257: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd258: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd259: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd260: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd261: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd262: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd263: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd264: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd265: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd266: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd267: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd268: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd269: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd270: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd271: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd272: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd273: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd274: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd275: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd276: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd277: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd278: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd279: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd280: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd281: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd282: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd283: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd284: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd285: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd286: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd287: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd288: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd289: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd290: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd291: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd292: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd293: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd294: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd295: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd296: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd297: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd298: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd299: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd300: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd301: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd302: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd303: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd304: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd305: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd306: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd307: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd308: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd309: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd310: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd311: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd312: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd313: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd314: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd315: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd316: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd317: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd318: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd319: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd320: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd321: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd322: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd323: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd324: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd325: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd326: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd327: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd328: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd329: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd330: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd331: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd332: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd333: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd334: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd335: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd336: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd337: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd338: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X120, UOP_OPERAND_INVERT_R1};
+            9'd339: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd340: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd341: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd342: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd343: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd344: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd345: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd346: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd347: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd348: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd349: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd350: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd351: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd352: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd353: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd354: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X15, UOP_OPERAND_INVERT_R1};
+            9'd355: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd356: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd357: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd358: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd359: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd360: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd361: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd362: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd363: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd364: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd365: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd366: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd367: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd368: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd369: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd370: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd371: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd372: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd373: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd374: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd375: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd376: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd377: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd378: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd379: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd380: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd381: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd382: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd383: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd384: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd385: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd386: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X30, UOP_OPERAND_INVERT_R1};
+            9'd387: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd388: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd389: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_X2, UOP_OPERAND_INVERT_R2};
+            9'd390: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd391: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd392: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd393: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd394: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd395: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd396: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd397: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd398: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd399: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd400: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd401: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd402: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd403: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd404: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd405: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd406: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd407: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd408: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd409: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd410: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd411: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd412: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd413: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd414: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd415: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd416: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd417: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd418: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd419: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd420: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd421: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd422: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd423: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd424: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd425: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd426: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd427: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd428: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd429: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd430: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd431: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd432: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd433: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd434: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd435: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd436: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd437: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd438: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd439: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd440: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd441: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd442: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd443: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd444: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd445: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd446: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd447: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd448: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd449: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd450: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd451: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd452: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd453: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd454: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd455: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd456: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd457: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd458: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd459: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd460: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd461: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd462: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd463: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd464: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd465: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd466: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd467: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd468: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd469: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd470: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd471: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd472: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd473: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd474: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd475: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd476: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd477: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd478: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd479: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd480: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd481: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd482: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd483: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd484: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_X30, UOP_OPERAND_INVERT_R1};
+            9'd485: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R1, UOP_OPERAND_INVERT_R2};
+            9'd486: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R2, UOP_OPERAND_INVERT_R1};
+            9'd487: data <= {UOP_OPCODE_COPY, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_DONTCARE, UOP_OPERAND_INVERT_A2};
+            9'd488: data <= {UOP_OPCODE_MUL, UOP_BANKS_HI2LO, UOP_OPERAND_INVERT_A2, UOP_OPERAND_INVERT_A2, UOP_OPERAND_INVERT_R1};
+            9'd489: data <= {UOP_OPCODE_MUL, UOP_BANKS_LO2HI, UOP_OPERAND_INVERT_R1, UOP_OPERAND_CYCLE_RZ, UOP_OPERAND_INVERT_A3};
+            9'd490: data <= {UOP_OPCODE_STOP, UOP_BANKS_DUMMY, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE, UOP_OPERAND_DONTCARE};
+
+    endcase
+
+endmodule
diff --git a/rtl/ecdsa384_operand_bank.v b/rtl/ecdsa384_operand_bank.v
new file mode 100644
index 0000000..ef0c397
--- /dev/null
+++ b/rtl/ecdsa384_operand_bank.v
@@ -0,0 +1,188 @@
+//======================================================================
+//
+// 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 ecdsa384_operand_bank
+(
+    input               clk,
+
+    input   [10-1:0]    a_addr,
+    input               a_wr,
+    input   [32-1:0]    a_in,
+
+    input   [10-1:0]    b_addr,
+    output  [32-1:0]    b_out
+);
+
+
+    //
+    // BRAM
+    //
+    reg [31:0] bram[0:64*16-1];
+
+
+    //
+    // Initialization
+    //
+    initial begin
+        //
+        // CONST_ZERO 
+        //
+        bram[ 0*16 + 11] = 32'h00000000;
+        bram[ 0*16 + 10] = 32'h00000000;
+        bram[ 0*16 +  9] = 32'h00000000;
+        bram[ 0*16 +  8] = 32'h00000000;
+        bram[ 0*16 +  7] = 32'h00000000;
+        bram[ 0*16 +  6] = 32'h00000000;
+        bram[ 0*16 +  5] = 32'h00000000;
+        bram[ 0*16 +  4] = 32'h00000000;
+        bram[ 0*16 +  3] = 32'h00000000;
+        bram[ 0*16 +  2] = 32'h00000000;
+        bram[ 0*16 +  1] = 32'h00000000;
+        bram[ 0*16 +  0] = 32'h00000000;
+        //
+        // CONST_ONE
+        //
+        bram[ 1*16 + 11] = 32'h00000000;
+        bram[ 1*16 + 10] = 32'h00000000;
+        bram[ 1*16 +  9] = 32'h00000000;
+        bram[ 1*16 +  8] = 32'h00000000;
+        bram[ 1*16 +  7] = 32'h00000000;
+        bram[ 1*16 +  6] = 32'h00000000;
+        bram[ 1*16 +  5] = 32'h00000000;
+        bram[ 1*16 +  4] = 32'h00000000;
+        bram[ 1*16 +  3] = 32'h00000000;
+        bram[ 1*16 +  2] = 32'h00000000;
+        bram[ 1*16 +  1] = 32'h00000000;
+        bram[ 1*16 +  0] = 32'h00000001;
+        //
+        // CONST_DELTA
+        //
+        bram[ 2*16 + 11] = 32'h7fffffff;
+        bram[ 2*16 + 10] = 32'hffffffff;
+        bram[ 2*16 +  9] = 32'hffffffff;
+        bram[ 2*16 +  8] = 32'hffffffff;
+        bram[ 2*16 +  7] = 32'hffffffff;
+        bram[ 2*16 +  6] = 32'hffffffff;
+        bram[ 2*16 +  5] = 32'hffffffff;
+        bram[ 2*16 +  4] = 32'hffffffff;
+        bram[ 2*16 +  3] = 32'h7fffffff;
+        bram[ 2*16 +  2] = 32'h80000000;
+        bram[ 2*16 +  1] = 32'h00000000;
+        bram[ 2*16 +  0] = 32'h80000000;
+        //
+        // G_X
+        //
+        bram[ 3*16 + 11] = 32'haa87ca22;
+        bram[ 3*16 + 10] = 32'hbe8b0537;
+        bram[ 3*16 +  9] = 32'h8eb1c71e;
+        bram[ 3*16 +  8] = 32'hf320ad74;
+        bram[ 3*16 +  7] = 32'h6e1d3b62;
+        bram[ 3*16 +  6] = 32'h8ba79b98;
+        bram[ 3*16 +  5] = 32'h59f741e0;
+        bram[ 3*16 +  4] = 32'h82542a38;
+        bram[ 3*16 +  3] = 32'h5502f25d;
+        bram[ 3*16 +  2] = 32'hbf55296c;
+        bram[ 3*16 +  1] = 32'h3a545e38;
+        bram[ 3*16 +  0] = 32'h72760ab7;
+        //
+        // G_Y
+        //
+        bram[ 4*16 + 11] = 32'h3617de4a;
+        bram[ 4*16 + 10] = 32'h96262c6f;
+        bram[ 4*16 +  9] = 32'h5d9e98bf;
+        bram[ 4*16 +  8] = 32'h9292dc29;
+        bram[ 4*16 +  7] = 32'hf8f41dbd;
+        bram[ 4*16 +  6] = 32'h289a147c;
+        bram[ 4*16 +  5] = 32'he9da3113;
+        bram[ 4*16 +  4] = 32'hb5f0b8c0;
+        bram[ 4*16 +  3] = 32'h0a60b1ce;
+        bram[ 4*16 +  2] = 32'h1d7e819d;
+        bram[ 4*16 +  1] = 32'h7a431d7c;
+        bram[ 4*16 +  0] = 32'h90ea0e5f;
+        //
+        // H_X
+        //
+        bram[ 5*16 + 11] = 32'h08d99905;
+        bram[ 5*16 + 10] = 32'h7ba3d2d9;
+        bram[ 5*16 +  9] = 32'h69260045;
+        bram[ 5*16 +  8] = 32'hc55b97f0;
+        bram[ 5*16 +  7] = 32'h89025959;
+        bram[ 5*16 +  6] = 32'ha6f434d6;
+        bram[ 5*16 +  5] = 32'h51d207d1;
+        bram[ 5*16 +  4] = 32'h9fb96e9e;
+        bram[ 5*16 +  3] = 32'h4fe0e86e;
+        bram[ 5*16 +  2] = 32'hbe0e64f8;
+        bram[ 5*16 +  1] = 32'h5b96a9c7;
+        bram[ 5*16 +  0] = 32'h5295df61;
+        //
+        // H_Y
+        //
+        bram[ 6*16 + 11] = 32'h8e80f1fa;
+        bram[ 6*16 + 10] = 32'h5b1b3ced;
+        bram[ 6*16 +  9] = 32'hb7bfe8df;
+        bram[ 6*16 +  8] = 32'hfd6dba74;
+        bram[ 6*16 +  7] = 32'hb275d875;
+        bram[ 6*16 +  6] = 32'hbc6cc43e;
+        bram[ 6*16 +  5] = 32'h904e505f;
+        bram[ 6*16 +  4] = 32'h256ab425;
+        bram[ 6*16 +  3] = 32'h5ffd43e9;
+        bram[ 6*16 +  2] = 32'h4d39e22d;
+        bram[ 6*16 +  1] = 32'h61501e70;
+        bram[ 6*16 +  0] = 32'h0a940e80;
+	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/ecdsa384_uop_worker.v b/rtl/ecdsa384_uop_worker.v
new file mode 100644
index 0000000..03c9494
--- /dev/null
+++ b/rtl/ecdsa384_uop_worker.v
@@ -0,0 +1,604 @@
+//------------------------------------------------------------------------------
+//
+// ecdsa384_uop_worker.v
+// -----------------------------------------------------------------------------
+// ECDSA uOP Worker for P-384
+//
+// 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 ecdsa384_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  [ 3: 0] xy_addr;
+    output  [31: 0] xy_dout;
+    output          x_wren;
+    output          y_wren;
+    
+    
+    //
+    // Constants
+    //
+    localparam integer OPERAND_NUM_WORDS = 12;   // 384 bits -> 12 x 32-bit words
+    localparam integer WORD_COUNTER_WIDTH = 4;  // 0..11 -> 4 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];
+    
+    ecdsa384_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;
+    
+    ecdsa384_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)
+    //
+    ecdsa384_modulus_distmem modulus_add
+    (
+        .clk    (clk),
+        .b_addr (mod_add_n_addr),
+        .b_out  (mod_add_n_din)
+    );    
+
+    ecdsa384_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     [ 3:0]  banks_src1_addr;
+    reg     [ 3:0]  banks_src2_addr;
+    reg     [ 3: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;    
+    
+    ecdsa384_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 [ 3: 0] xy_addr_reg = 4'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 <= 4'b0000;
+        
+    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/ecdsa384_wrapper.v b/rtl/ecdsa384_wrapper.v
index 672be96..a01d798 100644
--- a/rtl/ecdsa384_wrapper.v
+++ b/rtl/ecdsa384_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 ecdsa384_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 [6: 0]   address,
-   input wire [31: 0]  write_data,
-   output wire [31: 0] read_data
-   );
+   input  wire [ 6:0] address,
+   input  wire [31:0] write_data,
+   output wire [31:0] read_data
+);
 
 
    //
@@ -50,15 +50,15 @@ module ecdsa384_wrapper
    localparam ADDR_MSB_REGS = 1'b0;
    localparam ADDR_MSB_CORE = 1'b1;
 
-   wire [0:0] 	       addr_msb = address[6];
-   wire [5:0] 	       addr_lsb = address[5:0];
+   wire [0:0] addr_msb = address[6];
+   wire [5:0] addr_lsb = address[5: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 ecdsa384_wrapper
 
    localparam CORE_NAME0        = 32'h65636473; // "ecds"
    localparam CORE_NAME1        = 32'h61333834; // "a384"
-   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;
 
 
-   //
-   // ECDSA384
-   //
-   ecdsa384 ecdsa384_inst
-     (
-      .clk                      (clk),
-      .rst_n                    (reset_n),
+    //
+    // ECDSA384
+    //
+    ecdsa384_core_top ecdsa384_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 ecdsa384_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 ecdsa384_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_384.v b/rtl/modular/modular_multiplier_384.v
deleted file mode 100644
index b2e1251..0000000
--- a/rtl/modular/modular_multiplier_384.v
+++ /dev/null
@@ -1,402 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// modular_multiplier_384.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_384
-  (
-   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				= 12;
-   localparam	WORD_COUNTER_WIDTH				=  4;
-
-
-   //
-   // 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-384!)
-   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	[383:0]	buf_a_wide;
-
-   always @(posedge clk)
-     //
-     if (store_word_a)
-       buf_a_wide <= {buf_a_wide[16 +: 384 - 3 * 16], {a_din[15:0], a_din[31:16]}, buf_a_wide[384 - 2 * 16 +: 16]};
-     else if (shift_wide_a)
-       buf_a_wide <= {buf_a_wide[384-(16+1):0], buf_a_wide[384-16+:16]};
-
-
-   //
-   // Multiplier Array
-   //
-   wire 	mac_inhibit;			// control signal to pause all accumulators
-
-   wire [46: 0] mac[0:23];	// outputs of all accumulators
-   reg [23: 0] 	mac_clear;	// individual per-accumulator clear flag
-
-   assign mac_inhibit = ~enable_mac_ab;
-
-   always @(posedge clk)
-     //
-     if (!clear_mac_ab)
-       mac_clear <= {24{1'b1}};
-     else begin
-
-	if (mac_clear == {24{1'b1}})
-	  mac_clear <= {{22{1'b0}}, 1'b1, 1'b0};
-	else
-	  mac_clear <= (mac_clear[23] == 1'b0) ? {mac_clear[22:0], 1'b0} : {24{1'b1}};
-
-
-     end
-
-     //
-     // Array of parallel multipliers
-     //
-     genvar i;
-     generate for (i=0; i<24; 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<24; i=i+1)
-       begin : gen_si_lsb_new
-	  assign si_lsb_new[47*i+:47] = mac[23-i];
-       end
-     endgenerate
-
-     generate for (i=1; i<24; i=i+1)
-       begin : gen_si_msb_new
-	  assign si_msb_new[47*(23-i)+:47] = mac_clear[i] ? mac[i] : si_msb[47*(23-i)+:47];
-       end
-     endgenerate
-
-     always @(posedge clk) begin
-	//
-	if (shift_si) begin
-	   si_msb <= {{2*47{1'b0}}, si_msb[23*47-1:2*47]};
-	   si_lsb <= {si_msb[2*47-1:0], si_lsb[24*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_384 reduce_384_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_384.v b/rtl/modular/modular_reductor_384.v
deleted file mode 100644
index 866ad7d..0000000
--- a/rtl/modular/modular_reductor_384.v
+++ /dev/null
@@ -1,739 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// modular_reductor_384.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_384
-  (
-   clk, rst_n,
-   ena, rdy,
-   x_addr, n_addr, p_addr, p_wren,
-   x_din, n_din, p_dout
-   );
-
-   //
-   // Constants
-   //
-   localparam	OPERAND_NUM_WORDS	= 12;
-   localparam	WORD_COUNTER_WIDTH	=  4;
-
-
-   //
-   // 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 384-bit values ("z-words") from 32-bit parts
-   // of the full 768-bit product ("c-word"). The problem with z10 is
-   // that it contains c23 two times. This implementation scans from
-   // c23 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 c23 and then write
-   // the delayed value at the corresponding location in z10 instead of
-   // the next c22. "z_save" flag is used to indicate that the current
-   // word should be delayed and written once again during the next cycle.
-   //
-
-
-   reg	[10*WORD_COUNTER_WIDTH-1:0]	z_addr;	//
-   reg [10                   -1:0] 	z_wren;	//
-   reg [10                   -1:0] 	z_mask;	// mask input to store zero word
-   reg [10                   -1:0] 	z_save;	// save previous word once again
-
-   always @(posedge clk)
-     //
-     if (inc_index_x)
-       //
-       case (index_x)
-	 //
-	 //                    s10     s9     s8     s7     s6     s5     s4     s3     s2     s1
-	 //                     ||     ||     ||     ||     ||     ||     ||     ||     ||     ||
-	 5'd00:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd00};
-	 5'd01:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd01};
-	 5'd02:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd02};
-	 5'd03:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd03};
-	 5'd04:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd04};
-	 5'd05:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd05};
-	 5'd06:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd06};
-	 5'd07:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd07};
-	 5'd08:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd08};
-	 5'd09:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd09};
-	 5'd10:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd10};
-	 5'd11:	z_addr <= {4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'dxx, 4'd11};
-
-	 5'd12:	z_addr <= {4'd00, 4'd00, 4'd01, 4'd01, 4'd00, 4'd04, 4'd03, 4'd00, 4'd00, 4'dxx};
-	 5'd13:	z_addr <= {4'd01, 4'd05, 4'd02, 4'd02, 4'd01, 4'd05, 4'd04, 4'd01, 4'd01, 4'dxx};
-	 5'd14:	z_addr <= {4'd02, 4'd06, 4'd03, 4'd06, 4'd02, 4'd06, 4'd05, 4'd02, 4'd02, 4'dxx};
-	 5'd15:	z_addr <= {4'd05, 4'd07, 4'd04, 4'd07, 4'd03, 4'd07, 4'd06, 4'd03, 4'd03, 4'dxx};
-	 5'd16:	z_addr <= {4'd06, 4'd08, 4'd05, 4'd08, 4'd08, 4'd08, 4'd07, 4'd04, 4'd07, 4'dxx};
-	 5'd17:	z_addr <= {4'd07, 4'd09, 4'd06, 4'd09, 4'd09, 4'd09, 4'd08, 4'd05, 4'd08, 4'dxx};
-	 5'd18:	z_addr <= {4'd08, 4'd10, 4'd07, 4'd10, 4'd10, 4'd10, 4'd09, 4'd06, 4'd09, 4'dxx};
-	 5'd19:	z_addr <= {4'd09, 4'd11, 4'd08, 4'd11, 4'd11, 4'd11, 4'd10, 4'd07, 4'd10, 4'dxx};
-	 5'd20:	z_addr <= {4'd10, 4'd01, 4'd09, 4'd00, 4'd04, 4'd03, 4'd11, 4'd08, 4'd11, 4'dxx};
-	 5'd21:	z_addr <= {4'd11, 4'd02, 4'd10, 4'd03, 4'd05, 4'd00, 4'd00, 4'd09, 4'd04, 4'dxx};
-	 5'd22:	z_addr <= {4'd04, 4'd03, 4'd11, 4'd04, 4'd06, 4'd02, 4'd01, 4'd10, 4'd05, 4'dxx};
-	 5'd23:	z_addr <= {4'd03, 4'd04, 4'd00, 4'd05, 4'd07, 4'd01, 4'd02, 4'd11, 4'd06, 4'dxx};
-	 //
-         default:	z_addr <= {10*WORD_COUNTER_WIDTH{1'bX}};
-	 //
-       endcase
-
-   always @(posedge clk)
-     //
-     case (index_x)
-       //
-       //                    10     9     8     7     6     5     4     3     2     1
-       //                     |     |     |     |     |     |     |     |     |     |
-       5'd00:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd01:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd02:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd03:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd04:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd05:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd06:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd07:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd08:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd09:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd10:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-       5'd11:	z_wren <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1};
-
-       5'd12:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd13:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd14:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd15:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd16:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd17:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd18:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd19:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd20:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd21:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd22:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       5'd23:	z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0};
-       //
-       default:	z_wren <= {10{1'b0}};
-       //
-     endcase
-
-   always @(posedge clk)
-     //
-     if (inc_index_x)
-       //
-       case (index_x)
-	 //
-	 //                    10     9     8     7     6     5     4     3     2     1
-	 //                     |     |     |     |     |     |     |     |     |     |
-	 5'd00:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd01:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd02:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd03:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd04:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd05:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd06:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd07:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd08:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd09:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd10:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd11:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-
-	 5'd12:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd13:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd14:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd15:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd16:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd17:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd18:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd19:	z_mask <= {1'b1, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd20:	z_mask <= {1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0};
-	 5'd21:	z_mask <= {1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd22:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd23:	z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 //
-         default:	z_mask <= {10{1'bX}};
-	 //
-       endcase
-
-   always @(posedge clk)
-     //
-     if (inc_index_x)
-       //
-       case (index_x)
-	 //
-	 //                    10     9     8     7     6     5     4     3     2     1
-	 //                     |     |     |     |     |     |     |     |     |     |
-	 5'd00:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd01:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd02:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd03:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd04:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd05:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd06:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd07:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd08:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd09:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd10:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd11:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-
-	 5'd12:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd13:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd14:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd15:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd16:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd17:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd18:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd19:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd20:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd21:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd22:	z_save <= {1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 5'd23:	z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
-	 //
-         default:	z_save <= {10{1'bX}};
-	 //
-       endcase
-
-
-   //
-   // Intermediate Numbers
-   //
-   reg [WORD_COUNTER_WIDTH-1:0] 	reduce_z_addr[1:10];
-   wire [                32-1:0] 	reduce_z_dout[1:10];
-
-   reg [31: 0] 				x_din_dly;
-   always @(posedge clk)
-     //
-     x_din_dly <= x_din;
-
-
-   genvar 				z;
-   generate for (z=1; z<=10; 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]	= adder0_ab_addr;
-	  reduce_z_addr[ 2]	= adder1_ab_addr;
-	  reduce_z_addr[ 3]	= adder0_ab_addr;
-	  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]	= subtractor_ab_addr;
-	  reduce_z_addr[ 9]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[10]	= {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]	= {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]	= adder0_ab_addr;
-	  reduce_z_addr[ 5]	= adder1_ab_addr;
-	  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;
-	  reduce_z_addr[10]	= {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]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[6]	= adder0_ab_addr;
-	  reduce_z_addr[7]	= adder1_ab_addr;
-	  reduce_z_addr[8]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[9]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[10]	= subtractor_ab_addr;
-	  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]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  reduce_z_addr[10]	= {WORD_COUNTER_WIDTH{1'bX}};
-	  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}};
-	  reduce_z_addr[10]	= {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}};
-	  reduce_z_addr[10]	= {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[1];
-	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[3];
-	5'b01000:	adder0_b_din = reduce_z_dout[4];
-	5'b00100:	adder0_b_din = reduce_z_dout[6];
-	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[2];
-	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[2];
-	5'b01000:	adder1_b_din = reduce_z_dout[5];
-	5'b00100:	adder1_b_din = reduce_z_dout[7];
-	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[8];
-	5'b01000:	subtractor_b_din = reduce_z_dout[9];
-	5'b00100:	subtractor_b_din = reduce_z_dout[10];
-	5'b00010:	subtractor_b_din = {32{1'b0}};
-	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
-//------------------------------------------------------------------------------

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


More information about the Commits mailing list