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