diff --git a/ip_cores/common/src/rtl/common_if.sv b/ip_cores/common/src/rtl/common_if.sv index 18528f9..62298a9 100644 --- a/ip_cores/common/src/rtl/common_if.sv +++ b/ip_cores/common/src/rtl/common_if.sv @@ -130,10 +130,10 @@ interface if_axi_stream # ( logic sop_l = 0; logic done = 0; logic rdy_l; - rdy = ($urandom % 100) >= bp; len = 0; data = 0; rdy_l = rdy; + rdy = ($urandom % 100) >= bp; @(posedge i_clk); while (1) begin diff --git a/zcash_fpga/src/rtl/secp256k1/secp256k1_pkg.sv b/zcash_fpga/src/rtl/secp256k1/secp256k1_pkg.sv index 881ff77..f196bf6 100644 --- a/zcash_fpga/src/rtl/secp256k1/secp256k1_pkg.sv +++ b/zcash_fpga/src/rtl/secp256k1/secp256k1_pkg.sv @@ -39,6 +39,11 @@ package secp256k1_pkg; parameter [255:0] p_eq = (1 << 256) - (1 << 32) - (1 << 9) - (1 << 8) - (1 << 7) - (1 << 6) - (1 << 4) - 1; + 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 + // more FPGA logic + // Use register map for debug, holds information on current operation parameter REGISTER_SIZE = 64; // The mapping to index diff --git a/zcash_fpga/src/rtl/secp256k1/secp256k1_point_mult_endo.sv b/zcash_fpga/src/rtl/secp256k1/secp256k1_point_mult_endo.sv index 9caec18..ac7cb1b 100644 --- a/zcash_fpga/src/rtl/secp256k1/secp256k1_point_mult_endo.sv +++ b/zcash_fpga/src/rtl/secp256k1/secp256k1_point_mult_endo.sv @@ -156,16 +156,16 @@ always_ff @ (posedge i_clk) begin if (o_val1 && o_val2) begin i_rdy1 <= 1; i_rdy2 <= 1; - p2_k1 <= p_o1; - p_k1 <= p_o2; + p_k1 <= p_o1; + p2_k1 <= p_o2; p2_k1_val <= 1; state <= COMBINE_K_PROD; i_rdy_decom <= 1; - if (k2_decom[255]) begin - p_k1.y <= secp256k1_pkg::p_eq - p_o2.y; - end if (k1_decom[255]) begin - p2_k1.y <= secp256k1_pkg::p_eq - p_o1.y; + p_k1.y <= secp256k1_pkg::p_eq - p_o1.y; + end + if (k2_decom[255]) begin + p2_k1.y <= secp256k1_pkg::p_eq - p_o2.y; end end diff --git a/zcash_fpga/src/rtl/secp256k1/secp256k1_top.sv b/zcash_fpga/src/rtl/secp256k1/secp256k1_top.sv index 95882c7..dd0f85a 100644 --- a/zcash_fpga/src/rtl/secp256k1/secp256k1_top.sv +++ b/zcash_fpga/src/rtl/secp256k1/secp256k1_top.sv @@ -1,8 +1,6 @@ -module secp256k1_top #( - parameter DAT_BYTS = 8, - parameter DAT_BITS = DAT_BYTS*8, - parameter DO_AFFINE_CHECK = 0, - parameter USE_ENDOMORPH = 0 +module secp256k1_top import secp256k1_pkg::*; #( + parameter DO_AFFINE_CHECK = secp256k1_pkg::DO_AFFINE_CHECK, + parameter USE_ENDOMORPH = secp256k1_pkg::USE_ENDOMORPH )( input i_clk, input i_rst, @@ -13,7 +11,8 @@ module secp256k1_top #( if_axi_mm.sink if_axi_mm ); -import secp256k1_pkg::*; +localparam DAT_BYTS = 8; +localparam DAT_BITS = DAT_BYTS*8; import zcash_fpga_pkg::*; // Register map is used for storing command data @@ -296,7 +295,7 @@ always_ff @ (posedge i_clk) begin cnt <= 0; // Just store our value temp pt_mult0_in_p2 <= pt_mult0_out_p; - if (DO_AFFINE_CHECK) begin + if (DO_AFFINE_CHECK == "YES") begin secp256k1_state <= CALC_X_AFFINE; mult_in_if[2].val <= 1; mult_in_if[2].dat <= {pt_mult0_out_p.z, pt_mult0_out_p.z}; @@ -469,8 +468,6 @@ bin_inv ( .i_rdy ( bin_inv_out_if.rdy ) ); - -localparam RESOURCE_SHARE = "YES"; localparam ARB_BIT = 12; localparam MULT_CTL_BIT = 6; // 2 bits @@ -588,50 +585,91 @@ always_comb begin mult_out_if[3].mod = 0; end -secp256k1_point_mult #( - .RESOURCE_SHARE ( RESOURCE_SHARE ) -) -secp256k1_point_mult0 ( - .i_clk ( i_clk ), - .i_rst ( i_rst ), - .i_p ( pt_mult0_in_p ), - .i_k ( pt_mult0_in_k ), - .i_val ( pt_mult0_in_val ), - .o_rdy ( pt_mult0_in_rdy ), - .o_p ( pt_mult0_out_p ), - .i_rdy ( pt_mult0_out_rdy ), - .o_val ( pt_mult0_out_val ), - .o_err ( pt_mult0_out_err ), - .o_mult_if ( mult_in_if[0] ), - .i_mult_if ( mult_out_if[0] ), - .o_mod_if ( mod_in_if[0] ), - .i_mod_if ( mod_out_if[0] ), - .i_p2 ( pt_mult0_in_p2 ), - .i_p2_val ( pt_mult0_in_p2_val ) -); - -secp256k1_point_mult #( - .RESOURCE_SHARE ( RESOURCE_SHARE ) -) -secp256k1_point_mult1 ( - .i_clk ( i_clk ), - .i_rst ( i_rst ), - .i_p ( pt_mult1_in_p ), - .i_k ( pt_mult1_in_k ), - .i_val ( pt_mult1_in_val ), - .o_rdy ( pt_mult1_in_rdy ), - .o_p ( pt_mult1_out_p ), - .i_rdy ( pt_mult1_out_rdy ), - .o_val ( pt_mult1_out_val ), - .o_err ( pt_mult1_out_err ), - .o_mult_if ( mult_in_if[1] ), - .i_mult_if ( mult_out_if[1] ), - .o_mod_if ( mod_in_if[1] ), - .i_mod_if ( mod_out_if[1] ), - .i_p2 ( '0 ), - .i_p2_val ( 1'b0 ) -); +generate if (USE_ENDOMORPH == "NO") begin + secp256k1_point_mult #( + .RESOURCE_SHARE ( "YES" ) + ) + secp256k1_point_mult0 ( + .i_clk ( i_clk ), + .i_rst ( i_rst ), + .i_p ( pt_mult0_in_p ), + .i_k ( pt_mult0_in_k ), + .i_val ( pt_mult0_in_val ), + .o_rdy ( pt_mult0_in_rdy ), + .o_p ( pt_mult0_out_p ), + .i_rdy ( pt_mult0_out_rdy ), + .o_val ( pt_mult0_out_val ), + .o_err ( pt_mult0_out_err ), + .o_mult_if ( mult_in_if[0] ), + .i_mult_if ( mult_out_if[0] ), + .o_mod_if ( mod_in_if[0] ), + .i_mod_if ( mod_out_if[0] ), + .i_p2 ( pt_mult0_in_p2 ), + .i_p2_val ( pt_mult0_in_p2_val ) + ); + + secp256k1_point_mult #( + .RESOURCE_SHARE ( "YES" ) + ) + secp256k1_point_mult1 ( + .i_clk ( i_clk ), + .i_rst ( i_rst ), + .i_p ( pt_mult1_in_p ), + .i_k ( pt_mult1_in_k ), + .i_val ( pt_mult1_in_val ), + .o_rdy ( pt_mult1_in_rdy ), + .o_p ( pt_mult1_out_p ), + .i_rdy ( pt_mult1_out_rdy ), + .o_val ( pt_mult1_out_val ), + .o_err ( pt_mult1_out_err ), + .o_mult_if ( mult_in_if[1] ), + .i_mult_if ( mult_out_if[1] ), + .o_mod_if ( mod_in_if[1] ), + .i_mod_if ( mod_out_if[1] ), + .i_p2 ( '0 ), + .i_p2_val ( 1'b0 ) + ); +end else begin + secp256k1_point_mult_endo + secp256k1_point_mult_endo0 ( + .i_clk ( i_clk ), + .i_rst ( i_rst ), + .i_p ( pt_mult0_in_p ), + .i_k ( pt_mult0_in_k ), + .i_val ( pt_mult0_in_val ), + .o_rdy ( pt_mult0_in_rdy ), + .o_p ( pt_mult0_out_p ), + .i_rdy ( pt_mult0_out_rdy ), + .o_val ( pt_mult0_out_val ), + .o_err ( pt_mult0_out_err ), + .o_mult_if ( mult_in_if[0] ), + .i_mult_if ( mult_out_if[0] ), + .o_mod_if ( mod_in_if[0] ), + .i_mod_if ( mod_out_if[0] ), + .i_p2 ( pt_mult0_in_p2 ), + .i_p2_val ( pt_mult0_in_p2_val ) + ); + secp256k1_point_mult_endo + secp256k1_point_mult_endo1 ( + .i_clk ( i_clk ), + .i_rst ( i_rst ), + .i_p ( pt_mult1_in_p ), + .i_k ( pt_mult1_in_k ), + .i_val ( pt_mult1_in_val ), + .o_rdy ( pt_mult1_in_rdy ), + .o_p ( pt_mult1_out_p ), + .i_rdy ( pt_mult1_out_rdy ), + .o_val ( pt_mult1_out_val ), + .o_err ( pt_mult1_out_err ), + .o_mult_if ( mult_in_if[1] ), + .i_mult_if ( mult_out_if[1] ), + .o_mod_if ( mod_in_if[1] ), + .i_mod_if ( mod_out_if[1] ), + .i_p2 ( '0 ), + .i_p2_val ( 1'b0 ) + ); +end endgenerate // Task to help build reply messages. Assume no message will be more than MAX_BYT_MSG bytes task send_message(input logic [$clog2(MAX_BYT_MSG)-1:0] msg_size); if (~if_cmd_tx.val || (if_cmd_tx.rdy && if_cmd_tx.val)) begin diff --git a/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv b/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv index ce6d960..8cafcaa 100644 --- a/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv +++ b/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv @@ -29,7 +29,7 @@ package zcash_fpga_pkg; // What features are enabled in this build parameter bit ENB_VERIFY_SECP256K1_SIG = 1; - parameter bit ENB_VERIFY_EQUIHASH = 1; + parameter bit ENB_VERIFY_EQUIHASH = 0; localparam [63:0] FPGA_CMD_CAP = {{61'd0}, ENB_VERIFY_SECP256K1_SIG, diff --git a/zcash_fpga/src/tb/secp256k1_mult_mod_tb.sv b/zcash_fpga/src/tb/secp256k1_mult_mod_tb.sv index 95f280f..f04587d 100644 --- a/zcash_fpga/src/tb/secp256k1_mult_mod_tb.sv +++ b/zcash_fpga/src/tb/secp256k1_mult_mod_tb.sv @@ -24,7 +24,7 @@ localparam CLK_PERIOD = 100; logic clk, rst; -if_axi_stream #(.DAT_BYTS(512/8), .CTL_BITS(1)) in_if(clk); +if_axi_stream #(.DAT_BYTS(512/8), .CTL_BITS(2)) in_if(clk); if_axi_stream #(.DAT_BYTS(256/8)) out_if(clk); initial begin @@ -55,7 +55,7 @@ secp256k1_mult_mod secp256k1_mult_mod ( .i_cmd( in_if.ctl ), .i_ctl ( 8'd0 ), .i_dat_a( in_if.dat[0 +: 256] ), - .i_dat_b( in_if.dat[256 +: 256] ), + .i_dat_b( in_if.dat[256 +: 256] ), .i_val( in_if.val ), .i_err( in_if.err ), .o_rdy( in_if.rdy ), @@ -71,46 +71,70 @@ begin logic [common_pkg::MAX_SIM_BYTS*8-1:0] expected, get_dat; logic [255:0] in_a, in_b; integer i, max; - logic type_ctl; - + logic [1:0] type_ctl; + $display("Running test_loop..."); i = 0; max = 10000; - + while (i < max) begin - type_ctl = $random; + type_ctl = $urandom % 3; in_a = random_vector(256/8) % (type_ctl == 0 ? p_eq : secp256k1_pkg::n); in_b = random_vector(256/8) % (type_ctl== 0 ? p_eq : secp256k1_pkg::n); - expected = (in_a * in_b) % (type_ctl == 0 ? p_eq : secp256k1_pkg::n); + expected = (in_a * in_b); + case (type_ctl) + 0: begin + expected = expected % p_eq; + end + 1: begin + expected = expected % secp256k1_pkg::n; + end + 2: begin + expected = expected >> 256; + expected = expected % p_eq; + end + endcase fork in_if.put_stream({in_b, in_a}, 512/8, type_ctl); - out_if.get_stream(get_dat, get_len, 0); + out_if.get_stream(get_dat, get_len, 50); join - + common_pkg::compare_and_print(get_dat, expected); $display("test_loop PASSED loop %d/%d", i, max); i = i + 1; end - + $display("test_loop PASSED"); end endtask; task test_pipeline(); begin - logic type_cmd [10]; + logic [1:0] type_cmd [10]; logic [255:0] in_a [10]; logic [255:0] in_b [10]; logic [511:0] expected [10]; integer max = 10; $display("Running test_pipeline..."); for(int i = 0; i < 10; i++) begin - type_cmd[i] = $random; - in_a[i] = random_vector(256/8) % (type_cmd[i] == 0 ? p_eq : secp256k1_pkg::n); - in_b[i] = random_vector(256/8) % (type_cmd[i]== 0 ? p_eq : secp256k1_pkg::n); - expected[i] = (in_a[i] * in_b[i]) % (type_cmd[i] == 0 ? p_eq : secp256k1_pkg::n); + type_cmd[i] = $urandom % 3; + in_a[i] = random_vector(256/8) % ((type_cmd[i] == 2'd0 || type_cmd[i] == 2'd2) ? p_eq : secp256k1_pkg::n); + in_b[i] = random_vector(256/8) % ((type_cmd[i] == 2'd0 || type_cmd[i] == 2'd2) ? p_eq : secp256k1_pkg::n); + expected[i] = (in_a[i] * in_b[i]); + case (type_cmd[i]) + 0: begin + expected[i] = expected[i] % p_eq; + end + 1: begin + expected[i] = expected[i] % secp256k1_pkg::n; + end + 2: begin + expected[i] = expected[i] >> 256; + expected[i] = expected[i] % p_eq; + end + endcase end - + fork begin for(int i = 0; i < max; i++) begin @@ -129,12 +153,12 @@ begin integer signed get_len; logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; for(int i = 0; i < max; i++) begin - out_if.get_stream(get_dat, get_len); + out_if.get_stream(get_dat, get_len, 50); common_pkg::compare_and_print(get_dat, expected[i]); $display("test_pipeline PASSED loop %d/%d", i, max); end end - join + join $display("test_pipeline PASSED"); end @@ -144,7 +168,7 @@ initial begin out_if.rdy = 0; in_if.reset_source(); #(40*CLK_PERIOD); - + test_pipeline(); test_loop(); diff --git a/zcash_fpga/src/tb/secp256k1_point_add_tb.sv b/zcash_fpga/src/tb/secp256k1_point_add_tb.sv index 28f013a..bbdbf37 100644 --- a/zcash_fpga/src/tb/secp256k1_point_add_tb.sv +++ b/zcash_fpga/src/tb/secp256k1_point_add_tb.sv @@ -27,18 +27,18 @@ logic clk, rst; if_axi_stream #(.DAT_BYTS(256*6/8)) in_if(clk); // Two points if_axi_stream #(.DAT_BYTS(256*3/8)) out_if(clk); -if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(8)) mult_in_if(clk); -if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(8)) mult_out_if(clk); +if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(16)) mult_in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(16)) mult_out_if(clk); -if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(8)) mod_in_if(clk); -if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(8)) mod_out_if(clk); +if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(16)) mod_in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(16)) mod_out_if(clk); jb_point_t in_p1, in_p2, out_p; always_comb begin - in_p1 = in_if.dat[0 +: 256*3]; - in_p2 = in_if.dat[256*3 +: 256*3]; + in_p1 = in_if.dat[0 +: 256*3]; + in_p2 = in_if.dat[256*3 +: 256*3]; out_if.dat = out_p; end @@ -82,10 +82,22 @@ secp256k1_point_add secp256k1_point_add( .i_mod_if ( mod_out_if ) ); +always_comb begin + mult_out_if.sop = 1; + mult_out_if.eop = 1; + mult_out_if.err = 1; + mult_out_if.mod = 1; + + mod_out_if.sop = 1; + mod_out_if.eop = 1; + mod_out_if.err = 1; + mod_out_if.mod = 1; +end + // Attach a mod reduction unit and multiply - mod unit // In full design these could use dedicated multipliers or be arbitrated secp256k1_mult_mod #( - .CTL_BITS ( 8 ) + .CTL_BITS ( 16 ) ) secp256k1_mult_mod ( .i_clk ( clk ), @@ -95,17 +107,18 @@ secp256k1_mult_mod ( .i_val ( mult_in_if.val ), .i_err ( mult_in_if.err ), .i_ctl ( mult_in_if.ctl ), + .i_cmd ( 2'd0 ), .o_rdy ( mult_in_if.rdy ), .o_dat ( mult_out_if.dat ), .i_rdy ( mult_out_if.rdy ), .o_val ( mult_out_if.val ), .o_ctl ( mult_out_if.ctl ), - .o_err ( mult_out_if.err ) + .o_err ( mult_out_if.err ) ); secp256k1_mod #( .USE_MULT ( 0 ), - .CTL_BITS ( 8 ) + .CTL_BITS ( 16 ) ) secp256k1_mod ( .i_clk( clk ), @@ -122,65 +135,78 @@ secp256k1_mod ( .o_val( mod_out_if.val ) ); -task test_0(); +task test(input integer index, input jb_point_t p1, p2); begin integer signed get_len; logic [common_pkg::MAX_SIM_BYTS*8-1:0] expected, get_dat; logic [255:0] in_a, in_b; - jb_point_t p1, p2, p_exp, p_temp, p_out; - $display("Running test_0..."); - - //p1 = {x:3, y:4, z:1}; - // p2 = {x:1, y:2, z:1}; - - /*p1 = {x:256'h79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, - y:256'h483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, - z:256'h0000000000000000000000000000000000000000000000000000000000000001}; - p2 = {x:256'h7d152c041ea8e1dc2191843d1fa9db55b68f88fef695e2c791d40444b365afc2, - y:256'h56915849f52cc8f76f5fd7e4bf60db4a43bf633e1b1383f85fe89164bfadcbdb, - z:256'h9075b4ee4d4788cabb49f7f81c221151fa2f68914d0aa833388fa11ff621a970}; - */ - p1 = {x:256'h79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, - y:256'h483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, - z:256'h1}; - p2 = {x:256'h7d152c041ea8e1dc2191843d1fa9db55b68f88fef695e2c791d40444b365afc2, - y:256'h56915849f52cc8f76f5fd7e4bf60db4a43bf633e1b1383f85fe89164bfadcbdb, - z:256'h9075b4ee4d4788cabb49f7f81c221151fa2f68914d0aa833388fa11ff621a970}; - - + jb_point_t p_exp, p_temp, p_out; + $display("Running test %d ...", index); + p_exp = add_jb_point(p1, p2); - + fork in_if.put_stream({p2, p1}, 256*6/8); out_if.get_stream(get_dat, get_len); join - + p_out = get_dat; - + $display("%d %d %d", on_curve(p1), on_curve(p2), on_curve(p_out));//, on_curve(p_temp)); - + if (p_exp != p_out) begin $display("Expected:"); print_jb_point(p_exp); $display("Was:"); print_jb_point(p_out); $fatal(1, "%m %t ERROR: test_0 point was wrong", $time); - end - - $display("test_0 PASSED"); + end + + $display("test %d PASSED", index); end endtask; function compare_point(); - + endfunction initial begin out_if.rdy = 0; in_if.val = 0; #(40*CLK_PERIOD); - - test_0(); + + test(0, + {x:256'h2475abeb8f0fc52f627afb4c18227dfa756706ceb5923cd8a209bf43c2f08815, + y:256'h4361473bccf308998bbb8c0b9a0184d186ada6e85e1cb1b82ac202380df8f762, + z:256'hdda493ffbcdc8daf0996a769bf192cc4627839d0025b4ad960c3e25dab464863}, + {x:256'h4a58b6edef1379306fce3372763fd87eaf2c8f447c6408416e746e672ee6ce21, + y:256'h33adac20db34d12166586c56aa8a352b155bcfdd011f46b38c21e0c4d39968a4, + z:256'h8631df8718bcb2d2920dfd313c714a153cfc6db607891e341b0856411717cf4f}); + + test(1, + {x:256'd21093662951128507222548537960537987883266099219826518477955151519492458533937, + y:256'd11718937855299224635656538406325081070585145153119064354000306947171340794663, + z:256'd95062982235784117998228889817699378193266444799407382177811223706903593950986}, + {x:256'd56542328592951707446199365077593875570107826996267232506335199217850131398833, + y:256'd40054381197676821721097330834174068128555866625836435038947476656223470027610, + z:256'd55019374069926147245812105698770268552109628033761289528651825525953166671152} + ); + + test(2,{x:256'd56542328592951707446199365077593875570107826996267232506335199217850131398833, + y:256'd40054381197676821721097330834174068128555866625836435038947476656223470027610, + z:256'd55019374069926147245812105698770268552109628033761289528651825525953166671152}, + {x:256'd21093662951128507222548537960537987883266099219826518477955151519492458533937, + y:256'd11718937855299224635656538406325081070585145153119064354000306947171340794663, + z:256'd95062982235784117998228889817699378193266444799407382177811223706903593950986} + ); + + test(3, + {x:256'h79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, + y:256'h483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, + z:256'h1}, + {x:256'h7d152c041ea8e1dc2191843d1fa9db55b68f88fef695e2c791d40444b365afc2, + y:256'h56915849f52cc8f76f5fd7e4bf60db4a43bf633e1b1383f85fe89164bfadcbdb, + z:256'h9075b4ee4d4788cabb49f7f81c221151fa2f68914d0aa833388fa11ff621a970}); #1us $finish(); end diff --git a/zcash_fpga/src/tb/secp256k1_point_mult_endo_decom_tb.sv b/zcash_fpga/src/tb/secp256k1_point_mult_endo_decom_tb.sv new file mode 100644 index 0000000..491b190 --- /dev/null +++ b/zcash_fpga/src/tb/secp256k1_point_mult_endo_decom_tb.sv @@ -0,0 +1,170 @@ +/* + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +`timescale 1ps/1ps + +module secp256k1_point_mult_endo_decom_tb (); +import common_pkg::*; +import secp256k1_pkg::*; + +localparam CLK_PERIOD = 1000; + +logic clk, rst; + +if_axi_stream #(.DAT_BYTS(256*3/8)) in_if(clk); +if_axi_stream #(.DAT_BYTS((256*2+256*3)/8)) out_if(clk); + +if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(16)) mult_in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(16)) mult_out_if(clk); + + +jb_point_t in_p, out_p; +logic [255:0] k_in; +logic signed [255:0] k1_out, k2_out; + +always_comb begin + in_p = in_if.dat; + out_if.dat = {k2_out, k1_out, out_p}; +end + +initial begin + rst = 0; + repeat(2) #(20*CLK_PERIOD) rst = ~rst; +end + +initial begin + clk = 0; + forever #(CLK_PERIOD/2) clk = ~clk; +end + +always_comb begin + out_if.sop = 1; + out_if.eop = 1; + out_if.ctl = 0; + out_if.mod = 0; +end + +// Check for errors +always_ff @ (posedge clk) + if (out_if.val && out_if.err) begin + out_if.rdy = 1; + $error(1, "%m %t ERROR: output .err asserted", $time); + end + +always_comb begin + mult_out_if.sop = 1; + mult_out_if.eop = 1; + mult_out_if.mod = 0; +end + + +secp256k1_point_mult_endo_decom secp256k1_point_mult_endo_decom ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_p ( in_if.dat ), + .i_k ( k_in ), + .i_val ( in_if.val ), + .o_rdy ( in_if.rdy ), + .o_p ( out_p ), + .i_rdy ( out_if.rdy ), + .o_val ( out_if.val ), + .o_err ( out_if.err ), + .o_k1 ( k1_out ), + .o_k2 ( k2_out ), + .o_mult_if ( mult_in_if ), + .i_mult_if ( mult_out_if ) +); + +secp256k1_mult_mod #( + .CTL_BITS ( 16 ) +) +secp256k1_mult_mod ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_dat_a ( mult_in_if.dat[0 +: 256] ), + .i_dat_b ( mult_in_if.dat[256 +: 256] ), + .i_val ( mult_in_if.val ), + .i_err ( mult_in_if.err ), + .i_ctl ( mult_in_if.ctl ), + .i_cmd ( mult_in_if.ctl[7:6] ), + .o_rdy ( mult_in_if.rdy ), + .o_dat ( mult_out_if.dat ), + .i_rdy ( mult_out_if.rdy ), + .o_val ( mult_out_if.val ), + .o_ctl ( mult_out_if.ctl ), + .o_err ( mult_out_if.err ) +); + +// Test a point +task test(input integer index, input logic [255:0] k, jb_point_t p_exp, p_in, logic signed [255:0] k1_exp, k2_exp); +begin + integer signed get_len; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; + integer start_time, finish_time; + jb_point_t p_out; + logic signed [255:0] k1, k2; + $display("Running test %d...", index); + k_in = k; + start_time = $time; + fork + in_if.put_stream(p_in, 256*3/8); + out_if.get_stream(get_dat, get_len, 0); + join + finish_time = $time; + + p_out = get_dat[3*256-1:0]; + k1 = get_dat[3*256 +: 256]; + k2 = get_dat[4*256 +: 256]; + + if (p_exp != p_out || k1 != k1_exp || k2 != k2_exp) begin + $display("Expected:"); + print_jb_point(p_exp); + $display("k1 %h k2 %h", k1_exp, k2_exp); + $display("Was:"); + print_jb_point(p_out); + $display("k1 %h k2 %h", k1, k2); + $fatal(1, "%m %t ERROR: test %d was wrong", $time, index); + end + + $display("test %d PASSED in %d clocks", index, (finish_time-start_time)/CLK_PERIOD); +end +endtask; + + +initial begin + out_if.rdy = 0; + in_if.val = 0; + #(40*CLK_PERIOD); + +test (0, + 256'd55241786844846723798409522554861295376012334658573106804016642051374977891741, + {x:256'd85340279321737800624759429340272274763154997815782306132637707972559913914315, + y:256'd32670510020758816978083085130507043184471273380659243275938904335757337482424, z:256'd1}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'd1}, + 256'd384458048086738728616354309893792094261, + 256'd5290804493113523428570938576690193618); + +test (1, + 256'd529517403483370943333515471837290126144817603611185636669178179344924684232, + {x:256'd85340279321737800624759429340272274763154997815782306132637707972559913914315, + y:256'd32670510020758816978083085130507043184471273380659243275938904335757337482424, z:256'd1}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'd1}, + 256'd220390740267097681469989715867489183793, + -256'd233066591111900161328361760514744826974); + + #1us $finish(); +end +endmodule \ No newline at end of file diff --git a/zcash_fpga/src/tb/secp256k1_point_mult_endo_tb.sv b/zcash_fpga/src/tb/secp256k1_point_mult_endo_tb.sv new file mode 100644 index 0000000..217f30e --- /dev/null +++ b/zcash_fpga/src/tb/secp256k1_point_mult_endo_tb.sv @@ -0,0 +1,186 @@ +/* + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +`timescale 1ps/1ps + +module secp256k1_point_mult_endo_tb (); +import common_pkg::*; +import secp256k1_pkg::*; + +localparam CLK_PERIOD = 1000; + +logic clk, rst; + +if_axi_stream #(.DAT_BYTS(256*3/8)) in_if(clk); +if_axi_stream #(.DAT_BYTS(256*3/8)) out_if(clk); + +if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(16)) mult_in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(16)) mult_out_if(clk); + +if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(16)) mod_in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(16)) mod_out_if(clk); + +logic [255:0] k_in; + + +initial begin + rst = 0; + repeat(2) #(20*CLK_PERIOD) rst = ~rst; +end + +initial begin + clk = 0; + forever #(CLK_PERIOD/2) clk = ~clk; +end + +always_comb begin + out_if.sop = 1; + out_if.eop = 1; + out_if.ctl = 0; + out_if.mod = 0; +end + +// Check for errors +always_ff @ (posedge clk) + if (out_if.val && out_if.err) begin + out_if.rdy = 1; + $error(1, "%m %t ERROR: output .err asserted", $time); + end + +always_comb begin + mult_out_if.sop = 1; + mult_out_if.eop = 1; + mult_out_if.mod = 0; + mod_out_if.sop = 1; + mod_out_if.eop = 1; + mod_out_if.mod = 0; +end + + secp256k1_point_mult_endo secp256k1_point_mult_endo ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_p ( in_if.dat ), + .i_k ( k_in ), + .i_val ( in_if.val ), + .o_rdy ( in_if.rdy ), + .o_p ( out_if.dat ), + .i_rdy ( out_if.rdy ), + .o_val ( out_if.val ), + .o_err ( out_if.err ), + .o_mult_if ( mult_in_if ), + .i_mult_if ( mult_out_if ), + .o_mod_if ( mod_in_if ), + .i_mod_if ( mod_out_if ), + .i_p2_val (0), + .i_p2 (0 ) + ); + +secp256k1_mult_mod #( + .CTL_BITS ( 16 ) +) +secp256k1_mult_mod ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_dat_a ( mult_in_if.dat[0 +: 256] ), + .i_dat_b ( mult_in_if.dat[256 +: 256] ), + .i_val ( mult_in_if.val ), + .i_err ( mult_in_if.err ), + .i_ctl ( mult_in_if.ctl ), + .i_cmd ( mult_in_if.ctl[7:6] ), + .o_rdy ( mult_in_if.rdy ), + .o_dat ( mult_out_if.dat ), + .i_rdy ( mult_out_if.rdy ), + .o_val ( mult_out_if.val ), + .o_ctl ( mult_out_if.ctl ), + .o_err ( mult_out_if.err ) +); + +secp256k1_mod #( + .USE_MULT ( 0 ), + .CTL_BITS ( 16 ) +) +secp256k1_mod ( + .i_clk( clk ), + .i_rst( rst ), + .i_dat( mod_in_if.dat ), + .i_val( mod_in_if.val ), + .i_err( mod_in_if.err ), + .i_ctl( mod_in_if.ctl ), + .o_rdy( mod_in_if.rdy ), + .o_dat( mod_out_if.dat ), + .o_ctl( mod_out_if.ctl ), + .o_err( mod_out_if.err ), + .i_rdy( mod_out_if.rdy ), + .o_val( mod_out_if.val ) +); + +// Test a point +task test(input integer index, input logic [255:0] k, jb_point_t p_exp, p_in); +begin + integer signed get_len; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; + logic [255:0] in_a, in_b; + integer start_time, finish_time; + jb_point_t p_out; + $display("Running test %d ...", index); + k_in = k; + start_time = $time; + fork + in_if.put_stream(p_in, 256*3/8); + out_if.get_stream(get_dat, get_len, 0); + join + finish_time = $time; + + p_out = get_dat; + + if (p_exp != p_out) begin + $display("Expected:"); + print_jb_point(p_exp); + $display("Was:"); + print_jb_point(p_out); + $fatal(1, "%m %t ERROR: test %d was wrong", $time, index); + end + + $display("test %d PASSED in %d clocks", index, (finish_time-start_time)/CLK_PERIOD); +end +endtask; + + +initial begin + out_if.rdy = 0; + in_if.val = 0; + #(40*CLK_PERIOD); + + // k1 is positive, k2 is negative here + test(0, + 256'd36644297199723006697238902796853752627288044630575801382304802161070535512204, + {x:256'd45213033352668070164952185425578516070995776451206690854440958351598421068498, + y:256'd85642664275538481518837161207205935282875677695988033260377207212529188560350, + z:256'd46619474838719077565729441946941961955107434058466874326193136242340363932614}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + +// k1 and k2 is positive + test(1, + 256'd55241786844846723798409522554861295376012334658573106804016642051374977891741, + {x:256'd76090149308608015449280928223196394375371085422355638787623027177573248394427, + y:256'd52052533613727108316308539229264312767646640577338787268425139698990399010025, + z:256'd114906227987603512981917844669318868106181860518720331222560351511921461319286}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + + + #1us $finish(); +end +endmodule \ No newline at end of file diff --git a/zcash_fpga/src/tb/secp256k1_point_mult_tb.sv b/zcash_fpga/src/tb/secp256k1_point_mult_tb.sv index 7dbf603..7929995 100644 --- a/zcash_fpga/src/tb/secp256k1_point_mult_tb.sv +++ b/zcash_fpga/src/tb/secp256k1_point_mult_tb.sv @@ -27,19 +27,15 @@ logic clk, rst; if_axi_stream #(.DAT_BYTS(256*3/8)) in_if(clk); if_axi_stream #(.DAT_BYTS(256*3/8)) out_if(clk); -if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(8)) mult_in_if(clk); -if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(8)) mult_out_if(clk); +if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(16)) mult_in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(16)) mult_out_if(clk); -if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(8)) mod_in_if(clk); -if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(8)) mod_out_if(clk); +if_axi_stream #(.DAT_BYTS(256*2/8), .CTL_BITS(16)) mod_in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8), .CTL_BITS(16)) mod_out_if(clk); jb_point_t in_p, out_p; logic [255:0] k_in; -always_comb begin - in_p = in_if.dat; - out_if.dat = out_p; -end initial begin rst = 0; @@ -71,31 +67,35 @@ always_comb begin mult_out_if.mod = 0; mod_out_if.sop = 1; mod_out_if.eop = 1; - mod_out_if.mod = 0; + mod_out_if.mod = 0; end -secp256k1_point_mult #( - .RESOURCE_SHARE ("YES") + + secp256k1_point_mult #( + .RESOURCE_SHARE ("YES") ) -secp256k1_point_mult ( - .i_clk ( clk ), - .i_rst ( rst ), - .i_p ( in_if.dat ), - .i_k ( k_in ), - .i_val ( in_if.val ), - .o_rdy ( in_if.rdy ), - .o_p ( out_p ), - .i_rdy ( out_if.rdy ), - .o_val ( out_if.val ), - .o_err ( out_if.err ), - .o_mult_if ( mult_in_if ), - .i_mult_if ( mult_out_if ), - .o_mod_if ( mod_in_if ), - .i_mod_if ( mod_out_if ) -); + secp256k1_point_mult ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_p ( in_if.dat ), + .i_k ( k_in ), + .i_val ( in_if.val ), + .o_rdy ( in_if.rdy ), + .o_p ( out_if.dat ), + .i_rdy ( out_if.rdy ), + .o_val ( out_if.val ), + .o_err ( out_if.err ), + .o_mult_if ( mult_in_if ), + .i_mult_if ( mult_out_if ), + .o_mod_if ( mod_in_if ), + .i_mod_if ( mod_out_if ), + .i_p2_val (0), + .i_p2 (0 ) + ); + secp256k1_mult_mod #( - .CTL_BITS ( 8 ) + .CTL_BITS ( 16 ) ) secp256k1_mult_mod ( .i_clk ( clk ), @@ -105,18 +105,18 @@ secp256k1_mult_mod ( .i_val ( mult_in_if.val ), .i_err ( mult_in_if.err ), .i_ctl ( mult_in_if.ctl ), - .i_cmd (1'd0 ), + .i_cmd ( mult_in_if.ctl[7:6] ), .o_rdy ( mult_in_if.rdy ), .o_dat ( mult_out_if.dat ), .i_rdy ( mult_out_if.rdy ), .o_val ( mult_out_if.val ), .o_ctl ( mult_out_if.ctl ), - .o_err ( mult_out_if.err ) + .o_err ( mult_out_if.err ) ); secp256k1_mod #( .USE_MULT ( 0 ), - .CTL_BITS ( 8 ) + .CTL_BITS ( 16 ) ) secp256k1_mod ( .i_clk( clk ), @@ -134,14 +134,14 @@ secp256k1_mod ( ); // Test a point -task test(input logic [255:0] k, jb_point_t p_exp, p_in = secp256k1_pkg::G_p); +task test(input integer index, input logic [255:0] k, jb_point_t p_exp, p_in); begin integer signed get_len; - logic [common_pkg::MAX_SIM_BYTS*8-1:0] expected, get_dat; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; logic [255:0] in_a, in_b; integer start_time, finish_time; jb_point_t p_out; - $display("Running test_0..."); + $display("Running test %d ...", index); k_in = k; start_time = $time; fork @@ -149,17 +149,18 @@ begin out_if.get_stream(get_dat, get_len); join finish_time = $time; - + p_out = get_dat; + if (p_exp != p_out) begin $display("Expected:"); print_jb_point(p_exp); $display("Was:"); print_jb_point(p_out); - $fatal(1, "%m %t ERROR: test with k=%d was wrong", $time, integer'(k)); - end + $fatal(1, "%m %t ERROR: test %d was wrong", $time, index); + end - $display("test with k=%d PASSED in %d clocks", integer'(k), (finish_time-start_time)/CLK_PERIOD); + $display("test %d PASSED in %d clocks", index, (finish_time-start_time)/CLK_PERIOD); end endtask; @@ -168,35 +169,60 @@ initial begin out_if.rdy = 0; in_if.val = 0; #(40*CLK_PERIOD); -/* - test(1, {x:256'h79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, - y:256'h483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, - z:256'h1}); - test(2, {x:256'h7d152c041ea8e1dc2191843d1fa9db55b68f88fef695e2c791d40444b365afc2, - y:256'h56915849f52cc8f76f5fd7e4bf60db4a43bf633e1b1383f85fe89164bfadcbdb, - z:256'h9075b4ee4d4788cabb49f7f81c221151fa2f68914d0aa833388fa11ff621a970}); - - test(3, {x:256'hca90ef9b06d7eb51d650e9145e3083cbd8df8759168862036f97a358f089848, - y:256'h435afe76017b8d55d04ff8a98dd60b2ba7eb6f87f6b28182ca4493d7165dd127, - z:256'h9242fa9c0b9f23a3bfea6a0eb6dbcfcbc4853fe9a25ee948105dc66a2a9b5baa}); - - test(4, {x:256'h9bae2d5bac61e6ea5de635bca754b2564b7d78c45277cad67e45c4cbbea6e706, - y:256'h34fb8147eed1c0fbe29ead4d6c472eb4ef7b2191fde09e494b2a9845fe3f605e, - z:256'hc327b5d2636b32f27b051e4742b1bbd5324432c1000bfedca4368a29f6654152}); + test(0, + 1, {x:256'h79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, + y:256'h483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, + z:256'h1}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); - test(1514155, {x:256'h759267d17957f567381462db6e240b75c9f6016091a7427cfbef33c398964a9d, - y:256'hd81ce7034647587a9b0ea5b52ac08c91f5cfae30f4eba2ade7fa68856fc0d691, - z:256'h7c9d27fb2de7927c982792630a0c86f411f2de60e8df44c5e9caff976658009c}); -*/ - test(256'hbad45c59dcd6d81c6a96b46a678cb893c53decc8e57465bd84efa78676ccc64a, - {x:256'he7e2b526cd2822c69ea688586501db564f28430319cdeb95cb38feb2c77fdfc3, - y:256'h6dda26c3c991cfab33a12ed7b56a0afa17d375d8fa5cabe2d1d143bb21cab887, - z:256'h2f8a851f9aec0f095a31472456a91cca12dd21da865e5a83e5d1b1085835c36c}, - {x:256'h808a2c66c5b90fa1477d7820fc57a8b7574cdcb8bd829bdfcf98aa9c41fde3b4, // Not multiplying by generator - y:256'heed249ffde6e46d784cb53b4df8c9662313c1ce8012da56cb061f12e55a32249, - z:256'h1}); + test(1, + 2, {x:256'h7d152c041ea8e1dc2191843d1fa9db55b68f88fef695e2c791d40444b365afc2, + y:256'h56915849f52cc8f76f5fd7e4bf60db4a43bf633e1b1383f85fe89164bfadcbdb, + z:256'h9075b4ee4d4788cabb49f7f81c221151fa2f68914d0aa833388fa11ff621a970}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + + test(3, + 3, {x:256'hca90ef9b06d7eb51d650e9145e3083cbd8df8759168862036f97a358f089848, + y:256'h435afe76017b8d55d04ff8a98dd60b2ba7eb6f87f6b28182ca4493d7165dd127, + z:256'h9242fa9c0b9f23a3bfea6a0eb6dbcfcbc4853fe9a25ee948105dc66a2a9b5baa}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + + test(4, + 4, {x:256'h9bae2d5bac61e6ea5de635bca754b2564b7d78c45277cad67e45c4cbbea6e706, + y:256'h34fb8147eed1c0fbe29ead4d6c472eb4ef7b2191fde09e494b2a9845fe3f605e, + z:256'hc327b5d2636b32f27b051e4742b1bbd5324432c1000bfedca4368a29f6654152}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + test(5, + 256'd55241786844846723798409522554861295376012334658573106804016642051374977891741, + {x:256'd114452044609218547356220974436632746395277736533029276044444520652934189718100, + y:256'd105574650075160330358790852048157558974413633249451800413065016023266456843289, + z:256'd114502749188206279151476081115998896219274334632701318332065731739168923561257}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + + test(6, + 256'd36644297199723006697238902796853752627288044630575801382304802161070535512204, + {x:256'd19559730912111231547572828279398263948482589709742643847415187021767406006262, + y:256'd56669196538343662577389952407416094360513459515269228018156259621856885572646, + z:256'd93622651521811893405023705294943233553232134901881469090144140953361623198206}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + + test(7, + 1514155, {x:256'h759267d17957f567381462db6e240b75c9f6016091a7427cfbef33c398964a9d, + y:256'hd81ce7034647587a9b0ea5b52ac08c91f5cfae30f4eba2ade7fa68856fc0d691, + z:256'h7c9d27fb2de7927c982792630a0c86f411f2de60e8df44c5e9caff976658009c}, + {x:secp256k1_pkg::Gx, y:secp256k1_pkg::Gy, z:256'h1}); + + test(8, + 256'hbad45c59dcd6d81c6a96b46a678cb893c53decc8e57465bd84efa78676ccc64a, + {x:256'he7e2b526cd2822c69ea688586501db564f28430319cdeb95cb38feb2c77fdfc3, + y:256'h6dda26c3c991cfab33a12ed7b56a0afa17d375d8fa5cabe2d1d143bb21cab887, + z:256'h2f8a851f9aec0f095a31472456a91cca12dd21da865e5a83e5d1b1085835c36c}, + {x:256'h808a2c66c5b90fa1477d7820fc57a8b7574cdcb8bd829bdfcf98aa9c41fde3b4, // Not multiplying by generator + y:256'heed249ffde6e46d784cb53b4df8c9662313c1ce8012da56cb061f12e55a32249, + z:256'h1}); + #1us $finish(); end endmodule \ No newline at end of file diff --git a/zcash_fpga/src/tb/secp256k1_top_tb.sv b/zcash_fpga/src/tb/secp256k1_top_tb.sv index 14af4f0..dd9efec 100644 --- a/zcash_fpga/src/tb/secp256k1_top_tb.sv +++ b/zcash_fpga/src/tb/secp256k1_top_tb.sv @@ -22,6 +22,7 @@ import secp256k1_pkg::*; import zcash_fpga_pkg::*; localparam CLK_PERIOD = 5000; +localparam USE_ENDOMORPH = "NO"; logic clk, rst; @@ -42,8 +43,7 @@ end // Check for errors always_ff @ (posedge clk) - if (out_if.val && out_if.err) begin - out_if.rdy = 1; + if (out_if.val && out_if.err) begin; $error(1, "%m %t ERROR: output .err asserted", $time); end diff --git a/zcash_fpga/src/tb/zcash_fpga_top_tb.sv b/zcash_fpga/src/tb/zcash_fpga_top_tb.sv index 4841840..29769e1 100644 --- a/zcash_fpga/src/tb/zcash_fpga_top_tb.sv +++ b/zcash_fpga/src/tb/zcash_fpga_top_tb.sv @@ -1,6 +1,6 @@ /* The zcash_fpga_top testbench. - + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation This program is free software: you can redistribute it and/or modify @@ -77,7 +77,7 @@ end always_comb begin tx_346_if.rdy = 0; tx_if.val = 0; - + if (start_346 && ~done_346) begin tx_346_if.rdy = tx_if.rdy; tx_if.val = tx_346_if.val; @@ -88,7 +88,7 @@ always_comb begin tx_if.err = tx_346_if.err; tx_if.dat = tx_346_if.dat; end - + end @@ -135,8 +135,8 @@ begin logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat1, get_dat2, get_dat3; logic fail = 0; $display("Running test_block_346_equihash..."); - - fork + + fork begin // First send reset header.cmd = RESET_FPGA; @@ -158,18 +158,18 @@ begin rx_if.get_stream(get_dat3, get_len3); // equihash rpl end join - + fpga_reset_rpl = get_dat1; verify_equihash_rpl = get_dat3; fpga_status_rpl = get_dat2; - + fail |= get_len3 != $bits(verify_equihash_rpl_t)/8; fail |= verify_equihash_rpl.hdr.cmd != VERIFY_EQUIHASH_RPL; fail |= verify_equihash_rpl.hdr.len != $bits(verify_equihash_rpl_t)/8; fail |= verify_equihash_rpl.index != 1; fail |= verify_equihash_rpl.bm != 0; assert (~fail) else $fatal(1, "%m %t ERROR: test_block_346_equihash equihash rply was wrong:\n%p", $time, verify_equihash_rpl); - + fail |= get_len2 != $bits(fpga_status_rpl_t)/8; fail |= fpga_status_rpl.hdr.cmd != FPGA_STATUS_RPL; fail |= fpga_status_rpl.hdr.len != $bits(fpga_status_rpl_t)/8; @@ -179,13 +179,13 @@ begin fail |= fpga_status_rpl.build_date != "20180311"; fail |= fpga_status_rpl.fpga_state == 1; assert (~fail) else $fatal(1, "%m %t ERROR: test_block_346_equihash status reply was wrong:\n%p", $time, fpga_status_rpl); - + fail |= get_len1 != $bits(fpga_reset_rpl_t)/8; fail |= fpga_reset_rpl.hdr.cmd != RESET_FPGA_RPL; assert (~fail) else $fatal(1, "%m %t ERROR: test_block_346_equihash reset reply was wrong:\n%p", $time, fpga_reset_rpl); - + $display("test_block_346_equihash PASSED"); - + end endtask @@ -198,24 +198,24 @@ begin logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; logic fail = 0; $display("Running test_ignored_message..."); - + // Some header value that is invalid header = {$bits(header_t){1'b1}}; header.cmd[8 +: 8] = 0; - fork + fork tx_if.put_stream(header, $bits(header)/8); rx_if.get_stream(get_dat, get_len); join - + fpga_ignore_rpl = get_dat; - + fail |= get_len != $bits(fpga_ignore_rpl_t)/8; fail |= fpga_ignore_rpl.hdr.cmd != FPGA_IGNORE_RPL; fail |= fpga_ignore_rpl.hdr.len != $bits(fpga_ignore_rpl_t)/8; assert (~fail) else $fatal(1, "%m %t ERROR: test_ignored_message rply was wrong:\n%p", $time, fpga_ignore_rpl); - + $display("test_ignored_message PASSED"); - + end endtask @@ -228,7 +228,7 @@ begin logic fail = 0; verify_secp256k1_sig_t verify_secp256k1_sig; verify_secp256k1_sig_rpl_t verify_secp256k1_sig_rpl; - + $display("Running test_block_secp256k1..."); verify_secp256k1_sig.hdr.cmd = VERIFY_SECP256K1_SIG; verify_secp256k1_sig.hdr.len = $bits(verify_secp256k1_sig_t)/8; @@ -238,21 +238,21 @@ begin verify_secp256k1_sig.s = 256'hde0f72e442f7b5e8e7d53274bf8f97f0674f4f63af582554dbecbb4aa9d5cbcb; verify_secp256k1_sig.Qx = 256'h808a2c66c5b90fa1477d7820fc57a8b7574cdcb8bd829bdfcf98aa9c41fde3b4; verify_secp256k1_sig.Qy = 256'heed249ffde6e46d784cb53b4df8c9662313c1ce8012da56cb061f12e55a32249; - + start_time = $time; fork tx_if.put_stream(verify_secp256k1_sig, $bits(verify_secp256k1_sig)/8); rx_if.get_stream(get_dat, get_len); join finish_time = $time; - + verify_secp256k1_sig_rpl = get_dat; - + fail |= verify_secp256k1_sig_rpl.hdr.cmd != VERIFY_SECP256K1_SIG_RPL; fail |= (verify_secp256k1_sig_rpl.bm != 0); fail |= (verify_secp256k1_sig_rpl.index != verify_secp256k1_sig.index); assert (~fail) else $fatal(1, "%m %t ERROR: test_block_secp256k1 failed :\n%p", $time, verify_secp256k1_sig_rpl); - + $display("test_block_secp256k1 PASSED"); end @@ -262,11 +262,11 @@ endtask; initial begin rx_if.rdy = 0; #20us; // Let internal memories reset - - test_ignored_message(); - test_block_346_equihash(); + + //test_ignored_message(); + //test_block_346_equihash(); test_block_secp256k1(); - + #1us $finish(); end