Bug fix and timeout feature.

Removed memory map from top. Added timeout to secp256k1 in case logic
gets stuck.
This commit is contained in:
bsdevlin 2019-04-11 09:29:34 -04:00
parent daf7c65157
commit a9fd07b8f3
4 changed files with 45 additions and 111 deletions

View File

@ -41,7 +41,7 @@ package secp256k1_pkg;
parameter DO_AFFINE_CHECK = "NO"; // Setting this to YES will convert the final result back to affine coordinates to check signature
// Requires an inversion and so is slower than doing the check in jacobson coordinates
parameter USE_ENDOMORPH = "YES"; // Use the secp256k1 endomorphism to reduce the key bit size. Improves throughput by 2x but uses
parameter USE_ENDOMORPH = "NO"; // Use the secp256k1 endomorphism to reduce the key bit size. Improves throughput by 2x but uses
// more FPGA logic
// Use register map for debug, holds information on current operation
@ -66,7 +66,8 @@ package secp256k1_pkg;
} jb_point_t;
typedef struct packed {
logic [3:0] padding;
logic [2:0] padding;
logic TIMEOUT_FAIL;
logic FAILED_SIG_VER;
logic X_INFINITY_POINT;
logic OUT_OF_RANGE_S;

View File

@ -6,19 +6,13 @@ module secp256k1_top import secp256k1_pkg::*; #(
input i_rst,
// Command interface
if_axi_stream.sink if_cmd_rx,
if_axi_stream.source if_cmd_tx,
// Memory map interface for debug
if_axi_mm.sink if_axi_mm
if_axi_stream.source if_cmd_tx
);
localparam DAT_BYTS = 8;
localparam DAT_BITS = DAT_BYTS*8;
import zcash_fpga_pkg::*;
// Register map is used for storing command data
if_ram #(.RAM_WIDTH(64), .RAM_DEPTH(REGISTER_SIZE)) register_file_a (i_clk, i_rst);
if_ram #(.RAM_WIDTH(64), .RAM_DEPTH(REGISTER_SIZE)) register_file_b (i_clk, i_rst);
// 256 bit inverse calculation
if_axi_stream #(.DAT_BYTS(256/8)) bin_inv_in_if(i_clk);
if_axi_stream #(.DAT_BYTS(256/8)) bin_inv_out_if(i_clk);
@ -34,8 +28,8 @@ logic [255:0] pt_mult0_in_k, pt_mult1_in_k;
logic pt_mult0_in_val, pt_mult0_in_rdy, pt_mult0_out_rdy, pt_mult0_out_val, pt_mult0_out_err, pt_mult0_in_p2_val;
logic pt_mult1_in_val, pt_mult1_in_rdy, pt_mult1_out_rdy, pt_mult1_out_val, pt_mult1_out_err;
// Can avoid final inverstion converting from projected coord by some check in c++ code
// Global timeout in case we get stuck somewhere, we send a failed message back to host
logic [(USE_ENDOMORPH == "YES" ? 14 : 15):0] timeout;
// Controlling state machine
typedef enum {IDLE,
GET_INDEX,
@ -45,14 +39,13 @@ typedef enum {IDLE,
CALC_X,
CALC_X_AFFINE,
CHECK_IN_JB,
UPDATE_RAM_VARIABLES,
IGNORE,
FINISHED} secp256k1_state_t;
secp256k1_state_t secp256k1_state;
header_t header, header_l;
secp256k1_ver_t secp256k1_ver;
// Other temporary values - could use RAM insead?
// Other temporary values
logic [255:0] r, u2;
logic [63:0] index;
logic u2_val;
@ -61,7 +54,6 @@ localparam MAX_BYT_MSG = 64; // Max bytes in a reply message
logic [MAX_BYT_MSG*8 -1:0] msg;
logic [$clog2(MAX_BYT_MSG)-1:0] cnt; // Counter for parsing command inputs
logic if_axi_mm_rd;
logic [255:0] inv_p;
@ -76,7 +68,6 @@ always_ff @ (posedge i_clk) begin
if_cmd_tx.reset_source();
if_cmd_rx.rdy <= 0;
cnt <= 0;
register_file_a.reset_source();
r <= 0;
u2 <= 0;
u2_val <= 0;
@ -104,11 +95,10 @@ always_ff @ (posedge i_clk) begin
index <= 0;
timeout <= 0;
end else begin
register_file_a.en <= 1;
register_file_a.we <= 0;
register_file_a.re <= 1;
mult_out_if[2].rdy <= 1;
mult_in_if[2].sop <= 1;
mult_in_if[2].eop <= 1;
@ -134,6 +124,7 @@ always_ff @ (posedge i_clk) begin
case(secp256k1_state)
{IDLE}: begin
timeout <= 0;
inv_p <= secp256k1_pkg::n;
u2_val <= 0;
secp256k1_ver <= 0;
@ -148,9 +139,6 @@ always_ff @ (posedge i_clk) begin
if (if_cmd_rx.val && if_cmd_rx.rdy) begin
case(header.cmd)
{VERIFY_SECP256K1_SIG}: begin
register_file_a.we <= 1;
register_file_a.a <= CURR_CMD;
register_file_a.d <= header;
secp256k1_state <= GET_INDEX;
end
default: begin
@ -172,7 +160,6 @@ always_ff @ (posedge i_clk) begin
{VERIFY_SECP256K1_SIG_PARSE}: begin
if_cmd_rx.rdy <= 1;
if (if_cmd_rx.val && if_cmd_rx.rdy) begin
register_file_a.we <= 1;
cnt <= cnt + 1;
if (cnt == 19 && if_cmd_rx.val && if_cmd_rx.rdy) begin
secp256k1_state <= CALC_S_INV;
@ -182,8 +169,6 @@ always_ff @ (posedge i_clk) begin
case(cnt) inside
[0:3]: begin
register_file_a.a <= SIG_VER_S/8 + (cnt);
register_file_a.d <= if_cmd_rx.dat;
// Can start calculating the inverse here
bin_inv_in_if.dat[(cnt % 4)*64 +: 64] <= if_cmd_rx.dat;
if (cnt == 3 && if_cmd_rx.val && if_cmd_rx.rdy) begin
@ -191,25 +176,19 @@ always_ff @ (posedge i_clk) begin
end
end
[4:7]: begin
register_file_a.a <= SIG_VER_R/8 + (cnt - 4);
r[(cnt % 4)*64 +: 64] <= if_cmd_rx.dat; // TODO remove
register_file_a.d <= if_cmd_rx.dat;
r[(cnt % 4)*64 +: 64] <= if_cmd_rx.dat;
mult_in_if[2].dat[(cnt % 4)*64 +: 64] <= if_cmd_rx.dat;
end
[8:11]: begin
pt_mult0_in_k[(cnt % 4)*64 +: 64] <= if_cmd_rx.dat;
register_file_a.a <= SIG_VER_HASH/8 + (cnt - 8);
register_file_a.d <= if_cmd_rx.dat;
end
[12:19]: begin
register_file_a.a <= SIG_VER_Q/8 + (cnt - 12);
pt_mult0_in_p.z <= 1;
if ((cnt-12) < 4) begin
pt_mult0_in_p.x[(cnt % 4)*64 +: 64] <= if_cmd_rx.dat;
end else begin
pt_mult0_in_p.y[(cnt % 4)*64 +: 64] <= if_cmd_rx.dat;
end
register_file_a.d <= if_cmd_rx.dat;
end
endcase
end
@ -226,7 +205,6 @@ always_ff @ (posedge i_clk) begin
mult_in_if[2].val <= 1;
secp256k1_state <= CALC_U1_U2;
cnt <= 0;
// TODO also write this to RAM
// need to do 2 multiplications % n to get u1 and u2
end
end
@ -242,8 +220,6 @@ always_ff @ (posedge i_clk) begin
end
end
// Check for result
// TODO load into RAM
if (mult_out_if[2].val && mult_out_if[2].rdy) begin
case(cnt[2])
{1'd0}: begin
@ -267,22 +243,19 @@ always_ff @ (posedge i_clk) begin
{CALC_X}: begin
// Wait for u1.P to finish
if (pt_mult0_out_rdy && pt_mult0_out_val) begin
// TODO load equation into point ADD
pt_X0 <= pt_mult0_out_p;
pt_mult0_in_p <= pt_mult0_out_p;
cnt[0] <= 1;
end
// Wait for u2.Q to finish
if (pt_mult1_out_rdy && pt_mult1_out_val) begin
// TODO load equation into point ADD
pt_X1 <= pt_mult1_out_p; // TODO remove these
pt_X1 <= pt_mult1_out_p;
pt_mult0_in_p2 <= pt_mult1_out_p;
cnt[1] <= 1;
end
// Do the final point add
if (cnt[2:0] == 3'b011) begin
// TODO the final add /checks
pt_mult0_in_p2_val <= 1;
cnt[2:0] <= 3'b100;
end
@ -394,14 +367,8 @@ always_ff @ (posedge i_clk) begin
end
endcase
end
{UPDATE_RAM_VARIABLES}: begin
// Here we write all our calculated variables to RAM
end
{FINISHED}: begin
// TODO send message back
send_message($bits(verify_secp256k1_sig_rpl_t)/8);
// TODO also write result into RAM
end
{IGNORE}: begin
if_cmd_rx.rdy <= 1;
@ -410,47 +377,20 @@ always_ff @ (posedge i_clk) begin
end
endcase
// We use this to write to the RAM as results are valid
end
end
logic if_axi_mm_rd_;
always_comb begin
register_file_b.a = if_axi_mm.addr/8;
end
always_ff @ (posedge i_clk) begin
if (i_rst) begin
if_axi_mm.reset_sink();
register_file_b.en <= 1;
register_file_b.re <= 1;
register_file_b.we <= 0;
register_file_b.d <= 0;
if_axi_mm_rd_ <= 0;
// Something went wrong - send a message back to host
if (&timeout) begin
secp256k1_ver.TIMEOUT_FAIL <= 1;
end else begin
if_axi_mm_rd_ <= if_axi_mm_rd;
if_axi_mm.rd_dat_val <= 0;
register_file_b.en <= 1;
register_file_b.re <= 1;
if_axi_mm_rd <= if_axi_mm.rd;
if (if_axi_mm_rd_) begin
if_axi_mm.rd_dat_val <= 1;
if_axi_mm.rd_dat <= register_file_b.q;
timeout <= timeout + 1;
end
if (secp256k1_ver.TIMEOUT_FAIL && secp256k1_state != FINISHED) begin
cnt <= $bits(verify_secp256k1_sig_rpl_t)/8;
msg <= verify_secp256k1_sig_rpl(secp256k1_ver, index);
secp256k1_state <= FINISHED;
end
end
end
// BRAM for storing parsed inputs
bram #(
.RAM_WIDTH ( 64 ),
.RAM_DEPTH ( REGISTER_SIZE ),
.RAM_PERFORMANCE ( "HIGH_PERFORMANCE" )
) register_file (
.a ( register_file_a ),
.b ( register_file_b )
);
// Calculate binary inverse mod n
bin_inv #(

View File

@ -42,7 +42,6 @@ if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS)) equihash_axi(i_clk_core0);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS)) secp256k1_out_if(i_clk_core0);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS)) secp256k1_in_if(i_clk_core0);
if_axi_mm secp256k1_mm_if(i_clk_core0);
equihash_bm_t equihash_mask;
logic equihash_mask_val;
@ -109,15 +108,12 @@ equihash_verif_top (
// This block is the ECCDSA block for curve secp256k1
always_comb begin
secp256k1_mm_if.reset_source();
end
secp256k1_top secp256k1_top (
.i_clk ( i_clk_core0 ),
.i_rst ( rst_core0 || ENB_VERIFY_SECP256K1_SIG == 0 ),
.if_cmd_rx ( secp256k1_out_if ),
.if_cmd_tx ( secp256k1_in_if ),
.if_axi_mm ( secp256k1_mm_if )
.if_cmd_tx ( secp256k1_in_if )
);

View File

@ -28,7 +28,6 @@ logic clk, rst;
if_axi_stream #(.DAT_BYTS(8)) in_if(clk);
if_axi_stream #(.DAT_BYTS(8)) out_if(clk);
if_axi_mm mm_if(clk);
initial begin
rst = 0;
@ -51,8 +50,7 @@ secp256k1_top secp256k1_top (
.i_clk ( clk ),
.i_rst ( rst ),
.if_cmd_rx ( in_if ),
.if_cmd_tx ( out_if ),
.if_axi_mm ( mm_if )
.if_cmd_tx ( out_if )
);
// Test a point
@ -90,12 +88,6 @@ begin
fail |= (verify_secp256k1_sig_rpl.index != k);
assert (~fail) else $fatal(1, "%m %t ERROR: test failed :\n%p", $time, verify_secp256k1_sig_rpl);
// Also try reading some RAM values
mm_if.get_data(mm_data, SIG_VER_HASH);
fail |= mm_data != hash[0 +: 64];
assert (~fail) else $fatal(1, "%m %t ERROR: mm_if data read back wrong hash", $time);
$display("test #%d PASSED in %d clocks", integer'(k), (finish_time-start_time)/CLK_PERIOD);
end
endtask;
@ -104,9 +96,8 @@ endtask;
initial begin
out_if.rdy = 0;
in_if.val = 0;
mm_if.reset_source();
#(40*CLK_PERIOD);
/*
test(1, 256'h4c7dbc46486ad9569442d69b558db99a2612c4f003e6631b593942f531e67fd4, // message hash
256'h1375af664ef2b74079687956fd9042e4e547d57c4438f1fc439cbfcb4c9ba8b, // r
256'hde0f72e442f7b5e8e7d53274bf8f97f0674f4f63af582554dbecbb4aa9d5cbcb, // s
@ -118,6 +109,12 @@ initial begin
256'h6abcd5e40fcee8bca6b506228a2dcae67daa5d743e684c4d3fb1cb77e43b48fe, // s
256'hb661c143ffbbad5acfe16d427767cdc57fb2e4c019a4753ba68cd02c29e4a153, //Qx
256'h6e1fb00fdb9ddd39b55596bfb559bc395f220ae51e46dbe4e4df92d1a5599726); //Qy
*/
test(3, 256'h10, // message hash
256'h10, // r
256'h10, // s
256'hb661c143ffbbad5acfe16d427767cdc57fb2e4c019a4753ba68cd02c29e4a153, //Qx
256'h6e1fb00fdb9ddd39b55596bfb559bc395f220ae51e46dbe4e4df92d1a5599726); //Qy
#1us $finish();
end