-
Notifications
You must be signed in to change notification settings - Fork 762
/
entropy_src_tb.sv
344 lines (314 loc) · 12.6 KB
/
entropy_src_tb.sv
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Description: entropy_src system verilog unit test bench
// The intent of this test bench is to get basics running,
// such as clocks and reset, basic register writes and reads,
// basic block operation. No configurable BFMs are included
// in this environment.
module entropy_src_tb;
import tlul_pkg::*;
import entropy_src_reg_pkg::*;
// tests
bit smoke_test = 0;
bit interrupt_test = 0;
bit lfsr_update_test = 0;
bit basic_entropy_test = 0;
bit stress_test = 1;
// options
bit msg_rd_data = 0;
// parameters`
localparam EsFifoDepth = 32;
localparam MAX_INTRP_CNT = 25;
localparam WD_DELAY = 1000*MAX_INTRP_CNT;
// general signals
logic clk;
logic rst_n;
logic es_entropy_valid_o;
logic es_entropy_fifo_err_o;
// tlul signals
tlul_pkg::tl_h2d_t tl_i;
tlul_pkg::tl_d2h_t tl_o;
// imported register parameters (for reference)
// Register Address
// parameter ENTROPY_SRC_INTR_STATE_OFFSET = 6'h 0;
// parameter ENTROPY_SRC_INTR_ENABLE_OFFSET = 6'h 4;
// parameter ENTROPY_SRC_INTR_TEST_OFFSET = 6'h 8;
// parameter ENTROPY_SRC_ES_REGEN_OFFSET = 6'h c;
// parameter ENTROPY_SRC_ES_CONF_OFFSET = 6'h 10;
// parameter ENTROPY_SRC_ES_REV_OFFSET = 6'h 14;
// parameter ENTROPY_SRC_ES_ENTROPY_OFFSET = 6'h 1c;
// parameter ENTROPY_SRC_ES_CTRL_OFFSET = 6'h 20;
// parameter ENTROPY_SRC_ES_STATUS_OFFSET = 6'h 24;
// parameter ENTROPY_SRC_ES_FDEPTHST_OFFSET = 6'h 28;
// parameter ENTROPY_SRC_ES_THRESH_OFFSET = 6'h 2c;
// parameter ENTROPY_SRC_ES_RATE_OFFSET = 6'h 30;
// parameter ENTROPY_SRC_ES_SEED_OFFSET = 6'h 34;
//---------------------------
// testbench support
//---------------------------
bit errflag = 0;
logic [31:0] rd_data = 0;
logic [31:0] thresh_level = 0;
logic [31:0] entropy_rate = 0;
logic [31:0] fifo_depth = 0;
logic [31:0] intrp_cnt = 0;
initial
begin // initial values
clk = 0;
rst_n = 0;
tl_i.a_valid = 0;
tl_i.a_address = 0;
tl_i.a_opcode = PutFullData; // write as default
tl_i.a_param = 3'h0;
tl_i.a_size = 2'h0;
tl_i.a_source = 8'h0;
tl_i.a_user = 0;
tl_i.a_mask = 0;
tl_i.a_data = 0;
tl_i.d_ready =1;
end
initial // clock generation
begin
clk = 0;
forever begin
#4ns clk = !clk;
end
end
initial // reset generation
begin
repeat (4) @ (posedge clk);
rst_n = 1;
end
initial // watchdog
begin
repeat (WD_DELAY) @ (posedge clk);
$display("%t %c[1;31mEntropy_Src watchdog triggered - FAIL!!! %c[0m",$time,27,27);
$finish;
end
task wr_reg(input logic [31:0] addr, logic [31:0] wdata);
repeat (1) @ (posedge clk); #1ps;
while (tl_o.a_ready != 1) begin
repeat (1) @ (posedge clk); #1ps;
end
tl_i.a_valid =1;
tl_i.a_address = addr;
tl_i.a_opcode = PutFullData; // write = 0
tl_i.a_param = 3'h0;
tl_i.a_size = 2'h2;
tl_i.a_source = 8'h0;
tl_i.a_mask = 4'hf;
tl_i.a_data = wdata;
repeat (1) @ (posedge clk); #1ps;
tl_i.a_valid = 0;
tl_i.a_address = 0;
tl_i.a_opcode = PutFullData; // write as default
tl_i.a_param = 3'h0;
tl_i.a_size = 2'h0;
tl_i.a_source = 8'h0;
tl_i.a_mask = 0;
tl_i.a_data = 0;
repeat (1) @ (posedge clk); #1ps;
endtask
task rd_reg(input logic [31:0] addr, output logic [31:0] rdata);
repeat (1) @ (posedge clk); #1ps;
tl_i.d_ready =1;
while (tl_o.a_ready != 1) begin
repeat (1) @ (posedge clk); #1ps;
end
tl_i.a_valid =1;
tl_i.a_address = addr;
tl_i.a_opcode = Get; // read = 4
tl_i.a_param = 3'h0;
tl_i.a_size = 2'h2;
tl_i.a_source = 8'h0;
tl_i.a_mask = 4'hf;
while (tl_o.d_valid != 1) begin
repeat (1) @ (posedge clk); #1ps;
end
tl_i.a_valid = 0;
tl_i.d_ready = 1;
tl_i.a_address = 0;
tl_i.a_opcode = PutFullData; // write as default
tl_i.a_param = 3'h0;
tl_i.a_size = 2'h0;
tl_i.a_source = 8'h0;
tl_i.a_mask = 0;
tl_i.a_data = 0;
rdata = tl_o.d_data;
if (msg_rd_data) $display("%t rdata = %h",$time,rdata);
repeat (1) @ (posedge clk); #1ps;
endtask
task cmp_reg(input logic [31:0] addr, logic [31:0] cdata, logic [31:0] cmask);
logic [31:0] rdata;
rd_reg(addr,rdata);
if ((rdata & cmask) !== cdata) begin
$display("%t reg addr: %h",$time,addr);
$display("%t act raw data: %h",$time,rdata);
$display("%t exp mask data: %h",$time,(rdata & cmask));
$display("%t exp data: %h",$time,cdata);
$display("%t %c[1;31mRead register miscompare!!! %c[0m",$time,27,27);
$finish;
// errflag = 1;
end
endtask
task test_end(input bit errflag);
cmp_reg(ENTROPY_SRC_ES_STATUS_OFFSET,32'h0000_0000,32'hffff_ffff);
if (errflag == 1) begin
$display("%t %c[1;31mEntropy_Src Test FAIL!!! %c[0m",$time,27,27);
end else begin
$display("%t %c[1;32mEntropy_Src Test PASSED... %c[0m",$time,27,27);
end
$finish;
endtask
always @ (posedge es_entropy_valid_o) // interrupt handler
begin
if (rst_n) begin // handle reset case
if (stress_test) begin
rd_data = 0;
for (int i=0; i < thresh_level; i=i+1) begin
rd_reg({26'b0,ENTROPY_SRC_ES_ENTROPY_OFFSET},rd_data);
end
repeat (1) @ (posedge clk); #1ps;
// reset interrupt
wr_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h0000_0001);
if (es_entropy_valid_o !== 0) begin
$display("%t %c[1;31mInterrupt did not reset FAIL!!! %c[0m",$time,27,27);
$finish;
end
// randomly change entropy_rate
void'(randomize (entropy_rate) with { entropy_rate inside {[3:30]};});
$display("%t Interrupt entropy_rate = %h ",$time,entropy_rate);
wr_reg({26'b0,ENTROPY_SRC_ES_RATE_OFFSET},(entropy_rate)); // rate
intrp_cnt++;
$display("%t Interrupt intrp_cnt = %h ",$time,intrp_cnt);
end
end
end
//-------------------------------------
// testcases
//-------------------------------------
initial begin
while (rst_n !== 1'b1) begin // avoid initial x case
repeat (1) @ (posedge clk); #1ps;
end
repeat (10) @ (posedge clk); #1ps;
// Comon register setup
// -> placeholder
repeat (20) @ (posedge clk); #1ps;
//-----------------------------------------------------
if (smoke_test) begin
$display("%t Running smoke_test...",$time);
cmp_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h1234_5678,32'hffff_ffff);
wr_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'habdc_efab); // wr config reg
cmp_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'habdc_efab,32'hffff_ffff);
cmp_reg({26'b0,ENTROPY_SRC_ES_REV_OFFSET},32'h0001_0201,32'hffff_ffff);
end
//-----------------------------------------------------
if (interrupt_test) begin
$display("%t Running interrupt_test...",$time);
wr_reg({26'b0,ENTROPY_SRC_INTR_ENABLE_OFFSET},32'h0000_0003); // enable intrs
cmp_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h000000000,32'hffff_ffff); // check to see that interrupts are off
// test intrp 0
wr_reg({26'b0,ENTROPY_SRC_INTR_TEST_OFFSET},32'h0000_0001);
cmp_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h000000001,32'hffff_ffff); // check interrupt state
wr_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h0000_0001);
cmp_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h000000000,32'hffff_ffff); // check to see that interrupts are off
// test intrp 1
wr_reg({26'b0,ENTROPY_SRC_INTR_TEST_OFFSET},32'h0000_0002);
cmp_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h000000002,32'hffff_ffff); // check interrupt state
wr_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h0000_0002);
cmp_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h000000000,32'hffff_ffff); // check to see that interrupts are off
end
//-----------------------------------------------------
if (lfsr_update_test) begin
$display("%t Running lfsr_update_test...",$time);
wr_reg({26'b0,ENTROPY_SRC_ES_RATE_OFFSET},32'h0000_0001); // rate
wr_reg({26'b0,ENTROPY_SRC_ES_THRESH_OFFSET},32'h0000_0001); // thresh level
wr_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h1111_1111); // seed
wr_reg({26'b0,ENTROPY_SRC_ES_CONF_OFFSET},32'h0000_0001); // primary enable
repeat (10) @ (posedge clk);
wr_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h2222_2222); // change seed, should not write since fifo is not full
wr_reg({26'b0,ENTROPY_SRC_ES_CTRL_OFFSET},32'h0000_0001); // init bit on
wr_reg({26'b0,ENTROPY_SRC_ES_CTRL_OFFSET},32'h0000_0000); // init bit off
repeat (30) @ (posedge clk);
cmp_reg({26'b0,ENTROPY_SRC_ES_FDEPTHST_OFFSET},32'h000000020,32'hffff_ffff); // check to see if FIFO is full
wr_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h3333_3333); // change seed, should write since init bit is on
wr_reg({26'b0,ENTROPY_SRC_ES_CTRL_OFFSET},32'h0000_0001); // init bit on
wr_reg({26'b0,ENTROPY_SRC_ES_CTRL_OFFSET},32'h0000_0000); // init bit off
repeat (10) @ (posedge clk);
wr_reg({26'b0,ENTROPY_SRC_ES_REGEN_OFFSET},32'h0000_0001); // clear write enable register, make it off
wr_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h4444_4444); // change seed, should not write since lock seed bit is on
cmp_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h3333_3333,32'hffff_ffff); // check to see that seed did not change
wr_reg({26'b0,ENTROPY_SRC_ES_CTRL_OFFSET},32'h0000_0001); // init bit on
wr_reg({26'b0,ENTROPY_SRC_ES_CTRL_OFFSET},32'h0000_0000); // init bit off
repeat (5) @ (posedge clk);
// set entropy to off
wr_reg({26'b0,ENTROPY_SRC_ES_RATE_OFFSET},32'h0000_0000); // rate turned off
// drain the fifo
for (int i=0; i < 32; i=i+1) begin
rd_reg({26'b0,ENTROPY_SRC_ES_ENTROPY_OFFSET},rd_data);
end
// clear any interrupts
wr_reg({26'b0,ENTROPY_SRC_INTR_STATE_OFFSET},32'h0000_0003);
end
//-----------------------------------------------------
if (basic_entropy_test) begin
$display("%t Running basic_entropy_test...",$time);
thresh_level = 32'h0000_000f;
wr_reg({26'b0,ENTROPY_SRC_INTR_ENABLE_OFFSET},32'h0000_0003); // enable intrs
wr_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h2345_3456); // seed
wr_reg({26'b0,ENTROPY_SRC_ES_RATE_OFFSET},32'h0000_0008); // rate
wr_reg({26'b0,ENTROPY_SRC_ES_THRESH_OFFSET},thresh_level); // thresh level
wr_reg({26'b0,ENTROPY_SRC_ES_CONF_OFFSET},32'h0000_0001); // primary enable
// read out entropy
rd_data = 0;
repeat (20) @ (posedge clk);
while (rd_data < thresh_level) begin
rd_reg({26'b0,ENTROPY_SRC_ES_FDEPTHST_OFFSET},rd_data);
end
// set entropy to super slow
wr_reg({26'b0,ENTROPY_SRC_ES_RATE_OFFSET},32'h0000_ffff); // rate
for (int i=0; i < thresh_level; i=i+1) begin
rd_reg({26'b0,ENTROPY_SRC_ES_ENTROPY_OFFSET},rd_data);
end
rd_reg({26'b0,ENTROPY_SRC_ES_FDEPTHST_OFFSET},fifo_depth);
// drain the rest of the fifo
for (int i=0; i < fifo_depth; i=i+1) begin
rd_reg({26'b0,ENTROPY_SRC_ES_ENTROPY_OFFSET},rd_data);
end
repeat (10) @ (posedge clk);
end
//-----------------------------------------------------
if (stress_test) begin
$display("%t Running stress_test...",$time);
thresh_level = 32'h0000_0008;
wr_reg({26'b0,ENTROPY_SRC_INTR_ENABLE_OFFSET},32'h0000_0003); // enable intrs
wr_reg({26'b0,ENTROPY_SRC_ES_SEED_OFFSET},32'h2345_3456); // seed
wr_reg({26'b0,ENTROPY_SRC_ES_RATE_OFFSET},32'h0000_0006); // rate
wr_reg({26'b0,ENTROPY_SRC_ES_THRESH_OFFSET},thresh_level); // thresh level
wr_reg({26'b0,ENTROPY_SRC_ES_CONF_OFFSET},32'h0000_0001); // primary enable
// wait for interrupts to process
while (intrp_cnt < MAX_INTRP_CNT) begin
repeat (20) @ (posedge clk);
end
end
//-----------------------------------------------------
repeat (10) @ (posedge clk);
test_end(errflag);
end
//-------------------------------------
// entropy_src instantiation
//-------------------------------------
entropy_src #(.EsFifoDepth(EsFifoDepth))
u_entropy_src
(
.clk_i(clk),
.rst_ni(rst_n),
.tl_i(tl_i),
.tl_o(tl_o),
.es_entropy_valid_o(es_entropy_valid_o),
.es_entropy_fifo_err_o(es_entropy_fifo_err_o)
);
endmodule