From 90a3fc9ba7793a971698e6bb5c12ae360dad8d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Tue, 2 Jun 2015 13:24:12 +0200 Subject: Refactored into core and top. --- src/rtl/modexp.v | 839 ++++-------------------------------------------- src/rtl/modexp_core.v | 863 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 927 insertions(+), 775 deletions(-) create mode 100644 src/rtl/modexp_core.v (limited to 'src/rtl') diff --git a/src/rtl/modexp.v b/src/rtl/modexp.v index 88060ea..e5158ed 100644 --- a/src/rtl/modexp.v +++ b/src/rtl/modexp.v @@ -104,34 +104,9 @@ module modexp( localparam DEFAULT_MODLENGTH = 8'h80; // 2048 bits. localparam DEFAULT_EXPLENGTH = 8'h80; - localparam MONTPROD_SELECT_ONE_NR = 3'h0; - localparam MONTPROD_SELECT_X_NR = 3'h1; - localparam MONTPROD_SELECT_Z_P = 3'h2; - localparam MONTPROD_SELECT_P_P = 3'h3; - localparam MONTPROD_SELECT_Z_ONE = 3'h4; - - localparam MONTPROD_DEST_Z = 2'b00; - localparam MONTPROD_DEST_P = 2'b01; - localparam MONTPROD_DEST_NOWHERE = 2'b10; - - localparam CTRL_IDLE = 4'h0; - localparam CTRL_RESIDUE = 4'h1; - localparam CTRL_CALCULATE_Z0 = 4'h2; - localparam CTRL_CALCULATE_P0 = 4'h3; - localparam CTRL_ITERATE = 4'h4; - localparam CTRL_ITERATE_Z_P = 4'h5; - localparam CTRL_ITERATE_P_P = 4'h6; - localparam CTRL_ITERATE_END = 4'h7; - localparam CTRL_CALCULATE_ZN = 4'h8; - localparam CTRL_DONE = 4'h9; - - localparam EXPONATION_MODE_SECRET_SECURE = 1'b0; - localparam EXPONATION_MODE_PUBLIC_FAST = 1'b1; //for rsa, c=M^65537 etc, there is no need to slow down to hide the exponent - - - localparam CORE_NAME0 = 32'h6d6f6465; // "mode" - localparam CORE_NAME1 = 32'h78702020; // "xp " - localparam CORE_VERSION = 32'h302e3531; // "0.51" + localparam CORE_NAME0 = 32'h6d6f6465; // "mode" + localparam CORE_NAME1 = 32'h78702020; // "xp " + localparam CORE_VERSION = 32'h302e3532; // "0.52" //---------------------------------------------------------------- @@ -145,146 +120,36 @@ module modexp( reg [07 : 0] modulus_length_new; reg modulus_length_we; - reg [07 : 0] length_m1_reg; - reg [07 : 0] length_m1_new; - reg start_reg; reg start_new; - reg start_we; - reg clear_start; - - reg ready_reg; - reg ready_new; - reg ready_we; - - reg [2 : 0] montprod_select_reg; - reg [2 : 0] montprod_select_new; - reg montprod_select_we; - reg [1 : 0] montprod_dest_reg; - reg [1 : 0] montprod_dest_new; - reg montprod_dest_we; - - reg [3 : 0] modexp_ctrl_reg; - reg [3 : 0] modexp_ctrl_new; - reg modexp_ctrl_we; - - reg [31 : 0] one_reg; - reg [31 : 0] one_new; - reg [31 : 0] b_one_reg; - reg [31 : 0] b_one_new; - - reg [12 : 0] loop_counter_reg; - reg [12 : 0] loop_counter_new; - reg loop_counter_we; - - reg [07 : 0] E_word_index; - reg [04 : 0] E_bit_index; - reg last_iteration; - - reg ei_reg; - reg ei_new; - reg ei_we; - - reg exponation_mode_reg; - reg exponation_mode_new; - reg exponation_mode_we; - - reg [31 : 0] cycle_ctr_low_reg; - reg [31 : 0] cycle_ctr_low_new; - reg cycle_ctr_low_we; - reg [31 : 0] cycle_ctr_high_reg; - reg [31 : 0] cycle_ctr_high_new; - reg cycle_ctr_high_we; - reg cycle_ctr_state_reg; - reg cycle_ctr_state_new; - reg cycle_ctr_state_we; - reg cycle_ctr_start; - reg cycle_ctr_stop; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- - reg [07 : 0] modulus_mem_int_rd_addr; - wire [31 : 0] modulus_mem_int_rd_data; - wire [31 : 0] modulus_mem_api_rd_data; - - reg [07 : 0] message_mem_int_rd_addr; - wire [31 : 0] message_mem_int_rd_data; - wire [31 : 0] message_mem_api_rd_data; - - reg [07 : 0] exponent_mem_int_rd_addr; - wire [31 : 0] exponent_mem_int_rd_data; - wire [31 : 0] exponent_mem_api_rd_data; - - wire [31 : 0] result_mem_api_rd_data; - reg [07 : 0] result_mem_int_rd_addr; - wire [31 : 0] result_mem_int_rd_data; - reg [07 : 0] result_mem_int_wr_addr; - reg [31 : 0] result_mem_int_wr_data; - reg result_mem_int_we; - - reg [07 : 0] p_mem_rd0_addr; - wire [31 : 0] p_mem_rd0_data; - reg [07 : 0] p_mem_rd1_addr; - wire [31 : 0] p_mem_rd1_data; - reg [07 : 0] p_mem_wr_addr; - reg [31 : 0] p_mem_wr_data; - reg p_mem_we; - - reg [31 : 0] tmp_read_data; - - reg montprod_calc; - wire montprod_ready; - reg [07 : 0] montprod_length; - - wire [07 : 0] montprod_opa_addr; - reg [31 : 0] montprod_opa_data; - - wire [07 : 0] montprod_opb_addr; - reg [31 : 0] montprod_opb_data; - - wire [07 : 0] montprod_opm_addr; - reg [31 : 0] montprod_opm_data; - - wire [07 : 0] montprod_result_addr; - wire [31 : 0] montprod_result_data; - wire montprod_result_we; - - reg residue_calculate; - wire residue_ready; - reg [14 : 0] residue_nn; - reg [07 : 0] residue_length; - wire [07 : 0] residue_opa_rd_addr; - wire [31 : 0] residue_opa_rd_data; - wire [07 : 0] residue_opa_wr_addr; - wire [31 : 0] residue_opa_wr_data; - wire residue_opa_wr_we; - wire [07 : 0] residue_opm_addr; - reg [31 : 0] residue_opm_data; - - reg [07 : 0] residue_mem_montprod_read_addr; - wire [31 : 0] residue_mem_montprod_read_data; - - reg residue_valid_reg; - reg residue_valid_new; - reg invalidate_residue; - reg residue_valid_int_validated; + reg exponent_mem_api_rst; + reg exponent_mem_api_cs; + reg exponent_mem_api_wr; + wire [31 : 0] exponent_mem_api_read_data; reg modulus_mem_api_rst; reg modulus_mem_api_cs; reg modulus_mem_api_wr; - - reg exponent_mem_api_rst; - reg exponent_mem_api_cs; - reg exponent_mem_api_wr; + wire [31 : 0] modulus_mem_api_read_data; reg message_mem_api_rst; reg message_mem_api_cs; reg message_mem_api_wr; + wire [31 : 0] message_mem_api_read_data; reg result_mem_api_rst; reg result_mem_api_cs; + wire [31 : 0] result_mem_api_read_data; + + wire ready; + wire [63 : 0] cycles; + + reg [31 : 0] tmp_read_data; //---------------------------------------------------------------- @@ -296,119 +161,40 @@ module modexp( //---------------------------------------------------------------- // core instantiations. //---------------------------------------------------------------- - montprod montprod_inst( - .clk(clk), - .reset_n(reset_n), - - .calculate(montprod_calc), - .ready(montprod_ready), - - .length(montprod_length), - - .opa_addr(montprod_opa_addr), - .opa_data(montprod_opa_data), - - .opb_addr(montprod_opb_addr), - .opb_data(montprod_opb_data), - - .opm_addr(montprod_opm_addr), - .opm_data(montprod_opm_data), - - .result_addr(montprod_result_addr), - .result_data(montprod_result_data), - .result_we(montprod_result_we) - ); - - - residue residue_inst( - .clk(clk), - .reset_n(reset_n), - .calculate(residue_calculate), - .ready(residue_ready), - .nn(residue_nn), - .length(residue_length), - .opa_rd_addr(residue_opa_rd_addr), - .opa_rd_data(residue_opa_rd_data), - .opa_wr_addr(residue_opa_wr_addr), - .opa_wr_data(residue_opa_wr_data), - .opa_wr_we(residue_opa_wr_we), - .opm_addr(residue_opm_addr), - .opm_data(residue_opm_data) - ); - - blockmem2r1w residue_mem( - .clk(clk), - .read_addr0(residue_opa_rd_addr), - .read_data0(residue_opa_rd_data), - .read_addr1(residue_mem_montprod_read_addr), - .read_data1(residue_mem_montprod_read_data), - .wr(residue_opa_wr_we), - .write_addr(residue_opa_wr_addr), - .write_data(residue_opa_wr_data) - ); - - blockmem2r1wptr modulus_mem( - .clk(clk), - .reset_n(reset_n), - .read_addr0(modulus_mem_int_rd_addr), - .read_data0(modulus_mem_int_rd_data), - .read_data1(modulus_mem_api_rd_data), - .rst(modulus_mem_api_rst), - .cs(modulus_mem_api_cs), - .wr(modulus_mem_api_wr), - .write_data(write_data) - ); - - - blockmem2r1wptr message_mem( - .clk(clk), - .reset_n(reset_n), - .read_addr0(message_mem_int_rd_addr), - .read_data0(message_mem_int_rd_data), - .read_data1(message_mem_api_rd_data), - .rst(message_mem_api_rst), - .cs(message_mem_api_cs), - .wr(message_mem_api_wr), - .write_data(write_data) - ); - - - blockmem2r1wptr exponent_mem( - .clk(clk), - .reset_n(reset_n), - .read_addr0(exponent_mem_int_rd_addr), - .read_data0(exponent_mem_int_rd_data), - .read_data1(exponent_mem_api_rd_data), - .rst(exponent_mem_api_rst), - .cs(exponent_mem_api_cs), - .wr(exponent_mem_api_wr), - .write_data(write_data) - ); - - - blockmem2rptr1w result_mem( - .clk(clk), - .reset_n(reset_n), - .read_addr0(result_mem_int_rd_addr[7 : 0]), - .read_data0(result_mem_int_rd_data), - .read_data1(result_mem_api_rd_data), - .rst(result_mem_api_rst), - .cs(result_mem_api_cs), - .wr(result_mem_int_we), - .write_addr(result_mem_int_wr_addr), - .write_data(result_mem_int_wr_data) - ); - - blockmem2r1w p_mem( - .clk(clk), - .read_addr0(p_mem_rd0_addr), - .read_data0(p_mem_rd0_data), - .read_addr1(p_mem_rd1_addr), - .read_data1(p_mem_rd1_data), - .wr(p_mem_we), - .write_addr(p_mem_wr_addr), - .write_data(p_mem_wr_data) - ); + modexp_core core_inst( + .clk(clk), + .reset_n(reset_n), + + .start(start_reg), + .ready(ready), + + .exponent_length(exponent_length_reg), + .modulus_length(modulus_length_reg), + + .cycles(cycles), + + .exponent_mem_api_cs(exponent_mem_api_cs), + .exponent_mem_api_wr(exponent_mem_api_wr), + .exponent_mem_api_rst(exponent_mem_api_rst), + .exponent_mem_api_write_data(write_data), + .exponent_mem_api_read_data(exponent_mem_api_read_data), + + .modulus_mem_api_cs(modulus_mem_api_cs), + .modulus_mem_api_wr(modulus_mem_api_wr), + .modulus_mem_api_rst(modulus_mem_api_rst), + .modulus_mem_api_write_data(write_data), + .modulus_mem_api_read_data(modulus_mem_api_read_data), + + .message_mem_api_cs(message_mem_api_cs), + .message_mem_api_wr(message_mem_api_wr), + .message_mem_api_rst(message_mem_api_rst), + .message_mem_api_write_data(write_data), + .message_mem_api_read_data(message_mem_api_read_data), + + .result_mem_api_cs(result_mem_api_cs), + .result_mem_api_rst(result_mem_api_rst), + .result_mem_api_read_data(result_mem_api_read_data) + ); //---------------------------------------------------------------- @@ -422,73 +208,23 @@ module modexp( begin if (!reset_n) begin + start_reg <= 1'b0; exponent_length_reg <= DEFAULT_EXPLENGTH; modulus_length_reg <= DEFAULT_MODLENGTH; - start_reg <= 1'b0; - ready_reg <= 1'b1; - montprod_select_reg <= MONTPROD_SELECT_ONE_NR; - montprod_dest_reg <= MONTPROD_DEST_NOWHERE; - modexp_ctrl_reg <= CTRL_IDLE; - one_reg <= 32'h0; - b_one_reg <= 32'h0; - length_m1_reg <= 8'h0; - loop_counter_reg <= 13'b0; - ei_reg <= 1'b0; - residue_valid_reg <= 1'b0; - exponation_mode_reg <= EXPONATION_MODE_SECRET_SECURE; - cycle_ctr_low_reg <= 32'h00000000; - cycle_ctr_high_reg <= 32'h00000000; - cycle_ctr_state_reg <= 1'b0; end else begin - one_reg <= one_new; - b_one_reg <= b_one_new; - residue_valid_reg <= residue_valid_new; + start_reg <= start_new; if (exponent_length_we) begin - exponent_length_reg <= exponent_length_new; + exponent_length_reg <= write_data[7 : 0]; end if (modulus_length_we) begin - modulus_length_reg <= modulus_length_new; - length_m1_reg <= length_m1_new; + modulus_length_reg <= write_data[7 : 0]; end - - if (start_we) - start_reg <= start_new; - - if (ready_we) - ready_reg <= ready_new; - - if (montprod_select_we) - montprod_select_reg <= montprod_select_new; - - if (montprod_dest_we) - montprod_dest_reg <= montprod_dest_new; - - if (loop_counter_we) - loop_counter_reg <= loop_counter_new; - - if (ei_we) - ei_reg <= ei_new; - - if (exponation_mode_we) - exponation_mode_reg <= exponation_mode_new; - - if (cycle_ctr_low_we) - cycle_ctr_low_reg <= cycle_ctr_low_new; - - if (cycle_ctr_high_we) - cycle_ctr_high_reg <= cycle_ctr_high_new; - - if (cycle_ctr_state_we) - cycle_ctr_state_reg <= cycle_ctr_state_new; - - if (modexp_ctrl_we) - modexp_ctrl_reg <= modexp_ctrl_new; end end // reg_update @@ -500,11 +236,9 @@ module modexp( //---------------------------------------------------------------- always @* begin : api - modulus_length_we = 1'b0; - exponent_length_we = 1'b0; - start_new = 1'b0; - start_we = 1'b0; - invalidate_residue = 1'b0; + modulus_length_we = 1'b0; + exponent_length_we = 1'b0; + start_new = 1'b0; modulus_mem_api_rst = 1'b0; modulus_mem_api_cs = 1'b0; @@ -521,24 +255,7 @@ module modexp( result_mem_api_rst = 1'b0; result_mem_api_cs = 1'b0; - - //TODO: Add API code to enable fast exponation for working with public exponents. - exponation_mode_we = 1'b0; - - exponation_mode_new = EXPONATION_MODE_SECRET_SECURE; - modulus_length_new = write_data[7 : 0]; - exponent_length_new = write_data[7 : 0]; - length_m1_new = write_data[7 : 0] - 8'h1; - - tmp_read_data = 32'h00000000; - - // We need to be able to clear start bit after we have - // started a modexp operation. - if (clear_start) - begin - start_new = 1'b0; - start_we = 1'b1; - end + tmp_read_data = 32'h00000000; if (cs) begin @@ -551,7 +268,6 @@ module modexp( ADDR_CTRL: begin start_new = write_data[0]; - start_we = 1'b1; end ADDR_MODULUS_LENGTH: @@ -573,7 +289,6 @@ module modexp( begin modulus_mem_api_cs = 1'b1; modulus_mem_api_wr = 1'b1; - invalidate_residue = 1'b1; end ADDR_EXPONENT_PTR_RST: @@ -624,13 +339,13 @@ module modexp( tmp_read_data = {31'h00000000, start_reg}; ADDR_STATUS: - tmp_read_data = {31'h00000000, ready_reg}; + tmp_read_data = {31'h00000000, ready}; ADDR_CYCLES_HIGH: - tmp_read_data = cycle_ctr_high_reg; + tmp_read_data = cycles[63 : 32]; ADDR_CYCLES_LOW: - tmp_read_data = cycle_ctr_low_reg; + tmp_read_data = cycles[31 : 0]; ADDR_MODULUS_LENGTH: tmp_read_data = {24'h000000, modulus_length_reg}; @@ -641,25 +356,25 @@ module modexp( ADDR_MODULUS_DATA: begin modulus_mem_api_cs = 1'b1; - tmp_read_data = modulus_mem_api_rd_data; + tmp_read_data = modulus_mem_api_read_data; end ADDR_EXPONENT_DATA: begin exponent_mem_api_cs = 1'b1; - tmp_read_data = exponent_mem_api_rd_data; + tmp_read_data = exponent_mem_api_read_data; end ADDR_MESSAGE_DATA: begin message_mem_api_cs = 1'b1; - tmp_read_data = message_mem_api_rd_data; + tmp_read_data = message_mem_api_read_data; end ADDR_RESULT_DATA: begin result_mem_api_cs = 1'b1; - tmp_read_data = result_mem_api_rd_data; + tmp_read_data = result_mem_api_read_data; end default: @@ -677,432 +392,6 @@ module modexp( end // if (cs) end // api - - //---------------------------------------------------------------- - // cycle_ctr - // - // Implementation of the cycle counter - //---------------------------------------------------------------- - always @* - begin : cycle_ctr - cycle_ctr_low_new = 32'h00000000; - cycle_ctr_low_we = 1'b0; - cycle_ctr_high_new = 32'h00000000; - cycle_ctr_high_we = 1'b0; - cycle_ctr_state_new = 1'b0; - cycle_ctr_state_we = 1'b0; - - if (cycle_ctr_start) - begin - cycle_ctr_low_new = 32'h00000000; - cycle_ctr_low_we = 1'b1; - cycle_ctr_high_new = 32'h00000000; - cycle_ctr_high_we = 1'b1; - cycle_ctr_state_new = 1'b1; - cycle_ctr_state_we = 1'b1; - end - - if (cycle_ctr_stop) - begin - cycle_ctr_state_new = 1'b0; - cycle_ctr_state_we = 1'b1; - end - - if (cycle_ctr_state_reg) - begin - cycle_ctr_low_new = cycle_ctr_low_reg + 1'b1; - cycle_ctr_low_we = 1'b1; - - if (cycle_ctr_low_new == 32'h00000000) - begin - cycle_ctr_high_new = cycle_ctr_high_reg + 1'b1; - cycle_ctr_high_we = 1'b1; - end - end - end // cycle_ctr - - - //---------------------------------------------------------------- - // one - // - // generates the big integer one ( 00... 01 ) - //---------------------------------------------------------------- - always @* - begin : one_process - one_new = 32'h00000000; - b_one_new = 32'h00000000; - - if (montprod_opa_addr == length_m1_reg) - one_new = 32'h00000001; - - if (montprod_opb_addr == length_m1_reg) - b_one_new = 32'h00000001; - end - - - //---------------------------------------------------------------- - // Read mux for modulus. Needed since it is being - // addressed by two sources. - //---------------------------------------------------------------- - always @* - begin : modulus_mem_reader_process - if (modexp_ctrl_reg == CTRL_RESIDUE) - modulus_mem_int_rd_addr = residue_opm_addr; - else - modulus_mem_int_rd_addr = montprod_opm_addr; - end - - - //---------------------------------------------------------------- - // Feeds residue calculator. - //---------------------------------------------------------------- - always @* - begin : residue_process - //N*2, N=length*32, *32 = shl5, *64 = shl6 - residue_nn = { 1'b0, modulus_length_reg, 6'h0 }; - residue_length = modulus_length_reg; - residue_opm_data = modulus_mem_int_rd_data; - end - - - //---------------------------------------------------------------- - // Sets the register that decides if residue is valid or not. - //---------------------------------------------------------------- - always @* - begin : residue_valid_process - if (invalidate_residue) - residue_valid_new = 1'b0; - else if ( residue_valid_int_validated == 1'b1) - residue_valid_new = 1'b1; - else - residue_valid_new = residue_valid_reg; - end - - - //---------------------------------------------------------------- - // montprod_op_select - // - // Select operands used during montprod calculations depending - // on what operation we want to do. - //---------------------------------------------------------------- - always @* - begin : montprod_op_select - - montprod_length = modulus_length_reg; - - result_mem_int_rd_addr = montprod_opa_addr; - message_mem_int_rd_addr = montprod_opa_addr; - p_mem_rd0_addr = montprod_opa_addr; - - residue_mem_montprod_read_addr = montprod_opb_addr; - p_mem_rd1_addr = montprod_opb_addr; - - montprod_opm_data = modulus_mem_int_rd_data; - case (montprod_select_reg) - MONTPROD_SELECT_ONE_NR: - begin - montprod_opa_data = one_reg; - montprod_opb_data = residue_mem_montprod_read_data; - end - - MONTPROD_SELECT_X_NR: - begin - montprod_opa_data = message_mem_int_rd_data; - montprod_opb_data = residue_mem_montprod_read_data; - end - - MONTPROD_SELECT_Z_P: - begin - montprod_opa_data = result_mem_int_rd_data; - montprod_opb_data = p_mem_rd1_data; - end - - MONTPROD_SELECT_P_P: - begin - montprod_opa_data = p_mem_rd0_data; - montprod_opb_data = p_mem_rd1_data; - end - - MONTPROD_SELECT_Z_ONE: - begin - montprod_opa_data = result_mem_int_rd_data; - montprod_opb_data = b_one_reg; - end - - default: - begin - montprod_opa_data = 32'h00000000; - montprod_opb_data = 32'h00000000; - end - endcase // case (montprod_selcect_reg) - end - - - //---------------------------------------------------------------- - // memory write mux - // - // Direct memory write signals to correct memory. - //---------------------------------------------------------------- - always @* - begin : memory_write_process - result_mem_int_wr_addr = montprod_result_addr; - result_mem_int_wr_data = montprod_result_data; - result_mem_int_we = 1'b0; - - p_mem_wr_addr = montprod_result_addr; - p_mem_wr_data = montprod_result_data; - p_mem_we = 1'b0; - - case (montprod_dest_reg) - MONTPROD_DEST_Z: - result_mem_int_we = montprod_result_we; - MONTPROD_DEST_P: - p_mem_we = montprod_result_we; - default: - begin - end - endcase - - // inhibit Z=Z*P when ei = 0 - if (modexp_ctrl_reg == CTRL_ITERATE_Z_P) - result_mem_int_we = result_mem_int_we & ei_reg; - end - - - //---------------------------------------------------------------- - // loop_counter - // - // Calculate the loop counter and related variables. - //---------------------------------------------------------------- - always @* - begin : loop_counters_process - loop_counter_new = 13'b0; - loop_counter_we = 1'b0; - - if (loop_counter_reg == { length_m1_reg, 5'b11111 }) - last_iteration = 1'b1; - else - last_iteration = 1'b0; - - case (modexp_ctrl_reg) - CTRL_CALCULATE_P0: - begin - loop_counter_new = 13'b0; - loop_counter_we = 1'b1; - end - - CTRL_ITERATE_END: - begin - loop_counter_new = loop_counter_reg + 1'b1; - loop_counter_we = 1'b1; - end - - default: - begin - end - endcase - end - - - //---------------------------------------------------------------- - // exponent - // - // Reads the exponent. - //---------------------------------------------------------------- - always @* - begin : exponent_process - // Accessing new instead of reg - pick up update at - // CTRL_ITERATE_NEW to remove a pipeline stall. - E_word_index = length_m1_reg - loop_counter_new[ 12 : 5 ]; - - E_bit_index = loop_counter_reg[ 04 : 0 ]; - - exponent_mem_int_rd_addr = E_word_index; - - ei_new = exponent_mem_int_rd_data[ E_bit_index ]; - - if (modexp_ctrl_reg == CTRL_ITERATE) - ei_we = 1'b1; - else - ei_we = 1'b0; - end - - - //---------------------------------------------------------------- - // modexp_ctrl - // - // Control FSM logic needed to perform the modexp operation. - //---------------------------------------------------------------- - always @* - begin - ready_new = 1'b0; - ready_we = 1'b0; - montprod_select_new = MONTPROD_SELECT_ONE_NR; - montprod_select_we = 0; - montprod_dest_new = MONTPROD_DEST_NOWHERE; - montprod_dest_we = 0; - montprod_calc = 0; - modexp_ctrl_new = CTRL_IDLE; - modexp_ctrl_we = 1'b0; - clear_start = 1'b0; - cycle_ctr_start = 1'b0; - cycle_ctr_stop = 1'b0; - - residue_calculate = 1'b0; - - residue_valid_int_validated = 1'b0; - - case (modexp_ctrl_reg) - CTRL_IDLE: - begin - if (start_reg) - begin - ready_new = 1'b0; - ready_we = 1'b1; - clear_start = 1'b1; - cycle_ctr_start = 1'b1; - - if (residue_valid_reg) - begin - //residue has alrady been calculated, start with MONTPROD( 1, Nr, MODULUS ) - montprod_select_new = MONTPROD_SELECT_ONE_NR; - montprod_select_we = 1; - montprod_dest_new = MONTPROD_DEST_Z; - montprod_dest_we = 1; - montprod_calc = 1; - modexp_ctrl_new = CTRL_CALCULATE_Z0; - modexp_ctrl_we = 1; - end - else - begin - //modulus has been written and residue (Nr) must be calculated - modexp_ctrl_new = CTRL_RESIDUE; - modexp_ctrl_we = 1; - residue_calculate = 1'b1; - end - end - end - - CTRL_RESIDUE: - begin - if (residue_ready) - begin - montprod_select_new = MONTPROD_SELECT_ONE_NR; - montprod_select_we = 1; - montprod_dest_new = MONTPROD_DEST_Z; - montprod_dest_we = 1; - montprod_calc = 1; - modexp_ctrl_new = CTRL_CALCULATE_Z0; - modexp_ctrl_we = 1; - residue_valid_int_validated = 1'b1; //update registers telling residue is valid - end - end - - CTRL_CALCULATE_Z0: - begin - if (montprod_ready) - begin - montprod_select_new = MONTPROD_SELECT_X_NR; - montprod_select_we = 1; - montprod_dest_new = MONTPROD_DEST_P; - montprod_dest_we = 1; - montprod_calc = 1; - modexp_ctrl_new = CTRL_CALCULATE_P0; - modexp_ctrl_we = 1; - end - end - - CTRL_CALCULATE_P0: - begin - if (montprod_ready == 1'b1) - begin - modexp_ctrl_new = CTRL_ITERATE; - modexp_ctrl_we = 1; - end - end - - CTRL_ITERATE: - begin - montprod_select_new = MONTPROD_SELECT_Z_P; - montprod_select_we = 1; - montprod_dest_new = MONTPROD_DEST_Z; - montprod_dest_we = 1; - montprod_calc = 1; - modexp_ctrl_new = CTRL_ITERATE_Z_P; - modexp_ctrl_we = 1; - - if (ei_new == 1'b0 && exponation_mode_reg == EXPONATION_MODE_PUBLIC_FAST) - begin - //Skip the fake montgomery calculation, exponation_mode_reg optimizing for speed not blinding. - montprod_select_new = MONTPROD_SELECT_P_P; - montprod_dest_new = MONTPROD_DEST_P; - modexp_ctrl_new = CTRL_ITERATE_P_P; - end - end - - CTRL_ITERATE_Z_P: - if (montprod_ready) - begin - montprod_select_new = MONTPROD_SELECT_P_P; - montprod_select_we = 1; - montprod_dest_new = MONTPROD_DEST_P; - montprod_dest_we = 1; - montprod_calc = 1; - modexp_ctrl_new = CTRL_ITERATE_P_P; - modexp_ctrl_we = 1; - end - - CTRL_ITERATE_P_P: - if (montprod_ready == 1'b1) - begin - modexp_ctrl_new = CTRL_ITERATE_END; - modexp_ctrl_we = 1; - end - - CTRL_ITERATE_END: - begin - if (!last_iteration) - begin - modexp_ctrl_new = CTRL_ITERATE; - modexp_ctrl_we = 1; - end - else - begin - montprod_select_new = MONTPROD_SELECT_Z_ONE; - montprod_select_we = 1; - montprod_dest_new = MONTPROD_DEST_Z; - montprod_dest_we = 1; - montprod_calc = 1; - modexp_ctrl_new = CTRL_CALCULATE_ZN; - modexp_ctrl_we = 1; - end - end - - CTRL_CALCULATE_ZN: - begin - if (montprod_ready) - begin - modexp_ctrl_new = CTRL_DONE; - modexp_ctrl_we = 1; - end - end - - CTRL_DONE: - begin - cycle_ctr_stop = 1'b1; - ready_new = 1'b1; - ready_we = 1'b1; - modexp_ctrl_new = CTRL_IDLE; - modexp_ctrl_we = 1; - end - - default: - begin - end - - endcase // case (modexp_ctrl_reg) - end - endmodule // modexp //====================================================================== diff --git a/src/rtl/modexp_core.v b/src/rtl/modexp_core.v new file mode 100644 index 0000000..b8c4403 --- /dev/null +++ b/src/rtl/modexp_core.v @@ -0,0 +1,863 @@ +//====================================================================== +// +// modexp_core.v +// ------------- +// Modular exponentiation core for implementing public key algorithms +// such as RSA, DH, ElGamal etc. +// +// The core calculates the following function: +// +// C = M ** e mod N +// +// M is a message with a length of n bits +// e is the exponent with a length of m bits +// N is the modulus with a length of n bits +// +// n can be 32 and up to and including 8192 bits in steps +// of 32 bits. +// m can be one and up to and including 8192 bits in steps +// of 32 bits. +// +// The core has access ports for the exponent, modulus, message and +// result memories. +// +// +// Author: Joachim Strombergson, Peter Magnusson +// Copyright (c) 2015, Assured AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. 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. +// +// 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 OWNER 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 modexp_core( + input wire clk, + input wire reset_n, + + input wire start, + output wire ready, + + input wire [07 : 0] exponent_length, + input wire [07 : 0] modulus_length, + + output wire [63 : 0] cycles, + + input wire exponent_mem_api_cs, + input wire exponent_mem_api_wr, + input wire exponent_mem_api_rst, + input wire [31 : 0] exponent_mem_api_write_data, + output wire [31 : 0] exponent_mem_api_read_data, + + input wire modulus_mem_api_cs, + input wire modulus_mem_api_wr, + input wire modulus_mem_api_rst, + input wire [31 : 0] modulus_mem_api_write_data, + output wire [31 : 0] modulus_mem_api_read_data, + + input wire message_mem_api_cs, + input wire message_mem_api_wr, + input wire message_mem_api_rst, + input wire [31 : 0] message_mem_api_write_data, + output wire [31 : 0] message_mem_api_read_data, + + input wire result_mem_api_cs, + input wire result_mem_api_rst, + output wire [31 : 0] result_mem_api_read_data + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam MONTPROD_SELECT_ONE_NR = 3'h0; + localparam MONTPROD_SELECT_X_NR = 3'h1; + localparam MONTPROD_SELECT_Z_P = 3'h2; + localparam MONTPROD_SELECT_P_P = 3'h3; + localparam MONTPROD_SELECT_Z_ONE = 3'h4; + + localparam MONTPROD_DEST_Z = 2'b00; + localparam MONTPROD_DEST_P = 2'b01; + localparam MONTPROD_DEST_NOWHERE = 2'b10; + + localparam CTRL_IDLE = 4'h0; + localparam CTRL_RESIDUE = 4'h1; + localparam CTRL_CALCULATE_Z0 = 4'h2; + localparam CTRL_CALCULATE_P0 = 4'h3; + localparam CTRL_ITERATE = 4'h4; + localparam CTRL_ITERATE_Z_P = 4'h5; + localparam CTRL_ITERATE_P_P = 4'h6; + localparam CTRL_ITERATE_END = 4'h7; + localparam CTRL_CALCULATE_ZN = 4'h8; + localparam CTRL_DONE = 4'h9; + + //for rsa, c=M^65537 etc, there is no need to slow down to hide the exponent + localparam EXPONATION_MODE_SECRET_SECURE = 1'b0; + localparam EXPONATION_MODE_PUBLIC_FAST = 1'b1; + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [2 : 0] montprod_select_reg; + reg [2 : 0] montprod_select_new; + reg montprod_select_we; + reg [1 : 0] montprod_dest_reg; + reg [1 : 0] montprod_dest_new; + reg montprod_dest_we; + + reg [3 : 0] modexp_ctrl_reg; + reg [3 : 0] modexp_ctrl_new; + reg modexp_ctrl_we; + + reg [31 : 0] one_reg; + reg [31 : 0] one_new; + reg [31 : 0] b_one_reg; + reg [31 : 0] b_one_new; + + reg [12 : 0] loop_counter_reg; + reg [12 : 0] loop_counter_new; + reg loop_counter_we; + + reg [07 : 0] E_word_index; + reg [04 : 0] E_bit_index; + reg last_iteration; + + reg ei_reg; + reg ei_new; + reg ei_we; + + reg exponation_mode_reg; + reg exponation_mode_new; + reg exponation_mode_we; + + reg [31 : 0] cycle_ctr_low_reg; + reg [31 : 0] cycle_ctr_low_new; + reg cycle_ctr_low_we; + reg [31 : 0] cycle_ctr_high_reg; + reg [31 : 0] cycle_ctr_high_new; + reg cycle_ctr_high_we; + reg cycle_ctr_state_reg; + reg cycle_ctr_state_new; + reg cycle_ctr_state_we; + reg cycle_ctr_start; + reg cycle_ctr_stop; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [07 : 0] modulus_mem_int_rd_addr; + wire [31 : 0] modulus_mem_int_rd_data; + + reg [07 : 0] message_mem_int_rd_addr; + wire [31 : 0] message_mem_int_rd_data; + + reg [07 : 0] exponent_mem_int_rd_addr; + wire [31 : 0] exponent_mem_int_rd_data; + + reg [07 : 0] result_mem_int_rd_addr; + wire [31 : 0] result_mem_int_rd_data; + reg [07 : 0] result_mem_int_wr_addr; + reg [31 : 0] result_mem_int_wr_data; + reg result_mem_int_we; + + reg [07 : 0] p_mem_rd0_addr; + wire [31 : 0] p_mem_rd0_data; + reg [07 : 0] p_mem_rd1_addr; + wire [31 : 0] p_mem_rd1_data; + reg [07 : 0] p_mem_wr_addr; + reg [31 : 0] p_mem_wr_data; + reg p_mem_we; + + reg [31 : 0] tmp_read_data; + + reg montprod_calc; + wire montprod_ready; + reg [07 : 0] montprod_length; + + wire [07 : 0] montprod_opa_addr; + reg [31 : 0] montprod_opa_data; + + wire [07 : 0] montprod_opb_addr; + reg [31 : 0] montprod_opb_data; + + wire [07 : 0] montprod_opm_addr; + reg [31 : 0] montprod_opm_data; + + wire [07 : 0] montprod_result_addr; + wire [31 : 0] montprod_result_data; + wire montprod_result_we; + + reg residue_calculate; + wire residue_ready; + reg [14 : 0] residue_nn; + reg [07 : 0] residue_length; + wire [07 : 0] residue_opa_rd_addr; + wire [31 : 0] residue_opa_rd_data; + wire [07 : 0] residue_opa_wr_addr; + wire [31 : 0] residue_opa_wr_data; + wire residue_opa_wr_we; + wire [07 : 0] residue_opm_addr; + reg [31 : 0] residue_opm_data; + + reg [07 : 0] residue_mem_montprod_read_addr; + wire [31 : 0] residue_mem_montprod_read_data; + + reg residue_valid_reg; + reg residue_valid_new; + reg residue_valid_int_validated; + + wire [7 : 0] length_m1; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign ready = ready_reg; + assign cycles = {cycle_ctr_high_reg, cycle_ctr_low_reg}; + + assign length_m1 = modulus_length - 8'h1; + + + //---------------------------------------------------------------- + // core instantiations. + //---------------------------------------------------------------- + montprod montprod_inst( + .clk(clk), + .reset_n(reset_n), + + .calculate(montprod_calc), + .ready(montprod_ready), + + .length(montprod_length), + + .opa_addr(montprod_opa_addr), + .opa_data(montprod_opa_data), + + .opb_addr(montprod_opb_addr), + .opb_data(montprod_opb_data), + + .opm_addr(montprod_opm_addr), + .opm_data(montprod_opm_data), + + .result_addr(montprod_result_addr), + .result_data(montprod_result_data), + .result_we(montprod_result_we) + ); + + + residue residue_inst( + .clk(clk), + .reset_n(reset_n), + .calculate(residue_calculate), + .ready(residue_ready), + .nn(residue_nn), + .length(residue_length), + .opa_rd_addr(residue_opa_rd_addr), + .opa_rd_data(residue_opa_rd_data), + .opa_wr_addr(residue_opa_wr_addr), + .opa_wr_data(residue_opa_wr_data), + .opa_wr_we(residue_opa_wr_we), + .opm_addr(residue_opm_addr), + .opm_data(residue_opm_data) + ); + + blockmem2r1w residue_mem( + .clk(clk), + .read_addr0(residue_opa_rd_addr), + .read_data0(residue_opa_rd_data), + .read_addr1(residue_mem_montprod_read_addr), + .read_data1(residue_mem_montprod_read_data), + .wr(residue_opa_wr_we), + .write_addr(residue_opa_wr_addr), + .write_data(residue_opa_wr_data) + ); + + + blockmem2r1w p_mem( + .clk(clk), + .read_addr0(p_mem_rd0_addr), + .read_data0(p_mem_rd0_data), + .read_addr1(p_mem_rd1_addr), + .read_data1(p_mem_rd1_data), + .wr(p_mem_we), + .write_addr(p_mem_wr_addr), + .write_data(p_mem_wr_data) + ); + + + blockmem2r1wptr exponent_mem( + .clk(clk), + .reset_n(reset_n), + .read_addr0(exponent_mem_int_rd_addr), + .read_data0(exponent_mem_int_rd_data), + .read_data1(exponent_mem_api_read_data), + .rst(exponent_mem_api_rst), + .cs(exponent_mem_api_cs), + .wr(exponent_mem_api_wr), + .write_data(exponent_mem_api_write_data) + ); + + + blockmem2r1wptr modulus_mem( + .clk(clk), + .reset_n(reset_n), + .read_addr0(modulus_mem_int_rd_addr), + .read_data0(modulus_mem_int_rd_data), + .read_data1(modulus_mem_api_read_data), + .rst(modulus_mem_api_rst), + .cs(modulus_mem_api_cs), + .wr(modulus_mem_api_wr), + .write_data(modulus_mem_api_write_data) + ); + + + blockmem2r1wptr message_mem( + .clk(clk), + .reset_n(reset_n), + .read_addr0(message_mem_int_rd_addr), + .read_data0(message_mem_int_rd_data), + .read_data1(message_mem_api_read_data), + .rst(message_mem_api_rst), + .cs(message_mem_api_cs), + .wr(message_mem_api_wr), + .write_data(message_mem_api_write_data) + ); + + + blockmem2rptr1w result_mem( + .clk(clk), + .reset_n(reset_n), + .read_addr0(result_mem_int_rd_addr[7 : 0]), + .read_data0(result_mem_int_rd_data), + .read_data1(result_mem_api_read_data), + .rst(result_mem_api_rst), + .cs(result_mem_api_cs), + .wr(result_mem_int_we), + .write_addr(result_mem_int_wr_addr), + .write_data(result_mem_int_wr_data) + ); + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin + if (!reset_n) + begin + ready_reg <= 1'b1; + montprod_select_reg <= MONTPROD_SELECT_ONE_NR; + montprod_dest_reg <= MONTPROD_DEST_NOWHERE; + modexp_ctrl_reg <= CTRL_IDLE; + one_reg <= 32'h0; + b_one_reg <= 32'h0; + loop_counter_reg <= 13'b0; + ei_reg <= 1'b0; + residue_valid_reg <= 1'b0; + exponation_mode_reg <= EXPONATION_MODE_SECRET_SECURE; + cycle_ctr_low_reg <= 32'h00000000; + cycle_ctr_high_reg <= 32'h00000000; + cycle_ctr_state_reg <= 1'b0; + end + else + begin + one_reg <= one_new; + b_one_reg <= b_one_new; + residue_valid_reg <= residue_valid_new; + + if (ready_we) + ready_reg <= ready_new; + + if (montprod_select_we) + montprod_select_reg <= montprod_select_new; + + if (montprod_dest_we) + montprod_dest_reg <= montprod_dest_new; + + if (loop_counter_we) + loop_counter_reg <= loop_counter_new; + + if (ei_we) + ei_reg <= ei_new; + + if (exponation_mode_we) + exponation_mode_reg <= exponation_mode_new; + + if (cycle_ctr_low_we) + cycle_ctr_low_reg <= cycle_ctr_low_new; + + if (cycle_ctr_high_we) + cycle_ctr_high_reg <= cycle_ctr_high_new; + + if (cycle_ctr_state_we) + cycle_ctr_state_reg <= cycle_ctr_state_new; + + if (modexp_ctrl_we) + modexp_ctrl_reg <= modexp_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // cycle_ctr + // + // Implementation of the cycle counter + //---------------------------------------------------------------- + always @* + begin : cycle_ctr + cycle_ctr_low_new = 32'h00000000; + cycle_ctr_low_we = 1'b0; + cycle_ctr_high_new = 32'h00000000; + cycle_ctr_high_we = 1'b0; + cycle_ctr_state_new = 1'b0; + cycle_ctr_state_we = 1'b0; + + if (cycle_ctr_start) + begin + cycle_ctr_low_new = 32'h00000000; + cycle_ctr_low_we = 1'b1; + cycle_ctr_high_new = 32'h00000000; + cycle_ctr_high_we = 1'b1; + cycle_ctr_state_new = 1'b1; + cycle_ctr_state_we = 1'b1; + end + + if (cycle_ctr_stop) + begin + cycle_ctr_state_new = 1'b0; + cycle_ctr_state_we = 1'b1; + end + + if (cycle_ctr_state_reg) + begin + cycle_ctr_low_new = cycle_ctr_low_reg + 1'b1; + cycle_ctr_low_we = 1'b1; + + if (cycle_ctr_low_new == 32'h00000000) + begin + cycle_ctr_high_new = cycle_ctr_high_reg + 1'b1; + cycle_ctr_high_we = 1'b1; + end + end + end // cycle_ctr + + + //---------------------------------------------------------------- + // one + // + // generates the big integer one ( 00... 01 ) + //---------------------------------------------------------------- + always @* + begin : one_process + one_new = 32'h00000000; + b_one_new = 32'h00000000; + + if (montprod_opa_addr == length_m1) + one_new = 32'h00000001; + + if (montprod_opb_addr == length_m1) + b_one_new = 32'h00000001; + end + + + //---------------------------------------------------------------- + // Read mux for modulus. Needed since it is being + // addressed by two sources. + //---------------------------------------------------------------- + always @* + begin : modulus_mem_reader_process + if (modexp_ctrl_reg == CTRL_RESIDUE) + modulus_mem_int_rd_addr = residue_opm_addr; + else + modulus_mem_int_rd_addr = montprod_opm_addr; + end + + + //---------------------------------------------------------------- + // Feeds residue calculator. + //---------------------------------------------------------------- + always @* + begin : residue_process + //N*2, N=length*32, *32 = shl5, *64 = shl6 + residue_nn = { 1'b0, modulus_length, 6'h0 }; + residue_length = modulus_length; + residue_opm_data = modulus_mem_int_rd_data; + end + + + //---------------------------------------------------------------- + // Detects if modulus has been updated and we need to + // recalculate the residue + // and we need residue is valid or not. + //---------------------------------------------------------------- + always @* + begin : residue_valid_process + residue_valid_new = residue_valid_reg; + + if (modulus_mem_api_cs & modulus_mem_api_wr) + residue_valid_new = 1'b0; + else if ( residue_valid_int_validated == 1'b1) + residue_valid_new = 1'b1; + end + + + //---------------------------------------------------------------- + // montprod_op_select + // + // Select operands used during montprod calculations depending + // on what operation we want to do. + //---------------------------------------------------------------- + always @* + begin : montprod_op_select + + montprod_length = modulus_length; + + result_mem_int_rd_addr = montprod_opa_addr; + message_mem_int_rd_addr = montprod_opa_addr; + p_mem_rd0_addr = montprod_opa_addr; + + residue_mem_montprod_read_addr = montprod_opb_addr; + p_mem_rd1_addr = montprod_opb_addr; + + montprod_opm_data = modulus_mem_int_rd_data; + case (montprod_select_reg) + MONTPROD_SELECT_ONE_NR: + begin + montprod_opa_data = one_reg; + montprod_opb_data = residue_mem_montprod_read_data; + end + + MONTPROD_SELECT_X_NR: + begin + montprod_opa_data = message_mem_int_rd_data; + montprod_opb_data = residue_mem_montprod_read_data; + end + + MONTPROD_SELECT_Z_P: + begin + montprod_opa_data = result_mem_int_rd_data; + montprod_opb_data = p_mem_rd1_data; + end + + MONTPROD_SELECT_P_P: + begin + montprod_opa_data = p_mem_rd0_data; + montprod_opb_data = p_mem_rd1_data; + end + + MONTPROD_SELECT_Z_ONE: + begin + montprod_opa_data = result_mem_int_rd_data; + montprod_opb_data = b_one_reg; + end + + default: + begin + montprod_opa_data = 32'h00000000; + montprod_opb_data = 32'h00000000; + end + endcase // case (montprod_selcect_reg) + end + + + //---------------------------------------------------------------- + // memory write mux + // + // Direct memory write signals to correct memory. + //---------------------------------------------------------------- + always @* + begin : memory_write_process + result_mem_int_wr_addr = montprod_result_addr; + result_mem_int_wr_data = montprod_result_data; + result_mem_int_we = 1'b0; + + p_mem_wr_addr = montprod_result_addr; + p_mem_wr_data = montprod_result_data; + p_mem_we = 1'b0; + + case (montprod_dest_reg) + MONTPROD_DEST_Z: + result_mem_int_we = montprod_result_we; + MONTPROD_DEST_P: + p_mem_we = montprod_result_we; + default: + begin + end + endcase + + // inhibit Z=Z*P when ei = 0 + if (modexp_ctrl_reg == CTRL_ITERATE_Z_P) + result_mem_int_we = result_mem_int_we & ei_reg; + end + + + //---------------------------------------------------------------- + // loop_counter + // + // Calculate the loop counter and related variables. + //---------------------------------------------------------------- + always @* + begin : loop_counters_process + loop_counter_new = 13'b0; + loop_counter_we = 1'b0; + + if (loop_counter_reg == {length_m1, 5'b11111}) + last_iteration = 1'b1; + else + last_iteration = 1'b0; + + case (modexp_ctrl_reg) + CTRL_CALCULATE_P0: + begin + loop_counter_new = 13'b0; + loop_counter_we = 1'b1; + end + + CTRL_ITERATE_END: + begin + loop_counter_new = loop_counter_reg + 1'b1; + loop_counter_we = 1'b1; + end + + default: + begin + end + endcase + end + + + //---------------------------------------------------------------- + // exponent + // + // Reads the exponent. + //---------------------------------------------------------------- + always @* + begin : exponent_process + // Accessing new instead of reg - pick up update at + // CTRL_ITERATE_NEW to remove a pipeline stall. + E_word_index = length_m1 - loop_counter_new[ 12 : 5 ]; + + E_bit_index = loop_counter_reg[ 04 : 0 ]; + + exponent_mem_int_rd_addr = E_word_index; + + ei_new = exponent_mem_int_rd_data[ E_bit_index ]; + + if (modexp_ctrl_reg == CTRL_ITERATE) + ei_we = 1'b1; + else + ei_we = 1'b0; + end + + + //---------------------------------------------------------------- + // modexp_ctrl + // + // Control FSM logic needed to perform the modexp operation. + //---------------------------------------------------------------- + always @* + begin + ready_new = 1'b0; + ready_we = 1'b0; + montprod_select_new = MONTPROD_SELECT_ONE_NR; + montprod_select_we = 0; + montprod_dest_new = MONTPROD_DEST_NOWHERE; + montprod_dest_we = 0; + montprod_calc = 0; + modexp_ctrl_new = CTRL_IDLE; + modexp_ctrl_we = 1'b0; + cycle_ctr_start = 1'b0; + cycle_ctr_stop = 1'b0; + + residue_calculate = 1'b0; + + residue_valid_int_validated = 1'b0; + + case (modexp_ctrl_reg) + CTRL_IDLE: + begin + if (start) + begin + ready_new = 1'b0; + ready_we = 1'b1; + cycle_ctr_start = 1'b1; + + if (residue_valid_reg) + begin + //residue has alrady been calculated, start with MONTPROD( 1, Nr, MODULUS ) + montprod_select_new = MONTPROD_SELECT_ONE_NR; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_Z; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_CALCULATE_Z0; + modexp_ctrl_we = 1; + end + else + begin + //modulus has been written and residue (Nr) must be calculated + modexp_ctrl_new = CTRL_RESIDUE; + modexp_ctrl_we = 1; + residue_calculate = 1'b1; + end + end + end + + CTRL_RESIDUE: + begin + if (residue_ready) + begin + montprod_select_new = MONTPROD_SELECT_ONE_NR; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_Z; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_CALCULATE_Z0; + modexp_ctrl_we = 1; + residue_valid_int_validated = 1'b1; //update registers telling residue is valid + end + end + + CTRL_CALCULATE_Z0: + begin + if (montprod_ready) + begin + montprod_select_new = MONTPROD_SELECT_X_NR; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_P; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_CALCULATE_P0; + modexp_ctrl_we = 1; + end + end + + CTRL_CALCULATE_P0: + begin + if (montprod_ready == 1'b1) + begin + modexp_ctrl_new = CTRL_ITERATE; + modexp_ctrl_we = 1; + end + end + + CTRL_ITERATE: + begin + montprod_select_new = MONTPROD_SELECT_Z_P; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_Z; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_ITERATE_Z_P; + modexp_ctrl_we = 1; + + if (ei_new == 1'b0 && exponation_mode_reg == EXPONATION_MODE_PUBLIC_FAST) + begin + //Skip the fake montgomery calculation, exponation_mode_reg optimizing for speed not blinding. + montprod_select_new = MONTPROD_SELECT_P_P; + montprod_dest_new = MONTPROD_DEST_P; + modexp_ctrl_new = CTRL_ITERATE_P_P; + end + end + + CTRL_ITERATE_Z_P: + if (montprod_ready) + begin + montprod_select_new = MONTPROD_SELECT_P_P; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_P; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_ITERATE_P_P; + modexp_ctrl_we = 1; + end + + CTRL_ITERATE_P_P: + if (montprod_ready == 1'b1) + begin + modexp_ctrl_new = CTRL_ITERATE_END; + modexp_ctrl_we = 1; + end + + CTRL_ITERATE_END: + begin + if (!last_iteration) + begin + modexp_ctrl_new = CTRL_ITERATE; + modexp_ctrl_we = 1; + end + else + begin + montprod_select_new = MONTPROD_SELECT_Z_ONE; + montprod_select_we = 1; + montprod_dest_new = MONTPROD_DEST_Z; + montprod_dest_we = 1; + montprod_calc = 1; + modexp_ctrl_new = CTRL_CALCULATE_ZN; + modexp_ctrl_we = 1; + end + end + + CTRL_CALCULATE_ZN: + begin + if (montprod_ready) + begin + modexp_ctrl_new = CTRL_DONE; + modexp_ctrl_we = 1; + end + end + + CTRL_DONE: + begin + cycle_ctr_stop = 1'b1; + ready_new = 1'b1; + ready_we = 1'b1; + modexp_ctrl_new = CTRL_IDLE; + modexp_ctrl_we = 1; + end + + default: + begin + end + + endcase // case (modexp_ctrl_reg) + end + +endmodule // modexp_core + +//====================================================================== +// EOF modexp_core.v +//====================================================================== -- cgit v1.2.3