Turn three raw opcode bits into an enum only when they hold a legal code, and say so with a valid bit.
Hardware context: Command decoder and control-state machine for a transaction engine. Decode a raw hardware opcode into a typed operation with explicit validity.
A bus monitor converted its opcode with a static cast. When the DUT started sending a reserved code, the cast accepted it, coverage still looked complete, and nobody noticed the illegal traffic.
This engine knows three operations: READ = 3'b001, WRITE = 3'b100 and FENCE = 3'b110. Write decode_opcode(raw), which returns a valid bit and an operation.
For a legal, fully known code, return valid = 1 and that operation. For anything else, a reserved code or any x or z bit, return valid = 0 with the operation set to OP_READ, so the result is always known. The valid bit, not the operation, tells the next stage whether to act.
For raw = 3'b1x0 the bits could mean WRITE or FENCE. That is not a legal code, so valid is 0.
Signals in the timeline
| Signal | Width | Role |
|---|---|---|
raw | 3 | input of each check |
Full specification
typedef enum logic [2:0] {OP_READ = 3'b001, OP_WRITE = 3'b100, OP_FENCE = 3'b110} opcode_t;
function automatic logic [3:0] decode_opcode(input logic [2:0] raw); // returns {valid, op}
| raw | valid | op |
|---|---|---|
| 3'b001 | 1 | OP_READ |
| 3'b100 | 1 | OP_WRITE |
| 3'b110 | 1 | OP_FENCE |
| any other known code | 0 | OP_READ |
| any code with an x or z bit | 0 | OP_READ |
All 64 combinations of 0, 1, x and z in the three bits are tested. The returned four bits are always known.
Examples
Example 1
A legal write- Input
raw = 3'b100
- Output
valid = yes, op = OP_WRITE ('b100)
100 is WRITE, so valid = 1 and op = OP_WRITE.
Example 2
A reserved code- Input
raw = 3'b010
- Output
valid = no, op = OP_READ ('b001)
010 has no label. valid = 0, and op falls back to OP_READ so the result stays known.
Example 3
An unknown bit changes the meaning- Input
raw = 3'b1x0
- Output
valid = no, op = OP_READ ('b001)
1x0 could be 100 (WRITE) or 110 (FENCE). It is not a legal code, so valid = 0.
Constraints and contract
- raw may hold x or z in any bit.
- The result is always known: no x or z in valid or op.
- Keep opcode_t and the function signature.
Hints
Hint 1
A cast copies any value into an enum, even one with no label. What must you check before you trust the bits as an opcode?
Hint 2
Some ways of matching treat x or z as "don't care". Which kind of matching keeps an unknown bit from looking like a legal code?
Hint 3
Start from the invalid answer, {1'b0, OP_READ}, and change it only when raw exactly matches one of the three labels.
What this judge verifies: Your decoder is called on all 64 combinations of 0, 1, x and z in the three opcode bits. Passing shows every legal code is accepted and every other input is rejected with a known result.
67 checks on Icarus Verilog · browser. Run the examples first, then check the full regression. The suite is local and inspectable. A passing result establishes the tested cases, not a proof for all possible inputs.
See all 5 steps and the final capstone