Skip to content
Snippets Groups Projects
Commit e795c500 authored by David Mapstone's avatar David Mapstone
Browse files

remove subtree

parent 283cac89
No related branches found
No related tags found
No related merge requests found
Showing
with 0 additions and 1066 deletions
File deleted
*.vcd
*.vvp
*.DS_Store
\ No newline at end of file
{
"workbench.colorCustomizations": {
"activityBar.background": "#00360F",
"titleBar.activeBackground": "#004C16",
"titleBar.activeForeground": "#EDFFF2"
}
}
\ No newline at end of file
# SHA-2 Accelerator
This project is an example accelerator which will be combined with the SoC Labs SoC infrastructure.
TEST7
## Repository Structure
The respository is currently broken down into 2 main directories:
- hdl
- simulate
HDL contains all the verilog files. This is seperated into:
- src
- verif
src contains SystemVerilog design files and verif contains the SystemVerilog testbenches and verification resources.
The simulate directory contains the socsim script, along with a directory called "simulators" which contains simulator-specific scripts and a "sim" directory which contains dumps and logs from simulation runs. The files in this directory should not be commited to the Git.
## Setting Up Environment
To be able to simulate in this repository, you will first need to source the sourceme:
```
% source sourceme
```
## Stimulus Generation
Under `model/py`, there is `hash_model.py` which is a python model of the hashing accelerator. This produces numerous `.csv` files which can be fed in testbenches. These files are seperated into two types:
- stimiulus
- reference
Stimulus files are used to stimulate the DUT by feeding into the inputs of the module. Reference files are used to compare to the output of the DUT to check whether it is behaving correctly.
These files are present in the `simulate/stimulus/unit/` or `simulate/stimulus/system/` directories. Unit contains stimulus and reference files for unit tests - internal wrapper engine verification. System contains stimulus and reference files for System and Wrapper tests.
The `simulate/stimulus/model/` directory contains a hand-written stimulus file which is used to seed and constrain the python model. There are `5` values in this file and are listed as follows:
- Seed - random seed used to seed python model
- Payload Number - Number of payloads to generate
- Payload Size (Bits) - Number of bits a payload is comprised of. If set to 0, this is randomised each payload. If non-zero, each payload will have a size of this value.
- Gap Limit - Maximum number of clock cycles to gap on the input (cycles to wait before asserting valid on the input data)
- Stall Limit - Maximum number of clock cycles to stall on the output (cycles to wait before asseting ready on the output)
To generate the stimulus and reference, ensure the `sourceme` in the root of this repo has been sourced and then run `python3 hash_model.py` within the `model/py` directory. This will populate the directories with the `.csv` files in the `simulate/stimulus` directory.
## Simulation Setup
This will set up the environment variables and will set the simulator used. Defaultly, this is set to ivlog - Icarus Verilog. This can be overloaded from the command line with the following command:
```
% SIMULATOR=yoursimulator
```
Once this is done, a simulation can be ran using the socsim command:
```
% socsim
```
This will generate simulation dumps in the following directory:
```
% $SHA_2_ACC_DIR/simulate/sim
```
\ No newline at end of file
//-----------------------------------------------------------------------------
// SHA-2 Accelerator Filelist
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright � 2021-3, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Abstract : Verilog Command File for SHA-2 Accelerator example
//-----------------------------------------------------------------------------
// ============= Verilog library extensions ===========
+libext+.v+.vlib
// ============= Accelerator Module search path =============
-y $DESIGN/sha-2-accelerator/hdl/src/
+incdir+$DESIGN/sha-2-accelerator/hdl/src/
$DESIGN/sha-2-accelerator/hdl/src/fifo_vr.sv
$DESIGN/sha-2-accelerator/hdl/src/sha256_hash_compression.sv
$DESIGN/sha-2-accelerator/hdl/src/sha256_hashing_stream.sv
$DESIGN/sha-2-accelerator/hdl/src/sha256_message_build.sv
// $DESIGN/sha-2-accelerator/hdl/src/sha256_1_3_arbitrator.sv
// $DESIGN/sha-2-accelerator/hdl/src/sha256_config_sync.sv
// $DESIGN/sha-2-accelerator/hdl/src/sha256_engine.sv
// $DESIGN/sha-2-accelerator/hdl/src/sha256_id_buf.sv
// $DESIGN/sha-2-accelerator/hdl/src/sha256_id_issue.sv
// $DESIGN/sha-2-accelerator/hdl/src/sha256_id_validator.sv
// $DESIGN/sha-2-accelerator/hdl/src/sha256_packet_manager.sv
#-----------------------------------------------------------------------------
# SoC Labs socsim script to run linting
# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
#
# Contributors
#
# David Mapstone (d.a.mapstone@soton.ac.uk)
#
# Copyright 2022, SoC Labs (www.soclabs.org)
#-----------------------------------------------------------------------------
#!/usr/bin/env bash
verilator --lint-only $*
\ No newline at end of file
#-----------------------------------------------------------------------------
# SoC Labs icarus verilog simulation script for engine testbench
# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
#
# Contributors
#
# David Mapstone (d.a.mapstone@soton.ac.uk)
#
# Copyright 2022, SoC Labs (www.soclabs.org)
#-----------------------------------------------------------------------------
#!/usr/bin/env bash
mkdir -p $SOC_TOP/simulate/sim/
iverilog -I $SOC_TOP/hdl/verif/ -I $SOC_TOP/hdl/src/ -g2012 -o $SOC_TOP/simulate/sim/$1.vvp $SOC_TOP/hdl/verif/tb_$1.sv
cd $SOC_TOP/simulate/sim/ && vvp $1.vvp $2
\ No newline at end of file
#-----------------------------------------------------------------------------
# SoC Labs socsim script to run required simulation
# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
#
# Contributors
#
# David Mapstone (d.a.mapstone@soton.ac.uk)
#
# Copyright 2022, SoC Labs (www.soclabs.org)
#-----------------------------------------------------------------------------
#!/usr/bin/env bash
DEFAULT_SIMULATOR="ivlog"
if [[ -z "${SIMULATOR}" ]]; then
SIMULATOR=$DEFAULT_SIMULATOR
fi
$SOC_TOP"/flow/simulators/"$SIMULATOR"_sim.sh" $@
#-----------------------------------------------------------------------------
# SoC Labs socsim script to run required simulation
# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
#
# Contributors
#
# David Mapstone (d.a.mapstone@soton.ac.uk)
#
# Copyright 2022, SoC Labs (www.soclabs.org)
#-----------------------------------------------------------------------------
#!/usr/bin/env bash
python3 $SHA_2_ACC_DIR"/flow/socsim_py.py" $@
\ No newline at end of file
#-----------------------------------------------------------------------------
# SoC Labs socsim script to run required simulation
# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
#
# Contributors
#
# David Mapstone (d.a.mapstone@soton.ac.uk)
#
# Copyright 2022, SoC Labs (www.soclabs.org)
#-----------------------------------------------------------------------------
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--model", type=str, help="Python Model used to generate Sitmulus and Reference for design")
parser.add_argument("-s", "--stimulus", type=str, help="Stimulus to pass to Python Model to generate Testbench Stimulus and Reference")
parser.parse_args()
\ No newline at end of file
bus_width: 32
address_width: 4
protocol: apb
\ No newline at end of file
#ifndef STATUS_REGS_H
#define STATUS_REGS_H
#include "stdint.h"
#define STATUS_REGS_STATUS_0_STATUS_ID_BIT_WIDTH 6
#define STATUS_REGS_STATUS_0_STATUS_ID_BIT_MASK 0x3f
#define STATUS_REGS_STATUS_0_STATUS_ID_BIT_OFFSET 0
#define STATUS_REGS_STATUS_0_STATUS_BUFFERED_IDS_BIT_WIDTH 3
#define STATUS_REGS_STATUS_0_STATUS_BUFFERED_IDS_BIT_MASK 0x7
#define STATUS_REGS_STATUS_0_STATUS_BUFFERED_IDS_BIT_OFFSET 6
#define STATUS_REGS_STATUS_0_STATUS_ERR_BUFFER_BIT_WIDTH 1
#define STATUS_REGS_STATUS_0_STATUS_ERR_BUFFER_BIT_MASK 0x1
#define STATUS_REGS_STATUS_0_STATUS_ERR_BUFFER_BIT_OFFSET 9
#define STATUS_REGS_STATUS_0_STATUS_ERR_PACKET_BIT_WIDTH 1
#define STATUS_REGS_STATUS_0_STATUS_ERR_PACKET_BIT_MASK 0x1
#define STATUS_REGS_STATUS_0_STATUS_ERR_PACKET_BIT_OFFSET 10
#define STATUS_REGS_STATUS_0_STATUS_ERR_CLEAR_BIT_WIDTH 1
#define STATUS_REGS_STATUS_0_STATUS_ERR_CLEAR_BIT_MASK 0x1
#define STATUS_REGS_STATUS_0_STATUS_ERR_CLEAR_BIT_OFFSET 11
#define STATUS_REGS_STATUS_0_STATUS_PACKET_COUNT_BIT_WIDTH 10
#define STATUS_REGS_STATUS_0_STATUS_PACKET_COUNT_BIT_MASK 0x3ff
#define STATUS_REGS_STATUS_0_STATUS_PACKET_COUNT_BIT_OFFSET 12
#define STATUS_REGS_STATUS_0_BYTE_WIDTH 4
#define STATUS_REGS_STATUS_0_BYTE_SIZE 4
#define STATUS_REGS_STATUS_0_BYTE_OFFSET 0x0
typedef struct {
uint32_t status_0;
uint32_t __reserved_0x4;
uint32_t __reserved_0x8;
uint32_t __reserved_0xc;
} status_regs_t;
#endif
## status_regs
* byte_size
* 16
|name|offset_address|
|:--|:--|
|[status_0](#status_regs-status_0)|0x0|
### <div id="status_regs-status_0"></div>status_0
* offset_address
* 0x0
* type
* default
|name|bit_assignments|type|initial_value|reference|labels|comment|
|:--|:--|:--|:--|:--|:--|:--|
|status_id|[5:0]|ro|0x00|||Contains last ID Value in ID Buffer|
|status_buffered_ids|[8:6]|ro|0x0|||Number of IDs in ID Buffer|
|status_err_buffer|[9]|ro|0x0|||ID Buffer Error|
|status_err_packet|[10]|ro|0x0|||Dropped Packet Error|
|status_err_clear|[11]|wo|0x0|||Clear Error Flags|
|status_packet_count|[21:12]|ro|0x000|||Number of Packets Passed Through|
`ifndef rggen_connect_bit_field_if
`define rggen_connect_bit_field_if(RIF, FIF, LSB, WIDTH) \
assign FIF.valid = RIF.valid; \
assign FIF.read_mask = RIF.read_mask[LSB+:WIDTH]; \
assign FIF.write_mask = RIF.write_mask[LSB+:WIDTH]; \
assign FIF.write_data = RIF.write_data[LSB+:WIDTH]; \
assign RIF.read_data[LSB+:WIDTH] = FIF.read_data; \
assign RIF.value[LSB+:WIDTH] = FIF.value;
`endif
`ifndef rggen_tie_off_unused_signals
`define rggen_tie_off_unused_signals(WIDTH, VALID_BITS, RIF) \
if (1) begin : __g_tie_off \
genvar __i; \
for (__i = 0;__i < WIDTH;++__i) begin : g \
if (!(((VALID_BITS) >> __i) & 1'b1)) begin : g \
assign RIF.read_data[__i] = 1'b0; \
assign RIF.value[__i] = 1'b0; \
end \
end \
end
`endif
module status_regs
import rggen_rtl_pkg::*;
#(
parameter int ADDRESS_WIDTH = 4,
parameter bit PRE_DECODE = 0,
parameter bit [ADDRESS_WIDTH-1:0] BASE_ADDRESS = '0,
parameter bit ERROR_STATUS = 0,
parameter bit [31:0] DEFAULT_READ_DATA = '0
)(
input logic i_clk,
input logic i_rst_n,
rggen_apb_if.slave apb_if,
input logic [5:0] i_status_0_status_id,
input logic [2:0] i_status_0_status_buffered_ids,
input logic i_status_0_status_err_buffer,
input logic i_status_0_status_err_packet,
output logic o_status_0_status_err_clear,
input logic [9:0] i_status_0_status_packet_count
);
rggen_register_if #(4, 32, 32) register_if[1]();
rggen_apb_adapter #(
.ADDRESS_WIDTH (ADDRESS_WIDTH),
.LOCAL_ADDRESS_WIDTH (4),
.BUS_WIDTH (32),
.REGISTERS (1),
.PRE_DECODE (PRE_DECODE),
.BASE_ADDRESS (BASE_ADDRESS),
.BYTE_SIZE (16),
.ERROR_STATUS (ERROR_STATUS),
.DEFAULT_READ_DATA (DEFAULT_READ_DATA)
) u_adapter (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.apb_if (apb_if),
.register_if (register_if)
);
generate if (1) begin : g_status_0
rggen_bit_field_if #(32) bit_field_if();
`rggen_tie_off_unused_signals(32, 32'h003fffff, bit_field_if)
rggen_default_register #(
.READABLE (1),
.WRITABLE (1),
.ADDRESS_WIDTH (4),
.OFFSET_ADDRESS (4'h0),
.BUS_WIDTH (32),
.DATA_WIDTH (32),
.REGISTER_INDEX (0)
) u_register (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.register_if (register_if[0]),
.bit_field_if (bit_field_if)
);
if (1) begin : g_status_id
localparam bit [5:0] INITIAL_VALUE = 6'h00;
rggen_bit_field_if #(6) bit_field_sub_if();
`rggen_connect_bit_field_if(bit_field_if, bit_field_sub_if, 0, 6)
rggen_bit_field #(
.WIDTH (6),
.STORAGE (0),
.EXTERNAL_READ_DATA (1),
.TRIGGER (0)
) u_bit_field (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.bit_field_if (bit_field_sub_if),
.o_write_trigger (),
.o_read_trigger (),
.i_sw_write_enable ('0),
.i_hw_write_enable ('0),
.i_hw_write_data ('0),
.i_hw_set ('0),
.i_hw_clear ('0),
.i_value (i_status_0_status_id),
.i_mask ('1),
.o_value (),
.o_value_unmasked ()
);
end
if (1) begin : g_status_buffered_ids
localparam bit [2:0] INITIAL_VALUE = 3'h0;
rggen_bit_field_if #(3) bit_field_sub_if();
`rggen_connect_bit_field_if(bit_field_if, bit_field_sub_if, 6, 3)
rggen_bit_field #(
.WIDTH (3),
.STORAGE (0),
.EXTERNAL_READ_DATA (1),
.TRIGGER (0)
) u_bit_field (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.bit_field_if (bit_field_sub_if),
.o_write_trigger (),
.o_read_trigger (),
.i_sw_write_enable ('0),
.i_hw_write_enable ('0),
.i_hw_write_data ('0),
.i_hw_set ('0),
.i_hw_clear ('0),
.i_value (i_status_0_status_buffered_ids),
.i_mask ('1),
.o_value (),
.o_value_unmasked ()
);
end
if (1) begin : g_status_err_buffer
localparam bit INITIAL_VALUE = 1'h0;
rggen_bit_field_if #(1) bit_field_sub_if();
`rggen_connect_bit_field_if(bit_field_if, bit_field_sub_if, 9, 1)
rggen_bit_field #(
.WIDTH (1),
.STORAGE (0),
.EXTERNAL_READ_DATA (1),
.TRIGGER (0)
) u_bit_field (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.bit_field_if (bit_field_sub_if),
.o_write_trigger (),
.o_read_trigger (),
.i_sw_write_enable ('0),
.i_hw_write_enable ('0),
.i_hw_write_data ('0),
.i_hw_set ('0),
.i_hw_clear ('0),
.i_value (i_status_0_status_err_buffer),
.i_mask ('1),
.o_value (),
.o_value_unmasked ()
);
end
if (1) begin : g_status_err_packet
localparam bit INITIAL_VALUE = 1'h0;
rggen_bit_field_if #(1) bit_field_sub_if();
`rggen_connect_bit_field_if(bit_field_if, bit_field_sub_if, 10, 1)
rggen_bit_field #(
.WIDTH (1),
.STORAGE (0),
.EXTERNAL_READ_DATA (1),
.TRIGGER (0)
) u_bit_field (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.bit_field_if (bit_field_sub_if),
.o_write_trigger (),
.o_read_trigger (),
.i_sw_write_enable ('0),
.i_hw_write_enable ('0),
.i_hw_write_data ('0),
.i_hw_set ('0),
.i_hw_clear ('0),
.i_value (i_status_0_status_err_packet),
.i_mask ('1),
.o_value (),
.o_value_unmasked ()
);
end
if (1) begin : g_status_err_clear
localparam bit INITIAL_VALUE = 1'h0;
rggen_bit_field_if #(1) bit_field_sub_if();
`rggen_connect_bit_field_if(bit_field_if, bit_field_sub_if, 11, 1)
rggen_bit_field #(
.WIDTH (1),
.INITIAL_VALUE (INITIAL_VALUE),
.SW_READ_ACTION (RGGEN_READ_NONE),
.SW_WRITE_ONCE (0),
.TRIGGER (0)
) u_bit_field (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.bit_field_if (bit_field_sub_if),
.o_write_trigger (),
.o_read_trigger (),
.i_sw_write_enable ('1),
.i_hw_write_enable ('0),
.i_hw_write_data ('0),
.i_hw_set ('0),
.i_hw_clear ('0),
.i_value ('0),
.i_mask ('1),
.o_value (o_status_0_status_err_clear),
.o_value_unmasked ()
);
end
if (1) begin : g_status_packet_count
localparam bit [9:0] INITIAL_VALUE = 10'h000;
rggen_bit_field_if #(10) bit_field_sub_if();
`rggen_connect_bit_field_if(bit_field_if, bit_field_sub_if, 12, 10)
rggen_bit_field #(
.WIDTH (10),
.STORAGE (0),
.EXTERNAL_READ_DATA (1),
.TRIGGER (0)
) u_bit_field (
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.bit_field_if (bit_field_sub_if),
.o_write_trigger (),
.o_read_trigger (),
.i_sw_write_enable ('0),
.i_hw_write_enable ('0),
.i_hw_write_data ('0),
.i_hw_set ('0),
.i_hw_clear ('0),
.i_value (i_status_0_status_packet_count),
.i_mask ('1),
.o_value (),
.o_value_unmasked ()
);
end
end endgenerate
endmodule
package status_regs_ral_pkg;
import uvm_pkg::*;
import rggen_ral_pkg::*;
`include "uvm_macros.svh"
`include "rggen_ral_macros.svh"
class status_0_reg_model extends rggen_ral_reg;
rand rggen_ral_field status_id;
rand rggen_ral_field status_buffered_ids;
rand rggen_ral_field status_err_buffer;
rand rggen_ral_field status_err_packet;
rand rggen_ral_field status_err_clear;
rand rggen_ral_field status_packet_count;
function new(string name);
super.new(name, 32, 0);
endfunction
function void build();
`rggen_ral_create_field(status_id, 0, 6, "RO", 1, 6'h00, 1, -1, "")
`rggen_ral_create_field(status_buffered_ids, 6, 3, "RO", 1, 3'h0, 1, -1, "")
`rggen_ral_create_field(status_err_buffer, 9, 1, "RO", 1, 1'h0, 1, -1, "")
`rggen_ral_create_field(status_err_packet, 10, 1, "RO", 1, 1'h0, 1, -1, "")
`rggen_ral_create_field(status_err_clear, 11, 1, "WO", 0, 1'h0, 1, -1, "")
`rggen_ral_create_field(status_packet_count, 12, 10, "RO", 1, 10'h000, 1, -1, "")
endfunction
endclass
class status_regs_block_model extends rggen_ral_block;
rand status_0_reg_model status_0;
function new(string name);
super.new(name, 4, 0);
endfunction
function void build();
`rggen_ral_create_reg(status_0, '{}, 4'h0, "RW", "g_status_0.u_register")
endfunction
endclass
endpackage
package status_regs_rtl_pkg;
localparam int STATUS_0_BYTE_WIDTH = 4;
localparam int STATUS_0_BYTE_SIZE = 4;
localparam bit [3:0] STATUS_0_BYTE_OFFSET = 4'h0;
localparam int STATUS_0_STATUS_ID_BIT_WIDTH = 6;
localparam bit [5:0] STATUS_0_STATUS_ID_BIT_MASK = 6'h3f;
localparam int STATUS_0_STATUS_ID_BIT_OFFSET = 0;
localparam int STATUS_0_STATUS_BUFFERED_IDS_BIT_WIDTH = 3;
localparam bit [2:0] STATUS_0_STATUS_BUFFERED_IDS_BIT_MASK = 3'h7;
localparam int STATUS_0_STATUS_BUFFERED_IDS_BIT_OFFSET = 6;
localparam int STATUS_0_STATUS_ERR_BUFFER_BIT_WIDTH = 1;
localparam bit STATUS_0_STATUS_ERR_BUFFER_BIT_MASK = 1'h1;
localparam int STATUS_0_STATUS_ERR_BUFFER_BIT_OFFSET = 9;
localparam int STATUS_0_STATUS_ERR_PACKET_BIT_WIDTH = 1;
localparam bit STATUS_0_STATUS_ERR_PACKET_BIT_MASK = 1'h1;
localparam int STATUS_0_STATUS_ERR_PACKET_BIT_OFFSET = 10;
localparam int STATUS_0_STATUS_ERR_CLEAR_BIT_WIDTH = 1;
localparam bit STATUS_0_STATUS_ERR_CLEAR_BIT_MASK = 1'h1;
localparam int STATUS_0_STATUS_ERR_CLEAR_BIT_OFFSET = 11;
localparam int STATUS_0_STATUS_PACKET_COUNT_BIT_WIDTH = 10;
localparam bit [9:0] STATUS_0_STATUS_PACKET_COUNT_BIT_MASK = 10'h3ff;
localparam int STATUS_0_STATUS_PACKET_COUNT_BIT_OFFSET = 12;
endpackage
register_blocks:
- name: status_regs
byte_size: 16
registers:
- name: status_0
bit_fields:
- { name: status_id, bit_assignment: { width: 6 }, type: ro , initial_value: 0, comment: Contains last ID Value in ID Buffer }
- { name: status_buffered_ids, bit_assignment: { width: 3 }, type: ro , initial_value: 0, comment: Number of IDs in ID Buffer }
- { name: status_err_buffer, bit_assignment: { width: 1 }, type: ro , initial_value: 0, comment: ID Buffer Error }
- { name: status_err_packet, bit_assignment: { width: 1 }, type: ro , initial_value: 0, comment: Dropped Packet Error }
- { name: status_err_clear, bit_assignment: { width: 1 }, type: wo , initial_value: 0, comment: Clear Error Flags }
- { name: status_packet_count, bit_assignment: { width: 10 }, type: ro , initial_value: 0, comment: Number of Packets Passed Through }
\ No newline at end of file
//-----------------------------------------------------------------------------
// SoC Labs Basic Parameterisable Valid-Ready FIFO
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright 2022, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
module fifo_vr #(
parameter DEPTH = 4, // FIFO Row Depth
parameter DATA_W = 32, // FIFO Row Width
parameter PTR_W = $clog2(DEPTH) + 1 // Read/Write Pointer Width
)(
input logic clk,
input logic nrst,
input logic en,
// Synchronous, localised reset
input logic sync_rst,
// In (Write) Control
input logic [DATA_W-1:0] data_in,
input logic data_in_last,
input logic data_in_valid,
output logic data_in_ready,
// Out (Read) Control
output logic [DATA_W-1:0] data_out,
output logic data_out_last,
input logic data_out_ready,
output logic data_out_valid,
// Status
output logic [PTR_W-1:0] status_ptr_dif
);
logic data_in_shake; // Successful Write Handshake
logic data_out_shake; // Successful Read Handshake
assign data_in_shake = (data_in_valid == 1'b1) && (data_in_ready == 1'b1);
assign data_out_shake = (data_out_valid == 1'b1) && (data_out_ready == 1'b1);
logic [DATA_W:0] fifo [DEPTH-1:0]; // FIFO Memory Structure
logic [PTR_W-1:0] write_ptr; // FIFO Write Pointer
logic [PTR_W-1:0] read_ptr; // FIFO Read Pointer
logic [PTR_W-1:0] ptr_dif; // Difference between Write and Read Pointers
assign ptr_dif = write_ptr - read_ptr;
assign status_ptr_dif = ptr_dif;
// EXAMPLE: Conditions to write and read from FIFO's
// Write Ptr | Read Ptr | Ptr_Dif | Valid Write | Valid Read
// 000 - 000 = 000 | Y | N
// 001 - 000 = 001 | Y | Y
// 010 - 000 = 010 | Y | Y
// 011 - 000 = 011 | Y | Y
// 100 - 000 = 100 | N | Y
// 101 - 000 = 101 | N | N
// 110 - 000 = 110 | N | N
// 111 - 000 = 111 | N | N
// WriteValid: WritePtr - ReadPtr < 3'd4
// ReadValid: WritePtr - ReadPtr - 1 < 3'd4
assign {data_out,data_out_last} = fifo [read_ptr[PTR_W-2:0]]; // Output Data is dereferenced value of the Read Pointer
always_ff @(posedge clk, negedge nrst) begin
if ((!nrst) || sync_rst) begin
// Under Reset
// - Pointers reset to 0 (FIFO is empty without needing to reset the memories)
// - Control taken low
write_ptr <= 0;
read_ptr <= 0;
data_in_ready <= 1'b0;
data_out_valid <= 1'b0;
// Ensure FIFO Values are Known
for (int i = 0; i < DEPTH; i++) begin
fifo[i] <= 'b0;
end
end else if (en == 1'b1) begin
// Enable signal is High
// Write Logic
if (ptr_dif < DEPTH) begin
// Empty Rows in FIFO in FIFO
if (data_in_shake) begin
// Successful Handshake store data in FIFO and increment Write Pointer
fifo [write_ptr[PTR_W-2:0]] <= {data_in,data_in_last};
write_ptr <= write_ptr + 1;
if ((ptr_dif + {{(PTR_W-1){1'b0}},(1'b1 - data_out_shake)}) < DEPTH) begin
// Still space in FIFO after latest write
// If theres a successful read on this clock cycle,
// there will be an additional space in the FIFO next clock cycle
// (number of pieces of data in the FIFO won't have changed)
data_in_ready <= 1'b1;
end else begin
// FIFO is now full
data_in_ready <= 1'b0;
end
end else begin
// Unsuccessful handshake but space in FIFO
// If there's write space now, next cc it will be the same or more
// (more if a succesful read has been carried out in this cc)
data_in_ready <= 1'b1;
end
end else begin
if ((ptr_dif - {{(PTR_W-1){1'b0}}, data_out_shake}) < DEPTH) begin
// If there is a successful read this clock cycle,
// there will be space for another piece of data in the FIFO
// (number of pieces of data in FIFO will have decremented by 1)
data_in_ready <= 1'b1;
end else begin
// FIFO still Full
data_in_ready <= 1'b0;
end
end
// Read Logic
if ((ptr_dif - 1) < DEPTH) begin
// Data in FIFO - atleast one Piece of Data in FIFO
// -> the "-1" causes dif of 0 to wrap where (dif - 1) becomes > DEPTH
if (data_out_shake) begin
// Successful Handshake Increment Read Pointer
read_ptr <= read_ptr + 1;
if (((ptr_dif - 1) + {{(PTR_W-1){1'b0}},data_in_shake}) - 1 < DEPTH) begin
// Still Data in FIFO after latest Read
// If there is a successful write this clock cycle,
// there will be one more piece of data in the FIFO
// (number of pieces of data in FIFO wont have changed)
data_out_valid <= 1'b1;
end else begin
// FIFO empty after latest Read
data_out_valid <= 1'b0;
end
end else begin
// Unsuccessful handshake but Data in FIFO
// If there's read data now, next cc it will be the same or more
// (more if a succesful write has been carried out in this cc)
data_out_valid <= 1'b1;
end
end else begin
if (((ptr_dif - 1) + {{(PTR_W-1){1'b0}},data_in_shake}) < DEPTH) begin
// If there is a successful write this clock cycle,
// there will be one more piece of data in the FIFO
// (number of pieces of data in FIFO will have incremented by 1)
data_out_valid <= 1'b1;
end else begin
// FIFO still empty
data_out_valid <= 1'b0;
end
end
end else begin
// If Enable is Low, set Control Low
data_in_ready <= 1'b0;
data_out_valid <= 1'b0;
end
end
// Verif Notes to Check behaiour:
// 1) Fill FIFO up with Data
// 2) Read & Write in same clock cycle
endmodule
//-----------------------------------------------------------------------------
// SoC Labs Basic SHA-256 1 to 3 Arbitrator
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright 2022, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
module sha256_1_to_3_arbitrator (
input logic clk,
input logic nrst,
input logic en,
// Synchronous, localised reset
input logic sync_rst,
// Data In data and Handshaking
input logic [511:0] data_in,
input logic data_in_last,
input logic data_in_valid,
output logic data_in_ready,
// Data Out
output logic [511:0] data_out,
output logic data_out_last,
output logic [4:0] data_out_packet_id,
// Channel Enable - 1-hot
input [2:0] channel_en,
// Handshaking Channel 0
output logic data_out_valid_0,
input logic data_out_ready_0,
// Handshaking Channel 1
output logic data_out_valid_1,
input logic data_out_ready_1,
// Handshaking Channel 2
output logic data_out_valid_2,
input logic data_out_ready_2
);
logic [1:0] state, next_state;
logic [1:0] channel_select, next_channel_select;
logic [3:0] packet_id, next_packet_id;
logic [511:0] next_data_out;
logic [4:0] next_data_out_packet_id;
logic next_data_out_last;
logic [2:0] data_out_ready;
logic [2:0] data_out_valid, next_data_out_valid;
assign data_out_ready = {data_out_ready_0, data_out_ready_1, data_out_ready_2};
assign data_out_valid_0 = data_out_valid[0];
assign data_out_valid_1 = data_out_valid[1];
assign data_out_valid_2 = data_out_valid[2];
// State Machine Sequential Logic
always_ff @(posedge clk, negedge nrst) begin
if ((!nrst) | sync_rst) begin
state <= 3'd0;
data_in_ready <= 1'b0;
data_out_valid_0 <= 1'b0;
data_out_valid_1 <= 1'b0;
data_out_valid_2 <= 1'b0;
data_out_last <= 1'b0;
data_out <= 256'd0;
data_out_packet_id <= 4'd0;
channel_select <= 2'd0;
packet_id <= 4'd0;
end else if (en == 1'b1) begin
state <= next_state;
data_out <= next_data_out;
data_out_last <= next_data_out_last;
data_out_packet_id <= next_data_out_packet_id;
data_out_valid_0 <= next_data_out_valid_0;
data_out_valid_1 <= next_data_out_valid_1;
data_out_valid_2 <= next_data_out_valid_2;
channel_select <= next_channel_select;
packet_id <= next_packet_id;
end else begin
data_in_ready <= 1'b0;
data_out_valid_0 <= 1'b0;
data_out_valid_1 <= 1'b0;
data_out_valid_2 <= 1'b0;
end
end
always_comb begin
// Default
next_state = state;
next_data_in_ready = data_in_ready;
next_data_out_valid_0 = data_out_valid_0;
next_data_out_valid_1 = data_out_valid_1;
next_data_out_valid_2 = data_out_valid_2;
next_data_out_last = data_out_last;
next_data_out = data_out;
next_channel_select = channel_select;
next_packet_id = packet_id;
next_data_out_packet_id = data_out_packet_id
// Override
case (state)
2'd0: begin
if (!(data_out_valid[channel_select] && !data_out_ready[channel_select])) begin
// If data out handshake has been seen, drop valid
next_data_out_valid = 1'b0;
end
// Work out which Channel to use
// - Check in order of value 0-2
if (|data_out_ready) begin
next_state = 2'd1;
// If there is an avaliable channel, raise the ready signal on the input
next_data_in_ready = 1'b1;
if (data_out_ready[0] && channel_en[0]) next_channel_select = 2'd0;
else if (data_out_ready[1] && channel_en[1]) next_channel_select = 2'd1;
else if (data_out_ready[2] && channel_en[2]) next_channel_select = 2'd2;
// De-assert Valid on all Channels
next_data_out_valid = 3'd0;
end else begin
// No Channel is free, stay in this state
next_state = 2'd0;
end
end
2'd1: begin
// Check outputs can be written to
if (data_out_valid[channel_select] && !data_out_ready[channel_select]) begin
// If data out is valid and ready is low, there is already data waiting to be transferred
next_data_in_ready = 1'b0;
// If there is no Valid data at the output or there is a valid transfer happening on this clock cycle
end else begin
// These can be overloaded later if data is written to the outputs
next_data_out_valid = 3'b0;
next_data_in_ready = 1'b1;
// Check Inputs have data
if (data_in_valid && data_in_ready) begin
// Valid Handshake and data can be processed
// Data Processing Algorithm
next_data_in_ready = 1'b0;
// Write Input Data to Output
next_data_out = data_in;
next_data_out_packet_id = packet_id;
next_data_out_last = data_in_last;
next_data_out_valid = (3'b1 << next_channel_select);
if (data_in_last) begin
// Last Word of Packet - re-arbitrate
// Increment Packet ID
next_state = 2'd0;
next_packet_id = packet_id + 4'd1;
end
end
end
end
endcase
end
endmodule
\ No newline at end of file
//-----------------------------------------------------------------------------
// SoC Labs Basic SHA-256 Configuration Synchroniser
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright 2023, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
module sha256_config_sync (
input logic clk,
input logic nrst,
input logic en,
// Synchronous, localised reset
input logic sync_rst,
// ID In and Handshaking
input logic [5:0] id_in,
input logic id_in_last,
input logic id_in_valid,
output logic id_in_ready,
// Config data and Handshaking
input logic [63:0] cfg_in_size,
input logic [1:0] cfg_in_scheme,
input logic cfg_in_last,
input logic cfg_in_valid,
output logic cfg_in_ready,
// Data Out data and Handshaking
output logic [63:0] cfg_out_size,
output logic [1:0] cfg_out_scheme,
output logic [5:0] cfg_out_id,
output logic cfg_out_last,
output logic cfg_out_valid,
input logic cfg_out_ready,
// Status Out - Gets updated after every hash
// - outputs size and then clears size to 0
// - status regs are looking for non-zero size
output logic [63:0] status_size
);
logic [1:0] state, next_state;
logic next_cfg_in_ready;
logic next_id_in_ready;
logic [63:0] next_cfg_out_size;
logic [1:0] next_cfg_out_scheme;
logic [5:0] next_cfg_out_id;
logic next_cfg_out_last;
logic next_cfg_out_valid;
logic [63:0] next_status_size;
// State Machine Sequential Logic
always_ff @(posedge clk, negedge nrst) begin
if ((!nrst) | sync_rst) begin
state <= 2'd0;
cfg_out_size <= 64'd0;
cfg_out_scheme <= 2'd0;
cfg_out_id <= 6'd0;
cfg_out_last <= 1'b0;
cfg_out_valid <= 1'b0;
cfg_in_ready <= 1'b0;
id_in_ready <= 1'b0;
status_size <= 64'd0;
end else if (en == 1'b1) begin
state <= next_state;
cfg_out_size <= next_cfg_out_size;
cfg_out_scheme <= next_cfg_out_scheme;
cfg_out_id <= next_cfg_out_id;
cfg_out_last <= next_cfg_out_last;
cfg_out_valid <= next_cfg_out_valid;
cfg_in_ready <= next_cfg_in_ready;
id_in_ready <= next_id_in_ready;
status_size <= next_status_size;
end else begin
cfg_out_valid <= 1'b0;
cfg_in_ready <= 1'b0;
id_in_ready <= 1'b0;
status_size <= 64'd0;
end
end
always_comb begin
// Default
next_state = state;
next_cfg_out_size = cfg_out_size;
next_cfg_out_scheme = cfg_out_scheme;
next_cfg_out_id = cfg_out_id;
next_cfg_out_last = cfg_out_last;
next_cfg_out_valid = cfg_out_valid;
next_cfg_in_ready = cfg_in_ready;
next_id_in_ready = id_in_ready;
next_status_size = status_size;
// Override
case (state)
2'd0: begin
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
next_state = 2'd1;
end
2'd1: begin
// Handle Status Signals
next_status_size = 64'd0;
// Check outputs can be written to
if (cfg_out_valid && !cfg_out_ready) begin
// If data out is valid and ready is low, there is already data waiting to be transferred
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
// If there is no Valid data at the output or there is a valid transfer happening on this clock cycle
end else begin
// These can be overloaded later if data is written to the outputs
next_cfg_out_valid = 1'b0;
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
next_cfg_out_last = 1'b0;
// Check cfg input
if (cfg_in_ready && cfg_in_valid) begin
next_cfg_out_last = cfg_in_last;
next_cfg_out_scheme = cfg_in_scheme;
next_cfg_out_size = cfg_in_size;
next_status_size = cfg_in_size;
next_cfg_in_ready = 1'b0;
next_state = 2'd2;
end
// Check Id input
if (id_in_ready && id_in_valid) begin
next_cfg_out_id = id_in;
next_id_in_ready = 1'b0;
next_state = 2'd3;
end
// Check if both inputs handshaked
if ((id_in_ready && id_in_valid) && (cfg_in_ready && cfg_in_valid)) begin
next_cfg_out_valid = 1'b1;
if (!cfg_out_valid && cfg_out_ready) begin
// In case where no valid data and ready is waiting for valid data
// - (will be asserted next cc), guaranteed handshake next cycle
next_cfg_in_ready = 1'b1;
next_cfg_in_ready = 1'b1;
end else begin
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
end
next_state = 2'd1;
end
end
end
2'd2: begin // Cfg already handshaked - wait for ID handshake
// Handle Status Signals
next_status_size = 64'd0;
// These can be overloaded later if data is written to the outputs
next_cfg_out_valid = 1'b0;
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b1;
// Check Id input
if (id_in_ready && id_in_valid) begin
next_cfg_out_id = id_in;
next_cfg_out_valid = 1'b1;
if (cfg_out_ready) begin // Guaranteeded Handshake next clock cycle
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
end else begin
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
end
next_state = 2'd1;
end
end
2'd3: begin // ID already handshaked - wait for config handshake
// Handle Status Signals
next_status_size = 64'd0;
// These can be overloaded later if data is written to the outputs
next_cfg_out_valid = 1'b0;
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b0;
// Check config input
if (cfg_in_ready && cfg_in_valid) begin
next_cfg_out_last = cfg_in_last;
next_cfg_out_scheme = cfg_in_scheme;
next_cfg_out_size = cfg_in_size;
next_cfg_out_valid = 1'b1;
next_status_size = cfg_in_size;
if (cfg_out_ready) begin // Guaranteeded Handshake next clock cycle
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
end else begin
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
end
next_state = 2'd1;
end
end
endcase
end
endmodule
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment