Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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