Files
design-verification-onboard…/testplan_initial.md
T
2026-09-27 18:00:31 -04:00

37 KiB

Fall 2026 DV Onboarding Test Plan

NOTE: THIS IS A TEMPLATE FOR YOU TO FOLLOW. THIS IS NOT A COMPREHENSIVE TESTPLAN. YOU NEED TO EXTEND IT.

Document information

Field Value
Verification engineer Dylan Benzi, benziboy, dbenzi3
Plan revision Initial
Date 2026-09-26

Revision history

Revision Date Changes
Initial 2026-09-26 Initial planned tests
Final YYYY-MM-DD

1. Functional tests

Functional-test summary

Implemented ISA to test

  • ADD
  • ADDI
  • SUB
  • LW
  • SW
  • BEQ
  • SLL
  • SRL
  • EBREAK
Test ID Test name Functionality being tested Expected result Status
1.1 add overflow add two regs causing an overflow overflow discarded Planned
1.2 addi overflow add imm to reg causing an overflow overflow discarded Planned
1.3 addi negative add negative imm imm is subtracted Planned
1.4 add typical add two regs regs added properly Planned
1.5 addi typical add imm to reg imm added properly Planned
1.6 addi negative overflow add negative numbers causing an overflow negative overflow wrap around Planned
1.7 sub overflow subtract two regs causing an overflow negative overflow wrap around Planned
1.8 sub typical subtract two regs regs subtracted properly Planned
1.9 sll oob shift left by larger than 2^5 bits left shift constrainted to 2^5 Planned
1.10 srl oob shift right by larger than 2^5 bits right shift constrainted to 2^5 Planned
1.11 sll zero shift left by zero bits no shift Planned
1.12 srl zero shift right by zero bits no shift Planned
1.13 sll one shift left by one bit logical left shift by one bit Planned
1.14 srl one shift right by one bit logical right shift by one bit Planned
1.15 sll typical shift left by <2^5 bits correct logical left shift Planned
1.16 srl typical shift right by <2^5 bits correct logical right shift Planned
1.17 lw zero offset lw with zero offset zero offset computed Planned
1.18 sw zero offset sw with zero offset zero offset computed + stored Planned
1.19 lw positive lw with positive offset correct offset computed Planned
1.20 sw positive sw with positive offset correct offset computed + stored Planned
1.21 lw negative lw with negative offset correct offset computed Planned
1.22 sw negative sw with negative offset correct offset computed + stored Planned
1.23 lw x0 lw into x0 reg write discarded, x0 remains 0 Planned
1.24 beq x0 beq with both regs as x0 take branch Planned
1.25 beq not taken beq with non-equal regs branch not taken Planned
1.26 beq typical beq with equal regs branch taken Planned
1.27 ebreak immediately ebreak as first instruction halt CPU Planned

Functional-test details

1.1 — add overflow

Functionality: add two registers together that would cause an overflow

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADD), .rd(2), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x2 32'hFFFFFFFE 0xFFFFFFFF + 0xFFFFFFFF = 0x(1)FFFFFFFE, the leading 1 is truncated

Pass criteria: 3 cycle operation

Final result:

1.2 — addi overflow

Functionality: add an immediate to a register that would cause an overflow

Initial state:

  • Registers: x1 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(1), .imm(1)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'h00000000 0xFFFFFFFF + 0x1 = 0x(1)00000000, the leading 1 is truncated

Pass criteria: 2 cycle operation

Final result:

1.3 — addi negative

Functionality: adds a negative value to a register using addi, effectively subtracting from that register

Initial state:

  • Registers: x1 = 0x1
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(1)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(1), .imm(-1)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'h0 0x1 - 0x1 = 0x0

Pass criteria: 2 cycle operation

Final result:

1.4 — add typical

Functionality: add two registers with values that will not cause an overflow

Initial state:

  • Registers: x1 = 0x123, x2 = 0x123
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(0x123)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(0x123)),
  asm_instr(.op(OP_ADD), .rd(2), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x2 32'h246 0x123 + 0x123 = 0x246

Pass criteria: 3 cycle operation

Final result:

1.5 — addi typical

Functionality: addi with immediate added to register without causing an overflow

Initial state:

  • Registers: none
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(0x123)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'h123 0x0 + 0x123 = 0x123

Pass criteria: 1 cycle operation

Final result:

1.6 — addi negative overflow

Functionality: addi with a negative number causes an overflow wrap around to the register

Initial state:

  • Registers: x1 = 0x0
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF 0x0 - 0x1 = 0xFFFFFFFF, overflow back to full reg

Pass criteria: 1 cycle operation

Final result:

1.7 — sub overflow

Functionality: sub registers that would cause an overflow wrap around

Initial state:

  • Registers: x1 = 0x1
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(1)),
  asm_instr(.op(OP_SUB), .rd(1), .rs1(0), .rs2(1)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF 0x0 - 0x1 = 0xFFFFFFFF overflow wrap around

Pass criteria: 2 cycle operation

Final result:

1.8 — sub typical

Functionality: sub two registers without causing an overflow

Initial state:

  • Registers: x1 = 0x123, x2 = 0x23
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(0x123)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(0x23)),
  asm_instr(.op(OP_SUB), .rd(2), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x2 32'h100 0x123 - 0x23 = 0x100

Pass criteria: 3 cycle operation

Final result:

1.9 — srl oob

Functionality: srl masks to bottom 5 bits of data only, cannot shift more than 31

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 0x20
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(32)),
  asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF 0x20 == 2^5 => no shift

