diff --git a/ip_cores/ec/src/tb/ec_fp6_arithmetic_tb.sv b/ip_cores/ec/src/tb/ec_fp6_arithmetic_tb.sv new file mode 100644 index 0000000..668b848 --- /dev/null +++ b/ip_cores/ec/src/tb/ec_fp6_arithmetic_tb.sv @@ -0,0 +1,354 @@ +/* + 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 ec_fp6_arithmetic_tb (); +import common_pkg::*; +import bls12_381_pkg::*; + +localparam CLK_PERIOD = 1000; + +logic clk, rst; + +parameter type FE_TYPE = bls12_381_pkg::fe_t; +parameter type FE2_TYPE = bls12_381_pkg::fe2_t; +parameter type FE6_TYPE = bls12_381_pkg::fe6_t; +parameter P = bls12_381_pkg::P; + +`define MULT_FUNC(K, IN_POINT) fp2_point_mult(K, IN_POINT); +`define PRINT_FUNC(IN_POINT) print_fp2_jb_point(IN_POINT); +`define G_POINT bls12_381_pkg::g2_point +`define TO_AFFINE bls12_381_pkg::fp2_to_affine + +if_axi_stream #(.DAT_BITS(2*$bits(FE_TYPE)), .CTL_BITS(24)) mul_fe_in_if(clk); +if_axi_stream #(.DAT_BITS($bits(FE_TYPE)), .CTL_BITS(24)) mul_fe_out_if(clk); +if_axi_stream #(.DAT_BITS(2*$bits(FE_TYPE)), .CTL_BITS(24)) add_fe_in_if[2:0] (clk); +if_axi_stream #(.DAT_BITS($bits(FE_TYPE)), .CTL_BITS(24)) add_fe_out_if[2:0] (clk); +if_axi_stream #(.DAT_BITS(2*$bits(FE_TYPE)), .CTL_BITS(24)) sub_fe_in_if[2:0] (clk); +if_axi_stream #(.DAT_BITS($bits(FE_TYPE)), .CTL_BITS(24)) sub_fe_out_if[2:0] (clk); + +if_axi_stream #(.DAT_BITS(2*$bits(FE2_TYPE)), .CTL_BITS(24)) mul_fe2_o_if(clk); +if_axi_stream #(.DAT_BITS($bits(FE2_TYPE)), .CTL_BITS(24)) mul_fe2_i_if(clk); +if_axi_stream #(.DAT_BITS(2*$bits(FE2_TYPE)), .CTL_BITS(24)) add_fe2_o_if(clk); +if_axi_stream #(.DAT_BITS($bits(FE2_TYPE)), .CTL_BITS(24)) add_fe2_i_if(clk); +if_axi_stream #(.DAT_BITS(2*$bits(FE2_TYPE)), .CTL_BITS(24)) sub_fe2_o_if(clk); +if_axi_stream #(.DAT_BITS($bits(FE2_TYPE)), .CTL_BITS(24)) sub_fe2_i_if(clk); +if_axi_stream #(.DAT_BITS($bits(FE2_TYPE)), .CTL_BITS(24)) mnr_fe2_o_if(clk); +if_axi_stream #(.DAT_BITS($bits(FE2_TYPE)), .CTL_BITS(24)) mnr_fe2_i_if(clk); + +if_axi_stream #(.DAT_BYTS((2*$bits(FE6_TYPE)+7)/8), .CTL_BITS(24)) mul_fe6_o_if(clk); +if_axi_stream #(.DAT_BYTS(($bits(FE6_TYPE)+7)/8), .CTL_BITS(24)) mul_fe6_i_if(clk); +if_axi_stream #(.DAT_BYTS((2*$bits(FE6_TYPE)+7)/8), .CTL_BITS(24)) add_fe6_o_if(clk); +if_axi_stream #(.DAT_BYTS(($bits(FE6_TYPE)+7)/8), .CTL_BITS(24)) add_fe6_i_if(clk); +if_axi_stream #(.DAT_BYTS((2*$bits(FE6_TYPE)+7)/8), .CTL_BITS(24)) sub_fe6_o_if(clk); +if_axi_stream #(.DAT_BYTS(($bits(FE6_TYPE)+7)/8), .CTL_BITS(24)) sub_fe6_i_if(clk); + +initial begin + rst = 0; + repeat(2) #(20*CLK_PERIOD) rst = ~rst; +end + +initial begin + clk = 0; + forever #CLK_PERIOD clk = ~clk; +end + +ec_fe2_arithmetic #( + .FE_TYPE ( FE_TYPE ), + .FE2_TYPE( FE2_TYPE ), + .CTL_BIT ( 8 ) +) +ec_fe2_arithmetic ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_fp_mode ( 1'd0 ), + .o_mul_fe_if ( mul_fe_in_if ), + .i_mul_fe_if ( mul_fe_out_if ), + .o_add_fe_if ( add_fe_in_if[0] ), + .i_add_fe_if ( add_fe_out_if[0] ), + .o_sub_fe_if ( sub_fe_in_if[0] ), + .i_sub_fe_if ( sub_fe_out_if[0] ), + .o_mul_fe2_if ( mul_fe2_i_if ), + .i_mul_fe2_if ( mul_fe2_o_if ), + .o_add_fe2_if ( add_fe2_i_if ), + .i_add_fe2_if ( add_fe2_o_if ), + .o_sub_fe2_if ( sub_fe2_i_if ), + .i_sub_fe2_if ( sub_fe2_o_if ) +); + +ec_fe6_arithmetic #( + .FE_TYPE ( FE_TYPE ), + .FE2_TYPE( FE2_TYPE ), + .FE6_TYPE( FE6_TYPE ), + .CTL_BIT ( 0 ) +) +ec_fe6_arithmetic ( + .i_clk ( clk ), + .i_rst ( rst ), + .o_mul_fe2_if ( mul_fe2_o_if ), + .i_mul_fe2_if ( mul_fe2_i_if ), + .o_add_fe2_if ( add_fe2_o_if ), + .i_add_fe2_if ( add_fe2_i_if ), + .o_sub_fe2_if ( sub_fe2_o_if ), + .i_sub_fe2_if ( sub_fe2_i_if ), + .o_mnr_fe2_if ( mnr_fe2_o_if ), + .i_mnr_fe2_if ( mnr_fe2_i_if ), + .o_mul_fe6_if ( mul_fe6_i_if ), + .i_mul_fe6_if ( mul_fe6_o_if ), + .o_add_fe6_if ( add_fe6_i_if ), + .i_add_fe6_if ( add_fe6_o_if ), + .o_sub_fe6_if ( sub_fe6_i_if ), + .i_sub_fe6_if ( sub_fe6_o_if ) +); + +fe2_mul_by_nonresidue #( + .FE_TYPE ( FE_TYPE ) +) +fe2_mul_by_nonresidue ( + .i_clk ( clk ), + .i_rst ( rst ), + .o_mnr_fe2_if ( mnr_fe2_i_if ), + .i_mnr_fe2_if ( mnr_fe2_o_if ), + .o_add_fe_if ( add_fe_in_if[1] ), + .i_add_fe_if ( add_fe_out_if[1] ), + .o_sub_fe_if ( sub_fe_in_if[1] ), + .i_sub_fe_if ( sub_fe_out_if[1] ) +); + +ec_fp_mult_mod #( + .P ( P ), + .KARATSUBA_LVL ( 3 ), + .CTL_BITS ( 16 ) +) +ec_fp_mult_mod ( + .i_clk( clk ), + .i_rst( rst ), + .i_mul ( mul_fe_in_if ), + .o_mul ( mul_fe_out_if ) +); + +adder_pipe # ( + .BITS ( bls12_381_pkg::DAT_BITS ), + .P ( P ), + .CTL_BITS ( 24 ), + .LEVEL ( 2 ) +) +adder_pipe ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_add ( add_fe_in_if[2] ), + .o_add ( add_fe_out_if[2] ) +); + +subtractor_pipe # ( + .BITS ( bls12_381_pkg::DAT_BITS ), + .P ( P ), + .CTL_BITS ( 24 ), + .LEVEL ( 2 ) +) +subtractor_pipe ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_sub ( sub_fe_in_if[2] ), + .o_sub ( sub_fe_out_if[2] ) +); + +resource_share # ( + .NUM_IN ( 2 ), + .DAT_BITS ( 2*$bits(FE_TYPE) ), + .CTL_BITS ( 24 ), + .OVR_WRT_BIT ( 16 ), + .PIPELINE_IN ( 0 ), + .PIPELINE_OUT ( 0 ) +) +resource_share_sub ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_axi ( sub_fe_in_if[1:0] ), + .o_res ( sub_fe_in_if[2] ), + .i_res ( sub_fe_out_if[2] ), + .o_axi ( sub_fe_out_if[1:0] ) +); + +resource_share # ( + .NUM_IN ( 2 ), + .DAT_BITS ( 2*$bits(FE_TYPE) ), + .CTL_BITS ( 24 ), + .OVR_WRT_BIT ( 16 ), + .PIPELINE_IN ( 0 ), + .PIPELINE_OUT ( 0 ) +) +resource_share_add ( + .i_clk ( clk ), + .i_rst ( rst ), + .i_axi ( add_fe_in_if[1:0] ), + .o_res ( add_fe_in_if[2] ), + .i_res ( add_fe_out_if[2] ), + .o_axi ( add_fe_out_if[1:0] ) +); + + +task test_add(); +begin + integer signed get_len; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; + FE6_TYPE a, b, exp, out; + $display("Running test_add() ..."); + + for (int i = 0; i < 3; i++) begin + for (int j = 0; j < 2; j++) begin + a[i][j] = random_vector($bits(FE_TYPE)/8) % P; + b[i][j] = random_vector($bits(FE_TYPE)/8) % P; + end + end + + exp = fe6_add(a, b); + + fork + add_fe6_o_if.put_stream({a, b}, ((2*$bits(FE6_TYPE)+7)/8)); + add_fe6_i_if.get_stream(get_dat, get_len); + join + + out = get_dat; + + $display("Input a:"); + print_fe6(a); + $display("Input b:"); + print_fe6(b); + $display("Expected:"); + print_fe6(exp); + $display("Was:"); + print_fe6(out); + + if (exp != out) begin + $fatal(1, "%m %t ERROR: test_add output was wrong", $time); + end + + $display("test_add PASSED"); + +end +endtask; + +task test_sub(); +begin + integer signed get_len; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; + FE6_TYPE a, b, exp, out; + $display("Running test_sub() ..."); + + for (int i = 0; i < 3; i++) begin + for (int j = 0; j < 2; j++) begin + a[i][j] = random_vector($bits(FE_TYPE)/8) % P; + b[i][j] = random_vector($bits(FE_TYPE)/8) % P; + end + end + + exp = fe6_sub(a, b); + + fork + sub_fe6_o_if.put_stream({a, b}, ((2*$bits(FE6_TYPE)+7)/8)); + sub_fe6_i_if.get_stream(get_dat, get_len); + join + + out = get_dat; + + $display("Input a:"); + print_fe6(a); + $display("Input b:"); + print_fe6(b); + $display("Expected:"); + print_fe6(exp); + $display("Was:"); + print_fe6(out); + + if (exp != out) begin + $fatal(1, "%m %t ERROR: test_sub output was wrong", $time); + end + + $display("test_sub PASSED"); + +end +endtask; + +task test_mul(); +begin + integer signed get_len; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; + FE6_TYPE a, b, exp, out; + integer start_time, finish_time; + $display("Running test_mul() ..."); + + for (int loop = 0; loop < 10; loop++) begin + $display("loop %d", loop); + for (int i = 0; i < 3; i++) begin + for (int j = 0; j < 2; j++) begin + a[i][j] = random_vector($bits(FE_TYPE)/8) % P; + b[i][j] = random_vector($bits(FE_TYPE)/8) % P; + end + end + + exp = fe6_mul(a, b); + start_time = $time; + fork + mul_fe6_o_if.put_stream({a, b}, ((2*$bits(FE6_TYPE)+7)/8)); + mul_fe6_i_if.get_stream(get_dat, get_len); + join + finish_time = $time; + + out = get_dat; + + $display("Input a:"); + print_fe6(a); + $display("Input b:"); + print_fe6(b); + $display("Expected:"); + print_fe6(exp); + $display("Was:"); + print_fe6(out); + + $display("Test took %d clocks", (finish_time-start_time)/CLK_PERIOD); + + if (exp != out) begin + $fatal(1, "%m %t ERROR: test_mul output was wrong", $time); + end + end + + $display("test_mul PASSED"); + +end +endtask; + + +initial begin + #(40*CLK_PERIOD); + + mul_fe6_o_if.reset_source(); + mul_fe6_i_if.rdy <= 0; + add_fe6_o_if.reset_source(); + add_fe6_i_if.rdy <= 0; + sub_fe6_o_if.reset_source(); + sub_fe6_i_if.rdy <= 0; + + test_add(); + test_sub(); + test_mul(); + + $display("all tests PASSED!!!"); + + #1us $finish(); +end +endmodule \ No newline at end of file diff --git a/ip_cores/ec/src/tb/ec_fp_mult_mod_tb.sv b/ip_cores/ec/src/tb/ec_fp_mult_mod_tb.sv index c5d567c..f6a751f 100644 --- a/ip_cores/ec/src/tb/ec_fp_mult_mod_tb.sv +++ b/ip_cores/ec/src/tb/ec_fp_mult_mod_tb.sv @@ -25,8 +25,8 @@ localparam CLK_PERIOD = 100; logic clk, rst; -if_axi_stream #(.DAT_BYTS(384*2/8), .CTL_BITS(16)) in_if(clk); -if_axi_stream #(.DAT_BYTS(384/8), .CTL_BITS(16)) out_if(clk); +if_axi_stream #(.DAT_BYTS(2*384/8), .CTL_BITS(16)) in_if(clk); +if_axi_stream #(.DAT_BYTS(384/8), .CTL_BITS(16)) out_if(clk); initial begin rst = 0; @@ -57,20 +57,13 @@ always_comb out_if.dat = {3'd0, out_dat}; ec_fp_mult_mod #( .P ( bls12_381_pkg::P ), .KARATSUBA_LVL ( 3 ), - .CTL_BITS ( 8 ) + .CTL_BITS ( 16 ) ) ec_fp_mult_mod ( - .i_clk( clk ), - .i_rst( rst ), - .i_ctl ( 8'd0 ), - .i_dat_a( in_if.dat[0 +: 384] ), - .i_dat_b( in_if.dat[384 +: 384] ), - .i_val( in_if.val ), - .i_err( in_if.err ), - .o_rdy( in_if.rdy ), - .o_dat( out_dat ), - .i_rdy( out_if.rdy ), - .o_val( out_if.val ) + .i_clk( clk ), + .i_rst( rst ), + .i_mul ( in_if ), + .o_mul( out_if ) ); task test_loop(); @@ -78,6 +71,7 @@ begin integer signed get_len; logic [common_pkg::MAX_SIM_BYTS*8-1:0] expected, get_dat; logic [383:0] in_a, in_b; + logic [2*383:0] in_dat; integer i, max; $display("Running test_loop..."); @@ -85,16 +79,28 @@ begin max = 10000; while (i < max) begin + logic [15:0] ctl_out, ctl_exp; in_a = random_vector(384/8) % bls12_381_pkg::P; in_b = random_vector(384/8) % bls12_381_pkg::P; expected = (in_a * in_b) % bls12_381_pkg::P; - + ctl_exp = expected % (1 << 16); + in_dat = 0; + in_dat[0 +: 381] = in_a; + in_dat[381 +: 381] = in_b; fork - in_if.put_stream({in_b, in_a}, (384*2)/8, 0); + in_if.put_stream(in_dat, (384*2)/8, ctl_exp); out_if.get_stream(get_dat, get_len, 0); + while(1) begin + @(posedge out_if.i_clk); + if (out_if.val && out_if.rdy && out_if.sop) begin + ctl_out = out_if.ctl; + break; + end + end join common_pkg::compare_and_print(get_dat, expected); + assert(ctl_out == ctl_exp) else $fatal(1, "ERROR: Ctl did not match - was 0x%x, expected 0x%h", ctl_out, ctl_exp); $display("test_loop PASSED loop %d/%d", i, max); i = i + 1; end @@ -113,9 +119,15 @@ begin fork begin logic [383:0] i; + logic [2*383:0] in_dat; + logic [15:0] ctl_in; i = 0; while (i < max) begin - in_if.put_stream({i, i}, (384*2)/8, 0); + in_dat = 0; + in_dat[0 +: 381] = i; + in_dat[381 +: 381] = i; + ctl_in = i*i; + in_if.put_stream(in_dat, (384*2)/8, ctl_in); i++; end end @@ -123,10 +135,23 @@ begin integer i; integer signed get_len; logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat; + logic [15:0] ctl_out, ctl_exp; i = 0; while (i < max) begin - out_if.get_stream(get_dat, get_len, 0); + ctl_exp = (i * i); + fork + out_if.get_stream(get_dat, get_len, 0); + while(1) begin + if (out_if.val && out_if.rdy && out_if.sop) begin + @(negedge out_if.i_clk); + ctl_out = out_if.ctl; + break; + end + @(negedge out_if.i_clk); + end + join common_pkg::compare_and_print(get_dat, (i * i) % bls12_381_pkg::P); + assert(ctl_out == ctl_exp) else $fatal(1, "ERROR: Ctl did not match - was 0x%x, expected 0x%h", ctl_out, ctl_exp); i++; end end