Merge pull request #3 from bsdevlin/blake2b

Blake2b
This commit is contained in:
bsdevlin 2019-02-19 09:39:26 -05:00 committed by GitHub
commit 4b9ff85954
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1820 additions and 2 deletions

11
.project Normal file
View File

@ -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>

View File

@ -1,2 +1,22 @@
# zcash-fpga
Repo for ZCash FPGA projects code and documents
Repo for Zcash FPGA projects code and documents.
## Overview
These have been designed targetted for Xilinx boards (US+) and therefore contain Xilinx-specific IP.
## zcash_verif
This is the top level for the Zcash verification FPGA board. It targets both Xilinx Virtex UltraScale+ FPGA VCU118 Evaluation Kit, and Amazon EC2 F1 Instances.
Architecture document is [here]()
## ip_cores
These contain custom IP cores used in the projects in this repo.
* blake2b - A simple implementation of blake2b and a pipline-unrolled version for high performance.
* common - Packages and interfaces that are shared.
* fifo - Fifo implementations
* parsing - Blocks for parsing/processing streams, as well as testbench files.

View File

@ -1 +0,0 @@

View File

@ -0,0 +1,519 @@
#*****************************************************************************************
# Vivado (TM) v2018.3 (64-bit)
#
# create_project.tcl: Tcl script for re-creating project 'blake2b'
#
# Generated by Vivado on Wed Feb 13 16:57:58 -0500 2019
# IP Build 2404404 on Fri Dec 7 01:43:56 MST 2018
#
# This file contains the Vivado Tcl commands for re-creating the project to the state*
# when this script was generated. In order to re-create the project, please source this
# file in the Vivado Tcl Shell.
#
# * Note that the runs in the created project will be configured the same way as the
# original project, however they will not be launched automatically. To regenerate the
# 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 ] ] ]
puts $script_path
set origin_dir $script_path
# Set the project name
set _xil_proj_name_ "blake2b"
# Use project name variable, if specified in the tcl shell
if { [info exists ::user_project_name] } {
set _xil_proj_name_ $::user_project_name
}
variable script_file
set script_file "create_project.tcl"
if { $::argc > 0 } {
for {set i 0} {$i < $::argc} {incr i} {
set option [string trim [lindex $::argv $i]]
switch -regexp -- $option {
"--origin_dir" { incr i; set origin_dir [lindex $::argv $i] }
"--project_name" { incr i; set _xil_proj_name_ [lindex $::argv $i] }
"--help" { print_help }
default {
if { [regexp {^-} $option] } {
puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n"
return 1
}
}
}
}
}
# Set the directory path for the original project from where this script was exported
set orig_proj_dir "[file normalize "$origin_dir/../proj"]"
# Create project
create_project ${_xil_proj_name_} $origin_dir/../proj/ -part xcvu9p-flga2104-2L-e
# Set the directory path for the new project
set proj_dir [get_property directory [current_project]]
# Set project properties
set obj [current_project]
set_property -name "default_lib" -value "xil_defaultlib" -objects $obj
set_property -name "dsa.accelerator_binary_content" -value "bitstream" -objects $obj
set_property -name "dsa.accelerator_binary_format" -value "xclbin2" -objects $obj
set_property -name "dsa.description" -value "Vivado generated DSA" -objects $obj
set_property -name "dsa.dr_bd_base_address" -value "0" -objects $obj
set_property -name "dsa.emu_dir" -value "emu" -objects $obj
set_property -name "dsa.flash_interface_type" -value "bpix16" -objects $obj
set_property -name "dsa.flash_offset_address" -value "0" -objects $obj
set_property -name "dsa.flash_size" -value "1024" -objects $obj
set_property -name "dsa.host_architecture" -value "x86_64" -objects $obj
set_property -name "dsa.host_interface" -value "pcie" -objects $obj
set_property -name "dsa.num_compute_units" -value "60" -objects $obj
set_property -name "dsa.platform_state" -value "pre_synth" -objects $obj
set_property -name "dsa.vendor" -value "xilinx" -objects $obj
set_property -name "dsa.version" -value "0.0" -objects $obj
set_property -name "enable_vhdl_2008" -value "1" -objects $obj
set_property -name "ip_cache_permissions" -value "read write" -objects $obj
set_property -name "ip_output_repo" -value "$proj_dir/${_xil_proj_name_}.cache/ip" -objects $obj
set_property -name "mem.enable_memory_map_generation" -value "1" -objects $obj
set_property -name "part" -value "xcvu9p-flga2104-2L-e" -objects $obj
set_property -name "sim.central_dir" -value "$proj_dir/${_xil_proj_name_}.ip_user_files" -objects $obj
set_property -name "sim.ip.auto_export_scripts" -value "1" -objects $obj
set_property -name "simulator_language" -value "Mixed" -objects $obj
# Create 'sources_1' fileset (if not found)
if {[string equal [get_filesets -quiet sources_1] ""]} {
create_fileset -srcset sources_1
}
# Set 'sources_1' fileset object
set obj [get_filesets sources_1]
set files [list \
[file normalize "${origin_dir}/../src/rtl/blake2b_g.sv"] \
[file normalize "${origin_dir}/../src/rtl/blake2b_pkg.sv"] \
[file normalize "${origin_dir}/../../common/src/rtl/common_pkg.sv"] \
[file normalize "${origin_dir}/../../common/src/rtl/common_if.sv"] \
[file normalize "${origin_dir}/../src/rtl/blake2b_top.sv"] \
]
add_files -norecurse -fileset $obj $files
# Set 'sources_1' fileset file properties for remote files
set file "$origin_dir/../src/rtl/blake2b_g.sv"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "SystemVerilog" -objects $file_obj
set file "$origin_dir/../src/rtl/blake2b_pkg.sv"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "SystemVerilog" -objects $file_obj
set file "$origin_dir/../../common/src/rtl/common_pkg.sv"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "SystemVerilog" -objects $file_obj
set file "$origin_dir/../../common/src/rtl/common_if.sv"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "SystemVerilog" -objects $file_obj
set file "$origin_dir/../src/rtl/blake2b_top.sv"
set file [file normalize $file]
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]
set_property -name "top" -value "blake2b_top" -objects $obj
# Create 'constrs_1' fileset (if not found)
if {[string equal [get_filesets -quiet constrs_1] ""]} {
create_fileset -constrset constrs_1
}
# Set 'constrs_1' fileset object
set obj [get_filesets constrs_1]
# Add/Import constrs file and set constrs file properties
set file "[file normalize "$origin_dir/../synth/blake2b_top.xdc"]"
set file_added [add_files -norecurse -fileset $obj [list $file]]
set file "$origin_dir/../synth/blake2b_top.xdc"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets constrs_1] [list "*$file"]]
set_property -name "file_type" -value "XDC" -objects $file_obj
# Set 'constrs_1' fileset properties
set obj [get_filesets constrs_1]
set_property -name "target_part" -value "xcvu9p-flga2104-2L-e" -objects $obj
# Create 'sim_1' fileset (if not found)
if {[string equal [get_filesets -quiet sim_1] ""]} {
create_fileset -simset sim_1
}
# Set 'sim_1' fileset object
set obj [get_filesets sim_1]
set files [list \
[file normalize "${origin_dir}/../src/tb/blake2b_top_tb.sv"] \
]
add_files -norecurse -fileset $obj $files
# Set 'sim_1' fileset file properties for remote files
set file "$origin_dir/../src/tb/blake2b_top_tb.sv"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sim_1] [list "*$file"]]
set_property -name "file_type" -value "SystemVerilog" -objects $file_obj
# Set 'sim_1' fileset file properties for local files
# None
# Set 'sim_1' fileset properties
set obj [get_filesets sim_1]
set_property -name "top" -value "blake2b_top_tb" -objects $obj
set_property -name "top_lib" -value "xil_defaultlib" -objects $obj
# Set 'utils_1' fileset object
set obj [get_filesets utils_1]
# Empty (no sources present)
# Set 'utils_1' fileset properties
set obj [get_filesets utils_1]
# Create 'synth_1' run (if not found)
if {[string equal [get_runs -quiet synth_1] ""]} {
create_run -name synth_1 -part xcvu9p-flga2104-2L-e -flow {Vivado Synthesis 2018} -strategy "Vivado Synthesis Defaults" -report_strategy {No Reports} -constrset constrs_1
} else {
set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1]
set_property flow "Vivado Synthesis 2018" [get_runs synth_1]
}
set obj [get_runs synth_1]
set_property set_report_strategy_name 1 $obj
set_property report_strategy {Vivado Synthesis Default Reports} $obj
set_property set_report_strategy_name 0 $obj
# Create 'synth_1_synth_report_utilization_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } {
create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1
}
set obj [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0]
if { $obj != "" } {
set_property -name "display_name" -value "synth_1_synth_report_utilization_0" -objects $obj
}
set obj [get_runs synth_1]
set_property -name "part" -value "xcvu9p-flga2104-2L-e" -objects $obj
set_property -name "strategy" -value "Vivado Synthesis Defaults" -objects $obj
# set the current synth run
current_run -synthesis [get_runs synth_1]
# Create 'impl_1' run (if not found)
if {[string equal [get_runs -quiet impl_1] ""]} {
create_run -name impl_1 -part xcvu9p-flga2104-2L-e -flow {Vivado Implementation 2018} -strategy "Vivado Implementation Defaults" -report_strategy {No Reports} -constrset constrs_1 -parent_run synth_1
} else {
set_property strategy "Vivado Implementation Defaults" [get_runs impl_1]
set_property flow "Vivado Implementation 2018" [get_runs impl_1]
}
set obj [get_runs impl_1]
set_property set_report_strategy_name 1 $obj
set_property report_strategy {Vivado Implementation Default Reports} $obj
set_property set_report_strategy_name 0 $obj
# Create 'impl_1_init_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_init_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps init_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_init_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_opt_report_drc_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] "" ] } {
create_report_config -report_name impl_1_opt_report_drc_0 -report_type report_drc:1.0 -steps opt_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_opt_report_drc_0" -objects $obj
}
# Create 'impl_1_opt_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps opt_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_opt_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_power_opt_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps power_opt_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_power_opt_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_place_report_io_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] "" ] } {
create_report_config -report_name impl_1_place_report_io_0 -report_type report_io:1.0 -steps place_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_place_report_io_0" -objects $obj
}
# Create 'impl_1_place_report_utilization_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] "" ] } {
create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_place_report_utilization_0" -objects $obj
}
# Create 'impl_1_place_report_control_sets_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] "" ] } {
create_report_config -report_name impl_1_place_report_control_sets_0 -report_type report_control_sets:1.0 -steps place_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_place_report_control_sets_0" -objects $obj
}
# Create 'impl_1_place_report_incremental_reuse_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] "" ] } {
create_report_config -report_name impl_1_place_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_place_report_incremental_reuse_0" -objects $obj
}
# Create 'impl_1_place_report_incremental_reuse_1' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] "" ] } {
create_report_config -report_name impl_1_place_report_incremental_reuse_1 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_place_report_incremental_reuse_1" -objects $obj
}
# Create 'impl_1_place_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_place_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps place_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_place_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_post_place_power_opt_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_post_place_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_place_power_opt_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_post_place_power_opt_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_phys_opt_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps phys_opt_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0]
if { $obj != "" } {
set_property -name "is_enabled" -value "0" -objects $obj
set_property -name "display_name" -value "impl_1_phys_opt_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_route_report_drc_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] "" ] } {
create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_drc_0" -objects $obj
}
# Create 'impl_1_route_report_methodology_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] "" ] } {
create_report_config -report_name impl_1_route_report_methodology_0 -report_type report_methodology:1.0 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_methodology_0" -objects $obj
}
# Create 'impl_1_route_report_power_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] "" ] } {
create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_power_0" -objects $obj
}
# Create 'impl_1_route_report_route_status_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] "" ] } {
create_report_config -report_name impl_1_route_report_route_status_0 -report_type report_route_status:1.0 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_route_status_0" -objects $obj
}
# Create 'impl_1_route_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_route_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_route_report_incremental_reuse_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] "" ] } {
create_report_config -report_name impl_1_route_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_incremental_reuse_0" -objects $obj
}
# Create 'impl_1_route_report_clock_utilization_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] "" ] } {
create_report_config -report_name impl_1_route_report_clock_utilization_0 -report_type report_clock_utilization:1.0 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_clock_utilization_0" -objects $obj
}
# Create 'impl_1_route_report_bus_skew_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] "" ] } {
create_report_config -report_name impl_1_route_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps route_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_route_report_bus_skew_0" -objects $obj
}
# Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] "" ] } {
create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_route_phys_opt_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_post_route_phys_opt_report_timing_summary_0" -objects $obj
}
# Create 'impl_1_post_route_phys_opt_report_bus_skew_0' report (if not found)
if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] "" ] } {
create_report_config -report_name impl_1_post_route_phys_opt_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps post_route_phys_opt_design -runs impl_1
}
set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0]
if { $obj != "" } {
set_property -name "display_name" -value "impl_1_post_route_phys_opt_report_bus_skew_0" -objects $obj
}
set obj [get_runs impl_1]
set_property -name "part" -value "xcvu9p-flga2104-2L-e" -objects $obj
set_property -name "strategy" -value "Vivado Implementation Defaults" -objects $obj
set_property -name "steps.write_bitstream.args.readback_file" -value "0" -objects $obj
set_property -name "steps.write_bitstream.args.verbose" -value "0" -objects $obj
# set the current impl run
current_run -implementation [get_runs impl_1]
puts "INFO: Project created:${_xil_proj_name_}"
set obj [get_dashboards default_dashboard]
# Create 'drc_1' gadget (if not found)
if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "drc_1" ] ] ""]} {
create_dashboard_gadget -name {drc_1} -type drc
}
set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "drc_1" ] ]
set_property -name "reports" -value "impl_1#impl_1_route_report_drc_0" -objects $obj
# Create 'methodology_1' gadget (if not found)
if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "methodology_1" ] ] ""]} {
create_dashboard_gadget -name {methodology_1} -type methodology
}
set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "methodology_1" ] ]
set_property -name "reports" -value "impl_1#impl_1_route_report_methodology_0" -objects $obj
# Create 'power_1' gadget (if not found)
if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "power_1" ] ] ""]} {
create_dashboard_gadget -name {power_1} -type power
}
set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "power_1" ] ]
set_property -name "reports" -value "impl_1#impl_1_route_report_power_0" -objects $obj
# Create 'timing_1' gadget (if not found)
if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "timing_1" ] ] ""]} {
create_dashboard_gadget -name {timing_1} -type timing
}
set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "timing_1" ] ]
set_property -name "reports" -value "impl_1#impl_1_route_report_timing_summary_0" -objects $obj
# Create 'utilization_1' gadget (if not found)
if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_1" ] ] ""]} {
create_dashboard_gadget -name {utilization_1} -type utilization
}
set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_1" ] ]
set_property -name "reports" -value "synth_1#synth_1_synth_report_utilization_0" -objects $obj
set_property -name "run.step" -value "synth_design" -objects $obj
set_property -name "run.type" -value "synthesis" -objects $obj
# Create 'utilization_2' gadget (if not found)
if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_2" ] ] ""]} {
create_dashboard_gadget -name {utilization_2} -type utilization
}
set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_2" ] ]
set_property -name "reports" -value "impl_1#impl_1_place_report_utilization_0" -objects $obj
move_dashboard_gadget -name {utilization_1} -row 0 -col 0
move_dashboard_gadget -name {power_1} -row 1 -col 0
move_dashboard_gadget -name {drc_1} -row 2 -col 0
move_dashboard_gadget -name {timing_1} -row 0 -col 1
move_dashboard_gadget -name {utilization_2} -row 1 -col 1
move_dashboard_gadget -name {methodology_1} -row 2 -col 1
# Set current dashboard to 'default_dashboard'
current_dashboard default_dashboard

