feat: add per-generator NIST health tests and dead-ring monitor, onod3000 output test (FPGA v4)
This commit is contained in:
parent
585e755c66
commit
67bd7eec58
9 changed files with 436 additions and 28 deletions
|
|
@ -1,6 +1,6 @@
|
|||
// Testbench for strix_core: register access, generator XOR logic checked against the sampled
|
||||
// ring outputs, captures read back across transactions, generator enable, and the frequency
|
||||
// counter. Rings are replaced by the SIM model in ring_osc.v.
|
||||
// ring outputs, captures read back across transactions, generator enable, the frequency
|
||||
// counter, and the health monitors with injected faults. Rings are replaced by the SIM model in ring_osc.v.
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_strix_core;
|
||||
|
|
@ -14,7 +14,14 @@ module tb_strix_core;
|
|||
REG_GENERATORS = 7'h06, REG_RINGS = 7'h07, REG_SOURCE_A = 7'h08,
|
||||
REG_DECIM_LOW = 7'h0A, REG_CONTROL = 7'h0B, REG_STATUS = 7'h0C,
|
||||
REG_DATA = 7'h10, REG_RING_SELECT = 7'h11, REG_FREQ_COUNT0 = 7'h15,
|
||||
REG_GEN_ENABLE = 7'h16, REG_TEMPORAL = 7'h17, REG_FREQ_GEN = 7'h18;
|
||||
REG_GEN_ENABLE = 7'h16, REG_TEMPORAL = 7'h17, REG_FREQ_GEN = 7'h18,
|
||||
REG_HEALTHY = 7'h20, REG_HEALTH_CTRL = 7'h21;
|
||||
|
||||
// Per-generator health registers
|
||||
function [6:0] gen_reg(input integer generator, input integer index);
|
||||
gen_reg = 7'h30 + 4 * generator + index;
|
||||
endfunction
|
||||
localparam FLAGS = 0, RCT_EVENTS = 1, APT_EVENTS = 2, DEAD_RINGS = 3;
|
||||
|
||||
reg clk = 1'b0;
|
||||
always #4.1667 clk = ~clk; // 120 MHz
|
||||
|
|
@ -23,7 +30,8 @@ module tb_strix_core;
|
|||
reg sck = 1'b0, mosi = 1'b0, ss_n = 1'b1;
|
||||
wire miso, done;
|
||||
|
||||
strix_core #(.CAPTURE_ADDR_WIDTH(CAPTURE_ADDR_WIDTH), .FREQ_GATE_BITS(14), .RINGS_PER_GEN(RINGS)) dut (
|
||||
strix_core #(.CAPTURE_ADDR_WIDTH(CAPTURE_ADDR_WIDTH), .FREQ_GATE_BITS(14), .RINGS_PER_GEN(RINGS),
|
||||
.DEAD_WINDOW_BITS(6)) dut (
|
||||
.clk(clk), .reset(reset),
|
||||
.spi_sck(sck), .spi_mosi(mosi), .spi_ss_n(ss_n), .spi_miso(miso),
|
||||
.capture_done(done)
|
||||
|
|
@ -171,7 +179,7 @@ module tb_strix_core;
|
|||
// Identification
|
||||
read_reg(REG_ID0, v); expect(v, "S", "ID0");
|
||||
read_reg(REG_ID3, v); expect(v, "X", "ID3");
|
||||
read_reg(REG_VERSION, v); expect(v, 8'h03, "VERSION");
|
||||
read_reg(REG_VERSION, v); expect(v, 8'h04, "VERSION");
|
||||
read_reg(REG_GENERATORS, v); expect(v, 8'd4, "GENERATORS");
|
||||
read_reg(REG_RINGS, v); expect(v, RINGS, "RINGS");
|
||||
read_reg(REG_TEMPORAL, v); expect(v, 8'd5, "TEMPORAL");
|
||||
|
|
@ -216,6 +224,41 @@ module tb_strix_core;
|
|||
read_reg(REG_FREQ_COUNT0, v);
|
||||
if (v == 8'd0) begin $display("FAIL frequency count is zero"); errors = errors + 1; end
|
||||
|
||||
// Health: all generators healthy once a dead-ring sweep (90 x 64 cycles) has completed
|
||||
#100000;
|
||||
read_reg(REG_HEALTHY, v); expect(v, 8'h0F, "HEALTHY");
|
||||
read_reg(gen_reg(0, FLAGS), v); expect(v, 8'h38, "FLAGS g0"); // healthy, swept, active
|
||||
read_reg(gen_reg(0, DEAD_RINGS), v); expect(v, 8'd0, "DEAD g0");
|
||||
|
||||
// A dead ring is counted but tolerated
|
||||
force dut.gen[1].generator.raw_enhanced[7] = 1'b0;
|
||||
#120000;
|
||||
read_reg(gen_reg(1, DEAD_RINGS), v); expect(v, 8'd1, "DEAD g1");
|
||||
read_reg(REG_HEALTHY, v); expect(v, 8'h0F, "HEALTHY dead ring");
|
||||
release dut.gen[1].generator.raw_enhanced[7];
|
||||
|
||||
// A stuck spatial stream fails both NIST tests
|
||||
force dut.gen[2].generator.level4 = 1'b0;
|
||||
#20000;
|
||||
release dut.gen[2].generator.level4;
|
||||
read_reg(REG_HEALTHY, v); expect(v, 8'h0B, "HEALTHY stuck");
|
||||
read_reg(gen_reg(2, FLAGS), v); expect(v & 8'h03, 8'h03, "FLAGS g2 failed");
|
||||
read_reg(gen_reg(2, RCT_EVENTS), v);
|
||||
if (v == 8'd0) begin $display("FAIL no RCT events"); errors = errors + 1; end
|
||||
read_reg(gen_reg(2, APT_EVENTS), v);
|
||||
if (v == 8'd0) begin $display("FAIL no APT events"); errors = errors + 1; end
|
||||
|
||||
// Clear restores health without restarting the sweep
|
||||
write_reg(REG_HEALTH_CTRL, 8'h01);
|
||||
read_reg(REG_HEALTHY, v); expect(v, 8'h0F, "HEALTHY cleared");
|
||||
read_reg(gen_reg(2, RCT_EVENTS), v); expect(v, 8'd0, "RCT events cleared");
|
||||
|
||||
// A disabled generator is not healthy
|
||||
write_reg(REG_GEN_ENABLE, 8'h07);
|
||||
read_reg(REG_HEALTHY, v); expect(v, 8'h07, "HEALTHY disabled");
|
||||
read_reg(gen_reg(3, FLAGS), v); expect(v, 8'h00, "FLAGS g3 disabled");
|
||||
write_reg(REG_GEN_ENABLE, 8'h0F);
|
||||
|
||||
if (xor_checks < 100) begin
|
||||
$display("FAIL only %0d temporal XOR checks ran", xor_checks);
|
||||
errors = errors + 1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue