HDL simulator observations: thirty original examples
The thirty fixtures produced twenty matching and ten differing observation payloads across the two pinned simulator configurations. Eight differences involved unknown values or initialization, and two involved built-in seeded random streams. Every one of the sixty tool/fixture combinations repeated its own observation payload on a second execution; this is a reproducibility result for these examples, not a simulator compliance ranking.
Compare observations without discarding the original output
Each fixture prints lines beginning with OBS. The compact table compares those deliberate observations, while the data retains compiler output, runtime output, warnings and return codes. Simulator finish banners are not counted as design-behavior differences. A matching payload means the selected printed observations matched; it does not establish equivalence for behavior the fixture never observed.
| Example source | Icarus observation | Verilator observation | Payload |
|---|---|---|---|
| F01: Explicit unknown assignment | OBS value=10x1 unknown=1 | OBS value=1001 unknown=0 | Different |
| F02: Uninitialized register | OBS value=xxxxxxxx unknown=1 | OBS value=00000000 unknown=0 | Different |
| F03: Mixed signed comparison | OBS mixed_less=0 cast_less=1 | OBS mixed_less=0 cast_less=1 | Same |
| F04: Assignment-width truncation | OBS narrow=1 wide=17 | OBS narrow=1 wide=17 | Same |
| F05: Clocked nonblocking update | OBS a=1 b=0 | OBS a=1 b=0 | Same |
| F06: Signed extension | OBS a=-8 b=-8 bits=fff8 | OBS a=-8 b=-8 bits=fff8 | Same |
| F07: Unsigned extension | OBS a=248 b=248 bits=00f8 | OBS a=248 b=248 bits=00f8 | Same |
| F08: Logical and arithmetic shifts | OBS logical=3c arithmetic=fc | OBS logical=3c arithmetic=fc | Same |
| F09: Unsized literal widths | OBS decimal_bits=32 hex_bits=32 value=1 | OBS decimal_bits=32 hex_bits=32 value=1 | Same |
| F10: Expression assignment context | OBS narrow=0 wide=16 | OBS narrow=0 wide=16 | Same |
| F11: Concatenation unsigned comparison | OBS signed_less=1 concat_less=0 | OBS signed_less=1 concat_less=0 | Same |
| F12: Explicit signed cast | OBS unsigned=255 signed=-1 | OBS unsigned=255 signed=-1 | Same |
| F13: Unknown condition in if | OBS sel=x branch=2 | OBS sel=0 branch=2 | Different |
| F14: Unknown conditional bit merge | OBS value=10xx | OBS value=1001 | Different |
| F15: Case equality against unknown | OBS ordinary=x case_x=1 unknown=1 | OBS ordinary=1 case_x=0 unknown=0 | Different |
| F16: Reduction with unknown bit | OBS and=x or=1 xor=x | OBS and=0 or=1 xor=1 | Different |
| F17: Controlling bitwise zero | OBS x_and_0=0 x_or_1=1 | OBS x_and_0=0 x_or_1=1 | Same |
| F18: Unknown XOR operand | OBS x_xor_0=x | OBS x_xor_0=0 | Different |
| F19: Two-state bit assignment | OBS bit=0 logic=x | OBS bit=0 logic=0 | Different |
| F20: Explicit register initialization | OBS value=5a | OBS value=5a | Same |
| F21: Declaration initialization | OBS value=a5 | OBS value=a5 | Same |
| F22: Blocking statements in one process | OBS a=2 b=2 | OBS a=2 b=2 | Same |
| F23: Nonblocking swap after edge | OBS a=2 b=1 | OBS a=2 b=1 | Same |
| F24: Last nonblocking assignment in process | OBS a=2 | OBS a=2 | Same |
| F25: Three-stage pipeline | OBS a=1 b=0 c=0; OBS a=2 b=1 c=0; OBS a=3 b=2 c=1 | OBS a=1 b=0 c=0; OBS a=2 b=1 c=0; OBS a=3 b=2 c=1 | Same |
| F26: Opposite-edge stimulus | OBS d=1 q=1 | OBS d=1 q=1 | Same |
| F27: Asynchronous reset then clock | OBS reset_q=0; OBS clock_q=1 | OBS reset_q=0; OBS clock_q=1 | Same |
| F28: Explicit modulo arithmetic sequence | OBS state=3d20bdba; OBS state=e9dab1d1; OBS state=9ccc40fc | OBS state=3d20bdba; OBS state=e9dab1d1; OBS state=9ccc40fc | Same |
| F29: Seeded random sequence | OBS random=8011ec00 seed=0011ea9e; OBS random=61e0e9c3 seed=e1e0e687; OBS random=b3547666 seed=3354751c | OBS random=979a27f1 seed=a79f332a; OBS random=7d04cbad seed=83d6c4a7; OBS random=9c22637a seed=0e23cf8b | Different |
| F30: Seeded urandom process | OBS urandom=0011ec00; OBS urandom=e1e0e9c3; OBS urandom=33547666 | OBS urandom=a79f332a; OBS urandom=979a27f1; OBS urandom=b38d6fdb | Different |
The JSON, CSV and method retain commands, hashes and literal outputs. Original observations are CC BY 4.0; the original fixture code is MIT licensed.
Read unknown-value results with the selected configuration
F01 assigns an explicit unknown bit. Icarus prints OBS value=10x1 unknown=1; the selected Verilator configuration prints OBS value=1001 unknown=0. F02 likewise distinguishes an uninitialized register represented as unknown bits from the selected zero initialization policy. These outcomes must be read with the declared state model and command-line choices, not as evidence that a hardware signal starts at zero.
Verilator documents its treatment of unknown values and the options controlling unknown assignment and initialization1. The fixture records those settings so a recipient can reproduce the observation or deliberately run a different configuration. Changing an option creates a new experiment; it should not silently replace the published row.
F19 provides a useful contrast: the explicit two-state bit variable is printed as zero by both tools, while the accompanying logic value differs. That row keeps the declaration choice visible. It prevents the broad conclusion that every value in one source file has the same unknown-value behavior.
Keep widths, scheduling and seeds explicit
The width cases record their signedness, sizing and output rather than inferring behavior from a literal’s appearance. Icarus documents its expression-width choices and the strict-width option used here2. Use the exact source and options when interpreting a result involving an unsized expression, truncation or sign extension.
The ordering cases are intentionally small and deterministic under their recorded stimulus. They are not a licence to depend on the execution order of competing processes in a larger testbench. Preserve the observation point as well as the assignment: a value printed before an update and one sampled after it answer different questions.
F29 and F30 use fixed seeds with built-in random functions. Their streams repeat within each tool but differ between tools. Store the selected test and seed together with the simulator configuration; a shared numeric seed alone did not produce a shared stream in these observations. The row keeps literal values so that a repeat can be checked without reducing the output to a generic pass label.
Read warnings before reusing a fixture
A zero return code does not mean that no diagnostic was emitted. The dataset preserves warning text even when execution continued. Verilator’s warning documentation provides the named diagnostic context3; the recorded command states how warnings affected this run. Review the message and the source together before adopting the example’s configuration in another project.
For a project-specific investigation, reduce the disputed behavior to an original minimal fixture, name the expected observation and preserve both tool configurations. The handoff guide shows how a byte-level manifest can detect changed inputs. It complements the measured observations without converting agreement between two runs into a general correctness claim.
Use the observation viewer to search the same thirty examples.
Not covered on this page
- Complete language compliance or simulator rankings.
- Hardware power-up state, analog behavior or metastability safety.
- Cross-tool random-stream equivalence beyond the recorded cases.
- Performance, capacity or commercial UVM execution.
Sources
Code on this page is original and MIT licensed.
How we test: methodology. Found a mistake? Corrections.