Drill 1. rand bit is_read and rand bit [4:0] len: reads are 1 to 4 beats, writes are 8 to 16.
Drill 2. rand bit [31:0] size, count: both at least 1, and size * count at most 4096.
Drill 3. rand state_e cur, next over IDLE, REQ, WAIT, DONE: next is a legal move from cur. IDLE goes to IDLE or REQ, REQ to WAIT or IDLE, WAIT to WAIT or DONE, and DONE only to IDLE.
Write the three answers before opening the reveal. Copy the starter into the Code Lab, fill in each empty answer_c, and run it on Verilator. The grader solves each class hundreds of times and checks every result, then pins a few values that must be legal; it prints ok or the first rule your answer broke.
// Drill starter: write each answer_c, then run it.
// Drills: fields that depend on each other.
typedef enum bit [1:0] {IDLE, REQ, WAIT, DONE} state_e;
class drill1; // reads are 1 to 4 beats, writes 8 to 16
rand bit is_read;
rand bit [4:0] len;
constraint answer_c { /* your answer here */ }
endclass
class drill2; // size and count at least 1, size * count at most 4096
rand bit [31:0] size, count;
constraint answer_c { /* your answer here */ }
endclass
class drill3; // next is a legal move from cur
rand state_e cur, next;
constraint answer_c { /* your answer here */ }
endclass
size * count <= 4096 pass with size and count both near two billion?Both operands are 32 bits, so the product is computed in 32 bits and wraps. A product of 2^32 wraps to 0, which is at most 4096. Widen the operands before multiplying.
One set of answers, run through the same grader:
// Drills: fields that depend on each other.
typedef enum bit [1:0] {IDLE, REQ, WAIT, DONE} state_e;
class drill1; // reads are 1 to 4 beats, writes 8 to 16
rand bit is_read;
rand bit [4:0] len;
constraint answer_c { if (is_read) len inside {[1:4]}; else len inside {[8:16]}; }
endclass
class drill2; // size and count at least 1, size * count at most 4096
rand bit [31:0] size, count;
constraint answer_c { size inside {[1:4096]}; count inside {[1:4096]}; size * count <= 4096; }
endclass
class drill3; // next is a legal move from cur
rand state_e cur, next;
constraint answer_c {
cur == IDLE -> next inside {IDLE, REQ};
cur == REQ -> next inside {WAIT, IDLE};
cur == WAIT -> next inside {WAIT, DONE};
cur == DONE -> next == IDLE;
}
endclass
drill 1, two-armed length: ok
drill 2, product that cannot wrap: ok
drill 3, legal state moves: ok
PASS: all 3 drills rightSpelling | Arms covered | Use it when |
|---|---|---|
| Both, in one construct | Two-sided maps like read against write |
Paired implications | Both, only if you write both | Spec tables with one row per case |
Single implication | One: the other side stays free | Never for two-sided conditions |
A lone is_read -> len inside {[1:4]} leaves writes free to take any length, including 1 to 4 and 17 to 31. The grader's random results catch that within a few calls.
Two answers are right. Bound each factor first: with both at most 4096, the 32-bit product is at most 2^24 and cannot wrap. Or widen the operands, 64'(size) * 64'(count) <= 4096, unsigned, since 32 by 32 bits always fits in 64. Casting after the multiply is too late, because the wrap has already happened.
The reveal uses the bounds for a practical reason: Verilator's solver took about 39 seconds on the 64-bit product and under 5 on the bounded form. The grader caught the plain size * count <= 4096 at once, with a true product above 3 × 10^18 that had wrapped to a small number.
A move table needs a row for every state. A rand enum only takes its named values (IEEE 1800 18.3), so a rand state_e never becomes an unnamed code; the hole appears when states are plain bit [1:0] fields, and then a whitelist such as cur inside {IDLE, REQ, WAIT} closes it.
Run with Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown. Verilator prints a harmless WIDTHTRUNC warning for if (!obj.randomize()), because randomize() returns an int, and an UNSATCONSTR warning when a solve fails on purpose. Icarus 13 does not support constraints.
Each starter was run with its answers left empty, and its grader reported all three drills wrong; each revealed answer passed the same grader. The graders also caught an unwidened size * count and an over-tight even rule when tried.