aboutsummaryrefslogtreecommitdiff
path: root/rtl/modular/modular_invertor/helper
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2016-10-31 00:14:51 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2016-10-31 00:14:51 +0300
commit25e338149fdb8e06c82d99600769a8498a85ef2c (patch)
treecf4b855bcf1083f3cffebf6a98b5aaad45baf362 /rtl/modular/modular_invertor/helper
Initial commit of base point multiplier core for ECDSA curve P-256.
Diffstat (limited to 'rtl/modular/modular_invertor/helper')
-rw-r--r--rtl/modular/modular_invertor/helper/modinv_helper_copy.v148
-rw-r--r--rtl/modular/modular_invertor/helper/modinv_helper_init.v172
-rw-r--r--rtl/modular/modular_invertor/helper/modinv_helper_invert_compare.v286
-rw-r--r--rtl/modular/modular_invertor/helper/modinv_helper_invert_precalc.v408
-rw-r--r--rtl/modular/modular_invertor/helper/modinv_helper_invert_update.v257
-rw-r--r--rtl/modular/modular_invertor/helper/modinv_helper_reduce_precalc.v328
-rw-r--r--rtl/modular/modular_invertor/helper/modinv_helper_reduce_update.v153
7 files changed, 1752 insertions, 0 deletions
diff --git a/rtl/modular/modular_invertor/helper/modinv_helper_copy.v b/rtl/modular/modular_invertor/helper/modinv_helper_copy.v
new file mode 100644
index 0000000..07c1b4f
--- /dev/null
+++ b/rtl/modular/modular_invertor/helper/modinv_helper_copy.v
@@ -0,0 +1,148 @@
+`timescale 1ns / 1ps
+
+module modinv_helper_copy
+ (
+ clk, rst_n,
+ ena, rdy,
+ s_addr, s_din,
+ a1_addr, a1_wren, a1_dout
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter OPERAND_NUM_WORDS = 8;
+ parameter OPERAND_ADDR_BITS = 3;
+
+ parameter BUFFER_NUM_WORDS = 9;
+ parameter BUFFER_ADDR_BITS = 4;
+
+
+ //
+ // clog2
+ //
+`include "..\modinv_clog2.v"
+
+
+ //
+ // Constants
+ //
+ localparam PROC_NUM_CYCLES = OPERAND_NUM_WORDS + 2;
+ localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES);
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire rst_n;
+
+ input wire ena;
+ output wire rdy;
+
+ output wire [ BUFFER_ADDR_BITS-1:0] s_addr;
+ output wire [OPERAND_ADDR_BITS-1:0] a1_addr;
+
+ output wire a1_wren;
+
+ input wire [ 31:0] s_din;
+
+ output wire [ 31:0] a1_dout;
+
+
+ //
+ // Counter
+ //
+ reg [PROC_CNT_BITS-1:0] proc_cnt;
+
+ wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1;
+ wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}};
+ wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ?
+ proc_cnt + 1'b1 : proc_cnt_zero;
+
+ //
+ // Addresses
+ //
+ reg [OPERAND_ADDR_BITS-1:0] addr_s;
+
+ wire [OPERAND_ADDR_BITS-1:0] addr_s_max = OPERAND_NUM_WORDS - 1;
+ wire [OPERAND_ADDR_BITS-1:0] addr_s_zero = {OPERAND_ADDR_BITS{1'b0}};
+ wire [OPERAND_ADDR_BITS-1:0] addr_s_next = (addr_s < addr_s_max) ?
+ addr_s + 1'b1 : addr_s_zero;
+
+ reg [OPERAND_ADDR_BITS-1:0] addr_a1;
+
+ wire [OPERAND_ADDR_BITS-1:0] addr_a1_max = OPERAND_NUM_WORDS - 1;
+ wire [OPERAND_ADDR_BITS-1:0] addr_a1_zero = {OPERAND_ADDR_BITS{1'b0}};
+ wire [OPERAND_ADDR_BITS-1:0] addr_a1_next = (addr_a1 < addr_a1_max) ?
+ addr_a1 + 1'b1 : addr_a1_zero;
+
+ assign s_addr = {{(BUFFER_ADDR_BITS - OPERAND_ADDR_BITS){1'b0}}, addr_s};
+ assign a1_addr = addr_a1;
+
+
+ //
+ // Ready Flag
+ //
+ assign rdy = (proc_cnt == proc_cnt_zero);
+
+
+ //
+ // Address Increment Logic
+ //
+ wire inc_addr_s;
+ wire inc_addr_a1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_s_start = 1;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_s_stop = OPERAND_NUM_WORDS + 0;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_a1_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_a1_stop = OPERAND_NUM_WORDS + 1;
+
+ assign inc_addr_s = (proc_cnt >= cnt_inc_addr_s_start) && (proc_cnt <= cnt_inc_addr_s_stop);
+ assign inc_addr_a1 = (proc_cnt >= cnt_inc_addr_a1_start) && (proc_cnt <= cnt_inc_addr_a1_stop);
+
+ always @(posedge clk) begin
+ //
+ if (inc_addr_s) addr_s <= addr_s_next;
+ else addr_s <= addr_s_zero;
+ //
+ if (inc_addr_a1) addr_a1 <= addr_a1_next;
+ else addr_a1 <= addr_a1_zero;
+ //
+ end
+
+
+ //
+ // Write Enable Logic
+ //
+ wire wren_a1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_a1_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_a1_stop = OPERAND_NUM_WORDS + 1;
+
+ assign wren_a1 = (proc_cnt >= cnt_wren_a1_start) && (proc_cnt <= cnt_wren_a1_stop);
+
+ assign a1_wren = wren_a1;
+
+
+ //
+ // Data Logic
+ //
+ assign a1_dout = s_din;
+
+
+ //
+ // Primary Counter Logic
+ //
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero;
+ else begin
+ if (!rdy) proc_cnt <= proc_cnt_next;
+ else if (ena) proc_cnt <= proc_cnt_next;
+ end
+
+
+endmodule
diff --git a/rtl/modular/modular_invertor/helper/modinv_helper_init.v b/rtl/modular/modular_invertor/helper/modinv_helper_init.v
new file mode 100644
index 0000000..0468134
--- /dev/null
+++ b/rtl/modular/modular_invertor/helper/modinv_helper_init.v
@@ -0,0 +1,172 @@
+`timescale 1ns / 1ps
+
+module modinv_helper_init
+ (
+ clk, rst_n,
+ ena, rdy,
+ a_addr, a_din,
+ q_addr, q_din,
+ r_addr, r_wren, r_dout,
+ s_addr, s_wren, s_dout,
+ u_addr, u_wren, u_dout,
+ v_addr, v_wren, v_dout
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter OPERAND_NUM_WORDS = 8;
+ parameter OPERAND_ADDR_BITS = 3;
+
+ parameter BUFFER_NUM_WORDS = 9;
+ parameter BUFFER_ADDR_BITS = 4;
+
+
+ //
+ // clog2
+ //
+`include "..\modinv_clog2.v"
+
+
+ //
+ // Constants
+ //
+ localparam PROC_NUM_CYCLES = OPERAND_NUM_WORDS + 3;
+ localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES);
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire rst_n;
+ input wire ena;
+ output wire rdy;
+
+ output wire [OPERAND_ADDR_BITS-1:0] a_addr;
+ output wire [OPERAND_ADDR_BITS-1:0] q_addr;
+ output wire [ BUFFER_ADDR_BITS-1:0] r_addr;
+ output wire [ BUFFER_ADDR_BITS-1:0] s_addr;
+ output wire [ BUFFER_ADDR_BITS-1:0] u_addr;
+ output wire [ BUFFER_ADDR_BITS-1:0] v_addr;
+
+ output wire r_wren;
+ output wire s_wren;
+ output wire u_wren;
+ output wire v_wren;
+
+ input wire [ 31:0] a_din;
+ input wire [ 31:0] q_din;
+ output wire [ 31:0] r_dout;
+ output wire [ 31:0] s_dout;
+ output wire [ 31:0] u_dout;
+ output wire [ 31:0] v_dout;
+
+
+ //
+ // Counter
+ //
+ reg [PROC_CNT_BITS-1:0] proc_cnt;
+
+ wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1;
+ wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}};
+ wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ?
+ proc_cnt + 1'b1 : proc_cnt_zero;
+
+ //
+ // Addresses
+ //
+ reg [OPERAND_ADDR_BITS-1:0] addr_aq;
+
+ wire [OPERAND_ADDR_BITS-1:0] addr_aq_max = OPERAND_NUM_WORDS - 1;
+ wire [OPERAND_ADDR_BITS-1:0] addr_aq_zero = {OPERAND_ADDR_BITS{1'b0}};
+ wire [OPERAND_ADDR_BITS-1:0] addr_aq_next = (addr_aq < addr_aq_max) ?
+ addr_aq + 1'b1 : addr_aq_zero;
+
+ reg [BUFFER_ADDR_BITS-1:0] addr_rsuv;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_rsuv_max = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_rsuv_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_rsuv_next = (addr_rsuv < addr_rsuv_max) ?
+ addr_rsuv + 1'b1 : addr_rsuv_zero;
+
+ assign a_addr = addr_aq;
+ assign q_addr = addr_aq;
+
+ assign r_addr = addr_rsuv;
+ assign s_addr = addr_rsuv;
+ assign u_addr = addr_rsuv;
+ assign v_addr = addr_rsuv;
+
+
+ //
+ // Ready Flag
+ //
+ assign rdy = (proc_cnt == proc_cnt_zero);
+
+
+ //
+ // Address Increment Logic
+ //
+ wire inc_addr_aq;
+ wire inc_addr_rsuv;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_aq_start = 1;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_aq_stop = OPERAND_NUM_WORDS;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_rsuv_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_rsuv_stop = BUFFER_NUM_WORDS + 1;
+
+ assign inc_addr_aq = (proc_cnt >= cnt_inc_addr_aq_start) && (proc_cnt <= cnt_inc_addr_aq_stop);
+ assign inc_addr_rsuv = (proc_cnt >= cnt_inc_addr_rsuv_start) && (proc_cnt <= cnt_inc_addr_rsuv_stop);
+
+ always @(posedge clk) begin
+ //
+ if (inc_addr_aq) addr_aq <= addr_aq_next;
+ else addr_aq <= addr_aq_zero;
+ //
+ if (inc_addr_rsuv) addr_rsuv <= addr_rsuv_next;
+ else addr_rsuv <= addr_rsuv_zero;
+ //
+ end
+
+
+ //
+ // Write Enable Logic
+ //
+ wire wren_rsuv;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_rsuv_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_rsuv_stop = BUFFER_NUM_WORDS + 1;
+
+ assign wren_rsuv = (proc_cnt >= cnt_wren_rsuv_start) && (proc_cnt <= cnt_wren_rsuv_stop);
+
+ assign r_wren = wren_rsuv;
+ assign s_wren = wren_rsuv;
+ assign u_wren = wren_rsuv;
+ assign v_wren = wren_rsuv;
+
+
+ //
+ // Data Logic
+ //
+ assign r_dout = 32'd0;
+ assign s_dout = (proc_cnt == cnt_wren_rsuv_start) ? 32'd1 : 32'd0;
+ assign u_dout = (proc_cnt != cnt_wren_rsuv_stop) ? q_din : 32'd0;
+ assign v_dout = (proc_cnt != cnt_wren_rsuv_stop) ? a_din : 32'd0;
+
+
+ //
+ // Primary Counter Logic
+ //
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero;
+ else begin
+ if (!rdy) proc_cnt <= proc_cnt_next;
+ else if (ena) proc_cnt <= proc_cnt_next;
+ end
+
+
+endmodule
diff --git a/rtl/modular/modular_invertor/helper/modinv_helper_invert_compare.v b/rtl/modular/modular_invertor/helper/modinv_helper_invert_compare.v
new file mode 100644
index 0000000..6b65eb1
--- /dev/null
+++ b/rtl/modular/modular_invertor/helper/modinv_helper_invert_compare.v
@@ -0,0 +1,286 @@
+`timescale 1ns / 1ps
+
+module modinv_helper_invert_compare
+ (
+ clk, rst_n,
+ ena, rdy,
+
+ u_addr, u_din,
+ v_addr, v_din,
+
+ u_gt_v, v_eq_1,
+ u_is_even, v_is_even
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter BUFFER_NUM_WORDS = 9;
+ parameter BUFFER_ADDR_BITS = 4;
+
+
+ //
+ // clog2
+ //
+`include "..\modinv_clog2.v"
+
+
+ //
+ // Constants
+ //
+ localparam PROC_NUM_CYCLES = 1 * BUFFER_NUM_WORDS + 10;
+ localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES);
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire rst_n;
+ input wire ena;
+ output wire rdy;
+
+ output wire [BUFFER_ADDR_BITS-1:0] u_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_addr;
+
+ input wire [ 32-1:0] u_din;
+ input wire [ 32-1:0] v_din;
+
+ output wire u_gt_v;
+ output wire v_eq_1;
+ output wire u_is_even;
+ output wire v_is_even;
+
+
+ //
+ // Counter
+ //
+ reg [PROC_CNT_BITS-1:0] proc_cnt;
+
+ wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1;
+ wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}};
+ wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ?
+ proc_cnt + 1'b1 : proc_cnt_zero;
+
+ //
+ // Addresses
+ //
+ reg [BUFFER_ADDR_BITS-1:0] addr_in;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_prev = (addr_in > addr_in_zero) ?
+ addr_in - 1'b1 : addr_in_last;
+
+ assign u_addr = addr_in;
+ assign v_addr = addr_in;
+
+
+ //
+ // Ready Flag
+ //
+ assign rdy = (proc_cnt == proc_cnt_zero);
+
+
+ //
+ // Address Decrement Logic
+ //
+ wire dec_addr_in;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_in_start = 0 * BUFFER_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_in_stop = 1 * BUFFER_NUM_WORDS + 0;
+
+ assign dec_addr_in = (proc_cnt >= cnt_dec_addr_in_start) && (proc_cnt <= cnt_dec_addr_in_stop);
+
+ always @(posedge clk)
+ //
+ if (rdy) addr_in <= addr_in_last;
+ else if (dec_addr_in) addr_in <= addr_in_prev;
+
+
+ //
+ // Comparison Stage Flags
+ //
+ wire calc_leg;
+ wire calc_leg_final;
+ wire calc_parity;
+
+ wire [PROC_CNT_BITS-1:0] cnt_calc_leg_start = 0 * BUFFER_NUM_WORDS + 3;
+ wire [PROC_CNT_BITS-1:0] cnt_calc_leg_stop = 1 * BUFFER_NUM_WORDS + 2;
+ wire [PROC_CNT_BITS-1:0] cnt_calc_parity = 1 * BUFFER_NUM_WORDS + 1;
+
+ assign calc_leg = (proc_cnt >= cnt_calc_leg_start) && (proc_cnt <= cnt_calc_leg_stop);
+ assign calc_leg_final = (proc_cnt == cnt_calc_leg_stop);
+ assign calc_parity = (proc_cnt == cnt_calc_parity);
+
+
+ //
+ // Dummy Input
+ //
+ reg sub32_din_1_lsb;
+ wire [31: 0] sub32_din_1 = {{31{1'b0}}, sub32_din_1_lsb};
+
+ always @(posedge clk)
+ //
+ sub32_din_1_lsb <= (addr_in == addr_in_zero) ? 1'b1 : 1'b0;
+
+
+ //
+ // Subtractor (u - v)
+ //
+ wire [31: 0] sub32_u_minus_v_difference_out;
+ wire sub32_u_minus_v_borrow_in;
+ wire sub32_u_minus_v_borrow_out;
+
+ subtractor32_wrapper sub32_u_minus_v
+ (
+ .clk (clk),
+ .a (u_din),
+ .b (v_din),
+ .d (sub32_u_minus_v_difference_out),
+ .b_in (sub32_u_minus_v_borrow_in),
+ .b_out (sub32_u_minus_v_borrow_out)
+ );
+
+
+ //
+ // Subtractor (v - 1)
+ //
+ wire [31: 0] sub32_v_minus_1_difference_out;
+ wire sub32_v_minus_1_borrow_in;
+ wire sub32_v_minus_1_borrow_out;
+
+ subtractor32_wrapper sub32_v_minus_1
+ (
+ .clk (clk),
+ .a (v_din),
+ .b (sub32_din_1),
+ .d (sub32_v_minus_1_difference_out),
+ .b_in (sub32_v_minus_1_borrow_in),
+ .b_out (sub32_v_minus_1_borrow_out)
+ );
+
+
+
+ //
+ // Borrow Masking Logic
+ //
+ reg mask_borrow;
+
+ always @(posedge clk)
+ //
+ mask_borrow <= ((proc_cnt > cnt_dec_addr_in_start) && (proc_cnt <= cnt_dec_addr_in_stop)) ?
+ 1'b0 : 1'b1;
+
+ assign sub32_u_minus_v_borrow_in = sub32_u_minus_v_borrow_out & ~mask_borrow;
+ assign sub32_v_minus_1_borrow_in = sub32_v_minus_1_borrow_out & ~mask_borrow;
+
+
+ //
+ // Comparison Logic
+ //
+ reg cmp_u_v_l;
+ reg cmp_u_v_e;
+ reg cmp_u_v_g;
+
+ reg cmp_v_1_l;
+ reg cmp_v_1_e;
+ reg cmp_v_1_g;
+
+ wire cmp_unresolved_u_v = !(cmp_u_v_l || cmp_u_v_g);
+ wire cmp_unresolved_v_1 = !(cmp_v_1_l || cmp_v_1_g);
+
+ wire cmp_u_v_borrow_is_set = (sub32_u_minus_v_borrow_out == 1'b1) ? 1'b1 : 1'b0;
+ wire cmp_u_v_difference_is_nonzero = (sub32_u_minus_v_difference_out != 32'd0) ? 1'b1 : 1'b0;
+
+ wire cmp_v_1_borrow_is_set = (sub32_v_minus_1_borrow_out == 1'b1) ? 1'b1 : 1'b0;
+ wire cmp_v_1_difference_is_nonzero = (sub32_v_minus_1_difference_out != 32'd0) ? 1'b1 : 1'b0;
+
+ reg u_is_even_reg;
+ reg v_is_even_reg;
+
+ always @(posedge clk)
+ //
+ if (rdy) begin
+ //
+ if (ena) begin
+ //
+ cmp_u_v_l <= 1'b0;
+ cmp_u_v_e <= 1'b0;
+ cmp_u_v_g <= 1'b0;
+ //
+ cmp_v_1_l <= 1'b0;
+ cmp_v_1_e <= 1'b0;
+ cmp_v_1_g <= 1'b0;
+ //
+ u_is_even_reg <= 1'bX;
+ v_is_even_reg <= 1'bX;
+ //
+ end
+ //
+ end else begin
+ //
+ // parity
+ //
+ if (calc_parity) begin
+ u_is_even_reg <= ~u_din[0];
+ v_is_even_reg <= ~v_din[0];
+ end
+ //
+ // u <> v
+ //
+ if (cmp_unresolved_u_v && calc_leg) begin
+ //
+ if (cmp_u_v_borrow_is_set)
+ cmp_u_v_l <= 1'b1;
+ //
+ if (!cmp_u_v_borrow_is_set && cmp_u_v_difference_is_nonzero)
+ cmp_u_v_g <= 1'b1;
+ //
+ if (!cmp_u_v_borrow_is_set && !cmp_u_v_difference_is_nonzero && calc_leg_final)
+ cmp_u_v_e <= 1'b1;
+ //
+ end
+ //
+ // v <> 1
+ //
+ if (cmp_unresolved_v_1 && calc_leg) begin
+ //
+ if (cmp_v_1_borrow_is_set)
+ cmp_v_1_l <= 1'b1;
+ //
+ if (!cmp_v_1_borrow_is_set && cmp_v_1_difference_is_nonzero)
+ cmp_v_1_g <= 1'b1;
+ //
+ if (!cmp_v_1_borrow_is_set && !cmp_v_1_difference_is_nonzero && calc_leg_final)
+ cmp_v_1_e <= 1'b1;
+ //
+ end
+ //
+ end
+
+
+ //
+ // Output Flags
+ //
+ assign u_gt_v = !cmp_u_v_l && !cmp_u_v_e && cmp_u_v_g;
+ assign v_eq_1 = !cmp_v_1_l && cmp_v_1_e && !cmp_v_1_g;
+
+ assign u_is_even = u_is_even_reg;
+ assign v_is_even = v_is_even_reg;
+
+
+ //
+ // Primary Counter Logic
+ //
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero;
+ else begin
+ if (!rdy) proc_cnt <= proc_cnt_next;
+ else if (ena) proc_cnt <= proc_cnt_next;
+ end
+
+
+endmodule
diff --git a/rtl/modular/modular_invertor/helper/modinv_helper_invert_precalc.v b/rtl/modular/modular_invertor/helper/modinv_helper_invert_precalc.v
new file mode 100644
index 0000000..ab15563
--- /dev/null
+++ b/rtl/modular/modular_invertor/helper/modinv_helper_invert_precalc.v
@@ -0,0 +1,408 @@
+`timescale 1ns / 1ps
+
+module modinv_helper_invert_precalc
+ (
+ clk, rst_n,
+ ena, rdy,
+
+ r_addr, r_din,
+ s_addr, s_din,
+ u_addr, u_din,
+ v_addr, v_din,
+
+ r_dbl_addr, r_dbl_wren, r_dbl_dout,
+ s_dbl_addr, s_dbl_wren, s_dbl_dout,
+ r_plus_s_addr, r_plus_s_wren, r_plus_s_dout,
+ u_half_addr, u_half_wren, u_half_dout,
+ v_half_addr, v_half_wren, v_half_dout,
+ u_minus_v_addr, u_minus_v_wren, u_minus_v_dout, u_minus_v_din,
+ v_minus_u_addr, v_minus_u_wren, v_minus_u_dout, v_minus_u_din,
+ u_minus_v_half_addr, u_minus_v_half_wren, u_minus_v_half_dout,
+ v_minus_u_half_addr, v_minus_u_half_wren, v_minus_u_half_dout
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter BUFFER_NUM_WORDS = 9;
+ parameter BUFFER_ADDR_BITS = 4;
+
+
+ //
+ // clog2
+ //
+`include "..\modinv_clog2.v"
+
+
+ //
+ // Constants
+ //
+ localparam PROC_NUM_CYCLES = 2 * BUFFER_NUM_WORDS + 4;
+ localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES);
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire rst_n;
+ input wire ena;
+ output wire rdy;
+
+ output wire [BUFFER_ADDR_BITS-1:0] r_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] s_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_addr;
+
+ input wire [ 32-1:0] r_din;
+ input wire [ 32-1:0] s_din;
+ input wire [ 32-1:0] u_din;
+ input wire [ 32-1:0] v_din;
+
+ output wire [BUFFER_ADDR_BITS-1:0] r_dbl_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] s_dbl_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] r_plus_s_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_half_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_half_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_minus_v_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_minus_u_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_minus_v_half_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_minus_u_half_addr;
+
+ output wire [ 32-1:0] r_dbl_dout;
+ output wire [ 32-1:0] s_dbl_dout;
+ output wire [ 32-1:0] r_plus_s_dout;
+ output wire [ 32-1:0] u_half_dout;
+ output wire [ 32-1:0] v_half_dout;
+ output wire [ 32-1:0] u_minus_v_dout;
+ output wire [ 32-1:0] v_minus_u_dout;
+ output wire [ 32-1:0] u_minus_v_half_dout;
+ output wire [ 32-1:0] v_minus_u_half_dout;
+
+ output wire r_dbl_wren;
+ output wire s_dbl_wren;
+ output wire r_plus_s_wren;
+ output wire u_half_wren;
+ output wire v_half_wren;
+ output wire u_minus_v_wren;
+ output wire v_minus_u_wren;
+ output wire u_minus_v_half_wren;
+ output wire v_minus_u_half_wren;
+
+ input wire [ 32-1:0] u_minus_v_din;
+ input wire [ 32-1:0] v_minus_u_din;
+
+
+
+ //
+ // Counter
+ //
+ reg [PROC_CNT_BITS-1:0] proc_cnt;
+
+ wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1;
+ wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}};
+ wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ?
+ proc_cnt + 1'b1 : proc_cnt_zero;
+
+ //
+ // Addresses
+ //
+ reg [BUFFER_ADDR_BITS-1:0] addr_in;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_next = (addr_in < addr_in_last) ?
+ addr_in + 1'b1 : addr_in_zero;
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_prev = (addr_in > addr_in_zero) ?
+ addr_in - 1'b1 : addr_in_zero;
+
+ reg [BUFFER_ADDR_BITS-1:0] addr_out1;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out1_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out1_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out1_next = (addr_out1 < addr_out1_last) ?
+ addr_out1 + 1'b1 : addr_out1_zero;
+
+ reg [BUFFER_ADDR_BITS-1:0] addr_out2;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out2_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out2_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out2_next = (addr_out2 < addr_out2_last) ?
+ addr_out2 + 1'b1 : addr_out2_zero;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out2_prev = (addr_out2 > addr_out2_zero) ?
+ addr_out2 - 1'b1 : addr_out2_zero;
+
+ reg [BUFFER_ADDR_BITS-1:0] addr_out3;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out3_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out3_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out3_prev = (addr_out3 > addr_out3_zero) ?
+ addr_out3 - 1'b1 : addr_out3_last;
+
+ reg [BUFFER_ADDR_BITS-1:0] addr_out4;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out4_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out4_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out4_prev = (addr_out4 > addr_out4_zero) ?
+ addr_out4 - 1'b1 : addr_out4_last;
+
+
+ assign r_addr = addr_in;
+ assign s_addr = addr_in;
+ assign u_addr = addr_in;
+ assign v_addr = addr_in;
+
+ assign r_dbl_addr = addr_out1;
+ assign s_dbl_addr = addr_out1;
+ assign r_plus_s_addr = addr_out2;
+ assign u_half_addr = addr_out3;
+ assign v_half_addr = addr_out3;
+ assign u_minus_v_addr = addr_out2;
+ assign v_minus_u_addr = addr_out2;
+ assign u_minus_v_half_addr = addr_out4;
+ assign v_minus_u_half_addr = addr_out4;
+
+
+ //
+ // Ready Flag
+ //
+ assign rdy = (proc_cnt == proc_cnt_zero);
+
+
+ //
+ // Address Increment/Decrement Logic
+ //
+ wire inc_addr_in;
+ wire dec_addr_in;
+ wire inc_addr_out1;
+ wire inc_addr_out2;
+ wire dec_addr_out2;
+ wire dec_addr_out3;
+ wire dec_addr_out4;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_start = 0 * BUFFER_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_stop = 1 * BUFFER_NUM_WORDS - 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out1_start = 0 * BUFFER_NUM_WORDS + 2;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out1_stop = 1 * BUFFER_NUM_WORDS + 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out2_start = 0 * BUFFER_NUM_WORDS + 3;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out2_stop = 1 * BUFFER_NUM_WORDS + 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out2_start = 1 * BUFFER_NUM_WORDS + 3;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out2_stop = 2 * BUFFER_NUM_WORDS + 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_in_start = 1 * BUFFER_NUM_WORDS + 0;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_in_stop = 2 * BUFFER_NUM_WORDS - 2;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out3_start = 1 * BUFFER_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out3_stop = 2 * BUFFER_NUM_WORDS + 0;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out4_start = 1 * BUFFER_NUM_WORDS + 4;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out4_stop = 2 * BUFFER_NUM_WORDS + 3;
+
+ assign inc_addr_in = (proc_cnt >= cnt_inc_addr_in_start) && (proc_cnt <= cnt_inc_addr_in_stop);
+ assign dec_addr_in = (proc_cnt >= cnt_dec_addr_in_start) && (proc_cnt <= cnt_dec_addr_in_stop);
+ assign inc_addr_out1 = (proc_cnt >= cnt_inc_addr_out1_start) && (proc_cnt <= cnt_inc_addr_out1_stop);
+ assign inc_addr_out2 = (proc_cnt >= cnt_inc_addr_out2_start) && (proc_cnt <= cnt_inc_addr_out2_stop);
+ assign dec_addr_out2 = (proc_cnt >= cnt_dec_addr_out2_start) && (proc_cnt <= cnt_dec_addr_out2_stop);
+ assign dec_addr_out3 = (proc_cnt >= cnt_dec_addr_out3_start) && (proc_cnt <= cnt_dec_addr_out3_stop);
+ assign dec_addr_out4 = (proc_cnt >= cnt_dec_addr_out4_start) && (proc_cnt <= cnt_dec_addr_out4_stop);
+
+
+ always @(posedge clk) begin
+ //
+ if (rdy) begin
+ //
+ addr_in <= addr_in_zero;
+ addr_out1 <= addr_out1_zero;
+ addr_out2 <= addr_out2_zero;
+ addr_out3 <= addr_out3_last;
+ addr_out4 <= addr_out4_last;
+ //
+ end else begin
+ //
+ if (inc_addr_in) addr_in <= addr_in_next;
+ else if (dec_addr_in) addr_in <= addr_in_prev;
+ //
+ if (inc_addr_out1) addr_out1 <= addr_out1_next;
+ else addr_out1 <= addr_out1_zero;
+ //
+ if (inc_addr_out2) addr_out2 <= addr_out2_next;
+ else if (dec_addr_out2) addr_out2 <= addr_out2_prev;
+ //
+ if (dec_addr_out3) addr_out3 <= addr_out3_prev;
+ else addr_out3 <= addr_out3_last;
+ //
+ if (dec_addr_out4) addr_out4 <= addr_out4_prev;
+ else addr_out4 <= addr_out4_last;
+ //
+ end
+ //
+ end
+
+
+ //
+ // Write Enable Logic
+ //
+ wire wren_out1;
+ wire wren_out2;
+ wire wren_out3;
+ wire wren_out4;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out1_start = 0 * BUFFER_NUM_WORDS + 2;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out1_stop = 1 * BUFFER_NUM_WORDS + 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out2_start = 0 * BUFFER_NUM_WORDS + 3;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out2_stop = 1 * BUFFER_NUM_WORDS + 2;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out3_start = 1 * BUFFER_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out3_stop = 2 * BUFFER_NUM_WORDS + 0;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out4_start = 1 * BUFFER_NUM_WORDS + 4;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out4_stop = 2 * BUFFER_NUM_WORDS + 3;
+
+ assign wren_out1 = (proc_cnt >= cnt_wren_out1_start) && (proc_cnt <= cnt_wren_out1_stop);
+ assign wren_out2 = (proc_cnt >= cnt_wren_out2_start) && (proc_cnt <= cnt_wren_out2_stop);
+ assign wren_out3 = (proc_cnt >= cnt_wren_out3_start) && (proc_cnt <= cnt_wren_out3_stop);
+ assign wren_out4 = (proc_cnt >= cnt_wren_out4_start) && (proc_cnt <= cnt_wren_out4_stop);
+
+ assign r_dbl_wren = wren_out1;
+ assign s_dbl_wren = wren_out1;
+ assign r_plus_s_wren = wren_out2;
+ assign u_half_wren = wren_out3;
+ assign v_half_wren = wren_out3;
+ assign u_minus_v_wren = wren_out2;
+ assign v_minus_u_wren = wren_out2;
+ assign u_minus_v_half_wren = wren_out4;
+ assign v_minus_u_half_wren = wren_out4;
+
+
+ //
+ // Adder (r + s)
+ //
+ wire [31: 0] add32_r_plus_s_sum_out;
+ wire add32_r_plus_s_carry_in;
+ wire add32_r_plus_s_carry_out;
+
+ adder32_wrapper add32_r_plus_s
+ (
+ .clk (clk),
+ .a (r_din),
+ .b (s_din),
+ .s (add32_r_plus_s_sum_out),
+ .c_in (add32_r_plus_s_carry_in),
+ .c_out (add32_r_plus_s_carry_out)
+ );
+
+ //
+ // Subtractor (u - v)
+ //
+ wire [31: 0] sub32_u_minus_v_difference_out;
+ wire sub32_u_minus_v_borrow_in;
+ wire sub32_u_minus_v_borrow_out;
+
+ subtractor32_wrapper sub32_u_minus_v
+ (
+ .clk (clk),
+ .a (u_din),
+ .b (v_din),
+ .d (sub32_u_minus_v_difference_out),
+ .b_in (sub32_u_minus_v_borrow_in),
+ .b_out (sub32_u_minus_v_borrow_out)
+ );
+
+ //
+ // Subtractor (v - u)
+ //
+ wire [31: 0] sub32_v_minus_u_difference_out;
+ wire sub32_v_minus_u_borrow_in;
+ wire sub32_v_minus_u_borrow_out;
+
+ subtractor32_wrapper sub32_v_minus_u
+ (
+ .clk (clk),
+ .a (v_din),
+ .b (u_din),
+ .d (sub32_v_minus_u_difference_out),
+ .b_in (sub32_v_minus_u_borrow_in),
+ .b_out (sub32_v_minus_u_borrow_out)
+ );
+
+
+ //
+ // Carry & Borrow Masking Logic
+ //
+ reg mask_carry_borrow;
+
+ always @(posedge clk)
+ //
+ mask_carry_borrow <= ((proc_cnt >= cnt_wren_out1_start) && (proc_cnt < cnt_wren_out1_stop)) ?
+ 1'b0 : 1'b1;
+
+ assign add32_r_plus_s_carry_in = add32_r_plus_s_carry_out & ~mask_carry_borrow;
+ assign sub32_u_minus_v_borrow_in = sub32_u_minus_v_borrow_out & ~mask_carry_borrow;
+ assign sub32_v_minus_u_borrow_in = sub32_v_minus_u_borrow_out & ~mask_carry_borrow;
+
+
+ //
+ // Carry Bits
+ //
+ reg r_dbl_carry;
+ reg s_dbl_carry;
+ reg u_half_carry;
+ reg v_half_carry;
+ reg u_minus_v_half_carry;
+ reg v_minus_u_half_carry;
+
+ always @(posedge clk) begin
+
+ r_dbl_carry <= ((proc_cnt >= cnt_wren_out1_start) && (proc_cnt < cnt_wren_out1_stop)) ?
+ r_din[31] : 1'b0;
+
+ s_dbl_carry <= ((proc_cnt >= cnt_wren_out1_start) && (proc_cnt < cnt_wren_out1_stop)) ?
+ s_din[31] : 1'b0;
+
+ u_half_carry <= ((proc_cnt >= cnt_wren_out3_start) && (proc_cnt < cnt_wren_out3_stop)) ?
+ u_din[0] : 1'b0;
+
+ v_half_carry <= ((proc_cnt >= cnt_wren_out3_start) && (proc_cnt < cnt_wren_out3_stop)) ?
+ v_din[0] : 1'b0;
+
+ u_minus_v_half_carry <= ((proc_cnt >= cnt_wren_out4_start) && (proc_cnt < cnt_wren_out4_stop)) ?
+ u_minus_v_din[0] : 1'b0;
+
+ v_minus_u_half_carry <= ((proc_cnt >= cnt_wren_out4_start) && (proc_cnt < cnt_wren_out4_stop)) ?
+ v_minus_u_din[0] : 1'b0;
+
+ end
+
+
+ //
+ // Data Mapper
+ //
+ assign r_dbl_dout = {r_din[30:0], r_dbl_carry};
+ assign s_dbl_dout = {s_din[30:0], s_dbl_carry};
+ assign r_plus_s_dout = add32_r_plus_s_sum_out;
+ assign u_half_dout = {u_half_carry, u_din[31:1]};
+ assign v_half_dout = {v_half_carry, v_din[31:1]};
+ assign u_minus_v_dout = sub32_u_minus_v_difference_out;
+ assign v_minus_u_dout = sub32_v_minus_u_difference_out;
+ assign u_minus_v_half_dout = {u_minus_v_half_carry, u_minus_v_din[31:1]};
+ assign v_minus_u_half_dout = {v_minus_u_half_carry, v_minus_u_din[31:1]};
+
+
+ //
+ // Primary Counter Logic
+ //
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero;
+ else begin
+ if (!rdy) proc_cnt <= proc_cnt_next;
+ else if (ena) proc_cnt <= proc_cnt_next;
+ end
+
+
+endmodule
diff --git a/rtl/modular/modular_invertor/helper/modinv_helper_invert_update.v b/rtl/modular/modular_invertor/helper/modinv_helper_invert_update.v
new file mode 100644
index 0000000..0cd6ac5
--- /dev/null
+++ b/rtl/modular/modular_invertor/helper/modinv_helper_invert_update.v
@@ -0,0 +1,257 @@
+`timescale 1ns / 1ps
+
+module modinv_helper_invert_update
+ (
+ clk, rst_n,
+ ena, rdy,
+
+ u_gt_v, v_eq_1,
+ u_is_even, v_is_even,
+
+ r_addr, r_wren, r_dout,
+ s_addr, s_wren, s_dout,
+ u_addr, u_wren, u_dout,
+ v_addr, v_wren, v_dout,
+
+ r_dbl_addr, r_dbl_din,
+ s_dbl_addr, s_dbl_din,
+ r_plus_s_addr, r_plus_s_din,
+ u_half_addr, u_half_din,
+ v_half_addr, v_half_din,
+ u_minus_v_half_addr, u_minus_v_half_din,
+ v_minus_u_half_addr, v_minus_u_half_din
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter BUFFER_NUM_WORDS = 9;
+ parameter BUFFER_ADDR_BITS = 4;
+
+
+ //
+ // clog2
+ //
+`include "..\modinv_clog2.v"
+
+
+ //
+ // Constants
+ //
+ localparam PROC_NUM_CYCLES = BUFFER_NUM_WORDS + 3;
+ localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES);
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire rst_n;
+ input wire ena;
+ output wire rdy;
+
+ input wire u_gt_v;
+ input wire v_eq_1;
+ input wire u_is_even;
+ input wire v_is_even;
+
+ output wire [BUFFER_ADDR_BITS-1:0] r_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] s_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_addr;
+
+ output wire r_wren;
+ output wire s_wren;
+ output wire u_wren;
+ output wire v_wren;
+
+ output wire [ 32-1:0] r_dout;
+ output wire [ 32-1:0] s_dout;
+ output wire [ 32-1:0] u_dout;
+ output wire [ 32-1:0] v_dout;
+
+ output wire [BUFFER_ADDR_BITS-1:0] r_dbl_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] s_dbl_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] r_plus_s_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_half_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_half_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_minus_v_half_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_minus_u_half_addr;
+
+ input wire [ 32-1:0] r_dbl_din;
+ input wire [ 32-1:0] s_dbl_din;
+ input wire [ 32-1:0] r_plus_s_din;
+ input wire [ 32-1:0] u_half_din;
+ input wire [ 32-1:0] v_half_din;
+ input wire [ 32-1:0] u_minus_v_half_din;
+ input wire [ 32-1:0] v_minus_u_half_din;
+
+
+ //
+ // Counter
+ //
+ reg [PROC_CNT_BITS-1:0] proc_cnt;
+
+ wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1;
+ wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}};
+ wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ?
+ proc_cnt + 1'b1 : proc_cnt_zero;
+
+ //
+ // Addresses
+ //
+ reg [BUFFER_ADDR_BITS-1:0] addr_in;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_max = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_next = (addr_in < addr_in_max) ?
+ addr_in + 1'b1 : addr_in_zero;
+
+ reg [BUFFER_ADDR_BITS-1:0] addr_out;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out_max = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out_next = (addr_out < addr_out_max) ?
+ addr_out + 1'b1 : addr_out_zero;
+
+ assign r_addr = addr_out;
+ assign s_addr = addr_out;
+ assign u_addr = addr_out;
+ assign v_addr = addr_out;
+
+ assign r_dbl_addr = addr_in;
+ assign s_dbl_addr = addr_in;
+ assign r_plus_s_addr = addr_in;
+ assign u_half_addr = addr_in;
+ assign v_half_addr = addr_in;
+ assign u_minus_v_half_addr = addr_in;
+ assign v_minus_u_half_addr = addr_in;
+
+
+ //
+ // Ready Flag
+ //
+ assign rdy = (proc_cnt == proc_cnt_zero);
+
+
+ //
+ // Address Increment Logic
+ //
+ wire inc_addr_in;
+ wire inc_addr_out;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_start = 1;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_stop = BUFFER_NUM_WORDS;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out_stop = BUFFER_NUM_WORDS + 1;
+
+ assign inc_addr_in = (proc_cnt >= cnt_inc_addr_in_start) && (proc_cnt <= cnt_inc_addr_in_stop);
+ assign inc_addr_out = (proc_cnt >= cnt_inc_addr_out_start) && (proc_cnt <= cnt_inc_addr_out_stop);
+
+ always @(posedge clk) begin
+ //
+ if (inc_addr_in) addr_in <= addr_in_next;
+ else addr_in <= addr_in_zero;
+ //
+ if (inc_addr_out) addr_out <= addr_out_next;
+ else addr_out <= addr_out_zero;
+ //
+ end
+
+ //
+ // Write Enable Logic
+ //
+ wire wren_out;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out_stop = BUFFER_NUM_WORDS + 1;
+
+ assign wren_out = (proc_cnt >= cnt_wren_out_start) && (proc_cnt <= cnt_wren_out_stop);
+
+ reg r_wren_allow;
+ reg s_wren_allow;
+ reg u_wren_allow;
+ reg v_wren_allow;
+
+ assign r_wren = wren_out && r_wren_allow && !v_eq_1 && !rdy;
+ assign s_wren = wren_out && s_wren_allow && !v_eq_1 && !rdy;
+ assign u_wren = wren_out && u_wren_allow && !v_eq_1 && !rdy;
+ assign v_wren = wren_out && v_wren_allow && !v_eq_1 && !rdy;
+
+
+ //
+ // Data Logic
+ //
+ reg [31: 0] r_dout_mux;
+ reg [31: 0] s_dout_mux;
+ reg [31: 0] u_dout_mux;
+ reg [31: 0] v_dout_mux;
+
+ assign r_dout = r_dout_mux;
+ assign s_dout = s_dout_mux;
+ assign u_dout = u_dout_mux;
+ assign v_dout = v_dout_mux;
+
+ always @(*) begin
+ //
+ // r, s, u, v
+ //
+ if (u_is_even) begin
+ //
+ u_dout_mux = u_half_din;
+ v_dout_mux = {32{1'bX}};
+ r_dout_mux = {32{1'bX}};
+ s_dout_mux = s_dbl_din;
+ //
+ u_wren_allow = 1'b1;
+ v_wren_allow = 1'b0;
+ r_wren_allow = 1'b0;
+ s_wren_allow = 1'b1;
+ //
+ end else begin
+ //
+ if (v_is_even) begin
+ //
+ u_dout_mux = {32{1'bX}};
+ v_dout_mux = v_half_din;
+ r_dout_mux = r_dbl_din;
+ s_dout_mux = {32{1'bX}};
+ //
+ u_wren_allow = 1'b0;
+ v_wren_allow = 1'b1;
+ r_wren_allow = 1'b1;
+ s_wren_allow = 1'b0;
+ //
+ end else begin
+ //
+ u_dout_mux = u_gt_v ? u_minus_v_half_din : {32{1'bX}};
+ v_dout_mux = u_gt_v ? {32{1'bX}} : v_minus_u_half_din;
+ r_dout_mux = u_gt_v ? r_plus_s_din : r_dbl_din;
+ s_dout_mux = u_gt_v ? s_dbl_din : r_plus_s_din;
+ //
+ u_wren_allow = u_gt_v;
+ v_wren_allow = !u_gt_v;
+ r_wren_allow = 1'b1;
+ s_wren_allow = 1'b1;
+ //
+ end
+ //
+ end
+ //
+ end
+
+
+ //
+ // Primary Counter Logic
+ //
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero;
+ else begin
+ if (!rdy) proc_cnt <= proc_cnt_next;
+ else if (ena) proc_cnt <= proc_cnt_next;
+ end
+
+endmodule
diff --git a/rtl/modular/modular_invertor/helper/modinv_helper_reduce_precalc.v b/rtl/modular/modular_invertor/helper/modinv_helper_reduce_precalc.v
new file mode 100644
index 0000000..fb858a6
--- /dev/null
+++ b/rtl/modular/modular_invertor/helper/modinv_helper_reduce_precalc.v
@@ -0,0 +1,328 @@
+`timescale 1ns / 1ps
+
+module modinv_helper_reduce_precalc
+ (
+ clk, rst_n,
+ ena, rdy,
+
+ k,
+
+ s_is_odd, k_is_nul,
+
+ r_addr, r_din, r_wren, r_dout,
+ s_addr, s_din,
+ u_addr, u_wren, u_dout,
+ v_addr, v_wren, v_dout,
+ q_addr, q_din
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter OPERAND_NUM_WORDS = 8;
+ parameter OPERAND_ADDR_BITS = 3;
+ parameter BUFFER_NUM_WORDS = 9;
+ parameter BUFFER_ADDR_BITS = 4;
+ parameter K_NUM_BITS = 10;
+
+
+ //
+ // clog2
+ //
+`include "..\modinv_clog2.v"
+
+
+ //
+ // Constants
+ //
+ localparam PROC_NUM_CYCLES = 2 * BUFFER_NUM_WORDS + 4;
+ localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES);
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire rst_n;
+ input wire ena;
+ output wire rdy;
+
+ input wire [ K_NUM_BITS-1:0] k;
+
+ output wire s_is_odd;
+ output wire k_is_nul;
+
+ output wire [ BUFFER_ADDR_BITS-1:0] r_addr;
+ output wire [ BUFFER_ADDR_BITS-1:0] s_addr;
+ output wire [ BUFFER_ADDR_BITS-1:0] u_addr;
+ output wire [ BUFFER_ADDR_BITS-1:0] v_addr;
+ output wire [OPERAND_ADDR_BITS-1:0] q_addr;
+
+ input wire [ 32-1:0] r_din;
+ input wire [ 32-1:0] s_din;
+ input wire [ 32-1:0] q_din;
+
+ output wire r_wren;
+ output wire u_wren;
+ output wire v_wren;
+
+ output wire [ 32-1:0] r_dout;
+ output wire [ 32-1:0] u_dout;
+ output wire [ 32-1:0] v_dout;
+
+
+ //
+ // Counter
+ //
+ reg [PROC_CNT_BITS-1:0] proc_cnt;
+
+ wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1;
+ wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}};
+ wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ?
+ proc_cnt + 1'b1 : proc_cnt_zero;
+
+ //
+ // Addresses
+ //
+ reg [ BUFFER_ADDR_BITS-1:0] addr_in_buf;
+ reg [OPERAND_ADDR_BITS-1:0] addr_in_op;
+ reg [ BUFFER_ADDR_BITS-1:0] addr_out1;
+ reg [ BUFFER_ADDR_BITS-1:0] addr_out2;
+ reg [ BUFFER_ADDR_BITS-1:0] addr_out3;
+
+ wire [ BUFFER_ADDR_BITS-1:0] addr_in_buf_last = BUFFER_NUM_WORDS - 1;
+ wire [ BUFFER_ADDR_BITS-1:0] addr_in_buf_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [ BUFFER_ADDR_BITS-1:0] addr_in_buf_next = (addr_in_buf < addr_in_buf_last) ?
+ addr_in_buf + 1'b1 : addr_in_buf_zero;
+ wire [ BUFFER_ADDR_BITS-1:0] addr_in_buf_prev = (addr_in_buf > addr_in_buf_zero) ?
+ addr_in_buf - 1'b1 : addr_in_buf_zero;
+
+ wire [OPERAND_ADDR_BITS-1:0] addr_in_op_last = OPERAND_NUM_WORDS - 1;
+ wire [OPERAND_ADDR_BITS-1:0] addr_in_op_zero = {OPERAND_ADDR_BITS{1'b0}};
+ wire [OPERAND_ADDR_BITS-1:0] addr_in_op_next = (addr_in_op < addr_in_op_last) ?
+ addr_in_op + 1'b1 : addr_in_op_zero;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out1_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out1_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out1_next = (addr_out1 < addr_out1_last) ?
+ addr_out1 + 1'b1 : addr_out1_zero;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out1_prev = (addr_out1 > addr_out1_zero) ?
+ addr_out1 - 1'b1 : addr_out1_zero;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out2_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out2_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out2_prev = (addr_out2 > addr_out2_zero) ?
+ addr_out2 - 1'b1 : addr_out2_last;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out3_last = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out3_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out3_prev = (addr_out3 > addr_out3_zero) ?
+ addr_out3 - 1'b1 : addr_out3_last;
+
+
+ assign s_addr = addr_in_buf;
+ assign q_addr = addr_in_op;
+ assign r_addr = addr_out1;
+ assign u_addr = addr_out2;
+ assign v_addr = addr_out3;
+
+
+ //
+ // Ready Flag
+ //
+ assign rdy = (proc_cnt == proc_cnt_zero);
+
+
+ //
+ // Address Increment/Decrement Logic
+ //
+ wire inc_addr_buf_in;
+ wire dec_addr_buf_in;
+ wire inc_addr_op_in;
+ wire inc_addr_out1;
+ wire dec_addr_out1;
+ wire dec_addr_out2;
+ wire dec_addr_out3;
+
+ wire [PROC_CNT_BITS-1:0] cnt_calc_flags = 0 * BUFFER_NUM_WORDS + 2;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_buf_in_start = 0 * BUFFER_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_buf_in_stop = 1 * BUFFER_NUM_WORDS - 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_buf_in_start = 1 * BUFFER_NUM_WORDS + 0;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_buf_in_stop = 2 * BUFFER_NUM_WORDS - 2;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_op_in_start = 0 * OPERAND_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_op_in_stop = 1 * OPERAND_NUM_WORDS + 0;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out1_start = 0 * BUFFER_NUM_WORDS + 3;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out1_stop = 1 * BUFFER_NUM_WORDS + 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out1_start = 1 * BUFFER_NUM_WORDS + 3;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out1_stop = 2 * BUFFER_NUM_WORDS + 1;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out2_start = 1 * BUFFER_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out2_stop = 2 * BUFFER_NUM_WORDS + 0;
+
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out3_start = 1 * BUFFER_NUM_WORDS + 4;
+ wire [PROC_CNT_BITS-1:0] cnt_dec_addr_out3_stop = 2 * BUFFER_NUM_WORDS + 3;
+
+ assign inc_addr_buf_in = (proc_cnt >= cnt_inc_addr_buf_in_start) && (proc_cnt <= cnt_inc_addr_buf_in_stop);
+ assign dec_addr_buf_in = (proc_cnt >= cnt_dec_addr_buf_in_start) && (proc_cnt <= cnt_dec_addr_buf_in_stop);
+ assign inc_addr_op_in = (proc_cnt >= cnt_inc_addr_op_in_start) && (proc_cnt <= cnt_inc_addr_op_in_stop);
+ assign inc_addr_out1 = (proc_cnt >= cnt_inc_addr_out1_start) && (proc_cnt <= cnt_inc_addr_out1_stop);
+ assign dec_addr_out1 = (proc_cnt >= cnt_dec_addr_out1_start) && (proc_cnt <= cnt_dec_addr_out1_stop);
+ assign dec_addr_out2 = (proc_cnt >= cnt_dec_addr_out2_start) && (proc_cnt <= cnt_dec_addr_out2_stop);
+ assign dec_addr_out3 = (proc_cnt >= cnt_dec_addr_out3_start) && (proc_cnt <= cnt_dec_addr_out3_stop);
+
+ always @(posedge clk) begin
+ //
+ if (rdy) begin
+ //
+ addr_in_buf <= addr_in_buf_zero;
+ addr_in_op <= addr_in_op_zero;
+ addr_out1 <= addr_out1_zero;
+ addr_out2 <= addr_out2_last;
+ addr_out3 <= addr_out3_last;
+ //
+ end else begin
+ //
+ if (inc_addr_buf_in) addr_in_buf <= addr_in_buf_next;
+ else if (dec_addr_buf_in) addr_in_buf <= addr_in_buf_prev;
+ //
+ if (inc_addr_op_in) addr_in_op <= addr_in_op_next;
+ else addr_in_op <= addr_in_op_zero;
+ //
+ if (inc_addr_out1) addr_out1 <= addr_out1_next;
+ else if (dec_addr_out1) addr_out1 <= addr_out1_prev;
+ //
+ if (dec_addr_out2) addr_out2 <= addr_out2_prev;
+ else addr_out2 <= addr_out2_last;
+ //
+ if (dec_addr_out3) addr_out3 <= addr_out3_prev;
+ else addr_out3 <= addr_out3_last;
+ //
+ end
+ //
+ end
+
+
+ //
+ // Write Enable Logic
+ //
+ wire wren_out1;
+ wire wren_out2;
+ wire wren_out3;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out1_start = 0 * BUFFER_NUM_WORDS + 3;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out1_stop = 1 * BUFFER_NUM_WORDS + 2;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out2_start = 1 * BUFFER_NUM_WORDS + 1;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out2_stop = 2 * BUFFER_NUM_WORDS + 0;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out3_start = 1 * BUFFER_NUM_WORDS + 4;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out3_stop = 2 * BUFFER_NUM_WORDS + 3;
+
+ assign wren_out1 = (proc_cnt >= cnt_wren_out1_start) && (proc_cnt <= cnt_wren_out1_stop);
+ assign wren_out2 = (proc_cnt >= cnt_wren_out2_start) && (proc_cnt <= cnt_wren_out2_stop);
+ assign wren_out3 = (proc_cnt >= cnt_wren_out3_start) && (proc_cnt <= cnt_wren_out3_stop);
+
+ assign r_wren = wren_out1;
+ assign u_wren = wren_out2;
+ assign v_wren = wren_out3;
+
+ //
+ // Adder (s + q)
+ //
+ wire [31: 0] q_din_masked;
+ wire [31: 0] add32_s_plus_q_sum_out;
+ wire add32_s_plus_q_carry_in;
+ wire add32_s_plus_q_carry_out;
+
+ adder32_wrapper add32_r_plus_s
+ (
+ .clk (clk),
+ .a (s_din),
+ .b (q_din_masked),
+ .s (add32_s_plus_q_sum_out),
+ .c_in (add32_s_plus_q_carry_in),
+ .c_out (add32_s_plus_q_carry_out)
+ );
+
+
+ //
+ // Carry Masking Logic
+ //
+ wire mask_carry;
+
+ assign mask_carry = ((proc_cnt >= cnt_wren_out1_start) && (proc_cnt < cnt_wren_out1_stop)) ? 1'b0 : 1'b1;
+
+
+ //
+ // Addend Masking Logic
+ //
+ reg q_din_mask;
+
+ always @(posedge clk)
+ q_din_mask <= (addr_in_buf == addr_in_buf_last) ? 1'b1 : 1'b0;
+
+ assign q_din_masked = q_din_mask ? {32{1'b0}} : q_din;
+
+ assign add32_s_plus_q_carry_in = add32_s_plus_q_carry_out & ~mask_carry;
+
+
+ //
+ // Carry Bits
+ //
+ reg s_half_carry;
+ reg s_plus_q_half_carry;
+
+ always @(posedge clk) begin
+ //
+ s_half_carry <= ((proc_cnt >= cnt_wren_out2_start) && (proc_cnt < cnt_wren_out2_stop)) ?
+ s_din[0] : 1'b0;
+ //
+ s_plus_q_half_carry <= ((proc_cnt >= cnt_wren_out3_start) && (proc_cnt < cnt_wren_out3_stop)) ?
+ r_din[0] : 1'b0;
+ //
+ end
+
+ //
+ // Data Mapper
+ //
+ assign r_dout = add32_s_plus_q_sum_out;
+ assign u_dout = {s_half_carry, s_din[31:1]};
+ assign v_dout = {s_plus_q_half_carry, r_din[31:1]};
+
+
+ //
+ // Primary Counter Logic
+ //
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero;
+ else begin
+ if (!rdy) proc_cnt <= proc_cnt_next;
+ else if (ena) proc_cnt <= proc_cnt_next;
+ end
+
+
+ //
+ // Output Flags
+ //
+ reg s_is_odd_reg;
+ reg k_is_nul_reg;
+
+ assign s_is_odd = s_is_odd_reg;
+ assign k_is_nul = k_is_nul_reg;
+
+ always @(posedge clk)
+ //
+ if (proc_cnt == cnt_calc_flags) begin
+ s_is_odd_reg <= s_din[0];
+ k_is_nul_reg <= (k == {K_NUM_BITS{1'b0}}) ? 1'b1 : 1'b0;
+ end
+
+
+endmodule
diff --git a/rtl/modular/modular_invertor/helper/modinv_helper_reduce_update.v b/rtl/modular/modular_invertor/helper/modinv_helper_reduce_update.v
new file mode 100644
index 0000000..ea5b854
--- /dev/null
+++ b/rtl/modular/modular_invertor/helper/modinv_helper_reduce_update.v
@@ -0,0 +1,153 @@
+`timescale 1ns / 1ps
+
+module modinv_helper_reduce_update
+ (
+ clk, rst_n,
+ ena, rdy,
+
+ s_is_odd, k_is_nul,
+
+ s_addr, s_wren, s_dout,
+ u_addr, u_din,
+ v_addr, v_din
+ );
+
+
+ //
+ // Parameters
+ //
+ parameter BUFFER_NUM_WORDS = 9;
+ parameter BUFFER_ADDR_BITS = 4;
+
+
+ //
+ // clog2
+ //
+`include "..\modinv_clog2.v"
+
+
+ //
+ // Constants
+ //
+ localparam PROC_NUM_CYCLES = BUFFER_NUM_WORDS + 3;
+ localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES);
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire rst_n;
+ input wire ena;
+ output wire rdy;
+
+ input wire s_is_odd;
+ input wire k_is_nul;
+
+ output wire [BUFFER_ADDR_BITS-1:0] s_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] u_addr;
+ output wire [BUFFER_ADDR_BITS-1:0] v_addr;
+
+ output wire s_wren;
+
+ output wire [ 32-1:0] s_dout;
+
+ input wire [ 32-1:0] u_din;
+ input wire [ 32-1:0] v_din;
+
+
+ //
+ // Counter
+ //
+ reg [PROC_CNT_BITS-1:0] proc_cnt;
+
+ wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1;
+ wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}};
+ wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ?
+ proc_cnt + 1'b1 : proc_cnt_zero;
+
+ //
+ // Addresses
+ //
+ reg [BUFFER_ADDR_BITS-1:0] addr_in;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_max = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_in_next = (addr_in < addr_in_max) ?
+ addr_in + 1'b1 : addr_in_zero;
+
+ reg [BUFFER_ADDR_BITS-1:0] addr_out;
+
+ wire [BUFFER_ADDR_BITS-1:0] addr_out_max = BUFFER_NUM_WORDS - 1;
+ wire [BUFFER_ADDR_BITS-1:0] addr_out_zero = {BUFFER_ADDR_BITS{1'b0}};
+ wire [BUFFER_ADDR_BITS-1:0] addr_out_next = (addr_out < addr_out_max) ?
+ addr_out + 1'b1 : addr_out_zero;
+
+ assign s_addr = addr_out;
+ assign u_addr = addr_in;
+ assign v_addr = addr_in;
+
+
+ //
+ // Ready Flag
+ //
+ assign rdy = (proc_cnt == proc_cnt_zero);
+
+
+ //
+ // Address Increment Logic
+ //
+ wire inc_addr_in;
+ wire inc_addr_out;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_start = 1;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_stop = BUFFER_NUM_WORDS;
+
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out_stop = BUFFER_NUM_WORDS + 1;
+
+ assign inc_addr_in = (proc_cnt >= cnt_inc_addr_in_start) && (proc_cnt <= cnt_inc_addr_in_stop);
+ assign inc_addr_out = (proc_cnt >= cnt_inc_addr_out_start) && (proc_cnt <= cnt_inc_addr_out_stop);
+
+ always @(posedge clk) begin
+ //
+ if (inc_addr_in) addr_in <= addr_in_next;
+ else addr_in <= addr_in_zero;
+ //
+ if (inc_addr_out) addr_out <= addr_out_next;
+ else addr_out <= addr_out_zero;
+ //
+ end
+
+ //
+ // Write Enable Logic
+ //
+ wire wren_out;
+
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out_start = 2;
+ wire [PROC_CNT_BITS-1:0] cnt_wren_out_stop = BUFFER_NUM_WORDS + 1;
+
+ assign wren_out = (proc_cnt >= cnt_wren_out_start) && (proc_cnt <= cnt_wren_out_stop);
+
+ assign s_wren = wren_out && !k_is_nul; //s_wren_allow && !v_eq_1 && !rdy;
+
+
+ //
+ // Data Logic
+ //
+ assign s_dout = s_is_odd ? v_din : u_din;
+
+
+ //
+ // Primary Counter Logic
+ //
+ always @(posedge clk or negedge rst_n)
+ //
+ if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero;
+ else begin
+ if (!rdy) proc_cnt <= proc_cnt_next;
+ else if (ena) proc_cnt <= proc_cnt_next;
+ end
+
+
+endmodule