//------------------------------------------------------------------------------ // // ecdsa256_base_point_multiplier.v // ----------------------------------------------------------------------------- // ECDSA base point scalar multiplier. // // Authors: Pavel Shatov // // Copyright (c) 2016, 2018 NORDUnet A/S // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // - Neither the name of the NORDUnet nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // //------------------------------------------------------------------------------ module ecdsa256_base_point_multiplier ( clk, rst_n, ena, rdy, k_addr, rxy_addr, rx_wren, ry_wren, k_din, rxy_dout ); // // Microcode Header // `include "ecdsa_uop.vh" // // Ports // input clk; // system clock input rst_n; // active-low async reset input ena; // enable input output rdy; // ready output output [ 2:0] k_addr; // output [ 2:0] rxy_addr; // output rx_wren; // output ry_wren; // input [31:0] k_din; // output [31:0] rxy_dout; // // // FSM // localparam [4:0] FSM_STATE_IDLE = 5'd00; localparam [4:0] FSM_STATE_PREPARE_TRIG = 5'd01; localparam [4:0] FSM_STATE_PREPARE_WAIT = 5'd02; localparam [4:0] FSM_STATE_CYCLE_DBL_TRIG = 5'd03; localparam [4:0] FSM_STATE_CYCLE_DBL_WAIT = 5'd04; localparam [4:0] FSM_STATE_CYCLE_ADD_TRIG = 5'd05; localparam [4:0] FSM_STATE_CYCLE_ADD_WAIT = 5'd06; localparam [4:0] FSM_STATE_CYCLE_ADD_EXTRA_TRIG = 5'd07; localparam [4:0] FSM_STATE_CYCLE_ADD_EXTRA_WAIT = 5'd08; localparam [4:0] FSM_STATE_AFTER_CYCLE_TRIG = 5'd09; localparam [4:0] FSM_STATE_AFTER_CYCLE_WAIT = 5'd10; localparam [4:0] FSM_STATE_INVERT_TRIG = 5'd11; localparam [4:0] FSM_STATE_INVERT_WAIT = 5'd12; localparam [4:0] FSM_STATE_CONVERT_TRIG = 5'd13; localparam [4:0] FSM_STATE_CONVERT_WAIT = 5'd14; localparam [4:0] FSM_STATE_CONVERT_EXTRA_TRIG = 5'd15; localparam [4:0] FSM_STATE_CONVERT_EXTRA_WAIT = 5'd16; localparam [4:0] FSM_STATE_DONE = 5'd17; reg [4:0] fsm_state = FSM_STATE_IDLE; reg [4:0] fsm_state_next; // // Round Counter // reg [7:0] bit_counter; wire [7:0] bit_counter_last = 8'hFF; // 255 wire [7:0] bit_counter_zero = 8'h00; // 0 wire [7:0] bit_counter_prev = (bit_counter > bit_counter_zero) ? bit_counter - 1'b1 : bit_counter_last; assign k_addr = bit_counter[7:5]; // // Worker Trigger Logic // reg worker_trig = 1'b0; wire worker_done; wire fsm_wait_done = !worker_trig && worker_done; always @(posedge clk or negedge rst_n) // if (rst_n == 1'b0) worker_trig <= 1'b0; else case (fsm_state) FSM_STATE_PREPARE_TRIG, FSM_STATE_CYCLE_DBL_TRIG, FSM_STATE_CYCLE_ADD_TRIG, FSM_STATE_CYCLE_ADD_EXTRA_TRIG, FSM_STATE_AFTER_CYCLE_TRIG, FSM_STATE_INVERT_TRIG, FSM_STATE_CONVERT_TRIG, FSM_STATE_CONVERT_EXTRA_TRIG: worker_trig <= 1'b1; default: worker_trig <= 1'b0; endcase // // Round Counter Increment Logic // always @(posedge clk) // case (fsm_state_next) FSM_STATE_PREPARE_TRIG: bit_counter <= bit_counter_last; FSM_STATE_AFTER_CYCLE_TRIG: bit_counter <= bit_counter_prev; endcase // // Final Cycle Detection Logic // wire [ 3: 0] fsm_state_after_cycle = (bit_counter == bit_counter_last) ? FSM_STATE_INVERT_TRIG : FSM_STATE_CYCLE_DBL_TRIG; // // K Latch // reg [31:0] k_din_shreg; wire [4:0] k_bit_index = bit_counter[4:0]; always @(posedge clk) // if (fsm_state_next == FSM_STATE_CYCLE_DBL_TRIG) // if (k_bit_index == 5'd31) k_din_shreg <= k_din; else k_din_shreg <= {k_din_shreg[30:0], ~k_din_shreg[31]}; // // Worker Flags // wire worker_flagz_sz; wire worker_flagz_rz; wire worker_flagz_e; wire worker_flagz_f; wire [2:0] worker_flagz_cycle_add = {worker_flagz_sz, worker_flagz_e, worker_flagz_f}; wire worker_flagz_convert_extra = worker_flagz_rz; // // Worker Offset Logic // reg [UOP_ADDR_WIDTH-1:0] worker_offset; always @(posedge clk) // case (fsm_state) FSM_STATE_PREPARE_TRIG: worker_offset <= UOP_OFFSET_PREPARE; FSM_STATE_CYCLE_DBL_TRIG: worker_offset <= UOP_OFFSET_CYCLE_DOUBLE; FSM_STATE_CYCLE_ADD_TRIG: worker_offset <= UOP_OFFSET_CYCLE_ADD; FSM_STATE_CYCLE_ADD_EXTRA_TRIG: // {sz, e, f} casez(worker_flagz_cycle_add) 3'b1??: worker_offset <= UOP_OFFSET_CYCLE_ADD_AT_INFINITY; 3'b011: worker_offset <= UOP_OFFSET_CYCLE_ADD_SAME_X_SAME_Y; 3'b010: worker_offset <= UOP_OFFSET_CYCLE_ADD_SAME_X; 3'b00?: worker_offset <= UOP_OFFSET_CYCLE_ADD_REGULAR; endcase FSM_STATE_AFTER_CYCLE_TRIG: worker_offset <= k_din_shreg[31] ? UOP_OFFSET_CYCLE_K1 : UOP_OFFSET_CYCLE_K0; FSM_STATE_INVERT_TRIG: worker_offset <= UOP_OFFSET_INVERT; FSM_STATE_CONVERT_TRIG: worker_offset <= UOP_OFFSET_CONVERT; FSM_STATE_CONVERT_EXTRA_TRIG: worker_offset <= worker_flagz_convert_extra ? UOP_OFFSET_CONVERT_AT_INFINITY : UOP_OFFSET_CONVERT_REGULAR; default: worker_offset <= {UOP_ADDR_WIDTH{1'bX}}; endcase // // FSM Process // always @(posedge clk or negedge rst_n) // if (rst_n == 1'b0) fsm_state <= FSM_STATE_IDLE; else fsm_state <= fsm_state_next; // // FSM Transition Logic // always @* begin // fsm_state_next = FSM_STATE_IDLE; // case (fsm_state) FSM_STATE_IDLE: fsm_state_next = ena ? FSM_STATE_PREPARE_TRIG : FSM_STATE_IDLE; FSM_STATE_PREPARE_TRIG: fsm_state_next = FSM_STATE_PREPARE_WAIT ; FSM_STATE_PREPARE_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_CYCLE_DBL_TRIG : FSM_STATE_PREPARE_WAIT; FSM_STATE_CYCLE_DBL_TRIG: fsm_state_next = FSM_STATE_CYCLE_DBL_WAIT ; FSM_STATE_CYCLE_DBL_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_CYCLE_ADD_TRIG : FSM_STATE_CYCLE_DBL_WAIT; FSM_STATE_CYCLE_ADD_TRIG: fsm_state_next = FSM_STATE_CYCLE_ADD_WAIT ; FSM_STATE_CYCLE_ADD_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_CYCLE_ADD_EXTRA_TRIG : FSM_STATE_CYCLE_ADD_WAIT; FSM_STATE_CYCLE_ADD_EXTRA_TRIG: fsm_state_next = FSM_STATE_CYCLE_ADD_EXTRA_WAIT ; FSM_STATE_CYCLE_ADD_EXTRA_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_AFTER_CYCLE_TRIG : FSM_STATE_CYCLE_ADD_EXTRA_WAIT; FSM_STATE_AFTER_CYCLE_TRIG: fsm_state_next = FSM_STATE_AFTER_CYCLE_WAIT ; FSM_STATE_AFTER_CYCLE_WAIT: fsm_state_next = fsm_wait_done ? fsm_state_after_cycle : FSM_STATE_AFTER_CYCLE_WAIT; FSM_STATE_INVERT_TRIG: fsm_state_next = FSM_STATE_INVERT_WAIT ; FSM_STATE_INVERT_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_CONVERT_TRIG : FSM_STATE_INVERT_WAIT; FSM_STATE_CONVERT_TRIG: fsm_state_next = FSM_STATE_CONVERT_WAIT ; FSM_STATE_CONVERT_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_CONVERT_EXTRA_TRIG : FSM_STATE_CONVERT_WAIT; FSM_STATE_CONVERT_EXTRA_TRIG: fsm_state_next = FSM_STATE_CONVERT_EXTRA_WAIT ; FSM_STATE_CONVERT_EXTRA_WAIT: fsm_state_next = fsm_wait_done ? FSM_STATE_DONE : FSM_STATE_CONVERT_EXTRA_WAIT; FSM_STATE_DONE: fsm_state_next = FSM_STATE_IDLE ; endcase // end // // Worker // wire worker_output_now = (fsm_state == FSM_STATE_CONVERT_EXTRA_WAIT); ecdsa256_uop_worker uop_worker ( .clk (clk), .rst_n (rst_n), .ena (worker_trig), .rdy (worker_done), .uop_offset (worker_offset), .output_now (worker_output_now), .flagz_sz (worker_flagz_sz), .flagz_rz (worker_flagz_rz), .flagz_e (worker_flagz_e), .flagz_f (worker_flagz_f), .xy_addr (rxy_addr), .xy_dout (rxy_dout), .x_wren (rx_wren), .y_wren (ry_wren) ); // // Ready Flag Logic // reg rdy_reg = 1'b1; assign rdy = rdy_reg; always @(posedge clk or negedge rst_n) // if (rst_n == 1'b0) rdy_reg <= 1'b1; else case (fsm_state) FSM_STATE_IDLE: if (ena) rdy_reg <= 1'b0; FSM_STATE_DONE: rdy_reg <= 1'b1; endcase endmodule //------------------------------------------------------------------------------ // End-of-File //------------------------------------------------------------------------------