diff --git a/.DS_Store b/.DS_Store index b6fcc25b02128d8d68590a95cd6b43f435142f0c..617ce0426920c16bba8d96c7d48c2a8973b5490f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/hdl/verif/tb_sha256_id_buf.sv b/hdl/verif/tb_sha256_id_buf.sv new file mode 100644 index 0000000000000000000000000000000000000000..e49f82fec55ebd099071a880ecfbf4be384a541f --- /dev/null +++ b/hdl/verif/tb_sha256_id_buf.sv @@ -0,0 +1,244 @@ +//----------------------------------------------------------------------------- +// SoC Labs Basic SHA-2 ID Buffer 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) +//----------------------------------------------------------------------------- +`timescale 1ns/1ns +`include "sha256_id_buf.sv" + +module tb_sha256_id_buf; + + logic clk; + logic nrst; + logic en; + logic sync_rst; + + // ID Buffer IN + logic [5:0] id_in; + logic id_in_last; + logic id_in_valid; + logic id_in_ready; + + // ID Out + logic [5:0] id_out; + logic id_out_last; + logic id_out_valid; + logic id_out_ready; + + // Status Out - Gets updated after every hash + logic [5:0] status_id; + + + sha256_id_buf uut ( + .clk (clk), + .nrst (nrst), + .en (en), + .sync_rst (sync_rst), + + // ID IN + .id_in (id_in), + .id_in_last (id_in_last), + .id_in_valid (id_in_valid), + .id_in_ready (id_in_ready), + + // ID Out + .id_out (id_out), + .id_out_last (id_out_last), + .id_out_valid (id_out_valid), + .id_out_ready (id_out_ready), + + // Status Out - Gets updated on every output Handshake + .status_id (status_id) + ); + + logic id_in_drive_en; + + logic id_out_drive_ready; + + logic [5:0] id_in_queue [$]; + logic id_in_last_queue [$]; + int id_in_gap_queue [$]; + logic id_in_wait_queue; + + logic [5:0] id_out_queue [$]; + logic id_out_last_queue [$]; + int id_out_stall_queue [$]; + logic id_out_wait_queue; + + // TODO: Handle Status Checking + + // Handle Valid and Data for id_in + always_ff @(posedge clk, negedge nrst) begin: id_in_valid_drive + if (!nrst) begin + id_in <= 6'd0; + id_in_valid <= 1'b0; + id_in_last <= 1'b0; + id_in_gap <= 0; + id_in_wait_queue <= 1'b1; + end else if (id_in_drive_en) begin + if (id_in_gap > 1) begin + id_in_gap <= id_in_gap - 1; + id_in_valid <= 1'b0; + end else begin + id_in_valid <= 1'b1; + end + if (((id_in_valid == 1'b1) && (id_in_ready == 1'b1)) || + (id_in_wait_queue == 1'b1)) begin + // Data transfer just completed or transfers already up to date + if ((id_in_queue.size() > 0) && (id_in_last_queue.size() > 0) && (id_in_gap_queue.size() > 0)) begin + id_in <= id_in_queue.pop_front(); + id_in_last <= id_in_last_queue.pop_front(); + if (id_in_gap_queue[0] == 0) begin + id_in_valid <= 1'b1; + end else begin + id_in_valid <= 1'b0; + end + id_in_gap <= id_in_gap_queue.pop_front(); + id_in_wait_queue <= 1'b0; + end else begin + // No data currently avaiable in queue to write but transfers up to date + id_in_wait_queue <= 1'b1; + id_in_valid <= 1'b0; + end + end + end + end + + logic [5:0] id_out_check; + logic id_out_last_check; + + int id_in_gap; + int id_out_stall; + + int packet_num; + + // Handle Output Ready Signal Verification + always @(posedge clk) begin + // Check Override Control on Ready + if (id_out_drive_ready) begin + // Count down to zero before enabling Ready + if (id_out_stall > 1) begin + id_out_stall <= id_out_stall - 1; + id_out_ready <= 1'b0; + end else begin + // Wait for handshake before updating stall value + if ((id_out_valid == 1'b1) && (id_out_ready == 1'b1)) begin + if (id_out_stall_queue.size() > 0) begin + if (id_out_stall_queue[0] == 0) begin + id_out_ready <= 1'b1; + end else begin + id_out_ready <= 1'b0; + end + id_out_stall <= id_out_stall_queue.pop_front(); + end + // Keep Ready Asserted until handshake seen + end else begin + id_out_ready <= 1'b1; + end + end + end else begin + id_out_ready <= 1'b0; + end + end + + // Handle Output Data Verification + always @(posedge clk) begin + // Check Data on Handshake + if ((id_out_valid == 1'b1) && (id_out_ready == 1'b1)) begin + // Check Size + assert (id_out == id_out_check) else begin + $error("id_out missmatch! packet %d | recieve: %x != check: %x", packet_num, id_out, id_out_check); + $finish; + end + if ($test$plusargs ("DEBUG")) $display("id_out match! packet %d | recieve: %x == check: %x", packet_num, id_out, id_out_check); + + // Check Last Flag + assert (id_out_last == id_out_last_check) else begin + $error("id_out_last missmatch! packet %d | recieve: %x != check: %x", packet_num, id_out_last, id_out_last_check); + $finish; + end + if ($test$plusargs ("DEBUG")) $display("id_out_last match! packet %d | recieve: %x == check: %x", packet_num, id_out_last, id_out_last_check); + + // Pop new values + if ((id_out_queue.size() > 0) && (id_out_last_queue.size() > 0)) begin + id_out_check <= id_out_queue.pop_front(); + id_out_last_check <= id_out_last_queue.pop_front(); + if (id_out_last_check == 1'b1) begin + packet_num <= packet_num + 1; + end + end else begin + $display("Test Passes"); + $finish; + end + end + end + + // File Reading Variables + int fd; // File descriptor Handle + + logic [5:0] temp_id_in; // Temporary Input Data Storage + logic temp_id_in_last; // Temporary Input Data Last + int temp_id_in_gap; // Temporary Input Gap + + logic [5:0] temp_id_out; // Temporary Hash Value + logic temp_id_out_last; // Temporary Hash last; + int temp_id_out_stall; // Temporary Hash stall; + + initial begin + $dumpfile("sha256_id_buf.vcd"); + $dumpvars(0, tb_sha256_id_buf); + id_in_drive_en = 0; + id_out_drive_ready = 0; + + // Read input data into Queue in + fd = $fopen("../stimulus/testbench/input_validator_id_stim.csv", "r"); + while ($fscanf (fd, "%d,%b,%d", temp_id_in, temp_id_in_last, temp_id_in_gap) == 3) begin + id_in_queue.push_back(temp_id_in); + id_in_last_queue.push_back(temp_id_in_last); + id_in_gap_queue.push_back(temp_id_in_gap); + end + $fclose(fd); + + // Read output data into Queue + fd = $fopen("../stimulus/testbench/output_id_out_ref.csv", "r"); + while ($fscanf (fd, "%x,%b,%b,%d", temp_id_out, temp_id_out_last, temp_id_out_stall) == 3) begin + id_out_queue.push_back(temp_id_out); + id_out_last_queue.push_back(temp_id_out_last); + id_out_stall_queue.push_back(temp_id_out_stall); + end + $fclose(fd); + + // Initialise First Checking Values + id_out_check = id_out_queue.pop_front(); + id_out_last_check = id_out_last_queue.pop_front(); + id_out_stall = id_out_stall_queue.pop_front(); + + // Defaultly enable Message Builder + en = 1; + + // Defaultly set Sync Reset Low + sync_rst = 0; + + #20 nrst = 1; + #20 nrst = 0; + #20 nrst = 1; + + // Write some data into the config register + # 30 id_in_drive_en = 1; + + # 30 id_out_drive_ready = 1; + end + + initial begin + forever begin + #10 clk = 0; + #10 clk = 1; + end + end + +endmodule \ No newline at end of file