Fixes for blake2 engine and testbench passing rfc_test now

This commit is contained in:
bsdevlin 2019-02-11 21:53:27 -05:00
parent 7c0d5dab5b
commit a07b4a7cc6
4 changed files with 130 additions and 73 deletions

View File

@ -1,6 +1,9 @@
package blake2_pkg; package blake2_pkg;
// User configurable values
parameter [7:0] NN = 64; // Output hash byte length
// Initial values
// Initial values
parameter [7:0][63:0] IV = { parameter [7:0][63:0] IV = {
64'h5be0cd19137e2179, 64'h5be0cd19137e2179,
64'h1f83d9abfb41bd6b, 64'h1f83d9abfb41bd6b,
@ -12,17 +15,17 @@ package blake2_pkg;
64'h6a09e667f3bcc908 64'h6a09e667f3bcc908
}; };
parameter [15*10-1:0][31:0] SIGMA = { parameter [16*10-1:0][31:0] SIGMA = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 13, 12, 3, 14, 9, 11, 15, 5, 1, 6, 7, 4, 8, 2, 10,
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, 5, 10, 4, 1, 7, 13, 2, 12, 8, 0, 3, 11, 9, 14, 15, 6,
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, 10, 2, 6, 8, 4, 15, 0, 5, 9, 3, 1, 12, 14, 7, 11, 13,
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, 11, 8, 2, 9, 3, 6, 7, 0, 10, 4, 13, 14, 15, 1, 5, 12,
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, 9, 1, 14, 15, 5, 7, 13, 4, 3, 8, 11, 0, 10, 6, 12, 2,
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, 13, 3, 8, 6, 12, 11, 1, 14, 15, 10, 4, 2, 7, 5, 0, 9,
12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, 8, 15, 0, 4, 10, 5, 6, 2, 14, 11, 12, 13, 1, 3, 9, 7,
13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, 4, 9, 1, 7, 6, 3, 14, 10, 13, 15, 2, 5, 0, 12, 8, 11,
6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, 3, 5, 7, 11, 2, 0, 12, 1, 6, 13, 15, 9, 8, 4, 10, 14,
10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
}; };
@ -37,14 +40,13 @@ package blake2_pkg;
12, 8, 4, 0 12, 8, 4, 0
}; };
// Top 4 bits per entry is the nth G-function unit // This is so we can get the correct mapping back from the diagonal
// lower 4 bits is the ith output of the G-function // operation
parameter [15:0][5:0] G_FINAL_MAPPING = { parameter [4*4-1:0][31:0] G_MAPPING_DIAG = {
{3'd4,3'd3}, {3'd7,3'd3}, {3'd6,3'd3}, {3'd5,3'd3}, 3, 15, 11,7,
{3'd5,3'd2}, {3'd4,3'd2}, {3'd7,3'd2}, {3'd6,3'd2}, 6, 2, 14, 10,
{3'd6,3'd1}, {3'd5,3'd1}, {3'd4,3'd1}, {3'd7,3'd1}, 9, 5, 1, 13,
{3'd7,3'd0}, {3'd6,3'd0}, {3'd5,3'd0}, {3'd4, 3'd0} 12, 8 , 4, 0
}; };
endpackage endpackage

View File

@ -3,7 +3,6 @@
module blake2_top module blake2_top
import blake2_pkg::*; import blake2_pkg::*;
#( #(
) )
( (
input i_clk, i_rst, input i_clk, i_rst,
@ -20,9 +19,9 @@ module blake2_top
output logic[64*8-1:0] o_digest, output logic[64*8-1:0] o_digest,
output logic o_rdy, output logic o_rdy,
output logic o_val, output logic o_val,
output logic o_err output logic o_err,
if_axi_stream o_hash
); );
enum {STATE_IDLE = 0, enum {STATE_IDLE = 0,
@ -31,24 +30,27 @@ enum {STATE_IDLE = 0,
localparam ROUNDS = 12; localparam ROUNDS = 12;
logic [64*8-1:0] parameters; logic [64*8-1:0] parameters, parameters_r;
logic [7:0][63:0] h; // The state vector logic [7:0][63:0] h; // The state vector
logic [15:0][63:0] v; // The local work 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 [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 [127:0] t; // Counter - TODO make this smaller - related to param
logic [$clog2(ROUNDS)-1:0] round_cntr; logic [$clog2(ROUNDS)-1:0] round_cntr;
logic cnt; logic cnt;
logic g_row_col; logic g_col;
logic [15:0][63:0] block_r; // The message block registered and converted to a 2d array logic [15:0][63:0] block_r; // The message block registered and converted to a 2d array
logic final_block_r; logic final_block_r;
always_comb begin
parameters = {32'd0, 8'd1, 8'd1, i_key_byte_len, blake2_pkg::NN};
end
// Logic that is for pipelining // Logic that is for pipelining
always_ff @(posedge i_clk) begin 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 if (i_val && o_rdy) begin
block_r <= i_block; block_r <= i_block;
final_block_r <= i_final_block; final_block_r <= i_final_block;
parameters_r <= parameters;
end end
end end
@ -60,26 +62,30 @@ always_ff @(posedge i_clk) begin
o_rdy <= 0; o_rdy <= 0;
h <= 0; h <= 0;
v <= 0; v <= 0;
t <= 0; t <= 128;
g_row_col <= 0; g_col <= 0;
round_cntr <= 0; round_cntr <= 0;
o_err <= 0; o_err <= 0;
o_digest <= 0; o_digest <= 0;
cnt <= 0; cnt <= 0;
o_hash.reset();
end else begin end else begin
cnt <= cnt + 1; cnt <= cnt + 1;
case (blake2_state) case (blake2_state)
STATE_IDLE: begin STATE_IDLE: begin
o_val <= 0; o_val <= 0;
init_state_vector(); init_state_vector();
t <= 0; t <= 128;
o_err <= 0; o_err <= 0;
o_rdy <= 1; o_rdy <= 1;
v <= 0; v <= 0;
g_row_col <= 0; o_hash.val = 0;
g_col <= 0;
round_cntr <= 0; round_cntr <= 0;
if (o_rdy && i_val && i_new_block) begin if (o_rdy && i_val && i_new_block) begin
init_local_work_vector(); init_local_work_vector(i_final_block ? i_digest_byte_len : t);
blake2_state <= STATE_ROUNDS; blake2_state <= STATE_ROUNDS;
o_rdy <= 0; o_rdy <= 0;
end end
@ -89,19 +95,19 @@ always_ff @(posedge i_clk) begin
STATE_ROUNDS: begin STATE_ROUNDS: begin
// Update local work vector with output of G function blocks // Update local work vector with output of G function blocks
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
v[i] <= g_out[G_MAPPING[g_row_col*16 + i]]; v[i] <= g_col == 0 ? g_out[blake2_pkg::G_MAPPING[i]] : g_out[16 + blake2_pkg::G_MAPPING_DIAG[i]];
if (g_row_col) if (g_col)
round_cntr <= round_cntr + 1; round_cntr <= round_cntr + 1;
g_row_col <= ~g_row_col; g_col <= ~g_col;
// Update state vector on the final round // Update state vector on the final round
if (round_cntr == ROUNDS-1) begin if (round_cntr == ROUNDS-1 && g_col) begin
for (int i = 0; i < 7; i++) for (int i = 0; i < 8; i++)
h[i] <= h[i] ^ h[i] <= h[i] ^
g_out[G_FINAL_MAPPING[i][5:3]][G_FINAL_MAPPING[i][2:0]] ^ g_out[16 + blake2_pkg::G_MAPPING_DIAG[i]] ^
g_out[G_FINAL_MAPPING[i+8][5:3]][G_FINAL_MAPPING[i][2:0]]; g_out[16 + blake2_pkg::G_MAPPING_DIAG[i+8]];
blake2_state <= STATE_NEXT_BLOCK; blake2_state <= STATE_NEXT_BLOCK;
if (~final_block_r) if (~final_block_r)
@ -111,13 +117,23 @@ always_ff @(posedge i_clk) begin
end end
STATE_NEXT_BLOCK: begin STATE_NEXT_BLOCK: begin
if (final_block_r) begin if (final_block_r) begin
blake2_state <= STATE_IDLE;
o_val <= 1; o_val <= 1;
o_digest <= h; o_digest <= h;
t <= 128;
if (~o_hash.val) begin
o_hash.dat <= h;
o_hash.val <= 1;
o_hash.sop <= 1;
o_hash.eop <= 1;
end
if (o_hash.rdy)
blake2_state <= STATE_IDLE;
end else if (o_rdy && i_val) begin end else if (o_rdy && i_val) begin
round_cntr <= 0; round_cntr <= 0;
init_local_work_vector(); init_local_work_vector(t);
t <= (t+1) * 128; t <= t + 128;
blake2_state <= STATE_ROUNDS; blake2_state <= STATE_ROUNDS;
end end
end end
@ -133,12 +149,12 @@ generate begin
#(.PIPELINES(0)) #(.PIPELINES(0))
blake2_g ( blake2_g (
.i_clk(i_clk), .i_clk(i_clk),
.i_a(v[(gv_g*4 + 0) % 16]), .i_a(v[blake2_pkg::G_MAPPING[(gv_g*4 + 0)]]),
.i_b(v[(gv_g*4 + 1) % 16]), .i_b(v[blake2_pkg::G_MAPPING[(gv_g*4 + 1)]]),
.i_c(v[(gv_g*4 + 2) % 16]), .i_c(v[blake2_pkg::G_MAPPING[(gv_g*4 + 2)]]),
.i_d(v[(gv_g*4 + 3) % 16]), .i_d(v[blake2_pkg::G_MAPPING[(gv_g*4 + 3)]]),
.i_m0(block_r[blake2_pkg::SIGMA[(round_cntr % 10) + (gv_g*16)]]), .i_m0(block_r[blake2_pkg::SIGMA[16*(round_cntr % 10) + (gv_g*2)]]),
.i_m1(block_r[blake2_pkg::SIGMA[(round_cntr % 10) + ((gv_g+1))*16]]), .i_m1(block_r[blake2_pkg::SIGMA[16*(round_cntr % 10) + (gv_g*2 + 1)]]),
.o_a(g_out[gv_g*4 + 0]), .o_a(g_out[gv_g*4 + 0]),
.o_b(g_out[gv_g*4 + 1]), .o_b(g_out[gv_g*4 + 1]),
.o_c(g_out[gv_g*4 + 2]), .o_c(g_out[gv_g*4 + 2]),
@ -160,14 +176,14 @@ end
endtask endtask
// Task to initialize local work vector for the compression function // Task to initialize local work vector for the compression function
task init_local_work_vector(); task init_local_work_vector(input [127:0] cntr);
begin begin
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
case (i) inside case (i) inside
0,1,2,3,4,5,6,7: v[i] <= h[i]; 0,1,2,3,4,5,6,7: v[i] <= h[i];
8,9,10,11: v[i] <= blake2_pkg::IV[i%8]; 8,9,10,11: v[i] <= blake2_pkg::IV[i%8];
12: v[i] <= blake2_pkg::IV[i%8] ^ t[63:0]; 12: v[i] <= blake2_pkg::IV[i%8] ^ cntr[63:0];
13: v[i] <= blake2_pkg::IV[i%8] ^ t[64 +: 64]; 13: v[i] <= blake2_pkg::IV[i%8] ^ cntr[64 +: 64];
14: v[i] <= blake2_pkg::IV[i%8] ^ {64{i_final_block}}; 14: v[i] <= blake2_pkg::IV[i%8] ^ {64{i_final_block}};
15: v[i] <= blake2_pkg::IV[i%8]; 15: v[i] <= blake2_pkg::IV[i%8];
endcase endcase

View File

@ -1,5 +1,7 @@
module blake2_top_tb(); module blake2_top_tb();
import blake2_pkg::*;
logic clk, rst; logic clk, rst;
logic [7:0] digest_byte_len, key_byte_len; logic [7:0] digest_byte_len, key_byte_len;
logic [128*8-1:0] i_block; logic [128*8-1:0] i_block;
@ -11,6 +13,8 @@ logic o_rdy;
logic o_val; logic o_val;
logic o_err; logic o_err;
if_axi_stream #(.DAT_BYTS(blake2_pkg::NN)) out_hash(clk);
initial begin initial begin
rst = 0; rst = 0;
#100ns rst = 1; #100ns rst = 1;
@ -35,7 +39,9 @@ blake2_top DUT (
.o_digest(o_digest), .o_digest(o_digest),
.o_rdy(o_rdy), .o_rdy(o_rdy),
.o_val(o_val), .o_val(o_val),
.o_err(o_err) .o_err(o_err),
.o_hash(out_hash)
); );
// This test runs the hash which is shown in the RFC, for "abc" // This test runs the hash which is shown in the RFC, for "abc"
@ -49,19 +55,18 @@ begin
i_val = 1; i_val = 1;
i_final_block = 1; i_final_block = 1;
i_new_block = 1; i_new_block = 1;
digest_byte_len = 3;
key_byte_len = 0;
i_block = 'h636261; i_block = 'h636261;
@(negedge clk); @(negedge clk);
i_val = 0; i_val = 0;
// TODO check rdy goes low while (!out_hash.val) @(posedge clk);
while (!o_val) @(posedge clk); assert (out_hash.dat == 'h239900d4ed8623b95a92f1dba88ad31895cc3345ded552c22d79ab2a39c5877dd1a2ffdb6fbb124bb7c45a68142f214ce9f6129fb697276a0d4d1c983fa580ba) else $fatal(0, "%m %t:ERROR, out_hash.dat did not match, was:\n0x%h", $time, out_hash.dat);
assert (out_hash.sop == 1) else $fatal(0, "%m %t:ERROR, out_hash.sop was not high", $time);
@(posedge clk); assert (out_hash.eop == 1) else $fatal(0, "%m %t:ERROR, out_hash.sop was not high", $time);
@(posedge clk);
// TODO verify result
$display("rfc_test PASSED"); $display("rfc_test PASSED");
end end
@ -70,11 +75,13 @@ endtask
// Main testbench calls // Main testbench calls
initial begin initial begin
key_byte_len = 0; key_byte_len = 0;
digest_byte_len = 64; digest_byte_len = 3;
i_block = '0; i_block = '0;
i_new_block = '0; i_new_block = '0;
i_final_block = '0; i_final_block = '0;
i_val = '0; i_val = '0;
out_hash.rdy = 1;
#200ns; #200ns;

View File

@ -0,0 +1,32 @@
// Interface for a AXI stream
interface if_axi_stream # (
parameter DAT_BYTS = 8,
parameter CTL_BYTS = 8
)(
input i_clk
);
localparam DAT_BITS = DAT_BYTS*8;
localparam CTL_BITS = CTL_BYTS*8;
logic rdy;
logic val;
logic err;
logic sop;
logic eop;
logic [CTL_BITS-1:0] ctl;
logic [DAT_BITS-1:0] dat;
logic [$clog2(DAT_BYTS)-1:0] mod;
task reset();
val <= 0;
err <= 0;
sop <= 0;
eop <= 0;
dat <= 0;
ctl <= 0;
mod <= 0;
endtask
endinterface