aboutsummaryrefslogtreecommitdiff
path: root/src/rtl/montprod.v
diff options
context:
space:
mode:
Diffstat (limited to 'src/rtl/montprod.v')
-rw-r--r--src/rtl/montprod.v777
1 files changed, 406 insertions, 371 deletions
diff --git a/src/rtl/montprod.v b/src/rtl/montprod.v
index 6b525f7..3a310d7 100644
--- a/src/rtl/montprod.v
+++ b/src/rtl/montprod.v
@@ -4,6 +4,9 @@
// ---------
// Montgomery product calculator for the modular exponentiantion core.
//
+// parameter OPW is operand word width in bits.
+// parameter ADW is address width in bits.
+//
//
// Author: Peter Magnusson, Joachim Strombergson
// Copyright (c) 2015, NORDUnet A/S All rights reserved.
@@ -36,135 +39,158 @@
//
//======================================================================
-module montprod(
- input wire clk,
- input wire reset_n,
+module montprod #(parameter OPW = 32, parameter ADW = 8)
+ (
+ input wire clk,
+ input wire reset_n,
- input wire calculate,
- output wire ready,
+ input wire calculate,
+ output wire ready,
- input [7 : 0] length,
+ input wire [(ADW - 1) : 0] length,
- output wire [7 : 0] opa_addr,
- input wire [31 : 0] opa_data,
+ output wire [(ADW - 1) : 0] opa_addr,
+ input wire [(OPW - 1) : 0] opa_data,
- output wire [7 : 0] opb_addr,
- input wire [31 : 0] opb_data,
+ output wire [(ADW - 1) : 0] opb_addr,
+ input wire [(OPW - 1) : 0] opb_data,
- output wire [7 : 0] opm_addr,
- input wire [31 : 0] opm_data,
+ output wire [(ADW - 1) : 0] opm_addr,
+ input wire [(OPW - 1) : 0] opm_data,
- output wire [7 : 0] result_addr,
- output wire [31 : 0] result_data,
- output wire result_we
+ output wire [(ADW - 1) : 0] result_addr,
+ output wire [(OPW - 1) : 0] result_data,
+ output wire result_we
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
- localparam DEBUG = 0;
-
- localparam CTRL_IDLE = 4'h0;
- localparam CTRL_INIT_S = 4'h1;
- localparam CTRL_LOOP_INIT = 4'h2;
- localparam CTRL_LOOP_ITER = 4'h3;
- localparam CTRL_LOOP_BQ = 4'h4;
- localparam CTRL_L_CALC_SM = 4'h5;
- localparam CTRL_L_STALLPIPE_SM = 4'h6;
- localparam CTRL_L_CALC_SA = 4'h7;
- localparam CTRL_L_STALLPIPE_SA = 4'h8;
- localparam CTRL_L_CALC_SDIV2 = 4'h9;
- localparam CTRL_L_STALLPIPE_D2 = 4'hA;
- localparam CTRL_L_STALLPIPE_ES = 4'hB;
- localparam CTRL_EMIT_S = 4'hC;
- localparam CTRL_DONE = 4'hD;
-
- localparam SMUX_0 = 2'h0;
- localparam SMUX_ADD_SM = 2'h1;
- localparam SMUX_ADD_SA = 2'h2;
- localparam SMUX_SHR = 2'h3;
+ localparam CTRL_IDLE = 4'h0;
+ localparam CTRL_LOOP_ITER = 4'h1;
+ localparam CTRL_LOOP_BQ = 4'h2;
+ localparam CTRL_CALC_ADD = 4'h3;
+ localparam CTRL_STALLPIPE_ADD = 4'h4;
+ localparam CTRL_CALC_SDIV2 = 4'h5;
+ localparam CTRL_STALLPIPE_SDIV2 = 4'h6;
+ localparam CTRL_L_STALLPIPE_ES = 4'h7;
+ localparam CTRL_EMIT_S = 4'h8;
+
+ localparam SMUX_ZERO = 2'h0;
+ localparam SMUX_ADD = 2'h1;
+ localparam SMUX_SHR = 2'h2;
+
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
+ reg ready_reg;
+ reg ready_new;
+ reg ready_we;
- reg [07 : 0] opa_addr_reg;
- reg [07 : 0] opb_addr_reg;
- reg [07 : 0] opm_addr_reg;
+ reg [3 : 0] montprod_ctrl_reg;
+ reg [3 : 0] montprod_ctrl_new;
+ reg montprod_ctrl_we;
- reg [07 : 0] result_addr_reg;
- reg [31 : 0] result_data_reg;
+ reg [1 : 0] s_mux_new;
+ reg [1 : 0] s_mux_reg;
- reg ready_reg;
- reg ready_new;
- reg ready_we;
+ reg s_mem_we_reg;
+ reg s_mem_we_new;
- reg [3 : 0] montprod_ctrl_reg;
- reg [3 : 0] montprod_ctrl_new;
- reg montprod_ctrl_we;
+ reg [(ADW - 1) : 0] s_mem_read_addr_reg;
- reg [1 : 0] s_mux_new;
- reg [1 : 0] s_mux_reg;
+ reg q_new;
+ reg q_reg;
+ reg b_new;
+ reg b_reg;
+ reg bq_we;
- reg [31 : 0] s_mem_new;
- reg s_mem_we;
- reg s_mem_we_new;
- reg [07 : 0] s_mem_addr;
- reg [07 : 0] s_mem_wr_addr;
- wire [31 : 0] s_mem_read_data;
+ reg [12 : 0] loop_ctr_reg;
+ reg [12 : 0] loop_ctr_new;
+ reg loop_ctr_we;
+ reg loop_ctr_set;
+ reg loop_ctr_dec;
- reg q; //q = (s - b * A) & 1
- reg q_reg;
- reg b; //b: bit of B
- reg b_reg;
+ reg [(13 - ADW - 1) : 0] b_bit_index_reg;
+ reg [(13 - ADW - 1) : 0] b_bit_index_new;
+ reg b_bit_index_we;
- reg [12 : 0] loop_counter;
- reg [12 : 0] loop_counter_new;
- reg [12 : 0] loop_counter_dec;
- reg [07 : 0] B_word_index; //loop counter as a word index
- reg [04 : 0] B_bit_index; //loop counter as a bit index
- reg [04 : 0] B_bit_index_reg; //loop counter as a bit index
+ reg [(ADW - 1) : 0] word_index_reg;
+ reg [(ADW - 1) : 0] word_index_new;
+ reg word_index_we;
+ reg [(ADW - 1) : 0] word_index_prev_reg;
+ reg reset_word_index_lsw;
+ reg reset_word_index_msw;
+ reg inc_word_index;
+ reg dec_word_index;
- reg [07 : 0] word_index; //register of what word is being read
- reg [07 : 0] word_index_new; //calculation of what word to be read
- reg [07 : 0] word_index_prev; //register of what word was read previously (result address to emit)
- reg [07 : 0] length_m1;
+ reg add_carry_in_sa_reg;
+ reg add_carry_in_sa_new;
+ reg add_carry_in_sm_reg;
+ reg add_carry_in_sm_new;
- reg add_carry_in_sa;
- reg add_carry_new_sa;
- reg add_carry_in_sm;
- reg add_carry_new_sm;
+ reg shr_carry_in_reg;
+ reg shr_carry_in_new;
- reg shr_carry_in;
- reg shr_carry_new;
+ reg first_iteration_reg;
+ reg first_iteration_new;
+ reg first_iteration_we;
- reg reset_word_index_LSW;
- reg reset_word_index_MSW;
+ reg test_reg;
+ reg test_new;
+
+ reg [(OPW - 2) : 0] shr_data_out_reg;
+ reg shr_carry_out_reg;
+ reg shr_carry_out_new;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
- reg tmp_result_we;
- wire [31 : 0] add_result_sa;
- wire add_carry_out_sa;
- wire [31 : 0] add_result_sm;
- wire add_carry_out_sm;
+ wire [(OPW - 1) : 0] add_result_sa;
+ wire add_carry_out_sa;
+ wire [(OPW - 1) : 0] add_result_sm;
+ wire add_carry_out_sm;
+
+ reg [(ADW - 1) : 0] b_word_index; //loop counter as a word index
+
+ reg [(OPW - 1) : 0] shr_data_in;
+ wire shr_carry_out;
+ wire [(OPW - 1) : 0] shr_data_out;
+
+ reg [(ADW - 1) : 0] tmp_opa_addr;
+ reg tmp_result_we;
+
+ reg [(ADW - 1) : 0] s_mem_read_addr;
+ wire [(OPW - 1) : 0] s_mem_read_data;
+ reg [(ADW - 1) : 0] s_mem_write_addr;
+ reg [(OPW - 1) : 0] s_mem_write_data;
+ reg [(OPW - 1) : 0] tmp_s_mem_write_data;
+
+ reg [(OPW - 1) : 0] sa_adder_data_in;
+ reg [(OPW - 1) : 0] muxed_s_mem_read_data;
+ reg [(OPW - 1) : 0] shifted_s_mem_write_data;
+
+ wire [(ADW - 1) : 0] length_m1;
- wire shr_carry_out;
- wire [31 : 0] shr_adiv2;
+ // Temporary debug wires.
+ reg [1 : 0] state_trace;
+ reg [1 : 0] mux_trace;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
- assign opa_addr = opa_addr_reg;
- assign opb_addr = opb_addr_reg;
- assign opm_addr = opm_addr_reg;
+ assign length_m1 = length - 1'b1;
- assign result_addr = result_addr_reg;
- assign result_data = result_data_reg;
+ assign opa_addr = tmp_opa_addr;
+ assign opb_addr = b_word_index;
+ assign opm_addr = word_index_reg;
+
+ assign result_addr = word_index_prev_reg;
+ assign result_data = s_mem_read_data;
assign result_we = tmp_result_we;
assign ready = ready_reg;
@@ -173,55 +199,38 @@ module montprod(
//----------------------------------------------------------------
// Instantions
//----------------------------------------------------------------
-
- blockmem1r1w s_mem(
- .clk(clk),
- .read_addr(s_mem_addr),
- .read_data(s_mem_read_data),
- .wr(s_mem_we),
- .write_addr(s_mem_wr_addr),
- .write_data(s_mem_new)
- );
-
-
- adder32 s_adder_sa(
- .a(s_mem_read_data),
- .b(opa_data),
- .carry_in(add_carry_in_sa),
- .sum(add_result_sa),
- .carry_out(add_carry_out_sa)
- );
-
- adder32 s_adder_sm(
- .a(s_mem_read_data),
- .b(opm_data),
- .carry_in(add_carry_in_sm),
- .sum(add_result_sm),
- .carry_out(add_carry_out_sm)
- );
-
- shr32 shifter(
- .a( s_mem_read_data ),
- .carry_in( shr_carry_in ),
- .adiv2( shr_adiv2 ),
- .carry_out( shr_carry_out )
- );
-
- always @*
- begin : s_mux
- case (s_mux_reg)
- SMUX_0:
- s_mem_new = 32'b0;
- SMUX_ADD_SA:
- s_mem_new = add_result_sa;
- SMUX_ADD_SM:
- s_mem_new = add_result_sm;
- SMUX_SHR:
- s_mem_new = shr_adiv2;
- endcase
- if (DEBUG)
- $display("SMUX%x: %x", s_mux_reg, s_mem_new);
- end
+ blockmem1r1w #(.OPW(OPW), .ADW(ADW)) s_mem(
+ .clk(clk),
+ .read_addr(s_mem_read_addr),
+ .read_data(s_mem_read_data),
+ .wr(s_mem_we_reg),
+ .write_addr(s_mem_write_addr),
+ .write_data(s_mem_write_data)
+ );
+
+ adder #(.OPW(OPW)) s_adder_sm(
+ .a(muxed_s_mem_read_data),
+ .b(opm_data),
+ .carry_in(add_carry_in_sm_reg),
+ .sum(add_result_sm),
+ .carry_out(add_carry_out_sm)
+ );
+
+
+ adder #(.OPW(OPW)) s_adder_sa(
+ .a(sa_adder_data_in),
+ .b(opa_data),
+ .carry_in(add_carry_in_sa_reg),
+ .sum(add_result_sa),
+ .carry_out(add_carry_out_sa)
+ );
+
+ shr #(.OPW(OPW)) shifter(
+ .a(shr_data_in),
+ .carry_in(shr_carry_in_reg),
+ .adiv2(shr_data_out),
+ .carry_out(shr_carry_out)
+ );
//----------------------------------------------------------------
@@ -235,205 +244,246 @@ module montprod(
begin : reg_update
if (!reset_n)
begin
- ready_reg <= 1'b0;
- loop_counter <= 13'h0;
- word_index <= 8'h0;
- word_index_prev <= 8'h0;
- add_carry_in_sa <= 1'b0;
- add_carry_in_sm <= 1'b0;
- shr_carry_in <= 1'b0;
- montprod_ctrl_reg <= CTRL_IDLE;
- b_reg <= 1'b0;
- q_reg <= 1'b0;
- s_mux_reg <= SMUX_0;
- s_mem_we <= 1'b0;
- s_mem_wr_addr <= 8'h0;
- B_bit_index_reg <= 5'h0;
+ test_reg <= 1'b1;
+ ready_reg <= 1'b1;
+ loop_ctr_reg <= 13'h0;
+ word_index_reg <= {ADW{1'b0}};
+ word_index_prev_reg <= {ADW{1'b0}};
+ add_carry_in_sa_reg <= 1'b0;
+ add_carry_in_sm_reg <= 1'b0;
+ shr_data_out_reg <= {(OPW - 1){1'b0}};
+ shr_carry_in_reg <= 1'b0;
+ b_reg <= 1'b0;
+ q_reg <= 1'b0;
+ s_mux_reg <= SMUX_ZERO;
+ s_mem_we_reg <= 1'b0;
+ s_mem_read_addr_reg <= {ADW{1'b0}};
+ b_bit_index_reg <= {(13 - ADW){1'b0}};
+ first_iteration_reg <= 1'b0;
+ montprod_ctrl_reg <= CTRL_IDLE;
end
else
begin
- if (ready_we)
- ready_reg <= ready_new;
+ test_reg <= test_new;
- if (montprod_ctrl_we)
- begin
- montprod_ctrl_reg <= montprod_ctrl_new;
- end
+ s_mem_read_addr_reg <= s_mem_read_addr;
+ s_mem_we_reg <= s_mem_we_new;
+ s_mux_reg <= s_mux_new;
- s_mem_wr_addr <= s_mem_addr;
+ word_index_prev_reg <= word_index_reg;
- s_mem_we <= s_mem_we_new;
+ shr_carry_in_reg <= shr_carry_in_new;
+ add_carry_in_sa_reg <= add_carry_in_sa_new;
+ add_carry_in_sm_reg <= add_carry_in_sm_new;
+ shr_data_out_reg <= shr_data_out[(OPW - 2) : 0];
- word_index <= word_index_new;
- word_index_prev <= word_index;
+ if (word_index_we)
+ word_index_reg <= word_index_new;
- loop_counter <= loop_counter_new;
- shr_carry_in <= shr_carry_new;
- add_carry_in_sa <= add_carry_new_sa;
- add_carry_in_sm <= add_carry_new_sm;
+ if (first_iteration_we)
+ first_iteration_reg <= first_iteration_new;
- B_bit_index_reg <= B_bit_index;
- q_reg <= q;
- b_reg <= b;
+ if (b_bit_index_we)
+ b_bit_index_reg <= b_bit_index_new;
- s_mux_reg <= s_mux_new;
- end
- end // reg_update
+ if (bq_we)
+ begin
+ b_reg <= b_new;
+ q_reg <= q_new;
+ end
- always @*
- begin : bq_process
- b = b_reg;
- q = q_reg;
- if (montprod_ctrl_reg == CTRL_LOOP_BQ)
- begin
- b = opb_data[ B_bit_index_reg ];
- //opa_addr will point to length-1 to get A LSB.
- //s_read_addr will point to length-1
- q = s_mem_read_data[0] ^ (opa_data[0] & b);
- if (DEBUG)
- $display("s_mem_read_data: %x opa_data %x b %x q %x B_bit_index_reg %x", s_mem_read_data, opa_data, b, q, B_bit_index_reg);
+ if (ready_we)
+ ready_reg <= ready_new;
+
+ if (loop_ctr_we)
+ loop_ctr_reg <= loop_ctr_new;
+
+ if (montprod_ctrl_we)
+ begin
+ montprod_ctrl_reg <= montprod_ctrl_new;
+ end
end
- end
+ end // reg_update
//----------------------------------------------------------------
- // Process for iterating the loop counter and setting related B indexes
+ // s_logic
+ //
+ // Logic to calculate S memory updates including address
+ // and write enable. This is the main montprod datapath.
//----------------------------------------------------------------
always @*
- begin : loop_counter_process
- loop_counter_new = loop_counter;
- length_m1 = length - 1'b1;
- loop_counter_dec = loop_counter - 1'b1;
- B_word_index = loop_counter[12:5];
- B_bit_index = B_bit_index_reg;
+ begin : s_logic
+ shr_carry_in_new = 1'b0;
+ muxed_s_mem_read_data = {OPW{1'b0}};
+ sa_adder_data_in = {OPW{1'b0}};
+ add_carry_in_sa_new = 1'b0;
+ add_carry_in_sm_new = 1'b0;
+ s_mem_read_addr = word_index_reg;
+ s_mem_write_addr = s_mem_read_addr_reg;
+ s_mem_write_data = {OPW{1'b0}};
+ s_mem_we_new = 1'b0;
+ state_trace = 0;
+ mux_trace = 0;
+ tmp_s_mem_write_data = {OPW{1'b0}};
+ test_new = 1'b0;
case (montprod_ctrl_reg)
- CTRL_LOOP_INIT:
- loop_counter_new = {length, 5'b00000} - 1'b1;
-
CTRL_LOOP_ITER:
begin
- B_word_index = loop_counter[12:5];
- B_bit_index = 5'h1f - loop_counter[4:0];
+ s_mem_read_addr = length_m1;
end
- CTRL_L_STALLPIPE_D2:
- loop_counter_new = loop_counter_dec;
-
- default:
- loop_counter_new = loop_counter;
- endcase
- end
-
-
- //----------------------------------------------------------------
- // prodcalc
- //----------------------------------------------------------------
- always @*
- begin : prodcalc
-
- case (montprod_ctrl_reg)
- CTRL_LOOP_ITER:
- //q = (s[length-1] ^ A[length-1]) & 1;
- opa_addr_reg = length_m1;
-
- default:
- opa_addr_reg = word_index;
- endcase
+ CTRL_CALC_ADD:
+ begin
+ //s = (s + q*M + b*A) >>> 1;, if(b==1) S+= A. Takes (1..length) cycles.
+ s_mem_we_new = b_reg | q_reg | first_iteration_reg;
+ state_trace = 1;
+ test_new = 1'b1;
+ end
- opb_addr_reg = B_word_index;
- opm_addr_reg = word_index;
+ CTRL_CALC_SDIV2:
+ begin
+ //s = (s + q*M + b*A) >>> 1; s>>=1. Takes (1..length) cycles.
+ s_mem_we_new = 1'b1;
+ end
- case (montprod_ctrl_reg)
- CTRL_LOOP_ITER:
- s_mem_addr = length_m1;
default:
- s_mem_addr = word_index;
+ begin
+ end
endcase
+ case (s_mux_reg)
+ SMUX_ADD:
+ begin
+ mux_trace = 1;
+ if (first_iteration_reg)
+ muxed_s_mem_read_data = {OPW{1'b0}};
+ else
+ muxed_s_mem_read_data = s_mem_read_data;
- result_addr_reg = word_index_prev;
- result_data_reg = s_mem_read_data;
- case (montprod_ctrl_reg)
- CTRL_EMIT_S:
- tmp_result_we = 1'b1;
- default:
- tmp_result_we = 1'b0;
- endcase
+ if (q_reg)
+ sa_adder_data_in = add_result_sm;
+ else
+ sa_adder_data_in = muxed_s_mem_read_data;
- if (reset_word_index_LSW == 1'b1)
- word_index_new = length_m1;
- else if (reset_word_index_MSW == 1'b1)
- word_index_new = 8'h0;
- else if (montprod_ctrl_reg == CTRL_L_CALC_SDIV2)
- word_index_new = word_index + 1'b1;
- else
- word_index_new = word_index - 1'b1;
- end // prodcalc
+ if (b_reg)
+ tmp_s_mem_write_data = add_result_sa;
+ else if (q_reg)
+ tmp_s_mem_write_data = add_result_sm;
+ else if (first_iteration_reg)
+ tmp_s_mem_write_data = {OPW{1'b0}};
+ s_mem_write_data = tmp_s_mem_write_data;
+ add_carry_in_sa_new = add_carry_out_sa;
+ add_carry_in_sm_new = add_carry_out_sm;
- always @*
- begin : s_writer_process
- shr_carry_new = 1'b0;
- s_mux_new = SMUX_0;
- s_mem_we_new = 1'b0;
- case (montprod_ctrl_reg)
- CTRL_INIT_S:
- begin
- s_mem_we_new = 1'b1;
- s_mux_new = SMUX_0; // write 0
+ // Experimental integration of shift in add.
+ shr_data_in = tmp_s_mem_write_data;
+ shifted_s_mem_write_data = {shr_carry_out, shr_data_out_reg};
end
- CTRL_L_CALC_SM:
- begin
- //s = (s + q*M + b*A) >>> 1;, if(q==1) S+= M. Takes (1..length) cycles.
- s_mem_we_new = q_reg;
- s_mux_new = SMUX_ADD_SM;
- end
-
- CTRL_L_CALC_SA:
- begin
- //s = (s + q*M + b*A) >>> 1;, if(b==1) S+= A. Takes (1..length) cycles.
- s_mem_we_new = b_reg;
- s_mux_new = SMUX_ADD_SA;
- end
- CTRL_L_CALC_SDIV2:
+ SMUX_SHR:
begin
- //s = (s + q*M + b*A) >>> 1; s>>=1. Takes (1..length) cycles.
- s_mux_new = SMUX_SHR;
- s_mem_we_new = 1'b1;
+ shr_data_in = s_mem_read_data;
+ s_mem_write_data = shr_data_out;
+ shr_carry_in_new = shr_carry_out;
end
default:
begin
end
endcase
+ end // s_logic
- add_carry_new_sa = 1'b0;
- add_carry_new_sm = 1'b0;
- case (s_mux_reg)
- SMUX_ADD_SM:
- add_carry_new_sm = add_carry_out_sm;
+ //----------------------------------------------------------------
+ // bq
+ //
+ // Extract b and q bits.
+ // b: current bit of B used.
+ // q = (s - b * A) & 1
+ // update the b bit and word indices based on loop counter.
+ //----------------------------------------------------------------
+ always @*
+ begin : bq
+ b_new = opb_data[b_bit_index_reg];
- SMUX_ADD_SA:
- add_carry_new_sa = add_carry_out_sa;
+ if (first_iteration_reg)
+ q_new = 1'b0 ^ (opa_data[0] & b_new);
+ else
+ q_new = s_mem_read_data[0] ^ (opa_data[0] & b_new);
- SMUX_SHR:
- shr_carry_new = shr_carry_out;
+ // B_bit_index = 5'h1f - loop_counter[4:0];
+ b_bit_index_new = ((2**(13 - ADW)) - 1'b1) - loop_ctr_reg[(13 - ADW - 1) : 0];
+ b_word_index = loop_ctr_reg[12 : (13 - ADW)];
+ end // bq
- default:
- begin
- end
- endcase
- end // prodcalc
+ //----------------------------------------------------------------
+ // word_index
+ //
+ // Logic that implements the word index used to drive
+ // addresses for operands.
+ //----------------------------------------------------------------
+ always @*
+ begin : word_index
+ word_index_new = {ADW{1'b0}};
+ word_index_we = 1'b0;
+
+ if (reset_word_index_lsw)
+ begin
+ word_index_new = length_m1;
+ word_index_we = 1'b1;
+ end
+
+ if (reset_word_index_msw)
+ begin
+ word_index_new = {ADW{1'b0}};
+ word_index_we = 1'b1;
+ end
+
+ if (inc_word_index)
+ begin
+ word_index_new = word_index_reg + 1'b1;
+ word_index_we = 1'b1;
+ end
+
+ if (dec_word_index)
+ begin
+ word_index_new = word_index_reg - 1'b1;
+ word_index_we = 1'b1;
+ end
+ end // word_index
+
+
+ //----------------------------------------------------------------
+ // loop_ctr
+ // Logic for updating the loop counter.
+ //----------------------------------------------------------------
+ always @*
+ begin : loop_ctr
+ loop_ctr_new = 13'h0;
+ loop_ctr_we = 1'b0;
+
+ if (loop_ctr_set)
+ begin
+ loop_ctr_new = {length, {(13 - ADW){1'b0}}} - 1'b1;
+ loop_ctr_we = 1'b1;
+ end
+
+ if (loop_ctr_dec)
+ begin
+ loop_ctr_new = loop_ctr_reg - 1'b1;
+ loop_ctr_we = 1'b1;
+ end
+ end
//----------------------------------------------------------------
@@ -443,146 +493,131 @@ module montprod(
//----------------------------------------------------------------
always @*
begin : montprod_ctrl
- ready_new = 1'b0;
- ready_we = 1'b0;
- montprod_ctrl_new = CTRL_IDLE;
- montprod_ctrl_we = 1'b0;
+ ready_new = 1'b0;
+ ready_we = 1'b0;
+ loop_ctr_set = 1'b0;
+ loop_ctr_dec = 1'b0;
+ b_bit_index_we = 1'b0;
+ bq_we = 1'b0;
+ s_mux_new = SMUX_ZERO;
+ dec_word_index = 1'b0;
+ inc_word_index = 1'b0;
+ reset_word_index_lsw = 1'b0;
+ reset_word_index_msw = 1'b0;
+ first_iteration_new = 1'b0;
+ first_iteration_we = 1'b0;
+ tmp_opa_addr = word_index_reg;
+ tmp_result_we = 1'b0;
+ montprod_ctrl_new = CTRL_IDLE;
+ montprod_ctrl_we = 1'b0;
- reset_word_index_LSW = 1'b0;
- reset_word_index_MSW = 1'b0;
case (montprod_ctrl_reg)
CTRL_IDLE:
begin
if (calculate)
begin
- ready_new = 1'b0;
- ready_we = 1'b1;
- montprod_ctrl_new = CTRL_INIT_S;
- montprod_ctrl_we = 1'b1;
- reset_word_index_LSW = 1'b1;
- end
- else
- begin
- ready_new = 1'b1;
- ready_we = 1'b1;
+ first_iteration_new = 1'b1;
+ first_iteration_we = 1'b1;
+ ready_new = 1'b0;
+ ready_we = 1'b1;
+ reset_word_index_lsw = 1'b1;
+ loop_ctr_set = 1'b1;
+ montprod_ctrl_new = CTRL_LOOP_ITER;
+ montprod_ctrl_we = 1'b1;
end
end
- CTRL_INIT_S:
- begin
- if (word_index == 8'h0)
- begin
- montprod_ctrl_new = CTRL_LOOP_INIT;
- montprod_ctrl_we = 1'b1;
- end
- end
-
-
- CTRL_LOOP_INIT:
- begin
- montprod_ctrl_new = CTRL_LOOP_ITER;
- montprod_ctrl_we = 1'b1;
- end
-
//calculate q = (s - b * A) & 1;.
// Also abort loop if done.
CTRL_LOOP_ITER:
begin
- reset_word_index_LSW = 1'b1;
- montprod_ctrl_new = CTRL_LOOP_BQ;
- montprod_ctrl_we = 1'b1;
+ tmp_opa_addr = length_m1;
+ b_bit_index_we = 1'b1;
+ montprod_ctrl_new = CTRL_LOOP_BQ;
+ montprod_ctrl_we = 1'b1;
end
CTRL_LOOP_BQ:
begin
- reset_word_index_LSW = 1'b1;
- montprod_ctrl_new = CTRL_L_CALC_SM;
- montprod_ctrl_we = 1'b1;
+ reset_word_index_lsw = 1'b1;
+ bq_we = 1'b1;
+ montprod_ctrl_new = CTRL_CALC_ADD;
+ montprod_ctrl_we = 1'b1;
end
- CTRL_L_CALC_SM:
+ CTRL_CALC_ADD:
begin
- if (word_index == 8'h0)
+ s_mux_new = SMUX_ADD;
+
+ if (word_index_reg == 0)
begin
- reset_word_index_LSW = 1'b1;
- montprod_ctrl_we = 1'b1;
- montprod_ctrl_new = CTRL_L_STALLPIPE_SM;
+ reset_word_index_lsw = 1'b1;
+ montprod_ctrl_new = CTRL_STALLPIPE_ADD;
+ montprod_ctrl_we = 1'b1;
end
- end
-
- CTRL_L_STALLPIPE_SM:
- begin
- montprod_ctrl_new = CTRL_L_CALC_SA;
- montprod_ctrl_we = 1'b1;
- reset_word_index_LSW = 1'b1;
- end
-
- CTRL_L_CALC_SA:
- begin
- if (word_index == 8'h0)
+ else
begin
- reset_word_index_LSW = 1'b1;
- montprod_ctrl_new = CTRL_L_STALLPIPE_SA;
- montprod_ctrl_we = 1'b1;
+ dec_word_index = 1'b1;
end
end
- CTRL_L_STALLPIPE_SA:
+ CTRL_STALLPIPE_ADD:
begin
- montprod_ctrl_new = CTRL_L_CALC_SDIV2;
- montprod_ctrl_we = 1'b1;
- reset_word_index_MSW = 1'b1;
+ first_iteration_new = 1'b0;
+ first_iteration_we = 1'b1;
+ reset_word_index_msw = 1'b1;
+ montprod_ctrl_new = CTRL_CALC_SDIV2;
+ montprod_ctrl_we = 1'b1;
end
- CTRL_L_CALC_SDIV2:
+ CTRL_CALC_SDIV2:
begin
- if (word_index == length_m1)
+ s_mux_new = SMUX_SHR;
+
+ if (word_index_reg == length_m1)
begin
- montprod_ctrl_new = CTRL_L_STALLPIPE_D2;
- montprod_ctrl_we = 1'b1;
- //reset_word_index = 1'b1;
+ montprod_ctrl_new = CTRL_STALLPIPE_SDIV2;
+ montprod_ctrl_we = 1'b1;
end
+ else
+ inc_word_index = 1'b1;
end
- CTRL_L_STALLPIPE_D2:
+ CTRL_STALLPIPE_SDIV2:
begin
- montprod_ctrl_new = CTRL_LOOP_ITER; //loop
- montprod_ctrl_we = 1'b1;
- reset_word_index_LSW = 1'b1;
- if (loop_counter == 0)
+ loop_ctr_dec = 1'b1;
+ montprod_ctrl_new = CTRL_LOOP_ITER;
+ montprod_ctrl_we = 1'b1;
+ reset_word_index_lsw = 1'b1;
+
+ if (loop_ctr_reg == 0)
begin
montprod_ctrl_new = CTRL_L_STALLPIPE_ES;
- montprod_ctrl_we = 1'b1;
+ montprod_ctrl_we = 1'b1;
end
end
CTRL_L_STALLPIPE_ES:
begin
montprod_ctrl_new = CTRL_EMIT_S;
- montprod_ctrl_we = 1'b1;
- //reset_word_index_LSW = 1'b1;
+ montprod_ctrl_we = 1'b1;
end
CTRL_EMIT_S:
begin
- if (DEBUG)
- $display("EMIT_S word_index: %d", word_index);
- if (word_index_prev == 8'h0)
+ dec_word_index = 1'b1;
+ tmp_result_we = 1'b1;
+
+ if (word_index_prev_reg == 0)
begin
- montprod_ctrl_new = CTRL_DONE;
+ ready_new = 1'b1;
+ ready_we = 1'b1;
+ montprod_ctrl_new = CTRL_IDLE;
montprod_ctrl_we = 1'b1;
end
end
- CTRL_DONE:
- begin
- ready_new = 1'b1;
- ready_we = 1'b1;
- montprod_ctrl_new = CTRL_IDLE;
- montprod_ctrl_we = 1'b1;
- end
-
default:
begin
end