429 lines
22 KiB
Markdown
429 lines
22 KiB
Markdown
# Design Verification Onboarding — Fall 2026
|
|
|
|
## Subteam overview
|
|
|
|
### Description
|
|
|
|
The Design Verification (DV) subteam checks that a design behaves according to its specification
|
|
before it is manufactured. DV members work with RTL designers to identify functionality, write test plans,
|
|
build simulation environments, find failures, and report enough evidence for a designer to
|
|
reproduce and fix each bug.
|
|
|
|
This onboarding introduces that thought process using the CPU from the Digital Design onboarding.
|
|
You are not being asked to build another CPU or a testbench framework from scratch. The routine
|
|
class, mailbox, assembly-helper, waveform, and watchdog infrastructure is provided so you can focus
|
|
on deciding:
|
|
|
|
- what behavior needs to be tested,
|
|
- how to drive it without creating races,
|
|
- what must be observed independently,
|
|
- how to predict the correct result,
|
|
- how to recognize a failure, and
|
|
- how to show that the verification plan is complete.
|
|
|
|
> This testbench does **not** use UVM. Its sequencer, driver, monitor, scoreboard, and coverage
|
|
> components use the same separation of responsibilities found in larger UVM environments.
|
|
|
|
### Tools used
|
|
|
|
- Cadence Xcelium (`xrun`) for compilation and simulation
|
|
- Cadence SimVision for waveform debugging
|
|
- Cadence IMC for RTL code coverage
|
|
- SystemVerilog classes, mailboxes, constraints, assertions, and coverage reports
|
|
|
|
## Onboarding project
|
|
|
|
After you add your CPU RTL, the supplied verification scaffold compiles but is intentionally
|
|
incomplete.
|
|
|
|
Submit the first version of your test plan during the first week, before implementing its test cases. The plan is a working engineering document: revise it whenever coverage or debugging exposes missing behavior.
|
|
|
|
The final stage runs the same completed testbench against an encrypted CPU containing multiple
|
|
injected bugs. Finishing the onboarding means both demonstrating that your own CPU passes and using
|
|
constrained-random stimulus to find and characterize all three encrypted failures.
|
|
|
|
## Chip-level verification contract
|
|
|
|
You already learned the CPU datapath and supported instructions during Digital Design onboarding.
|
|
This section covers the external behavior that this testbench must drive and observe.
|
|
|
|
### External address map
|
|
|
|
The external port is byte addressed and accepts word-aligned accesses. `addr_i[13:12]` selects a
|
|
window:
|
|
|
|
| `addr_i[13:12]` | Window | Base | Size | Access |
|
|
| --- | --- | --- | --- | --- |
|
|
| `2'b00` | Instruction SRAM | `0x0000` | 1024 words | read/write |
|
|
| `2'b01` | Data SRAM | `0x1000` | 1024 words | read/write |
|
|
| `2'b10` | Register file | `0x2000` | 32 words | read only |
|
|
| `2'b11` | Unmapped | — | — | none |
|
|
|
|
Word `n` is located at `base + n*4`.
|
|
|
|
### External-port protocol
|
|
|
|
- A write presents `addr_i`, `wdata_i`, and `w_en_i`; the request is captured at the next rising
|
|
edge.
|
|
- A read holds `addr_i` and `r_en_i` until `rready_o` is observed. SRAM windows respond on the
|
|
following cycle; the register-file window responds in the request cycle.
|
|
- `w_en_i` and `r_en_i` must never be asserted together.
|
|
- The external port is serviced only while the CPU is disabled.
|
|
- Pulse `en_cpu_i` for one cycle to start a program at address zero.
|
|
- `cpu_halted_o` pulses when `ebreak` retires. A monitor must sample it every cycle rather than
|
|
treating it as a persistent status bit.
|
|
- `halt_cpu_i` stops execution and returns the memories to the external port. Reset before starting
|
|
another program.
|
|
|
|
### Running a program
|
|
|
|
At the chip boundary, a normal test has six phases:
|
|
|
|
1. Reset the chip and place all testbench-driven signals at idle values.
|
|
2. Write the program into instruction SRAM through the external port.
|
|
3. Write any initial values into data SRAM.
|
|
4. Pulse `en_cpu_i` to start execution.
|
|
5. Observe the halt pulse, with a bounded timeout in case the CPU is broken.
|
|
6. Read architectural state through the external port and compare it with an independent
|
|
prediction.
|
|
|
|
That sequence is simple, but the timing and ownership changes create most of the verification work.
|
|
The driver must obey the protocol, the monitor must reconstruct what actually occurred, and the
|
|
scoreboard must not assume that driver intent became DUT behavior.
|
|
|
|
## Testbench overview
|
|
|
|