Pass criteria: 3 cycle operation

Final result:

1.10 — sll oob

Functionality: sll masks to bottom 5 bits of data only, cannot shift more than 31

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 0x20
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(32)),
  asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF 0x20 == 2^5 => no shift

Pass criteria: 3 cycle operation

Final result:

1.11 — sll zero

Functionality: sll with zero, causing no shift

Initial state:

  • Registers: x1 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(0)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF 0xFFFFFFFF << 0x0 = 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.12 — srl zero

Functionality: srl with zero, causing no shift

Initial state:

  • Registers: x1 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(0)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF 0xFFFFFFFF << 0x0 = 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.13 — sll one

Functionality: sll with one, causing a shift once to the left

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 0x1
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(1)),
  asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFE 0xFFFFFFFF << 0x1 = 0xFFFFFFFE

Pass criteria: 3 cycle operation

Final result:

1.14 — srl one

Functionality: srl with one, causing a shift once to the right

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 1
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(1)),
  asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'h7FFFFFFF 0xFFFFFFFF >> 0x1 = 0x7FFFFFFF

Pass criteria: 3 cycle operation

Final result:

1.15 — sll typical

Functionality: sll with a shift greater than 1 and less than 2^5

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 0x4
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(4)),
  asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFF0 0xFFFFFFFF << 0x4 = 0xFFFFFFF0

Pass criteria: 3 cycle operation

Final result:

1.16 — srl typical

Functionality: srl with a shift greater than 1 and less than 2^5

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 0x4
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(4)),
  asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'h0FFFFFFF 0xFFFFFFFF >> 0x4 = 0x0FFFFFFF

Pass criteria: 3 cycle operation

Final result:

1.17 — lw zero offset

Functionality: lw with zero offset, loading in the register rs1

Initial state:

  • Registers: none
  • Data memory: dmem[0] = 0xFFFFFFFF
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_LW), .rd(1), .rs1(0), .imm(0)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF x1 = M[0] => 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.18 — sw zero offset

Functionality: sw with zero offset, storing in memory addr of rs1

Initial state:

  • Registers: x1 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_SW), .rs1(0), .rs2(1), .imm(0)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
dmem[0] 32'hFFFFFFFF M[0] = x1 => 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.19 — lw positive

Functionality: lw with a positive offset

Initial state:

  • Registers: none
  • Data memory: dmem[1] = 0xFFFFFFFF
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_LW), .rd(1), .rs1(0), .imm(4)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF x1 = dmem[1] => 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.20 — sw positive

Functionality: sw with a positive offset

Initial state:

  • Registers: x1 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_SW), .rs1(0), .rs2(1), .imm(4)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
dmem[1] 32'hFFFFFFFF dmem[1] = x1 => 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.21 — lw negative

Functionality: lw with a negative offset

Initial state:

  • Registers: none
  • Data memory: dmem[1023] = 0xFFFFFFFF
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_LW), .rd(1), .rs1(0), .imm(-1)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'hFFFFFFFF x1 = dmem[1023] => 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.22 — sw negative

Functionality: sw with a negative offset

Initial state:

  • Registers: x1 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_SW), .rs1(0), .rs2(1), .imm(-1)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
dmem[1023] 32'hFFFFFFFF dmem[1023] = x1 => 0xFFFFFFFF

Pass criteria: 2 cycle operation

Final result:

1.23 — lw x0

Functionality: attempt to lw into x0 register

Initial state:

  • Registers: none
  • Data memory: dmem[0] = 0xFFFFFFFF
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_LW), .rd(0), .rs1(0), .imm(0)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x0 32'h0 x0 is to always remain 0

Pass criteria: 2 cycle operation

Final result:

1.24 — beq x0

Functionality: beq with both sources as x0

Initial state:

  • Registers: none
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_BEQ), .rs1(0), .rs2(0), .imm(8)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(1)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'h2 skip ADDI x1, x0, 1, and run ADDI x1, x0, 2

Pass criteria: 2 cycle operation

Final result:

1.25 — beq not taken

Functionality: beq on two non-equal registers

Initial state:

  • Registers: x1 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_BEQ), .rs1(0), .rs2(1), .imm(8)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(-1)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x2 32'hFFFFFFFF do not skip to EBREAK, and run ADDI x2, x0, -1

Pass criteria: 3 cycle operation

Final result:

1.26 — beq typical

Functionality: beq on two equal registers that are not x0

