aboutsummaryrefslogtreecommitdiff
path: root/rtl/curve
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-02-12 22:10:17 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-02-12 22:10:17 +0300
commit747c165611c3016c997e092797bc20a4f900cdea (patch)
treeda11c5d240fc8a54ca37720d6a4ad863720e9c9e /rtl/curve
Initial commit of base point multiplier core for ECDSA curve P-384.
Diffstat (limited to 'rtl/curve')
-rw-r--r--rtl/curve/curve_dbl_add_384.v874
-rw-r--r--rtl/curve/curve_mul_384.v720
-rw-r--r--rtl/curve/rom/brom_p384_delta.v72
-rw-r--r--rtl/curve/rom/brom_p384_g_x.v72
-rw-r--r--rtl/curve/rom/brom_p384_g_y.v72
-rw-r--r--rtl/curve/rom/brom_p384_h_x.v71
-rw-r--r--rtl/curve/rom/brom_p384_h_y.v71
-rw-r--r--rtl/curve/rom/brom_p384_one.v72
-rw-r--r--rtl/curve/rom/brom_p384_q.v72
-rw-r--r--rtl/curve/rom/brom_p384_zero.v42
-rw-r--r--rtl/curve/uop/uop_add_rom.v66
-rw-r--r--rtl/curve/uop/uop_conv_rom.v38
-rw-r--r--rtl/curve/uop/uop_dbl_rom.v58
-rw-r--r--rtl/curve/uop/uop_init_rom.v33
-rw-r--r--rtl/curve/uop_ecdsa.v50
15 files changed, 2383 insertions, 0 deletions
diff --git a/rtl/curve/curve_dbl_add_384.v b/rtl/curve/curve_dbl_add_384.v
new file mode 100644
index 0000000..70a23bf
--- /dev/null
+++ b/rtl/curve/curve_dbl_add_384.v
@@ -0,0 +1,874 @@
+//------------------------------------------------------------------------------
+//
+// curve_dbl_add_384.v
+// -----------------------------------------------------------------------------
+// Elliptic curve point adder and 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.
+//
+//------------------------------------------------------------------------------
+
+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 "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
+ //
+ reg uop_trig;
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) uop_trig <= 1'b0;
+ else uop_trig <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0;
+
+
+ //
+ // 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 && 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 && 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;
+ assign mw_mov_ena = uop_opcode[1] & uop_trig;
+ assign mod_add_ena = uop_opcode[2] & uop_trig;
+ assign mod_sub_ena = uop_opcode[3] & uop_trig;
+ assign mod_mul_ena = uop_opcode[4] & uop_trig;
+
+
+ //
+ // 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) ) 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 && 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
new file mode 100644
index 0000000..9fcb884
--- /dev/null
+++ b/rtl/curve/curve_mul_384.v
@@ -0,0 +1,720 @@
+//------------------------------------------------------------------------------
+//
+// 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;
+
+ (* RAM_STYLE="BLOCK" *)
+ uop_init_rom op_rom_init
+ (
+ .clk (clk),
+ .addr (op_rom_addr),
+ .data (op_rom_init_data)
+ );
+
+ (* RAM_STYLE="BLOCK" *)
+ uop_dbl_rom op_rom_dbl
+ (
+ .clk (clk),
+ .addr (op_rom_addr),
+ .data (op_rom_dbl_data)
+ );
+
+ (* RAM_STYLE="BLOCK" *)
+ uop_add_rom op_rom_add
+ (
+ .clk (clk),
+ .addr (op_rom_addr),
+ .data (op_rom_add_data)
+ );
+
+ (* RAM_STYLE="BLOCK" *)
+ 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
new file mode 100644
index 0000000..754af3e
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_delta.v
@@ -0,0 +1,72 @@
+//======================================================================
+//
+// 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
new file mode 100644
index 0000000..25d5103
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_g_x.v
@@ -0,0 +1,72 @@
+//======================================================================
+//
+// 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
new file mode 100644
index 0000000..c2461eb
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_g_y.v
@@ -0,0 +1,72 @@
+//======================================================================
+//
+// 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
new file mode 100644
index 0000000..a6c474e
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_h_x.v
@@ -0,0 +1,71 @@
+//======================================================================
+//
+// 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'h1b13ea8a;
+ 4'b0001: bram_reg_b <= 32'h8b574391;
+ 4'b0010: bram_reg_b <= 32'h8155ad27;
+ 4'b0011: bram_reg_b <= 32'h55fa1b42;
+ 4'b0100: bram_reg_b <= 32'hfb57ab8d;
+ 4'b0101: bram_reg_b <= 32'h4c117c3e;
+ 4'b0110: bram_reg_b <= 32'he8b0c8cf;
+ 4'b0111: bram_reg_b <= 32'h23c5893a;
+ 4'b1000: bram_reg_b <= 32'h19bea517;
+ 4'b1001: bram_reg_b <= 32'he29c71c2;
+ 4'b1010: bram_reg_b <= 32'h82e9f590;
+ 4'b1011: bram_reg_b <= 32'haaf06bba;
+ endcase
+
+endmodule
diff --git a/rtl/curve/rom/brom_p384_h_y.v b/rtl/curve/rom/brom_p384_h_y.v
new file mode 100644
index 0000000..98c59ed
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_h_y.v
@@ -0,0 +1,71 @@
+//======================================================================
+//
+// 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'h6f15f19d;
+ 4'b0001: bram_reg_b <= 32'h85bce284;
+ 4'b0010: bram_reg_b <= 32'he2817e62;
+ 4'b0011: bram_reg_b <= 32'hf59f4e30;
+ 4'b0100: bram_reg_b <= 32'h4a0f473e;
+ 4'b0101: bram_reg_b <= 32'h1625ceec;
+ 4'b0110: bram_reg_b <= 32'hd765eb83;
+ 4'b0111: bram_reg_b <= 32'h070be242;
+ 4'b1000: bram_reg_b <= 32'h6d6d23d6;
+ 4'b1001: bram_reg_b <= 32'ha2616740;
+ 4'b1010: bram_reg_b <= 32'h69d9d390;
+ 4'b1011: bram_reg_b <= 32'hc9e821b5;
+ endcase
+
+endmodule
diff --git a/rtl/curve/rom/brom_p384_one.v b/rtl/curve/rom/brom_p384_one.v
new file mode 100644
index 0000000..fa8caa0
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_one.v
@@ -0,0 +1,72 @@
+//======================================================================
+//
+// 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
new file mode 100644
index 0000000..497c634
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_q.v
@@ -0,0 +1,72 @@
+//======================================================================
+//
+// 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
new file mode 100644
index 0000000..5166391
--- /dev/null
+++ b/rtl/curve/rom/brom_p384_zero.v
@@ -0,0 +1,42 @@
+//======================================================================
+//
+// 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/curve/uop/uop_add_rom.v b/rtl/curve/uop/uop_add_rom.v
new file mode 100644
index 0000000..c807736
--- /dev/null
+++ b/rtl/curve/uop/uop_add_rom.v
@@ -0,0 +1,66 @@
+`timescale 1ns / 1ps
+
+module uop_add_rom
+ (
+ input wire clk,
+ input wire [ 5: 0] addr,
+ output reg [19: 0] data
+ );
+
+
+ //
+ // Microcode
+ //
+`include "..\uop_ecdsa.v"
+
+
+ //
+ // Addition Microprogram
+ //
+ always @(posedge clk)
+
+ case (addr)
+
+/* 2. */6'd00: data <= {OPCODE_CMP, UOP_SRC_PZ, UOP_SRC_ZERO, UOP_DST_DUMMY, UOP_EXEC_ALWAYS};
+/* 3. */6'd01: data <= {OPCODE_MOV, UOP_SRC_PZ, UOP_SRC_DUMMY, UOP_DST_T1, UOP_EXEC_ALWAYS};
+ 6'd02: data <= {OPCODE_MUL, UOP_SRC_PZ, UOP_SRC_T1, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 4. */6'd03: data <= {OPCODE_MUL, UOP_SRC_PZ, UOP_SRC_T1, UOP_DST_T2, UOP_EXEC_ALWAYS};
+/* 5. */6'd04: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_G_X, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 6. */6'd05: data <= {OPCODE_MUL, UOP_SRC_T2, UOP_SRC_G_Y, UOP_DST_T2, UOP_EXEC_ALWAYS};
+/* 7. */6'd06: data <= {OPCODE_SUB, UOP_SRC_T1, UOP_SRC_PX, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 8. */6'd07: data <= {OPCODE_SUB, UOP_SRC_T2, UOP_SRC_PY, UOP_DST_T2, UOP_EXEC_ALWAYS};
+/* 9. */6'd08: data <= {OPCODE_CMP, UOP_SRC_T1, UOP_SRC_ZERO, UOP_DST_DUMMY, UOP_EXEC_ALWAYS};
+ 6'd09: data <= {OPCODE_CMP, UOP_SRC_T2, UOP_SRC_ZERO, UOP_DST_DUMMY, UOP_EXEC_ALWAYS};
+/* 10. */6'd10: data <= {OPCODE_MUL, UOP_SRC_PZ, UOP_SRC_T1, UOP_DST_RZ, UOP_EXEC_ALWAYS};
+/* 11. */6'd11: data <= {OPCODE_MOV, UOP_SRC_T1, UOP_SRC_DUMMY, UOP_DST_T3, UOP_EXEC_ALWAYS};
+ 6'd12: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_T3, UOP_DST_T3, UOP_EXEC_ALWAYS};
+/* 12. */6'd13: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_T3, UOP_DST_T4, UOP_EXEC_ALWAYS};
+/* 13. */6'd14: data <= {OPCODE_MUL, UOP_SRC_PX, UOP_SRC_T3, UOP_DST_T3, UOP_EXEC_ALWAYS};
+/* 14. */6'd15: data <= {OPCODE_ADD, UOP_SRC_T3, UOP_SRC_T3, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 15. */6'd16: data <= {OPCODE_MOV, UOP_SRC_T2, UOP_SRC_DUMMY, UOP_DST_RX, UOP_EXEC_ALWAYS};
+ 6'd17: data <= {OPCODE_MUL, UOP_SRC_RX, UOP_SRC_T2, UOP_DST_RX, UOP_EXEC_ALWAYS};
+/* 16. */6'd18: data <= {OPCODE_SUB, UOP_SRC_RX, UOP_SRC_T1, UOP_DST_RX, UOP_EXEC_ALWAYS};
+/* 17. */6'd19: data <= {OPCODE_SUB, UOP_SRC_RX, UOP_SRC_T4, UOP_DST_RX, UOP_EXEC_ALWAYS};
+/* 18. */6'd20: data <= {OPCODE_SUB, UOP_SRC_T3, UOP_SRC_RX, UOP_DST_T3, UOP_EXEC_ALWAYS};
+/* 19. */6'd21: data <= {OPCODE_MUL, UOP_SRC_T2, UOP_SRC_T3, UOP_DST_T3, UOP_EXEC_ALWAYS};
+/* 20. */6'd22: data <= {OPCODE_MUL, UOP_SRC_PY, UOP_SRC_T4, UOP_DST_T4, UOP_EXEC_ALWAYS};
+/* 21. */6'd23: data <= {OPCODE_SUB, UOP_SRC_T3, UOP_SRC_T4, UOP_DST_RY, UOP_EXEC_ALWAYS};
+
+ 6'd24: data <= {OPCODE_MOV, UOP_SRC_G_X, UOP_SRC_DUMMY, UOP_DST_RX, UOP_EXEC_PZT1T2_0XX};
+ 6'd25: data <= {OPCODE_MOV, UOP_SRC_G_Y, UOP_SRC_DUMMY, UOP_DST_RY, UOP_EXEC_PZT1T2_0XX};
+ 6'd26: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RZ, UOP_EXEC_PZT1T2_0XX};
+
+ 6'd27: data <= {OPCODE_MOV, UOP_SRC_H_X, UOP_SRC_DUMMY, UOP_DST_RX, UOP_EXEC_PZT1T2_100};
+ 6'd28: data <= {OPCODE_MOV, UOP_SRC_H_Y, UOP_SRC_DUMMY, UOP_DST_RY, UOP_EXEC_PZT1T2_100};
+ 6'd29: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RZ, UOP_EXEC_PZT1T2_100};
+
+ 6'd30: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RX, UOP_EXEC_PZT1T2_101};
+ 6'd31: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RY, UOP_EXEC_PZT1T2_101};
+ 6'd32: data <= {OPCODE_MOV, UOP_SRC_ZERO, UOP_SRC_DUMMY, UOP_DST_RZ, UOP_EXEC_PZT1T2_101};
+
+ default: data <= {OPCODE_RDY, UOP_SRC_DUMMY, UOP_SRC_DUMMY, UOP_DST_DUMMY};
+
+ endcase
+
+
+endmodule
diff --git a/rtl/curve/uop/uop_conv_rom.v b/rtl/curve/uop/uop_conv_rom.v
new file mode 100644
index 0000000..3097736
--- /dev/null
+++ b/rtl/curve/uop/uop_conv_rom.v
@@ -0,0 +1,38 @@
+`timescale 1ns / 1ps
+
+module uop_conv_rom
+ (
+ input wire clk,
+ input wire [ 5: 0] addr,
+ output reg [19: 0] data
+ );
+
+
+ //
+ // Microcode
+ //
+`include "..\uop_ecdsa.v"
+
+
+ //
+ // Doubling Microprogram
+ //
+ always @(posedge clk)
+
+ case (addr)
+
+ 6'd00: data <= {OPCODE_CMP, UOP_SRC_PZ, UOP_SRC_ZERO, UOP_DST_DUMMY, UOP_EXEC_ALWAYS};
+ 6'd01: data <= {OPCODE_MOV, UOP_SRC_V, UOP_SRC_DUMMY, UOP_DST_T1, UOP_EXEC_ALWAYS};
+ 6'd02: data <= {OPCODE_MUL, UOP_SRC_V, UOP_SRC_T1, UOP_DST_T2, UOP_EXEC_ALWAYS};
+ 6'd03: data <= {OPCODE_MUL, UOP_SRC_V, UOP_SRC_T2, UOP_DST_T3, UOP_EXEC_ALWAYS};
+ 6'd04: data <= {OPCODE_MUL, UOP_SRC_PX, UOP_SRC_T2, UOP_DST_RX, UOP_EXEC_ALWAYS};
+ 6'd05: data <= {OPCODE_MUL, UOP_SRC_PY, UOP_SRC_T3, UOP_DST_RY, UOP_EXEC_ALWAYS};
+ 6'd06: data <= {OPCODE_MOV, UOP_SRC_ZERO, UOP_SRC_DUMMY, UOP_DST_RX, UOP_EXEC_PZT1T2_0XX};
+ 6'd07: data <= {OPCODE_MOV, UOP_SRC_ZERO, UOP_SRC_DUMMY, UOP_DST_RY, UOP_EXEC_PZT1T2_0XX};
+
+ default: data <= {OPCODE_RDY, UOP_SRC_DUMMY, UOP_SRC_DUMMY, UOP_DST_DUMMY};
+
+ endcase
+
+
+endmodule
diff --git a/rtl/curve/uop/uop_dbl_rom.v b/rtl/curve/uop/uop_dbl_rom.v
new file mode 100644
index 0000000..1939ca9
--- /dev/null
+++ b/rtl/curve/uop/uop_dbl_rom.v
@@ -0,0 +1,58 @@
+`timescale 1ns / 1ps
+
+module uop_dbl_rom
+ (
+ input wire clk,
+ input wire [ 5: 0] addr,
+ output reg [19: 0] data
+ );
+
+
+ //
+ // Microcode
+ //
+`include "..\uop_ecdsa.v"
+
+
+ //
+ // Doubling Microprogram
+ //
+ always @(posedge clk)
+
+ case (addr)
+
+/* 1. */6'd00: data <= {OPCODE_CMP, UOP_SRC_PZ, UOP_SRC_ZERO, UOP_DST_DUMMY, UOP_EXEC_ALWAYS};
+/* 2. */6'd01: data <= {OPCODE_MOV, UOP_SRC_PZ, UOP_SRC_DUMMY, UOP_DST_T1, UOP_EXEC_ALWAYS};
+ 5'd02: data <= {OPCODE_MUL, UOP_SRC_PZ, UOP_SRC_T1, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 3. */6'd03: data <= {OPCODE_SUB, UOP_SRC_PX, UOP_SRC_T1, UOP_DST_T2, UOP_EXEC_ALWAYS};
+/* 4. */6'd04: data <= {OPCODE_ADD, UOP_SRC_PX, UOP_SRC_T1, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 5. */6'd05: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_T2, UOP_DST_T2, UOP_EXEC_ALWAYS};
+/* 6. */6'd06: data <= {OPCODE_ADD, UOP_SRC_T2, UOP_SRC_T2, UOP_DST_T1, UOP_EXEC_ALWAYS};
+ 6'd07: data <= {OPCODE_ADD, UOP_SRC_T1, UOP_SRC_T2, UOP_DST_T2, UOP_EXEC_ALWAYS};
+/* 7. */6'd08: data <= {OPCODE_ADD, UOP_SRC_PY, UOP_SRC_PY, UOP_DST_RY, UOP_EXEC_ALWAYS};
+/* 8. */6'd09: data <= {OPCODE_MUL, UOP_SRC_PZ, UOP_SRC_RY, UOP_DST_RZ, UOP_EXEC_ALWAYS};
+/* 9. */6'd10: data <= {OPCODE_MOV, UOP_SRC_RY, UOP_SRC_DUMMY, UOP_DST_T1, UOP_EXEC_ALWAYS};
+ 6'd11: data <= {OPCODE_MOV, UOP_SRC_RY, UOP_SRC_DUMMY, UOP_DST_T3, UOP_EXEC_ALWAYS};
+ 6'd12: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_T3, UOP_DST_RY, UOP_EXEC_ALWAYS};
+/* 10. */6'd13: data <= {OPCODE_MUL, UOP_SRC_PX, UOP_SRC_RY, UOP_DST_T3, UOP_EXEC_ALWAYS};
+/* 11. */6'd14: data <= {OPCODE_MOV, UOP_SRC_RY, UOP_SRC_DUMMY, UOP_DST_T1, UOP_EXEC_ALWAYS};
+ 6'd15: data <= {OPCODE_MUL, UOP_SRC_RY, UOP_SRC_T1, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 12. */6'd16: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_DELTA, UOP_DST_RY, UOP_EXEC_ALWAYS};
+/* 13. */6'd17: data <= {OPCODE_MOV, UOP_SRC_T2, UOP_SRC_DUMMY, UOP_DST_T1, UOP_EXEC_ALWAYS};
+ 6'd18: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_T2, UOP_DST_RX, UOP_EXEC_ALWAYS};
+/* 14. */6'd19: data <= {OPCODE_ADD, UOP_SRC_T3, UOP_SRC_T3, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 15. */6'd20: data <= {OPCODE_SUB, UOP_SRC_RX, UOP_SRC_T1, UOP_DST_RX, UOP_EXEC_ALWAYS};
+/* 16. */6'd21: data <= {OPCODE_SUB, UOP_SRC_T3, UOP_SRC_RX, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 17. */6'd22: data <= {OPCODE_MUL, UOP_SRC_T1, UOP_SRC_T2, UOP_DST_T1, UOP_EXEC_ALWAYS};
+/* 18. */6'd23: data <= {OPCODE_SUB, UOP_SRC_T1, UOP_SRC_RY, UOP_DST_RY, UOP_EXEC_ALWAYS};
+
+ 6'd24: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RX, UOP_EXEC_PZT1T2_0XX};
+ 6'd25: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RY, UOP_EXEC_PZT1T2_0XX};
+ 6'd26: data <= {OPCODE_MOV, UOP_SRC_ZERO, UOP_SRC_DUMMY, UOP_DST_RZ, UOP_EXEC_PZT1T2_0XX};
+
+ default: data <= {OPCODE_RDY, UOP_SRC_DUMMY, UOP_SRC_DUMMY, UOP_DST_DUMMY};
+
+ endcase
+
+
+endmodule
diff --git a/rtl/curve/uop/uop_init_rom.v b/rtl/curve/uop/uop_init_rom.v
new file mode 100644
index 0000000..ac44b55
--- /dev/null
+++ b/rtl/curve/uop/uop_init_rom.v
@@ -0,0 +1,33 @@
+`timescale 1ns / 1ps
+
+module uop_init_rom
+ (
+ input wire clk,
+ input wire [ 5: 0] addr,
+ output reg [19: 0] data
+ );
+
+
+ //
+ // Microcode
+ //
+`include "..\uop_ecdsa.v"
+
+
+ //
+ // Doubling Microprogram
+ //
+ always @(posedge clk)
+
+ case (addr)
+
+ 6'd00: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RX, UOP_EXEC_ALWAYS};
+ 6'd01: data <= {OPCODE_MOV, UOP_SRC_ONE, UOP_SRC_DUMMY, UOP_DST_RY, UOP_EXEC_ALWAYS};
+ 6'd02: data <= {OPCODE_MOV, UOP_SRC_ZERO, UOP_SRC_DUMMY, UOP_DST_RZ, UOP_EXEC_ALWAYS};
+
+ default: data <= {OPCODE_RDY, UOP_SRC_DUMMY, UOP_SRC_DUMMY, UOP_DST_DUMMY};
+
+ endcase
+
+
+endmodule
diff --git a/rtl/curve/uop_ecdsa.v b/rtl/curve/uop_ecdsa.v
new file mode 100644
index 0000000..e64119d
--- /dev/null
+++ b/rtl/curve/uop_ecdsa.v
@@ -0,0 +1,50 @@
+localparam [ 4: 0] OPCODE_CMP = 5'b00001;
+localparam [ 4: 0] OPCODE_MOV = 5'b00010;
+localparam [ 4: 0] OPCODE_ADD = 5'b00100;
+localparam [ 4: 0] OPCODE_SUB = 5'b01000;
+localparam [ 4: 0] OPCODE_MUL = 5'b10000;
+localparam [ 4: 0] OPCODE_RDY = 5'b00000;
+
+localparam [ 4: 0] UOP_SRC_PX = 5'h0_0;
+localparam [ 4: 0] UOP_SRC_PY = 5'h0_1;
+localparam [ 4: 0] UOP_SRC_PZ = 5'h0_2;
+
+localparam [ 4: 0] UOP_SRC_RX = 5'h0_3;
+localparam [ 4: 0] UOP_SRC_RY = 5'h0_4;
+localparam [ 4: 0] UOP_SRC_RZ = 5'h0_5;
+
+localparam [ 4: 0] UOP_SRC_T1 = 5'h0_6;
+localparam [ 4: 0] UOP_SRC_T2 = 5'h0_7;
+localparam [ 4: 0] UOP_SRC_T3 = 5'h0_8;
+localparam [ 4: 0] UOP_SRC_T4 = 5'h0_9;
+
+localparam [ 4: 0] UOP_SRC_ONE = 5'h0_A;
+localparam [ 4: 0] UOP_SRC_ZERO = 5'h0_B;
+localparam [ 4: 0] UOP_SRC_DELTA = 5'h0_C;
+
+localparam [ 4: 0] UOP_SRC_V = 5'h0_F;
+
+localparam [ 4: 0] UOP_SRC_G_X = 5'h1_0;
+localparam [ 4: 0] UOP_SRC_G_Y = 5'h1_1;
+
+localparam [ 4: 0] UOP_SRC_H_X = 5'h1_2;
+localparam [ 4: 0] UOP_SRC_H_Y = 5'h1_3;
+
+localparam [ 4: 0] UOP_SRC_DUMMY = 5'hX_X;
+
+localparam [ 2: 0] UOP_DST_RX = 3'd0;
+localparam [ 2: 0] UOP_DST_RY = 3'd1;
+localparam [ 2: 0] UOP_DST_RZ = 3'd2;
+
+localparam [ 2: 0] UOP_DST_T1 = 3'd3;
+localparam [ 2: 0] UOP_DST_T2 = 3'd4;
+localparam [ 2: 0] UOP_DST_T3 = 3'd5;
+localparam [ 2: 0] UOP_DST_T4 = 3'd6;
+
+localparam [ 2: 0] UOP_DST_DUMMY = 3'dX;
+
+localparam UOP_EXEC_ALWAYS = 2'b11; // R
+localparam UOP_EXEC_PZT1T2_0XX = 2'b10; // G
+localparam UOP_EXEC_PZT1T2_100 = 2'b00; // H
+localparam UOP_EXEC_PZT1T2_101 = 2'b01; // O
+