|
|
|
|
| File | Purpose | Your work |
|
|
| --- | --- | --- |
|
|
| `src/verilog/tb/cpu_if.sv` | Groups chip signals and supplies a clocking block that prevents testbench/RTL races. | Provided |
|
|
| `src/verilog/tb/cpu_seq_item.svh` | Represents one randomized instruction and encodes it into a program word. | Complete constraints |
|
|
| `src/verilog/tb/cpu_xbar_item.svh` | Represents external accesses and monitor observations. | Complete constraints |
|
|
| `src/verilog/tb/cpu_sequencer.svh` | Generates programs/accesses and sends them to the driver through a mailbox. | Provided |
|
|
| `src/verilog/tb/cpu_driver.svh` | Converts high-level requests into cycle-accurate chip pin activity. | Complete protocol tasks |
|
|
| `src/verilog/tb/cpu_monitor.svh` | Samples the interface and turns observed behavior into transactions. | Complete delayed-read and CPU-memory reconstruction |
|
|
| `src/verilog/tb/cpu_ref_model.svh` | Executes the supported architecture without modeling pipeline timing. | Provided; may be extended |
|
|
| `src/verilog/tb/cpu_sb.svh` | Maintains independent state and compares DUT observations with predictions. | Complete CPU prediction and checking paths |
|
|
| `src/verilog/tb/cpu_tb_pkg.sv` | Holds shared types, constants, helpers, and class includes. | Provided |
|
|
| `src/verilog/tb/cpu_tb_top.sv` | Instantiates the DUT and components, runs tests, and contains assertions. | Add tests and assertions |
|
|
| `Fall-26-Onboarding-TestPlan-Template.md` | Plan organized like the testbench: functional, chip-level, random, assertion, coverage, and bug-hunt sections. | Copy into initial and final plans |
|
|
| `sim/behav/Include/member.include` | Lists the your CPU and testbench sources compiled by Xcelium. | Update only if filenames differ |
|
|
| `sim/behav/Makefile` | Provides the simulation, waveform, coverage, and bug-hunt commands. | Provided |
|
|
|
|
### How the components cooperate
|
|
|
|
The **sequencer** decides what operation should be attempted. It sends transaction objects through
|
|
a mailbox to the **driver**, which is the only class allowed to drive DUT inputs.
|
|
|
|
The **monitor** independently samples signals at the chip boundary. It converts observed requests,
|
|
responses, CPU memory operations, reset, start, and halt into transactions for the **scoreboard**.
|
|
The monitor never asks the driver what it intended to do.
|
|
|
|
The scoreboard keeps shadow copies of instruction and data memory. When it observes a CPU start, it
|
|
loads those shadows into the supplied **reference model**. The model predicts architectural state
|
|
and ordered stores without relying on DUT timing. Later monitor transactions are checked against
|
|
those predictions.
|
|
|
|
This separation matters. If the scoreboard used the driver's requested data as proof of what the
|
|
DUT received, a broken driver or DUT interface could agree with the scoreboard and falsely pass.
|
|
Good verification needs an independent observation path and an independent source of expected
|
|
behavior.
|
|
|
|
**Code coverage** answers “which DUT implementation structures executed?” It does not prove
|
|
correctness by itself: tests still need expected-value checks, and uncovered RTL requires
|
|
investigation.
|
|
|
|
## Project stages
|
|
|
|
### 1. Write the first test plan
|
|
|
|
Copy [the Markdown test-plan template](Fall-26-Onboarding-TestPlan-Template.md) to
|
|
`testplan_initial.md` and submit it before writing test cases. Keep that reviewed copy unchanged;
|
|
make `testplan_final.md` for revisions during implementation and coverage closure. Markdown is used
|
|
so programs, assertions, commands, and expected values remain readable and copyable. For each
|
|
planned scenario, identify:
|
|
|
|
- the functionality or requirement,
|
|
- the stimulus and relevant initial state,
|
|
- the externally observable expected result,
|
|
- which component provides that expected result,
|
|
- the evidence that would distinguish a DUT failure from a testbench failure.
|
|
|
|
The first-week plan is a preliminary implementation outline. Duplicate the detailed test record and
|
|
add table rows as needed. In the final revision, record what changed after simulation. Do not silently
|
|
rewrite the original reasoning when results contradict it; the revision history is part of the DV work.
|
|
|
|
Do not make a checklist containing only one friendly example per operation. Think about value
|
|
classes, limits, state transitions, dependencies between adjacent operations, ownership changes,
|
|
and interactions between otherwise-correct features. The point is to explain why the selected
|
|
tests demonstrate the specified behavior, not to guess the golden test list.
|
|
|
|
### 2. Set up the environment
|
|
|
|
1. Sign the [Cadence EULA](https://eulas.ece.gatech.edu/cadence/), selecting research under advisor
|
|
Visvesh Sathe and project SiliconJackets.
|
|
2. Connect to `ece-rschsrv.ece.gatech.edu` using FastX, MobaXterm, or another X-capable client.
|
|
3. Run `tcsh` to enter the C shell.
|
|
4. Run `source /tools/software/cadence/setup.csh` to load the Cadence tools. You may add the setup
|
|
command to `~/.my-cshrc` so it runs when you start `tcsh`.
|
|
5. Clone this repository and enter `sim/behav`.
|
|
|
|
Useful commands:
|
|
|
|
```sh
|
|
make help # list the supported targets
|
|
make xrun # compile and run your CPU with the repeatable default seed
|
|
make simvision # open your CPU waveform
|
|
make coverage # open your coverage database in IMC
|
|
```
|
|
|
|
`make xrun` reads `member.include`, creates symbolic links under `WORKSPACE`, compiles with
|
|
Xcelium, and runs `cpu_tb_top`. The first run will stop at the earliest unfinished TODO. That is an
|
|
onboarding checkpoint, not a syntax failure.
|
|
|
|
### 3. Add your CPU RTL
|
|
|
|
Copy only your SystemVerilog CPU RTL into `src/verilog/cpu/`. Do not copy the previous project's
|
|
Makefile, memory-image flow, tests, or simulation scripts. The supplied `chip_top` expects the
|
|
existing `cpu_top` interface. If your implementation uses additional or differently named RTL
|
|
files, update the CPU section of `sim/behav/Include/member.include`.
|
|
|
|
Do not modify `chip_top.sv`, `memory_controller.sv`, `sram_wrapper.sv`, or the SRAM macro as part of
|
|
the normal onboarding solution.
|
|
|
|
### 4. Complete protocol, monitoring, and checking
|
|
|
|
Complete and debug one component milestone at a time:
|
|
|
|
| Milestone | What is already supplied |
|
|
| --- | --- |
|
|
| Driver | Mailbox dispatch, limits, and recovery bookkeeping |
|
|
| Monitor | Reset/start/halt recognition, protocol checks, and external writes |
|
|
| Scoreboard | Reset, shadow writes, and a complete external-read comparison |
|
|
| Constraints | A mix of complete examples |
|
|
| Tests | Test lifecycle, smoke test, halt-path smoke, and helpers |
|
|
| Assertions | One complete assertion and shared failure accounting |
|
|
|
|
Each TODO states an observable contract without prescribing the golden implementation. Before
|
|
writing code:
|
|
|
|
1. Find the relevant signals in `cpu_if.sv` and the protocol requirement in this README.
|
|
2. Decide which clocking event owns each drive or sample.
|
|
3. Identify state that must survive between cycles and state that reset must clear.
|
|
4. Decide how the component will fail if the DUT does not respond.
|
|
5. Run the smallest available scenario and inspect both the log and waveform.
|
|
|
|
Start with the driver, then the monitor, then the scoreboard. Re-run after each milestone. A
|
|
simulation may reach several kinds of event in one scenario, so the next failure is evidence about
|
|
the next missing runtime path—not necessarily the next numeric TODO. The supplied handlers are
|
|
working examples of component responsibilities, not proof that the remaining behavior is correct.
|
|
|
|
A useful mismatch reports the active test, operation, location, expected value, and actual value.
|
|
Every wait for a DUT response must be bounded. A program timeout must record a failure, reset the
|
|
environment, and avoid readback that would create misleading secondary errors.
|
|
|
|
### 5. Add directed tests and assertions
|
|
|
|
Translate the approved test plan into small, named scenarios in `cpu_tb_top.sv`. Use the supplied
|
|
assembly and `run_directed` helpers instead of rebuilding program-loading boilerplate. Prefer a test
|
|
whose failure points to one behavior over a long program that can fail for many unrelated reasons.
|
|
|
|
Add directed, random, and external-port scenarios to the supplied top-level `initial` block using
|
|
the existing helpers. Do not add separate top-level `initial` blocks for ordinary tests so reset,
|
|
ordering, final reporting, and the encrypted rerun remain consistent.
|
|
|
|
Assertions check temporal protocol rules on every cycle, independent of the active program. For
|
|
each assertion, decide:
|
|
|
|
- the sampling clock and reset behavior,
|
|
- whether the consequence begins immediately or on a later cycle,
|
|
- whether a response must occur within a bounded window, and
|
|
- how its failure contributes to the final result.
|
|
|
|
The supplied simultaneous-read/write assertion demonstrates the reporting path. Temporarily create
|
|
a violation for every assertion you add and retain log or waveform evidence that it fires. Revert
|
|
the deliberate violation afterward. Add at least two assertions of your own.
|
|
|
|
Complete instruction constraints in `cpu_seq_item.svh` and external-port constraints in
|
|
`cpu_xbar_item.svh` as part of the constrained-random phase described next.
|
|
|
|
### 6. Add constrained-random testing
|
|
|
|
SystemVerilog constrained random verification generates varied inputs while excluding illegal or
|
|
unproductive combinations. The constraint exercises intentionally use three levels:
|
|
|
|
- **Provided examples:** `c_opcode`, `c_reg_bias`, `c_imm_unused`, `c_no_branch_at_end`, `c_align`,
|
|
and `c_reg_read_only` demonstrate membership, weighted distribution, implication, and bit
|
|
constraints. Read them and explain what each one accomplishes.
|
|
- **Partial constraints:** `c_imm_range`, `c_branch_target`, and `c_valid_window` contain a legal
|
|
starting condition. Complete the missing part using the nearby contract.
|
|
- **Open constraints:** design `c_mem_align`, `c_branch_taken_bias`, and `c_data_corners` from the
|
|
required behavior.
|
|
|
|
For each constraint you complete, document the invalid state it removes, the useful distribution
|
|
or dependency it encourages, and any legal behavior it makes unreachable.
|
|
|
|
Random stimulus is valuable only when it is reproducible and checked. Generated instructions are
|
|
printed by default. The Makefile also controls Xcelium's seed:
|
|
|
|
```sh
|
|
make xrun SEED=1 # repeat a known run
|
|
make xrun SEED=random # ask Xcelium to choose a new seed
|
|
```
|
|
|
|
For a random run, record the numeric `SVSEED` printed by Xcelium and rerun with that number. Reset
|
|
between random programs, label each iteration, and ensure the monitor/scoreboard path checks every
|
|
relevant result. A seed without the generated program and failing iteration is weak evidence.
|
|
|
|
### 7. Report DUT code coverage and revise the plan
|
|
|
|
Run the complete member suite, then inspect coverage:
|
|
|
|
```sh
|
|
make xrun
|
|
make coverage
|
|
```
|
|
|
|

|
|
|
|
Completion requires:
|
|
|
|
- at least 98% code coverage under `cpu_tb_top.dut`,
|
|
- a revised test plan containing tests added during coverage closure.
|
|
|
|
Coverage is a question generator. An uncovered item may reveal missing stimulus, an impossible
|
|
scenario, a monitor sampling error, or a mistaken plan. Investigate which one applies before adding
|
|
another test or excluding the item.
|
|
|
|
### 8. Characterize the encrypted CPU
|
|
|
|
After your own CPU passes, run the same completed testbench against the provided encrypted CPU:
|
|
|
|
```sh
|
|
make bug_hunt # compile the encrypted CPU and run the complete suite
|
|
make bug_hunt_simvision # open the encrypted-CPU waveform
|
|
```
|
|
|
|
The encrypted CPU contains **three** injected bugs, and you are required to find and characterize
|
|
**all three**. This stage demonstrates why constrained-random testing is useful: a varied but legal
|
|
stream can expose an interaction that a short directed checklist missed. Your bugs must
|
|
first be observed in your constrained-random phase, not chosen from a disclosed trigger or written
|
|
as a directed test in advance.
|
|
|
|
```sh
|
|
make bug_hunt SEED=random # explore; record Xcelium's numeric SVSEED
|
|
make bug_hunt SEED=12345 # reproduce an interesting run
|
|
```
|
|
|
|
`make bug_hunt` deterministically assigns one of three encrypted CPUs from the local Unix
|
|
username and prints the selected variant before compiling. The same username receives the same
|
|
variant on every run, while the three variants distribute different additional corner cases
|
|
across the cohort.
|
|
|
|
Run multiple seeds, retain the first reproducible failure, and then reduce it into a focused
|
|
reproducer. `make bug_hunt` disables stop-on-first-scoreboard-error so the run can collect useful
|
|
evidence. It writes `bug_hunt.log` and `bug_hunt_waves.shm`, leaving the member run's
|
|
`simulation.log` and `waves.shm` intact. Do not modify, replace, decrypt, or attempt to recover the
|
|
protected RTL.
|
|
|
|
For each selected bug, record the minimum failing program that would reproduce the error. For each bug, submit:
|
|
|
|
1. A description of the bug, with the expected and actual behavior of the CPU.
|
|
2. Waveform evidence at readable chip-level signals.
|
|
3. The minimum failing program that triggers the bug and experiments used to separate the trigger from nearby possibilities.
|
|
|
|
## Deliverables
|
|
|
|
You may submit online as one archive or complete an in-person checkoff at a work session. Include:
|
|
|
|
1. `testplan_initial.md` and `testplan_final.md`; a rendered PDF of each is optional.
|
|
- `testplan_initial.md` **is due Sunday, September 27 at 11:59pm, no exceptions.**
|
|
- You will submit `testplan_final.md`, with any revisions, **on Sunday, October 4 at 11:59pm, no exceptions.**
|
|
2. The completed driver, monitor, scoreboard, sequence items, and top-level testbench (tb folder).
|
|
3. `simulation.log` showing your CPU suite passing.
|
|
4. An IMC screenshot showing at least 98% DUT code coverage.
|
|
5. Evidence that each added assertion detects its intended violation.
|
|
6. Encrypted-CPU bug report first found through constrained random, with its numeric seed,
|
|
failing iteration, minimized program, and waveform evidence for all three bugs.
|
|
|
|
**Deliverables #2-8 are due Sunday, October 4 at 11:59pm, no exceptions.**
|
|
|
|
For online submissions, send the archive to the Discord account **sjcheckoffs** (SiliconJackets
|
|
Checkoffs). In-person checkoffs at work sessions are preferred.
|
|
|
|
### Build the submission archive
|
|
|
|
Run the complete member suite, your automatically assigned encrypted-CPU suite, and coverage export
|
|
before packaging (make sure you have everything):
|
|
|
|
```sh
|
|
make submission
|
|
```
|
|
(need to `cd` back into the root directory).
|
|
|
|
## Submission disclaimer
|
|
|
|
- Submissions after 11:59 p.m. on the announced deadline will not be accepted.
|
|
- Verify the archive before the deadline; corrected late submissions are not accepted.
|
|
- You may collaborate on concepts and debugging methods, but you may not share code or bug triggers.
|
|
- Using AI to understand language or verification concepts is acceptable. Submitting generated code
|
|
or a generated bug report that you cannot justify from your own plan, logs, and waveforms is not.
|
|
- Do not share ECE server access. Request and test access early.
|
|
|
|
## Resources
|
|
|
|
### Testbench architecture
|
|
- [VerificationGuide: SystemVerilog](https://verificationguide.com/systemverilog/)
|
|
- [VerificationGuide: SystemVerilog Testbench](https://verificationguide.com/systemverilog/systemverilog-testbench/)
|
|
- [VerificationGuide: SystemVerilog Adder Testbench Example](https://verificationguide.com/systemverilog-examples/systemverilog-testbench-example-adder/)
|
|
- [ChipVerify: SystemVerilog Simple Testbench](https://chipverify.com/systemverilog/systemverilog-simple-testbench)
|
|
|
|
### SystemVerilog classes
|
|
|
|
- [ChipVerify: SystemVerilog Classes](https://www.chipverify.com/systemverilog/systemverilog-class)
|
|
- [Doulos: SystemVerilog Classes Tutorial](https://www.doulos.com/knowhow/systemverilog/systemverilog-tutorials/systemverilog-classes-tutorial/)
|
|
|
|
### Constrained random verification
|
|
|
|
- [SystemVerilog Randomization](https://www.chipverify.com/systemverilog/systemverilog-randomization)
|
|
- [SystemVerilog Constraints](https://www.chipverify.com/systemverilog/systemverilog-constraints)
|
|
- [Constraint Random Verification](https://www.chipverify.com/verification/constraint-random-verification)
|
|
|
|
### RTL code coverage
|
|
|
|
- [Code Coverage](https://www.chipverify.com/verification/code-coverage)
|
|
|
|
### SystemVerilog assertions
|
|
|
|
- [Doulos: Assertions Tutorial](https://www.doulos.com/knowhow/systemverilog/systemverilog-tutorials/systemverilog-assertions-tutorial/)
|
|
- [systemverilog.io: SVA Basics](https://www.systemverilog.io/verification/sva-basics/)
|
|
|
|
### Clocking blocks
|
|
|
|
- [Doulos: Clocking Tutorial](https://www.doulos.com/knowhow/systemverilog/systemverilog-tutorials/systemverilog-clocking-tutorial/)
|
|
- [ChipVerify: Clocking Blocks, Part 1](https://www.chipverify.com/systemverilog/systemverilog-clocking-blocks)
|
|
- [ChipVerify: Clocking Blocks, Part 2](https://www.chipverify.com/systemverilog/systemverilog-clocking-blocks-part2)
|
|
|
|
### Mailboxes and processes
|
|
|
|
- [SystemVerilog Mailboxes](https://www.chipverify.com/systemverilog/systemverilog-mailbox)
|
|
- [SystemVerilog fork/join](https://www.chipverify.com/systemverilog/systemverilog-fork-join-any)
|
|
|
|
### RISC-V
|
|
|
|
- [The RISC-V Instruction Set Manual, Volume I](https://riscv.org/technical/specifications/)
|
|
|
|
## Questions and contacts
|
|
|
|
Ask questions in the `onboarding-help` discussion channel on the
|
|
[Discord server](https://discord.com/invite/swK5QnTt4j), or contact a DV lead:
|
|
|
|
| Name | Discord | Email |
|
|
| --- | --- | --- |
|
|
| Kevin Luo | elmothefrog | kluo78@gatech.edu |
|
|
| Khai Tran | khxit | ktran333@gatech.edu |
|
|
| Mai Bharathi | moose8511 | mbharathi7@gatech.edu |
|
|
| Matthew Nichols | fastbreakd | mi72@gatech.edu |
|
|
| Ethan Huang | nathanhueg | ethanhuang@gatech.edu |
|