View File

@ -0,0 +1,78 @@
/*
The BLAKE2b g function.
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 <https://www.gnu.org/licenses/>.
*/
module blake2b_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

View File

@ -0,0 +1,257 @@
/*
This is a pipeline unrolled implementation of Blake2b (from RFC-7693)
In order to get maximum throughput, the entire message block is required on the first clock cycle,
so all hashes are single clock with .sop and .eop high.
You can optionally unroll the entire pipeline but this will use a large number of resources.
If you only unroll one pass, you need to interleave the hashes to get the best performance.
So the first part of input message comes on first clock cycle, and the next part comes 26 clocks later.
Does not support using keys.
Futher optimization to save area is fixing part of input message constant for
all hashes (just have nonce as input that changes and place this in i_block.ctl).
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 <https://www.gnu.org/licenses/>.
*/
module blake2b_pipe_top
import blake2b_pkg::*;
#(
// Do we fully unroll the pipeline (lot of resources) or just un-roll one pass
parameter FULLY_UNROLL = 0,
// If we fully unfold the pipeline, the message byte length is hard-coded
parameter MSG_LEN = 3,
parameter CTL_BITS = 8
)
(
input i_clk, i_rst,
input [7:0] i_byte_len, // Length of the input message
input [64*8-1:0] i_parameters, // Input parameters used in the inital state.
if_axi_stream.sink i_block, // Input block with valid and ready signals for flow control
if_axi_stream.source o_hash // Output digest with valid and ready signals for flow control
);
localparam NUM_ROUNDS = 12;
localparam NUM_PASSES = 1 + MSG_LEN/128;
localparam NUM_PIPE = 2 + NUM_PASSES*(NUM_ROUNDS*2) + 2*NUM_PASSES - 1;
logic [NUM_PIPE-1:0][15:0][63:0] v;
logic [NUM_PIPE-1:0][7:0][63:0] h;
logic [NUM_PIPE-1:0][15:0][63:0] msg;
logic [NUM_PIPE-1:0][CTL_BITS-1:0] ctl;
logic [NUM_PIPE-1:0] eop_l, sop_l, valid;
generate
genvar g0, g1, g2, g3;
// Since this is a single pipeline flow we pause if output is not ready
// Simplier than dealing with valid bubbles in the pipeline
always_comb i_block.rdy = o_hash.rdy;
// Assign the output from the final pipeline stage
always_comb begin
o_hash.val = valid[NUM_PIPE-1];
o_hash.ctl = ctl[NUM_PIPE-1];
o_hash.sop = 1;
o_hash.eop = 1;
o_hash.dat = h[NUM_PIPE-1];
end
// First stage has special logic
always_ff @ (posedge i_clk) begin
if (i_rst) begin
h[0] <= 0;
v[0] <= 0;
msg[0] <= i_block.dat;
ctl[0] <= i_block.ctl;
v[0] <= 0;
h[0] <= 0;
valid[0] <= 0;
valid[1] <= 0;
end else begin
if (i_block.rdy) begin
// First stage
h[0] <= i_parameters ^ blake2b_pkg::IV;
v[0] <= 0;
msg[0] <= i_block.dat;
ctl[0] <= i_block.ctl;
valid[0] <= i_block.val;
end
if (o_hash.rdy) begin
// Second stage
h[1] <= h[0];
init_local_work_vector_pipe(1, NUM_PASSES == 1); // initializes v[1]
msg[1] <= msg[0];
ctl[1] <= ctl[0];
valid[1] <= valid[0];
end
end
end
for (g0 = 0; g0 < NUM_PASSES; g0++) begin: GEN_PASS
localparam LAST_BLOCK = (g0 == NUM_PASSES -1);
localparam SR_MSG_BYTS = LAST_BLOCK ? MSG_LEN % 128 : 128;
localparam PIPE_G0 = 2 + NUM_ROUNDS*2 + g0*(NUM_ROUNDS*2 + 2);
// Each pass after 0 has a shift register for storing that part of the message
if_axi_stream #(.DAT_BYTS(SR_MSG_BYTS)) msg_in(clk);
if_axi_stream #(.DAT_BYTS(SR_MSG_BYTS)) msg_out(clk);
// At the end of each round are two pipeline stages for updating
// the local state
always_ff @ (posedge i_clk) begin
if (i_rst) begin
valid[PIPE_G0] <= 0;
valid[PIPE_G0+1] <= 0;
end else begin
if (o_hash.rdy) begin
valid[PIPE_G0] <= valid[PIPE_G0-1];
valid[PIPE_G0+1] <= valid[PIPE_G0];
end
end
end
always_ff @ (posedge i_clk) begin
msg_out.rdy <= 0;
// First stage
// Some pipelines not used in this stage
msg[PIPE_G0] <= 0;
ctl[PIPE_G0] <= 0;
v[PIPE_G0] <= 1;
if (o_hash.rdy) begin
for (int i = 0; i < 8; i++)
h[PIPE_G0][i] <= h[PIPE_G0-1][i] ^ v[PIPE_G0-1][i] ^ v[PIPE_G0-1][i+8];
end
// Second stage
if (o_hash.rdy) begin
h[PIPE_G0+1] <= h[PIPE_G0];
init_local_work_vector_pipe(PIPE_G0+2, LAST_BLOCK);
// Need to pull msg and ctl from the shift register if we have more than one pass
// and we fully unrolled. Otherwise next input will be on input. Assert the control
// matches.
msg_out.rdy <= 1;
if (g0 > 0) begin
msg[PIPE_G0+1] <= msg_out.dat;
ctl[PIPE_G0+1] <= msg_out.ctl;
end else begin
msg[PIPE_G0+1] <= 0;
ctl[PIPE_G0+1] <= 0;
end
end
end
if (g0 > 0 && FULLY_UNROLL != 0) begin: GEN_MSG_FIFO
always_ff @ (posedge i_clk) begin
if (msg_in.val && msg_in.rdy) begin
msg_in.dat <= i_block.dat[128*8*g0 :+ 128*8];
msg_in.sop <= 0;
msg_in.eop <= 0;
msg_in.err <= 0;
msg_in.ctl <= i_block.ctl;
msg_in.mod <= LAST_BLOCK ? i_block.mod : 0;
end
end
always_comb begin
if (g0 == 0) i_block.rdy = msg_in.rdy;
msg_in.val = i_block.val;
end
axi_stream_fifo #(
.A_BITS ( $clog2(NUM_ROUNDS + 2) ),
.DAT_BITS ( 128*8 ),
.CTL_BITS ( CTL_BITS )
)
message_fifo (
.i_clk ( i_clk ),
.i_rst ( i_rst ),
.i_axi ( msg_in ),
.o_axi ( msg_out )
);
end
for (g1 = 0; g1 < NUM_ROUNDS; g1++) begin: GEN_ROUND
for (g2 = 0; g2 < 2; g2++) begin: GEN_G_FUNC
// Each pipeline stage has 4 G function blocks in parallel
localparam PIPE_G2 = 2 + g0*(2 + NUM_ROUNDS*2) + g1*2 + g2;
always_ff @(posedge i_clk) begin
if (i_rst) begin
valid[PIPE_G2] <= 0;
end else begin
if (o_hash.rdy) valid[PIPE_G2] <= valid[PIPE_G2-1];
end
end
always_ff @(posedge i_clk) begin
if (o_hash.rdy) begin
msg[PIPE_G2] <= msg[PIPE_G2-1];
//if (PIPE_G2 != PIPE_G0)
h[PIPE_G2] <= h[PIPE_G2-1];
ctl[PIPE_G2] <= ctl[PIPE_G2-1]; // TODO could remove?
end
end
for (g3 = 0; g3 < 4; g3++) begin: GEN_G_FUNC_COL_DIAG
blake2b_g
#( .PIPELINES(1) )
blake2b_g (
.i_clk(i_clk),
.i_a(g2 == 0 ? v[PIPE_G2-1][blake2b_pkg::G_MAPPING[(g3*4 + 0)]] : v[PIPE_G2-1][blake2b_pkg::G_MAPPING[16 + (g3*4 + 0)]]),
.i_b(g2 == 0 ? v[PIPE_G2-1][blake2b_pkg::G_MAPPING[(g3*4 + 1)]] : v[PIPE_G2-1][blake2b_pkg::G_MAPPING[16 + (g3*4 + 1)]]),
.i_c(g2 == 0 ? v[PIPE_G2-1][blake2b_pkg::G_MAPPING[(g3*4 + 2)]] : v[PIPE_G2-1][blake2b_pkg::G_MAPPING[16 + (g3*4 + 2)]]),
.i_d(g2 == 0 ? v[PIPE_G2-1][blake2b_pkg::G_MAPPING[(g3*4 + 3)]] : v[PIPE_G2-1][blake2b_pkg::G_MAPPING[16 + (g3*4 + 3)]]),
.i_m0(msg[PIPE_G2-1][blake2b_pkg::SIGMA[16*(g1%10) + g2*8 + g3*2]]),
.i_m1(msg[PIPE_G2-1][blake2b_pkg::SIGMA[16*(g1%10) + g2*8 + g3*2 + 1]]),
.o_a(v[PIPE_G2][g2 == 0 ? blake2b_pkg::G_MAPPING[g3*4 + 0] : blake2b_pkg::G_MAPPING[16 + g3*4 + 0]]),
.o_b(v[PIPE_G2][g2 == 0 ? blake2b_pkg::G_MAPPING[g3*4 + 1] : blake2b_pkg::G_MAPPING[16 + g3*4 + 1]]),
.o_c(v[PIPE_G2][g2 == 0 ? blake2b_pkg::G_MAPPING[g3*4 + 2] : blake2b_pkg::G_MAPPING[16 + g3*4 + 2]]),
.o_d(v[PIPE_G2][g2 == 0 ? blake2b_pkg::G_MAPPING[g3*4 + 3] : blake2b_pkg::G_MAPPING[16 + g3*4 + 3]])
);
end
end
end
end
endgenerate
// Task to initialize local work vector for the compression function
// Modified to work with pipeline version
task init_local_work_vector_pipe(input integer j, input last_block);
begin
for (int i = 0; i < 16; i++)
case (i) inside
0,1,2,3,4,5,6,7: v[j][i] <= h[j-1][i];
8,9,10,11: v[j][i] <= blake2b_pkg::IV[i%8];
12: v[j][i] <= blake2b_pkg::IV[i%8] ^ (last_block ? (MSG_LEN % 128) : j*128);
13: v[j][i] <= blake2b_pkg::IV[i%8] ^ j*128 >> 64;
14: v[j][i] <= blake2b_pkg::IV[i%8] ^ {64{last_block}};
15: v[j][i] <= blake2b_pkg::IV[i%8];
endcase
end
endtask
endmodule

View File

@ -0,0 +1,69 @@
/*
The BLAKE2b package file.
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 <https://www.gnu.org/licenses/>.
*/
package blake2b_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
};
// Sigma permutations used for G function blocks and input messages
parameter [16*10-1:0][31:0] SIGMA = {
32'd0, 32'd13, 32'd12, 32'd3, 32'd14, 32'd9, 32'd11, 32'd15, 32'd5, 32'd1, 32'd6, 32'd7, 32'd4, 32'd8, 32'd2, 32'd10,
32'd5, 32'd10, 32'd4, 32'd1, 32'd7, 32'd13, 32'd2, 32'd12, 32'd8, 32'd0, 32'd3, 32'd11, 32'd9, 32'd14, 32'd15, 32'd6,
32'd10, 32'd2, 32'd6, 32'd8, 32'd4, 32'd15, 32'd0, 32'd5, 32'd9, 32'd3, 32'd1, 32'd12, 32'd14, 32'd7, 32'd11, 32'd13,
32'd11, 32'd8, 32'd2, 32'd9, 32'd3, 32'd6, 32'd7, 32'd0, 32'd10, 32'd4, 32'd13, 32'd14, 32'd15, 32'd1, 32'd5, 32'd12,
32'd9, 32'd1, 32'd14, 32'd15, 32'd5, 32'd7, 32'd13, 32'd4, 32'd3, 32'd8, 32'd11, 32'd0, 32'd10, 32'd6, 32'd12, 32'd2,
32'd13, 32'd3, 32'd8, 32'd6, 32'd12, 32'd11, 32'd1, 32'd14, 32'd15, 32'd10, 32'd4, 32'd2, 32'd7, 32'd5, 32'd0, 32'd9,
32'd8, 32'd15, 32'd0, 32'd4, 32'd10, 32'd5, 32'd6, 32'd2, 32'd14, 32'd11, 32'd12, 32'd13, 32'd1, 32'd3, 32'd9, 32'd7,
32'd4, 32'd9, 32'd1, 32'd7, 32'd6, 32'd3, 32'd14, 32'd10, 32'd13, 32'd15, 32'd2, 32'd5, 32'd0, 32'd12, 32'd8, 32'd11,
32'd3, 32'd5, 32'd7, 32'd11, 32'd2, 32'd0, 32'd12, 32'd1, 32'd6, 32'd13, 32'd15, 32'd9, 32'd8, 32'd4, 32'd10, 32'd14,
32'd15, 32'd14, 32'd13, 32'd12, 32'd11, 32'd10, 32'd9, 32'd8, 32'd7, 32'd6, 32'd5, 32'd4, 32'd3, 32'd2, 32'd1, 32'd0
};
// Mapping for each G function block to the state vector v
parameter [4*8-1:0][31:0] G_MAPPING = {
32'd14, 32'd9, 32'd4, 32'd3,
32'd13, 32'd8, 32'd7, 32'd2,
32'd12, 32'd11, 32'd6, 32'd1,
32'd15, 32'd10, 32'd5, 32'd0,
32'd15, 32'd11, 32'd7, 32'd3,
32'd14, 32'd10, 32'd6, 32'd2,
32'd13, 32'd9, 32'd5, 32'd1,
32'd12, 32'd8, 32'd4, 32'd0
};
// This is so we can get the correct mapping back from the diagonal
// operation
parameter [4*4-1:0][31:0] G_MAPPING_DIAG = {
32'd3, 32'd15, 32'd11, 32'd7,
32'd6, 32'd2, 32'd14, 32'd10,
32'd9, 32'd5, 32'd1, 32'd13,
32'd12, 32'd8 , 32'd4, 32'd0
};
endpackage

View File

@ -0,0 +1,229 @@
/*
Implemented from RFC-7693, The BLAKE2b Cryptographic Hash and Message Authentication Code (MAC)
Parameters are passed in as an input. Inputs and outputs are AXI stream and respect flow control.
Only only hash is computed at a time, and takes 26 clocks * number of 128 Byte message blocks.
Does not have functionalty to use a key.
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 <https://www.gnu.org/licenses/>.
*/
module blake2b_top
import blake2b_pkg::*;
(
input i_clk, i_rst,
input [7:0] i_byte_len, // Length of the input message
input [64*8-1:0] i_parameters, // Input parameters used in the inital state.
if_axi_stream.sink i_block, // Input block with valid and ready signals for flow control
if_axi_stream.source o_hash // Output digest with valid and ready signals for flow control
);
enum {STATE_IDLE = 0,
STATE_ROUNDS = 1,
STATE_NEXT_BLOCK = 2,
STATE_FINAL_BLOCK = 3} blake2_state;
localparam ROUNDS = 12;
logic [7:0][63:0] h, h_tmp; // The state vector
logic [15:0][63:0] v, v_tmp; // The local work vector and its intermediate value
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
logic [$clog2(ROUNDS)-1:0] round_cntr, round_cntr_msg, round_cntr_fin;
logic g_col;
logic [15:0][63:0] block, block_r; // The message block registered and converted to a 2d array
logic block_eop_l; // Use to latch if this is the final block
logic h_xor_done;
logic [7:0] byte_len_l;
// Pipelining logic that has no reset
always_ff @(posedge i_clk) begin
if (blake2_state == STATE_IDLE)
block_r <= 0;
if (i_block.val && i_block.rdy)
block_r <= i_block.dat;
for (int i = 0; i < 16; i++) begin
v_tmp[blake2b_pkg::G_MAPPING[i]] <= g_out[i];
end
for (int i = 0; i < 8; i++)
if (blake2_state == STATE_ROUNDS)
h_tmp[i] <= g_out[16 + blake2b_pkg::G_MAPPING_DIAG[i]] ^ g_out[16 + blake2b_pkg::G_MAPPING_DIAG[i+8]];
end
always_comb begin
block = i_block.dat;
end
// State machine logic for compressing
always_ff @(posedge i_clk) begin
if (i_rst) begin
blake2_state <= STATE_IDLE;
i_block.rdy <= 0;
h <= 0;
v <= 0;
t <= 128;
g_col <= 0;
round_cntr <= 0;
round_cntr_msg <= 0;
o_hash.reset_source();
round_cntr_fin <= 0;
block_eop_l <= 0;
h_xor_done <= 0;
byte_len_l <= 0;
end else begin
g_col <= ~g_col;
case (blake2_state)
STATE_IDLE: begin
h <= i_parameters ^ blake2b_pkg::IV;
t <= 2;
i_block.rdy <= 1;
v <= 0;
o_hash.val <= 0;
g_col <= 0;
round_cntr <= 0;
round_cntr_msg <= 0;
round_cntr_fin <= 0;
if (i_block.rdy && i_block.val && i_block.sop) begin
init_local_work_vector(i_block.eop ? i_byte_len : 128, i_block.eop);
blake2_state <= STATE_ROUNDS;
g_col <= 0;
i_block.rdy <= 0;
block_eop_l <= i_block.eop;
byte_len_l <= i_byte_len;
end
end
// Here we do the compression over 12 rounds, each round can be done in two clock cycles
STATE_ROUNDS: begin
// Update local work vector with output of G function blocks depending on column or diagonal operation
for (int i = 0; i < 16; i++)
v[i] <= g_out[16 + blake2b_pkg::G_MAPPING_DIAG[i]];
if (g_col)
round_cntr <= round_cntr + 1;
else
round_cntr_msg <= (round_cntr_msg + 1) % 10;
if (round_cntr == ROUNDS-1)
round_cntr_fin <= 1;
if (round_cntr_fin) begin
if (block_eop_l)
blake2_state <= STATE_FINAL_BLOCK;
else
blake2_state <= STATE_NEXT_BLOCK;
end
end
STATE_NEXT_BLOCK: begin
round_cntr <= 0;
round_cntr_msg <= 0;
round_cntr_fin <= 0;
h_xor_done <= 1;
i_block.rdy <= 1;
if (~h_xor_done)
for (int i = 0; i < 8; i++)
h[i] <= h[i] ^ h_tmp[i];
if (i_block.rdy && i_block.val) begin
init_local_work_vector(i_block.eop ? byte_len_l : t*128, i_block.eop);
block_eop_l <= i_block.eop;
t <= t + 1;
blake2_state <= STATE_ROUNDS;
h_xor_done <= 0;
i_block.rdy <= 0;
g_col <= 0;
end
end
STATE_FINAL_BLOCK: begin
round_cntr <= 0;
round_cntr_fin <= 0;
round_cntr_msg <= 0;
if (~o_hash.val || (o_hash.val && o_hash.rdy)) begin
if (~o_hash.val) begin
o_hash.dat <= h ^ h_tmp;
o_hash.val <= 1;
o_hash.sop <= 1;
o_hash.eop <= 1;
end
if (o_hash.rdy) begin
blake2_state <= STATE_IDLE;
i_block.rdy <= 1;
end
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
// For each G function we want to pipeline the input message to help timing
logic [63:0] m0, m1;
always_ff @ (posedge i_clk) begin
if(blake2_state == STATE_IDLE || blake2_state == STATE_NEXT_BLOCK) begin
m0 <= block[blake2b_pkg::SIGMA[gv_g*2]];
m1 <= block[blake2b_pkg::SIGMA[gv_g*2 + 1]];
end else begin
m0 <= block_r[blake2b_pkg::SIGMA[16*round_cntr_msg + gv_g*2]];
m1 <= block_r[blake2b_pkg::SIGMA[16*round_cntr_msg + gv_g*2 + 1]];
end
end
blake2b_g
#(.PIPELINES(0))
blake2b_g (
.i_clk(i_clk),
.i_a(gv_g < 4 ? v[blake2b_pkg::G_MAPPING[(gv_g*4 + 0)]] : v_tmp[blake2b_pkg::G_MAPPING[(gv_g*4 + 0)]]),
.i_b(gv_g < 4 ? v[blake2b_pkg::G_MAPPING[(gv_g*4 + 1)]] : v_tmp[blake2b_pkg::G_MAPPING[(gv_g*4 + 1)]]),
.i_c(gv_g < 4 ? v[blake2b_pkg::G_MAPPING[(gv_g*4 + 2)]] : v_tmp[blake2b_pkg::G_MAPPING[(gv_g*4 + 2)]]),
.i_d(gv_g < 4 ? v[blake2b_pkg::G_MAPPING[(gv_g*4 + 3)]] : v_tmp[blake2b_pkg::G_MAPPING[(gv_g*4 + 3)]]),
.i_m0(m0),
.i_m1(m1),
.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 local work vector for the compression function
task init_local_work_vector(input [127:0] cntr, input last_block);
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] <= blake2b_pkg::IV[i%8];
12: v[i] <= blake2b_pkg::IV[i%8] ^ cntr[63:0];
13: v[i] <= blake2b_pkg::IV[i%8] ^ cntr[64 +: 64];
14: v[i] <= blake2b_pkg::IV[i%8] ^ {64{last_block}};
15: v[i] <= blake2b_pkg::IV[i%8];
endcase
end
endtask
endmodule

View File

@ -0,0 +1,65 @@
/*
The BLAKE2b g function testbench.
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 <https://www.gnu.org/licenses/>.
*/
module blake2b_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;
blake2b_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

View File

@ -0,0 +1,133 @@
/*
The BLAKE2b testbench.
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 <https://www.gnu.org/licenses/>.
*/
module blake2b_top_tb();
parameter USE_BLAKE2B_PIPE = 1; // This instantiates the pipelined version instead
parameter USE_BLAKE2B_PIPE_MSG_LEN = 3;
import blake2b_pkg::*;
import common_pkg::*;
logic clk, rst;
logic [7:0] i_byte_len;
logic [64*8-1:0] parameters;
logic [64*8-1:0] expected;
if_axi_stream #(.DAT_BYTS(USE_BLAKE2B_PIPE == 0 ? 128 : USE_BLAKE2B_PIPE_MSG_LEN)) i_block(clk);
if_axi_stream #(.DAT_BYTS(64)) out_hash(clk);
initial begin
rst = 0;
#100ns rst = 1;
#100ns rst = 0;
end
initial begin
clk = 0;
forever #10ns clk = ~clk;
end
generate if ( USE_BLAKE2B_PIPE == 0 ) begin: DUT_GEN
blake2b_top DUT (
.i_clk ( clk ),
.i_rst ( rst ),
.i_parameters ( parameters ),
.i_byte_len ( i_byte_len ),
.i_block ( i_block ),
.o_hash ( out_hash )
);
end else begin
blake2b_pipe_top #(
.MSG_LEN ( 3 ),
.CTL_BITS ( 8 )
)
DUT (
.i_clk ( clk ),
.i_rst ( rst ),
.i_parameters ( parameters ),
.i_byte_len ( i_byte_len ),
.i_block ( i_block ),
.o_hash ( out_hash )
);
end
endgenerate
// This test runs the hash which is shown in the RFC, for "abc"
task rfc_test();
begin
integer signed get_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat;
$display("Running rfc_test...\n");
expected = 'h239900d4ed8623b95a92f1dba88ad31895cc3345ded552c22d79ab2a39c5877dd1a2ffdb6fbb124bb7c45a68142f214ce9f6129fb697276a0d4d1c983fa580ba;
i_byte_len = 3;
i_block.put_stream("cba", i_byte_len);
out_hash.get_stream(get_dat, get_len);
common_pkg::compare_and_print(get_dat, expected);
$display("rfc_test PASSED");
end
endtask
// This is a test for hashing random string of 128 bytes
task test_128_bytes();
begin
integer signed get_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat;
$display("Running test_128_bytes...");
expected = 'hd2a56bb7bb1ff1fffcf2f151522455e32969ddfeb409b105f45299b8cbd68eb370fd6d45d63981d23cd2686dfd9a76f5b1d134be076f7d08ecc457522042e34a;
i_byte_len = 128;
i_block.put_stream("monek14SFMpNgHz12zMfplMfcHkx6JhKhSWTNwzGiq8UiPa4n4Ehq363oHG92GPDVpvQut4ui5e6XxieeKTn1THLWiMZ0iaOFndxcT6FGPgmHXQ5zJU96X71zfWbvUQs", i_byte_len);
out_hash.get_stream(get_dat, get_len);
common_pkg::compare_and_print(get_dat, expected);
$display("test_128_bytes PASSED");
end
endtask
// This is a test for hashing random string of 140 bytes (does two passes which is required for equihash)
task test_140_bytes();
begin
integer signed get_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat;
$display("Running test_140_bytes...");
expected = 'h2012a869a3b89a69ffc954f6855c7f61a61190553dc487171ec3fe944d04c83cd4c842fff5a8258d5e14b05b7b6f30e8ddcb754d719137ec42fb5cdb562f8c89;
i_byte_len = 140;
i_block.put_stream("YbEAEzgJ1tgC3t6vDaJFqlWp1PaL482f7iZZzRj3xXpY2PPupwdTKAaBzB6KuN6j0alaoaFQfNboDbkNv5KDs5d7zN9JssrtOjGJdrVLfvb7uAdnVYoIgIv2zbXUQIPpwWdzEzj1CzX5", i_byte_len);
out_hash.get_stream(get_dat, get_len);
common_pkg::compare_and_print(get_dat, expected);
$display("test_140_bytes PASSED");
end
endtask
// Main testbench calls
initial begin
i_block.reset_source();
i_byte_len = 3;
out_hash.rdy = 1;
parameters = {32'd0, 8'd1, 8'd1, 8'd0, 8'd64};
#200ns;
rfc_test();
// test_128_bytes();
// test_140_bytes();
#10us $finish();
end
endmodule

View File

@ -0,0 +1 @@
create_clock -period 5.000 -name i_clk -waveform {0.000 2.500} [get_ports -filter { NAME =~ "i_clk" && DIRECTION == "IN" }]

View File

@ -0,0 +1,98 @@
/*
Interface for a AXI stream
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 <https://www.gnu.org/licenses/>.
*/
interface if_axi_stream # (
parameter DAT_BYTS = 128,
parameter CTL_BYTS = 8
)(
input clk
);
import common_pkg::*;
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;
modport sink (input val, err, sop, eop, ctl, dat, mod, output rdy);
modport source (output val, err, sop, eop, ctl, dat, mod, input rdy, import task reset_source());
// Task to reset a source interface signals to all 0
task reset_source();
val <= 0;
err <= 0;
sop <= 0;
eop <= 0;
dat <= 0;
ctl <= 0;
mod <= 0;
endtask
// Task used in simulation to drive data on a source interface
task automatic put_stream(input logic [common_pkg::MAX_SIM_BYTS*8-1:0] data, input integer signed len);
logic sop_l=0;
reset_source();
@(posedge clk);
while (len > 0) begin
sop = ~sop_l;
eop = len - DAT_BYTS <= 0;
val = 1;
dat = data;
if (eop) mod = len;
data = data >> DAT_BITS;
sop_l = 1;
len = len - DAT_BYTS;
@(posedge clk); // Go to next clock edge
while (!rdy) @(posedge clk); // If not rdy then wait here
end
reset_source();
endtask
// Task used in simulation to get data from a sink interface
task automatic get_stream(ref logic [common_pkg::MAX_SIM_BYTS*8-1:0] data, ref integer signed len);
logic sop_l = 0;
rdy = 1;
len = 0;
data = 0;
@(posedge clk);
while (1) begin
if (val && rdy) begin
sop_l = sop_l || sop;
if (!sop_l) $warning("%m %t:WARNING, get_stream() .val without seeing .sop", $time);
data[len*8 +: DAT_BITS] = dat;
len = len + (eop ? (mod == 0 ? DAT_BYTS : mod) : DAT_BYTS);
if (eop) break;
end
@(posedge clk);
end
endtask
endinterface

