commit
4b9ff85954
|
@ -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>
|
22
README.md
22
README.md
|
@ -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.
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
create_clock -period 5.000 -name i_clk -waveform {0.000 2.500} [get_ports -filter { NAME =~ "i_clk" && DIRECTION == "IN" }]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
This is the design for verifing the Zcash blockchain on an FPGA
|
Binary file not shown.
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
create_clock -period 5.000 -name i_clk -waveform {0.000 2.500} [get_ports -filter { NAME =~ "*i_clk*" && DIRECTION == "IN" }]
|
Loading…
Reference in New Issue