Initial state:

  • Registers: x1 = 0xFFFFFFFF, x2 = 0xFFFFFFFF
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(-1)),
  asm_instr(.op(OP_BEQ), .rs1(1), .rs2(2), .imm(8)),
  asm_instr(.op(OP_ADDI), .rd(3), .rs1(0), .imm(1)),
  asm_instr(.op(OP_ADDI), .rd(3), .rs1(0), .imm(2)),
  EBREAK_WORD
};

Expected result:

Register or memory word Expected value Calculation or explanation
x3 32'h2 skip ADDI x3, x0, 1, and run ADDI x3, x0, 2

Pass criteria: 4 cycle operation

Final result:

1.27 — ebreak immediately

Functionality: ebreak as first instruction, subsequent instructions not run

Initial state:

  • Registers: none
  • Data memory: none
  • Other setup: none

Program:

prog = '{
  // asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
  EBREAK_WORD,
  asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1))
};

Expected result:

Register or memory word Expected value Calculation or explanation
x1 32'h0 ebreak before ADDI instruction

Pass criteria: ebreak takes one cycle, other instructions not run

Final result:

2. Constrained-random tests

Instruction constraints

Constraint Provided, partial, or open Behavior and purpose Final implementation summary
c_opcode Provided use only opcodes implemented No member change
c_reg_bias Provided encourage more reg-reg collisions, test x0 r/w No member change
c_imm_range Partial use only immediates that fit into instruction separate imm_range for I/S and B types
c_mem_align Open force word immediates to be multiples of 4 mask/discard 2 LSBs for lw/sw
c_imm_unused Provided set imm to zero if not used in instr No member change
c_branch_target Partial keep the target within the program mem % 4, ≥ 4, <prog len
c_no_branch_at_end Provided prevent branching at the end of the program No member change
c_branch_taken_bias Open bias rs1/rs2 to being equal values to eachother weight rs1/rs2 values to encourage equal values

External-port constraints

Constraint Provided, partial, or open Behavior and purpose Final implementation summary
c_align Provided word align instr No member change
c_valid_window Partial ensure addr is inside register file restrict to 32 entries
c_reg_read_only Provided do not write to reg via port No member change
c_data_corners Open bias towards specific data values to test all 1s, all 0s, checkerboard, etc

Random-program test

Item Plan
Number of programs per seed 50
Program-length range 2 ≤ len ≤ 50
Information logged for reproduction Numeric SVSEED, iteration, and complete generated program

Implementation outline:

// Write the intended loop and lifecycle using seqr.gen_program(...).
int min_len = 2;
int max_len = 50;
int random_progs = 50;
int max_cycles = 2000;
int dmem_words = 16;

for (int i = 0; i < random_progs; i++) begin
	int len = $urandom_range(min_len, max_len);
	string name = $sformatf("random_gen_%0d_len_%0d", i, len);
	sb.set_test(name);
	
	drv.reset_task();
	seqr.gen_program(len);
	seqr.wait_for_empty();
	repeat (2) @(cpu_if.cb);
	drv.run_program(max_cycles);
	
	if (drv.last_run_completed) begin
		readback(2, REG_COUNT);
		readback(1, dmem_words);
	end else begin
		$display($stime, " TB: Skipping %s readback after CPU timeout\n", name);
		drv.reset_task();
	end
end

3. Assertions

Assertion summary

Assertion ID/name Behavior checked When it is sampled/disabled Activating test
3.1 / X0_REMAINS_0 x0 = 0 posedge clk lw_x0
3.2 / HALT_PULSE halt pulses high then low after ebreak ebreak_immediately

3.1 — X0_REMAINS_0

Timing requirement in words: on every clock pulse, check that x0 is 0

X0_REMAINS_0:
  assert property (@(posedge clk) disable iff (rst)
	  dut.register_crossbar[0] == 32'b0)
  else assertion_fail("x0 is nonzero");

Evidence that it detects a violation:

3.2 — HALT_PULSE

Timing requirement in words: halt pulses after ebreak

HALT_PULSE:
  assert property (@(posedge clk) disable iff (rst)
	  cpu_if.cpu_halted |=> !cpu_if.cpu_halted)
  else assertion_fail("halt did not pulse correctly");

Evidence that it detects a violation:

4. Encrypted CPU Bug Hunt

Random discovery

Field Evidence
Discovery command make bug_hunt SEED=random
Numeric SVSEED
Failing iteration
First failure message
Reproduction command make bug_hunt SEED=________
Reproduces consistently? Yes / No

Original failing program:

prog = '{
  // Paste original generated sequence
  EBREAK_WORD
};

Expected vs. actual

Instruction / event Expected Actual Cycle/time

First architectural divergence:

Minimization

Minimized reproducer:

prog = '{
  // Smallest sequence that still fails
  EBREAK_WORD
};

Waveform evidence

Include a screenshot showing the offending instruction and the first incorrect architectural result.

Conclusion

Trigger:

Expected behavior:

Observed behavior:

Behavioral characterization: