Updates to verfi module
This commit is contained in:
parent
c8f1c9223f
commit
8b853a7159
|
@ -15,27 +15,6 @@
|
|||
# run results please launch the synthesis/implementation runs as needed.
|
||||
#
|
||||
#*****************************************************************************************
|
||||
# NOTE: In order to use this script for source control purposes, please make sure that the
|
||||
# following files are added to the source control system:-
|
||||
#
|
||||
# 1. This project restoration tcl script (create_project.tcl) that was generated.
|
||||
#
|
||||
# 2. The following source(s) files that were local or imported into the original project.
|
||||
# (Please see the '$orig_proj_dir' and '$origin_dir' variable setting below at the start of the script)
|
||||
#
|
||||
# <none>
|
||||
#
|
||||
# 3. The following remote source files that were added to the original project:-
|
||||
#
|
||||
# "C:/Users/bsdevlin/git/zcash-fpga/ip_cores/blake2b/src/rtl/blake2b_g.sv"
|
||||
# "C:/Users/bsdevlin/git/zcash-fpga/ip_cores/blake2b/src/rtl/blake2b_pkg.sv"
|
||||
# "C:/Users/bsdevlin/git/zcash-fpga/ip_cores/common/src/rtl/common_pkg.sv"
|
||||
# "C:/Users/bsdevlin/git/zcash-fpga/ip_cores/common/src/rtl/common_if.sv"
|
||||
# "C:/Users/bsdevlin/git/zcash-fpga/ip_cores/blake2b/src/rtl/blake2b_top.sv"
|
||||
# "C:/Users/bsdevlin/git/zcash-fpga/ip_cores/blake2b/synth/blake2b_top.xdc"
|
||||
# "C:/Users/bsdevlin/git/zcash-fpga/ip_cores/blake2b/src/tb/blake2b_top_tb.sv"
|
||||
#
|
||||
#*****************************************************************************************
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set script_path [ file dirname [ file normalize [ info script ] ] ]
|
||||
|
@ -148,8 +127,6 @@ set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
|
|||
set_property -name "file_type" -value "SystemVerilog" -objects $file_obj
|
||||
|
||||
|
||||
# Set 'sources_1' fileset file properties for local files
|
||||
# None
|
||||
|
||||
# Set 'sources_1' fileset properties
|
||||
set obj [get_filesets sources_1]
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
3. No duplicates
|
||||
4. Difficulty passes
|
||||
|
||||
Code is split up into 3 main always blocks, one for loading RAM, one for parsing
|
||||
output and loading the Blake2b block, and the final for running checks.
|
||||
|
||||
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
@ -45,11 +48,9 @@ equihash_gen_in_t equihash_gen_in;
|
|||
logic [N-1:0] sol_hash_xor;
|
||||
logic [$clog2(SOL_LIST_LEN)-1:0] sol_cnt_out, sol_cnt_in; // This tracks how many solutions we have XORed
|
||||
logic [$clog2(DAT_BITS)-1:0] sol_pos; // This tracks the pos in our DAT_BITS RAM output
|
||||
logic [SOL_BITS-1:0] ram_out;
|
||||
|
||||
logic [64*8-1:0] parameters;
|
||||
logic [7:0] byte_len;
|
||||
logic all_checks_done;
|
||||
logic [DAT_BITS-1:0] sol_ram_byte_bit_flip;
|
||||
|
||||
|
||||
|
||||
|
@ -60,10 +61,19 @@ if_axi_stream #(.DAT_BYTS(EQUIHASH_GEN_BYTS)) blake2b_in_hash(i_clk);
|
|||
if_ram #(.RAM_WIDTH(DAT_BITS), .RAM_DEPTH(SOL_LIST_BYTS/DAT_BYTS)) equihash_sol_bram_if_a (i_clk, i_rst);
|
||||
if_ram #(.RAM_WIDTH(DAT_BITS), .RAM_DEPTH(SOL_LIST_BYTS/DAT_BYTS)) equihash_sol_bram_if_b (i_clk, i_rst);
|
||||
logic [DAT_BITS-1:0] equihash_sol_bram_if_b_l;
|
||||
logic [1:0] equihash_sol_bram_read;
|
||||
|
||||
enum {STATE_IDLE = 0,
|
||||
STATE_DATA_WRITE = 1,
|
||||
STATE_FINISH_WAIT = 2} ram_state;
|
||||
enum {STATE_WR_IDLE = 0,
|
||||
STATE_WR_DATA = 1,
|
||||
STATE_WR_WAIT = 2} ram_wr_state;
|
||||
|
||||
enum {STATE_RD_IDLE = 0,
|
||||
STATE_RD_DATA = 1,
|
||||
STATE_RD_WAIT = 2} ram_rd_state;
|
||||
|
||||
enum {STATE_CHK_IDLE = 0,
|
||||
STATE_CHK_DATA = 1,
|
||||
STATE_CHK_WAIT = 2} chk_state;
|
||||
|
||||
// State machine for controlling writing equihash solution into the RAM and registering the header
|
||||
always_ff @ (posedge i_clk) begin
|
||||
|
@ -73,7 +83,7 @@ always_ff @ (posedge i_clk) begin
|
|||
cblockheader <= 0;
|
||||
cblockheader_byts <= 0;
|
||||
cblockheader_val <= 0;
|
||||
ram_state <= STATE_IDLE;
|
||||
ram_wr_state <= STATE_WR_IDLE;
|
||||
end else begin
|
||||
// Defaults
|
||||
equihash_sol_bram_if_a.we <= 1;
|
||||
|
@ -86,31 +96,31 @@ always_ff @ (posedge i_clk) begin
|
|||
cblockheader_byts <= cblockheader_byts + DAT_BYTS;
|
||||
end
|
||||
|
||||
case (ram_state)
|
||||
case (ram_wr_state)
|
||||
// This state we are waiting for an input block
|
||||
STATE_IDLE: begin
|
||||
STATE_WR_IDLE: begin
|
||||
i_axi.rdy <= 1;
|
||||
if (i_axi.val && i_axi.rdy) begin
|
||||
ram_state <= STATE_DATA_WRITE;
|
||||
equihash_sol_bram_if_a.a <= equihash_sol_bram_if_a.a + 1;
|
||||
ram_wr_state <= STATE_WR_DATA;
|
||||
equihash_sol_bram_if_a.a <= 0;
|
||||
end
|
||||
end
|
||||
// Here we are checking header values as well as populating the RAM
|
||||
STATE_DATA_WRITE: begin
|
||||
STATE_WR_DATA: begin
|
||||
if (i_axi.val && i_axi.rdy) begin
|
||||
equihash_sol_bram_if_a.a <= equihash_sol_bram_if_a.a + 1;
|
||||
if (i_axi.eop) begin
|
||||
i_axi.rdy <= 0;
|
||||
ram_state <= STATE_FINISH_WAIT;
|
||||
ram_wr_state <= STATE_WR_WAIT;
|
||||
end
|
||||
end
|
||||
end
|
||||
// Here we are have finished populating RAM and waiting for all checks to finish
|
||||
STATE_FINISH_WAIT: begin
|
||||
STATE_WR_WAIT: begin
|
||||
equihash_sol_bram_if_a.we <= 0;
|
||||
equihash_sol_bram_if_a.a <= equihash_sol_bram_if_a.a;
|
||||
if (all_checks_done) begin
|
||||
ram_state <= STATE_IDLE;
|
||||
if (chk_state == STATE_CHK_WAIT) begin
|
||||
ram_wr_state <= STATE_WR_IDLE;
|
||||
i_axi.rdy <= 1;
|
||||
cblockheader_val <= 0;
|
||||
equihash_sol_bram_if_a.a <= 0;
|
||||
|
@ -120,99 +130,154 @@ always_ff @ (posedge i_clk) begin
|
|||
end
|
||||
end
|
||||
|
||||
// State machine for controlling the hash calculation
|
||||
// and checking the header values
|
||||
// State machine for loading the output of RAM into the Blake2b block
|
||||
always_ff @ (posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
blake2b_in_hash.reset_source();
|
||||
equihash_sol_bram_if_b.reset_source();
|
||||
sol_cnt_in <= 0;
|
||||
sol_pos <= 0;
|
||||
equihash_sol_bram_if_b_l <= 0;
|
||||
equihash_gen_in <= 0;
|
||||
equihash_sol_bram_read <= 0;
|
||||
ram_rd_state <= STATE_RD_IDLE;
|
||||
end else begin
|
||||
// Defaults
|
||||
equihash_sol_bram_if_b.re <= 1;
|
||||
equihash_sol_bram_if_b.en <= 1;
|
||||
blake2b_in_hash.sop <= 1;
|
||||
blake2b_in_hash.eop <= 1;
|
||||
blake2b_in_hash.val <= 0;
|
||||
equihash_sol_bram_read <= equihash_sol_bram_read << 1;
|
||||
|
||||
case(ram_rd_state)
|
||||
STATE_RD_IDLE: begin
|
||||
if (~|equihash_sol_bram_read)
|
||||
equihash_sol_bram_if_b.a <= $bits(cblockheader_t)/DAT_BITS;
|
||||
sol_pos <= 3*8 + ($bits(cblockheader_t) % DAT_BITS); // Add on 3*8 as this encodes the size of solution
|
||||
sol_cnt_in <= 0;
|
||||
blake2b_in_hash.val <= 0;
|
||||
|
||||
//First case has special state
|
||||
if (equihash_sol_bram_if_a.a >= ($bits(cblockheader_t)/8) + (DAT_BYTS*2)) begin
|
||||
if (~|equihash_sol_bram_read) begin
|
||||
equihash_sol_bram_if_b_l <= sol_ram_byte_bit_flip;// equihash_sol_bram_if_b.q;
|
||||
equihash_sol_bram_if_b.a <= equihash_sol_bram_if_b.a + 1;
|
||||
equihash_sol_bram_read[0] <= 1;
|
||||
end
|
||||
if (equihash_sol_bram_read[1])
|
||||
ram_rd_state <= STATE_RD_DATA;
|
||||
end
|
||||
end
|
||||
STATE_RD_DATA: begin
|
||||
equihash_gen_in <= 0;
|
||||
equihash_gen_in.bits <= cblockheader.bits;
|
||||
equihash_gen_in.my_time <= cblockheader.my_time;
|
||||
equihash_gen_in.hash_merkle_root <= cblockheader.hash_merkle_root;
|
||||
equihash_gen_in.hash_prev_block <= cblockheader.hash_prev_block;
|
||||
equihash_gen_in.version <= cblockheader.version;
|
||||
equihash_gen_in.nonce <= cblockheader.nonce;
|
||||
// Load the solution, need to flip it
|
||||
for (int i = 0; i < SOL_BITS; i++)
|
||||
if ((sol_pos + SOL_BITS) >= DAT_BITS && (i + sol_pos < DAT_BITS))
|
||||
equihash_gen_in.index[SOL_BITS-1-i] <= equihash_sol_bram_if_b_l[i + sol_pos];
|
||||
else
|
||||
equihash_gen_in.index[SOL_BITS-1-i] <= /*equihash_sol_bram_if_b.q*/sol_ram_byte_bit_flip[(i+sol_pos) % DAT_BITS];
|
||||
|
||||
// Stay 2 clocks behind the RAM write
|
||||
if ((equihash_sol_bram_if_a.a*DAT_BYTS + DAT_BYTS) >= (equihash_sol_bram_if_b.a + $bits(cblockheader_t)/DAT_BITS) ||
|
||||
ram_wr_state == STATE_WR_WAIT) begin
|
||||
// Check if we need to load next memory address
|
||||
if (sol_pos + 2*SOL_BITS >= DAT_BITS && ~|equihash_sol_bram_read) begin
|
||||
equihash_sol_bram_if_b_l <= sol_ram_byte_bit_flip;
|
||||
equihash_sol_bram_if_b.a <= equihash_sol_bram_if_b.a + 1;
|
||||
equihash_sol_bram_read[0] <= 1;
|
||||
end
|
||||
|
||||
// Load input into Blake2b block
|
||||
blake2b_in_hash.val <= 1;
|
||||
sol_cnt_in <= sol_cnt_in + 1;
|
||||
sol_pos <= sol_pos + SOL_BITS;
|
||||
if (sol_cnt_in == SOL_LIST_LEN - 2)
|
||||
ram_rd_state <= STATE_RD_WAIT;
|
||||
end
|
||||
|
||||
end
|
||||
STATE_RD_WAIT: begin
|
||||
if (chk_state == STATE_CHK_WAIT) begin
|
||||
ram_rd_state <= STATE_RD_IDLE;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @ (posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
o_mask_val <= 0;
|
||||
o_mask <= 0;
|
||||
sol_hash_xor <= 0;
|
||||
blake2b_in_hash.reset_source();
|
||||
blake2b_out_hash.rdy <= 0;
|
||||
equihash_sol_bram_if_b.reset_source();
|
||||
all_checks_done <= 0;
|
||||
sol_cnt_in <= 0;
|
||||
sol_cnt_out <= 0;
|
||||
sol_pos <= 0;
|
||||
equihash_sol_bram_if_b_l <= 0;
|
||||
chk_state <= STATE_CHK_IDLE;
|
||||
end else begin
|
||||
// Defaults
|
||||
equihash_sol_bram_if_b.re <= 1;
|
||||
equihash_sol_bram_if_b.en <= 1;
|
||||
blake2b_out_hash.rdy <= 1;
|
||||
blake2b_in_hash.sop <= 1;
|
||||
blake2b_in_hash.eop <= 1;
|
||||
blake2b_in_hash.val <= 0;
|
||||
|
||||
if (ram_state == STATE_IDLE) begin
|
||||
equihash_sol_bram_if_b.a <= $bits(cblockheader_t)/DAT_BITS;
|
||||
sol_pos <= $bits(cblockheader_t) % DAT_BITS;
|
||||
sol_cnt_out <= 0;
|
||||
sol_cnt_in <= 0;
|
||||
blake2b_in_hash.val <= 0;
|
||||
o_mask_val <= 0;
|
||||
o_mask <= 0;
|
||||
end
|
||||
|
||||
if (cblockheader_val) begin
|
||||
equihash_gen_in.bits <= cblockheader.bits;
|
||||
equihash_gen_in.my_time <= cblockheader.my_time;
|
||||
equihash_gen_in.hash_reserved <= 0;
|
||||
equihash_gen_in.hash_merkle_root <= cblockheader.hash_merkle_root;
|
||||
equihash_gen_in.hash_prev_block <= cblockheader.hash_prev_block;
|
||||
equihash_gen_in.version <= cblockheader.version;
|
||||
equihash_gen_in.nonce <= cblockheader.nonce;
|
||||
for (int i = 0; i < SOL_BITS; i++)
|
||||
if (i + sol_pos >= DAT_BITS)
|
||||
equihash_gen_in.index[i] <= equihash_sol_bram_if_b_l[i + sol_pos - DAT_BITS];
|
||||
else
|
||||
equihash_gen_in.index[i] <= equihash_sol_bram_if_b.q[i+sol_pos];
|
||||
end
|
||||
|
||||
// We can start loading the hash block
|
||||
if((sol_cnt_in < SOL_LIST_LEN - 1) &&
|
||||
blake2b_in_hash.rdy &&
|
||||
(equihash_sol_bram_if_a.a >= $bits(cblockheader_t)/8 + DAT_BYTS)) begin
|
||||
blake2b_in_hash.val <= 1; // TODO control if we take more than one hash per clock
|
||||
sol_cnt_in <= sol_cnt_in + 1;
|
||||
sol_pos <= sol_pos + SOL_BITS;
|
||||
// Calculate if we should increase our read pointer
|
||||
if (sol_pos + 2*SOL_BITS >= DAT_BITS) begin
|
||||
equihash_sol_bram_if_b_l <= equihash_sol_bram_if_b.q; // Latch current output as we might need some bits
|
||||
equihash_sol_bram_if_b.a <= equihash_sol_bram_if_b.a + 1;
|
||||
case(chk_state)
|
||||
STATE_CHK_IDLE: begin
|
||||
sol_cnt_out <= 0;
|
||||
o_mask_val <= 0;
|
||||
o_mask <= 0;
|
||||
sol_hash_xor <= 0;
|
||||
if (ram_rd_state == STATE_RD_DATA)
|
||||
chk_state <= STATE_CHK_DATA;
|
||||
end
|
||||
STATE_CHK_DATA: begin
|
||||
|
||||
//TODO here we also need to check the ordering, and duplicates?
|
||||
// When we start getting the hash results, start XORing them
|
||||
if (blake2b_out_hash.val) begin
|
||||
sol_hash_xor <= hash_solution(sol_hash_xor, blake2b_out_hash.dat);
|
||||
sol_cnt_out <= sol_cnt_out + 1;
|
||||
//TODO here we also need to check the ordering, and duplicates?
|
||||
end
|
||||
|
||||
end
|
||||
if (sol_cnt_out == SOL_LIST_LEN - 1) begin
|
||||
o_mask.XOR_FAIL <= |sol_hash_xor;
|
||||
o_mask_val <= 1;
|
||||
chk_state <= STATE_CHK_WAIT;
|
||||
end
|
||||
|
||||
// When we start getting the hash results, start XORing them
|
||||
if (blake2b_out_hash.val) begin
|
||||
sol_hash_xor <= hash_solution(sol_hash_xor, blake2b_out_hash.dat);
|
||||
sol_cnt_out <= sol_cnt_out + 1;
|
||||
end
|
||||
|
||||
if (sol_cnt_out == SOL_LIST_LEN - 1) begin
|
||||
o_mask.XOR_FAIL <= |sol_hash_xor;
|
||||
o_mask_val <= 1;
|
||||
sol_cnt_out <= sol_cnt_out;
|
||||
equihash_sol_bram_if_b.a <= 0;
|
||||
end
|
||||
end
|
||||
STATE_CHK_WAIT: begin
|
||||
if (ram_rd_state == STATE_RD_IDLE && ram_wr_state == STATE_WR_IDLE)
|
||||
chk_state <= STATE_CHK_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Constants
|
||||
always_comb begin
|
||||
parameters = {'0, 8'd1, 8'd1, 8'd0, BLAKE2B_DIGEST_BYTS};
|
||||
parameters[48*8-1 +: 16*8] = POW_TAG;
|
||||
blake2b_in_hash.dat = equihash_gen_in;
|
||||
for (int i = 0; i < DAT_BYTS; i++)
|
||||
sol_ram_byte_bit_flip[i*8 +: 8] = flip_bit_byte(equihash_sol_bram_if_b.q[i*8 +: 8]);
|
||||
end
|
||||
|
||||
// Function to OR the hash output depending on equihash parameters
|
||||
function hash_solution(input [N-1:0] curr, input [N*INDICIES_PER_HASH-1:0] in);
|
||||
function [N-1:0] hash_solution(input [N-1:0] curr, input [N*INDICIES_PER_HASH-1:0] in);
|
||||
hash_solution = curr;
|
||||
for (int i = 0; i < INDICIES_PER_HASH; i++)
|
||||
curr = curr ^ in[i*N +: N];
|
||||
return curr;
|
||||
hash_solution = hash_solution ^ in[i*N +: N];
|
||||
endfunction
|
||||
|
||||
// Function to convert bit order in each byte of the solution list
|
||||
function [7:0] flip_bit_byte(input [7:0] in);
|
||||
for (int i = 0; i < 8; i++)
|
||||
flip_bit_byte[8-1-i] = in[i];
|
||||
endfunction
|
||||
|
||||
// Instantiate the Blake2b block - use high performance pipelined version
|
||||
|
|
|
@ -89,7 +89,7 @@ begin
|
|||
start_241 = 1;
|
||||
|
||||
|
||||
while(!done_241 && !mask_val) @(posedge clk);
|
||||
while(!done_241 || !mask_val) @(posedge clk);
|
||||
|
||||
assert (~(|mask)) else $fatal(1, "%m %t ERROR: test_block_346 mask was non-zero", $time);
|
||||
assert (~mask.XOR_FAIL) else $fatal(1, "%m %t ERROR: test_block_346 failed XOR mask check", $time);
|
||||
|
|
Loading…
Reference in New Issue