forked from ZcashFoundation/zcash-fpga
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
bsdevlin
authored and
bsdevlin
committed
Feb 11, 2019
1 parent
ada8931
commit 361ece0
Showing
6 changed files
with
430 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<projectDescription> | ||
<name>zcash-fpga</name> | ||
<comment></comment> | ||
<projects> | ||
</projects> | ||
<buildSpec> | ||
</buildSpec> | ||
<natures> | ||
</natures> | ||
</projectDescription> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
module blake2_g | ||
#( | ||
parameter PIPELINES = 1 // Do we want to optionally add pipeline stages | ||
) | ||
( | ||
input i_clk, | ||
input [63:0] i_a, i_b, i_c, i_d, i_m0, i_m1, | ||
output logic [63:0] o_a, o_b, o_c, o_d | ||
); | ||
|
||
logic [63:0] a0, b0, c0, d0, a1, b1, c1, d1, b2, d2, b3, d3; | ||
logic [PIPELINES:0][64*4-1:0] pipeline; | ||
|
||
// Logic used to implement G function | ||
always_comb begin | ||
a0 = i_a + i_b + i_m0; | ||
d0 = i_d ^ a0; | ||
d1 = {d0[0 +: 32], d0[32 +: 32]}; | ||
c0 = i_c + d1; | ||
b0 = i_b ^ c0; | ||
b1 = {b0[0 +: 24], b0[24 +: 40]}; | ||
a1 = a0 + b1 + i_m1; | ||
d2 = d1 ^ a1; | ||
d3 = {d2[0 +: 16], d2[16 +: 48]}; | ||
c1 = c0 + d3; | ||
b2 = b1 ^ c1; | ||
b3 = {b2[0 +: 63], b2[63]}; | ||
end | ||
|
||
// Final output assignment | ||
always_comb begin | ||
o_a = pipeline[PIPELINES][0*64 +: 64]; | ||
o_b = pipeline[PIPELINES][1*64 +: 64]; | ||
o_c = pipeline[PIPELINES][2*64 +: 64]; | ||
o_d = pipeline[PIPELINES][3*64 +: 64]; | ||
end | ||
|
||
// Optional pipelines | ||
generate begin: PIPE_GEN | ||
genvar gv_p; | ||
always_comb begin | ||
pipeline[0][0*64 +: 64] = a1; | ||
pipeline[0][1*64 +: 64] = b3; | ||
pipeline[0][2*64 +: 64] = c1; | ||
pipeline[0][3*64 +: 64] = d3; | ||
end | ||
for (gv_p = 0; gv_p < PIPELINES; gv_p++) begin: PIPE_LOOP_GEN | ||
always_ff @ (posedge i_clk) begin | ||
pipeline[gv_p + 1][0*64 +: 64] <= pipeline[gv_p][0*64 +: 64]; | ||
pipeline[gv_p + 1][1*64 +: 64] <= pipeline[gv_p][1*64 +: 64]; | ||
pipeline[gv_p + 1][2*64 +: 64] <= pipeline[gv_p][2*64 +: 64]; | ||
pipeline[gv_p + 1][3*64 +: 64] <= pipeline[gv_p][3*64 +: 64]; | ||
end | ||
end | ||
end | ||
endgenerate | ||
|
||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package blake2_pkg; | ||
|
||
// Initial values | ||
parameter [7:0][63:0] IV = { | ||
64'h5be0cd19137e2179, | ||
64'h1f83d9abfb41bd6b, | ||
64'h9b05688c2b3e6c1f, | ||
64'h510e527fade682d1, | ||
64'ha54ff53a5f1d36f1, | ||
64'h3c6ef372fe94f82b, | ||
64'hbb67ae8584caa73b, | ||
64'h6a09e667f3bcc908 | ||
}; | ||
|
||
parameter [15*10-1:0][31:0] SIGMA = { | ||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, | ||
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, | ||
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, | ||
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, | ||
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, | ||
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, | ||
12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, | ||
13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, | ||
6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, | ||
10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 | ||
}; | ||
|
||
|
||
parameter [4*8-1:0][31:0] G_MAPPING = { | ||
14, 9, 4, 3, | ||
13, 8, 7, 2, | ||
12, 11, 6, 1, | ||
15, 10, 5, 0, | ||
15, 11, 7, 3, | ||
14, 10, 6, 2, | ||
13, 9, 5, 1, | ||
12, 8, 4, 0 | ||
}; | ||
|
||
// Top 4 bits per entry is the nth G-function unit | ||
// lower 4 bits is the ith output of the G-function | ||
parameter [15:0][5:0] G_FINAL_MAPPING = { | ||
{3'd4,3'd3}, {3'd7,3'd3}, {3'd6,3'd3}, {3'd5,3'd3}, | ||
{3'd5,3'd2}, {3'd4,3'd2}, {3'd7,3'd2}, {3'd6,3'd2}, | ||
{3'd6,3'd1}, {3'd5,3'd1}, {3'd4,3'd1}, {3'd7,3'd1}, | ||
{3'd7,3'd0}, {3'd6,3'd0}, {3'd5,3'd0}, {3'd4, 3'd0} | ||
}; | ||
|
||
|
||
endpackage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
// Implemented from RFC-7693, The BLAKE2 Cryptographic Hash and Message Authentication Code (MAC) | ||
|
||
module blake2_top | ||
import blake2_pkg::*; | ||
#( | ||
|
||
) | ||
( | ||
input i_clk, i_rst, | ||
|
||
// Parameter block input | ||
input [7:0] i_digest_byte_len, | ||
input [7:0] i_key_byte_len, | ||
|
||
input [128*8-1:0] i_block, | ||
input i_new_block, | ||
input i_final_block, | ||
input i_val, | ||
|
||
output logic[64*8-1:0] o_digest, | ||
output logic o_rdy, | ||
output logic o_val, | ||
output logic o_err | ||
|
||
|
||
); | ||
|
||
enum {STATE_IDLE = 0, | ||
STATE_ROUNDS = 1, | ||
STATE_NEXT_BLOCK = 2} blake2_state; | ||
|
||
localparam ROUNDS = 12; | ||
|
||
logic [64*8-1:0] parameters; | ||
logic [7:0][63:0] h; // The state vector | ||
logic [15:0][63:0] v; // The local work vector | ||
logic [31:0][63:0] g_out; // Outputs of the G mixing function - use 8 here to save on timing | ||
logic [127:0] t; // Counter - TODO make this smaller - related to param | ||
logic [$clog2(ROUNDS)-1:0] round_cntr; | ||
logic cnt; | ||
logic g_row_col; | ||
logic [15:0][63:0] block_r; // The message block registered and converted to a 2d array | ||
logic final_block_r; | ||
|
||
|
||
// Logic that is for pipelining | ||
always_ff @(posedge i_clk) begin | ||
parameters <= {32'd0, 8'd1, 8'd1, i_key_byte_len, i_digest_byte_len}; | ||
if (i_val && o_rdy) begin | ||
block_r <= i_block; | ||
final_block_r <= i_final_block; | ||
end | ||
end | ||
|
||
// State machine logic for compressing | ||
always_ff @(posedge i_clk) begin | ||
if (i_rst) begin | ||
blake2_state <= STATE_IDLE; | ||
o_val <= 0; | ||
o_rdy <= 0; | ||
h <= 0; | ||
v <= 0; | ||
t <= 0; | ||
g_row_col <= 0; | ||
round_cntr <= 0; | ||
o_err <= 0; | ||
o_digest <= 0; | ||
cnt <= 0; | ||
end else begin | ||
cnt <= cnt + 1; | ||
case (blake2_state) | ||
STATE_IDLE: begin | ||
o_val <= 0; | ||
init_state_vector(); | ||
t <= 0; | ||
o_err <= 0; | ||
o_rdy <= 1; | ||
v <= 0; | ||
g_row_col <= 0; | ||
round_cntr <= 0; | ||
if (o_rdy && i_val && i_new_block) begin | ||
init_local_work_vector(); | ||
blake2_state <= STATE_ROUNDS; | ||
o_rdy <= 0; | ||
end | ||
end | ||
// Here we do the compression over 12 rounds, each round can be done in two clock cycles | ||
// After we do 12 rounds we increment counter t | ||
STATE_ROUNDS: begin | ||
// Update local work vector with output of G function blocks | ||
for (int i = 0; i < 16; i++) | ||
v[i] <= g_out[G_MAPPING[g_row_col*16 + i]]; | ||
|
||
if (g_row_col) | ||
round_cntr <= round_cntr + 1; | ||
g_row_col <= ~g_row_col; | ||
|
||
// Update state vector on the final round | ||
if (round_cntr == ROUNDS-1) begin | ||
|
||
for (int i = 0; i < 7; i++) | ||
h[i] <= h[i] ^ | ||
g_out[G_FINAL_MAPPING[i][5:3]][G_FINAL_MAPPING[i][2:0]] ^ | ||
g_out[G_FINAL_MAPPING[i+8][5:3]][G_FINAL_MAPPING[i][2:0]]; | ||
|
||
blake2_state <= STATE_NEXT_BLOCK; | ||
if (~final_block_r) | ||
o_rdy <= 1; | ||
end | ||
|
||
end | ||
STATE_NEXT_BLOCK: begin | ||
if (final_block_r) begin | ||
blake2_state <= STATE_IDLE; | ||
o_val <= 1; | ||
o_digest <= h; | ||
end else if (o_rdy && i_val) begin | ||
round_cntr <= 0; | ||
init_local_work_vector(); | ||
t <= (t+1) * 128; | ||
blake2_state <= STATE_ROUNDS; | ||
end | ||
end | ||
endcase | ||
end | ||
end | ||
|
||
// 8x G-function blocks. 4 are col and 4 are diagonal | ||
generate begin | ||
genvar gv_g; | ||
for (gv_g = 0; gv_g < 8; gv_g++) begin: G_FUNCTION_GEN | ||
blake2_g | ||
#(.PIPELINES(0)) | ||
blake2_g ( | ||
.i_clk(i_clk), | ||
.i_a(v[(gv_g*4 + 0) % 16]), | ||
.i_b(v[(gv_g*4 + 1) % 16]), | ||
.i_c(v[(gv_g*4 + 2) % 16]), | ||
.i_d(v[(gv_g*4 + 3) % 16]), | ||
.i_m0(block_r[blake2_pkg::SIGMA[(round_cntr % 10) + (gv_g*16)]]), | ||
.i_m1(block_r[blake2_pkg::SIGMA[(round_cntr % 10) + ((gv_g+1))*16]]), | ||
.o_a(g_out[gv_g*4 + 0]), | ||
.o_b(g_out[gv_g*4 + 1]), | ||
.o_c(g_out[gv_g*4 + 2]), | ||
.o_d(g_out[gv_g*4 + 3])); | ||
end | ||
end | ||
endgenerate | ||
|
||
|
||
// Task to initialize the state vector | ||
task init_state_vector(); | ||
begin | ||
for (int i = 0; i < 8; i++) | ||
if (i == 0) | ||
h[i] <= parameters ^ blake2_pkg::IV[i]; | ||
else | ||
h[i] <= blake2_pkg::IV[i]; | ||
end | ||
endtask | ||
|
||
// Task to initialize local work vector for the compression function | ||
task init_local_work_vector(); | ||
begin | ||
for (int i = 0; i < 16; i++) | ||
case (i) inside | ||
0,1,2,3,4,5,6,7: v[i] <= h[i]; | ||
8,9,10,11: v[i] <= blake2_pkg::IV[i%8]; | ||
12: v[i] <= blake2_pkg::IV[i%8] ^ t[63:0]; | ||
13: v[i] <= blake2_pkg::IV[i%8] ^ t[64 +: 64]; | ||
14: v[i] <= blake2_pkg::IV[i%8] ^ {64{i_final_block}}; | ||
15: v[i] <= blake2_pkg::IV[i%8]; | ||
endcase | ||
end | ||
endtask | ||
|
||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
module blake2_g_tb(); | ||
|
||
logic clk; | ||
logic [63:0] o_a, o_b, o_c, o_d, i_a, i_b, i_c, i_d, i_m0, i_m1; | ||
localparam PIPELINES = 1; | ||
|
||
blake2_g #(.PIPELINES(PIPELINES)) DUT (.i_clk(clk), .o_a(o_a), .o_b(o_b), .o_c(o_c), .o_d(o_d), .i_a(i_a), .i_b(i_b), .i_c(i_c), .i_d(i_d), .i_m0(i_m0), .i_m1(i_m1)); | ||
|
||
initial begin | ||
clk = 0; | ||
forever #10ns clk = ~clk; | ||
end | ||
|
||
task test1(); | ||
begin | ||
@(posedge clk) | ||
i_a = 64'h6a09e667f2bdc948; | ||
i_b = 64'h510e527fade682d1; | ||
i_c = 64'h6a09e667f3bcc908; | ||
i_d = 64'h510e527fade68251; | ||
i_m0 = 64'h0000000000000000; | ||
i_m1 = 64'h0000000000000000; | ||
|
||
repeat (PIPELINES) @(posedge clk); | ||
|
||
#1; | ||
assert (o_a == 64'hf0c9aa0de38b1b89) else $fatal(0, "%m %t:ERROR, o_a did not match", $time); | ||
assert (o_b == 64'hbbdf863401fde49b) else $fatal(0, "%m %t:ERROR, o_b did not match", $time); | ||
assert (o_c == 64'he85eb23c42183d3d) else $fatal(0, "%m %t:ERROR, o_c did not match", $time); | ||
assert (o_d == 64'h7111fd8b6445099d) else $fatal(0, "%m %t:ERROR, o_d did not match", $time); | ||
|
||
$display("test1 PASSED"); | ||
end | ||
endtask | ||
|
||
// Main testbench calls | ||
|
||
initial begin | ||
#100ns; | ||
test1(); | ||
|
||
#100ns $finish(); | ||
|
||
end | ||
|
||
endmodule |
Oops, something went wrong.