View File

@ -0,0 +1,42 @@
/*
Common parameter values and tasks
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 <https://www.gnu.org/licenses/>.
*/
package common_pkg;
parameter MAX_SIM_BYTS = 1024; // In simulation tasks how big is the logic register for putting / getting data
// Compare bytes and print if they do not match
task compare_and_print(input logic [MAX_SIM_BYTS*8-1:0] data, expected);
if (data == expected) begin
$display("%m %t INFO: Data matched", $time);
end else begin
$write("exp: 0x");
while(expected != 0) begin
$write("%x", expected[7:0]);
expected = expected >> 8;
end
$write("\nwas: 0x");
while(data != 0) begin
$write("%x", data[7:0]);
data = data >> 8;
end
$write("\n");
$fatal(1, "%m %t ERROR: data did not match", $time);
end
endtask
endpackage

View File

@ -0,0 +1,70 @@
/*
This is a simple FIFO implementation using AXI stream source and sink interfaces.
It has a single clock delay from i_axi to o_axi in the case of an empty FIFO.
Only works with power of 2 A_BITS
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 <https://www.gnu.org/licenses/>.
*/
module axi_stream_fifo #(
parameter A_BITS,
parameter DAT_BITS,
parameter CTL_BITS
) (
input i_clk, i_rst,
if_axi_stream.sink i_axi,
if_axi_stream.source o_axi
);
localparam MOD_BITS = $clog2(DAT_BITS/8);
logic [$clog2(A_BITS):0] rd_ptr, wr_ptr;
logic empty, full;
logic [A_BITS-1:0][DAT_BITS + CTL_BITS + MOD_BITS + 3 -1:0] ram;
// Control for full and empty, and assigning outputs from the ram
always_comb begin
empty = (rd_ptr == wr_ptr);
full = (wr_ptr == rd_ptr - 1);
i_axi.rdy = ~full;
o_axi.dat = ram[rd_ptr][0 +: DAT_BITS];
o_axi.ctl = ram[rd_ptr][DAT_BITS +: CTL_BITS];
o_axi.mod = ram[rd_ptr][CTL_BITS+DAT_BITS +: MOD_BITS];
o_axi.sop = ram[rd_ptr][CTL_BITS+DAT_BITS+MOD_BITS +: 1];
o_axi.eop = ram[rd_ptr][CTL_BITS+DAT_BITS+MOD_BITS+1 +: 1];
o_axi.val = ~empty;
end
// Logic for writing and reading from ram without reset
always_ff @ (posedge i_clk) begin
if (i_axi.val && i_axi.rdy) begin
ram [wr_ptr] <= {i_axi.eop, i_axi.sop, i_axi.mod, i_axi.ctl, i_axi.dat};
end
end
// Control logic which requires a reset
always_ff @ (posedge i_clk) begin
if (i_rst) begin
rd_ptr <= 0;
wr_ptr <= 0;
end else begin
wr_ptr <= i_axi.val && i_axi.rdy ? (wr_ptr + 1) : wr_ptr;
rd_ptr <= o_axi.val && o_axi.rdy ? (rd_ptr + 1) : rd_ptr;
end
end
endmodule

View File

@ -0,0 +1,67 @@
/*
This reads a binary or ASCII file and creates an AXI stream,
used for testbench purposes. Can optionally add in random flow control.
Only binary is supported at this moment.
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 <https://www.gnu.org/licenses/>.
*/
module file_to_axi #(
parameter HDR_BYTS,
parameter DAT_BYTS,
parameter BINARY, // 0 for ASCII, 1 for binary
parameter string FILE = "", // Path to file
parameter FP = 0 // Forward pressure, if this is non-zero then this is the % of cycles o_axi.val will be low
) (
input i_clk, i_rst,
if_axi_stream.source o_axi
);
logic [DAT_BYTS*8-1:0] data_temp;
integer fp, r;
logic sop_l;
initial begin
o_axi.reset_source();
sop_l = 0;
fp = $fopen(FILE, BINARY ? "rb" : "r");
if (fp==0) $fatal(1, "%m %t ERROR: file_to_axi could not open file %s", $time, FILE);
if (BINARY == 0) begin
$fatal(1, "%m %t ERROR: file_to_axi BINARY == 0 not supported", $time);
end else begin
while(!$feof(fp)) begin
r = $fread(o_axi.dat, fp);
o_axi.val = 1; // TODO
o_axi.sop = ~sop_l;
sop_l = 1;
o_axi.eop = $feof(fp);
o_axi.mod = $feof(fp) ? r : 0;
@(posedge o_axi.clk);
while (!(o_axi.val && o_axi.rdy)) @(posedge o_axi.clk);
end
end
o_axi.reset_source();
$display("%m %t INFO: file_to_axi finished reading file %s", $time, FILE);
$fclose(fp);
end
endmodule

View File

@ -0,0 +1,67 @@
/*
This takes in a AXI stream, appends a header, and outputs the resulting stream.
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 <https://www.gnu.org/licenses/>.
*/
module header_adder #(
parameter HDR_BYTS,
parameter DAT_BYTS
) (
input i_clk, i_rst,
input [HDR_BYTS*8-1:0] i_header, // Must be valid during i_axi.val
if_axi_stream.sink i_axi,
if_axi_stream.source o_axi
);
logic [(DAT_BYTS+(HDR_BYTS % DAT_BYTS))*8-1:0] dat_buff;
logic sop_l;
logic [$clog2(HDR_BYTS)-1:0] hdr_cnt;
always_comb begin
i_axi.dat = dat_buff[HDR_BYTS*8 +: DAT_BYTS*8];
end
always_ff @ (posedge i_clk) begin
if (i_rst) begin
dat_buff <= 0;
hdr_cnt <= 0;
i_axi.rdy <= 0;
sop_l <= 0;
o_axi.reset_source();
end else begin
i_axi.rdy <= o_axi.rdy && (hdr_cnt + DAT_BYTS >= HDR_BYTS);
if (~o_axi.val || (~o_axi.val && o_axi.rdy)) begin
o_axi.sop <= ~sop_l;
o_axi.val <= i_axi.val;
o_axi.err <= i_axi.err;
o_axi.ctl <= i_axi.ctl;
o_axi.mod <= (i_axi.mod + HDR_BYTS) % DAT_BYTS;
o_axi.eop <= i_axi.eop;
hdr_cnt <= (hdr_cnt + DAT_BYTS >= HDR_BYTS) ? hdr_cnt : hdr_cnt + DAT_BYTS;
sop_l <= i_axi.sop;
//TODO
dat_buff <= {dat_buff[0 +: (HDR_BYTS % DAT_BYTS)*8], i_axi.dat};
if (i_axi.eop) hdr_cnt <= 0;
end
end
end
endmodule

1
zcash_verif/README.md Normal file
View File

@ -0,0 +1 @@
This is the design for verifing the Zcash blockchain on an FPGA

Binary file not shown.

View File

@ -0,0 +1,22 @@
/*
Parameter values and tasks for the verification system.
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 <https://www.gnu.org/licenses/>.
*/
package zcash_verif_pkg;
endpackage

View File

@ -0,0 +1,69 @@
/*
This takes in an AXI stream of a block and runs verification
checks (detailed in the architecture document). When all the checks are
completed the o_val will go high, and o_mask bit mask will be 1 for any
checks that failed.
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 <https://www.gnu.org/licenses/>.
*/
module zcash_verif_system(
input i_clk, i_rst,
if_axi_stream.sink i_axi,
output logic [31:0] o_mask,
output logic o_val
);
if_axi_stream #(.DAT_BYTS(128)) blake2b_in(clk);
if_axi_stream #(.DAT_BYTS(64)) blake2b_out(clk);
always_ff @ (posedge i_clk) begin
i_data.rdy <= blake2b_in.rdy;
blake2b_in.val <= i_data.val;
blake2b_in.sop <= i_data.sop;
blake2b_in.eop <= i_data.eop;
blake2b_in.dat <= i_data.dat;
blake2b_in.err <= 0;
blake2b_in.mod <= 0;
blake2b_in.ctl <= 0;
blake2b_out.rdy <= 1;
o_valid <= (blake2b_out.val && blake2b_out.dat == {64{1'b1}});
end
// The Blake2 core for generating hashes
logic [64*8-1:0] blake2_parameters;
always_comb begin
blake2_parameters = {32'd0, 8'd1, 8'd1, 8'd0, 8'd64};
end
blake2_top #(
.EQUIHASH( 1 )
)
blake2_top (
.i_clk ( i_clk ),
.i_rst ( i_rst ),
.i_byte_len ( 8'd128 ),
.i_parameters ( blake2_parameters ),
.i_block ( blake2b_in ),
.o_hash ( blake2b_out )
);
endmodule

View File

@ -0,0 +1 @@
create_clock -period 5.000 -name i_clk -waveform {0.000 2.500} [get_ports -filter { NAME =~ "*i_clk*" && DIRECTION == "IN" }]