Declare a packet header as a packed struct whose field order matches the wire, and decode a raw word with it.
Hardware context: Packet-header formatter and command decoder at a hardware endpoint. Decode the packed fields received from a header bus into named monitor fields.
A testbench sends a WRITE and the DUT performs a READ to a different address. The header struct in the testbench listed the fields in a different order from the specification. In a packed struct the first field is the most significant, so two fields traded places on the wire and nothing warned anyone.
This header is 16 bits: a 2-bit version on top, then a 2-bit kind, a 4-bit tag and an 8-bit length at the bottom. Declare header_t as a packed struct with exactly that layout, and write decode_header(word), which returns the header held in a raw 16-bit word.
For word = 16'h6512 the fields are version 1, kind 2, tag 5 and length 0x12.
The starter names the four fields for you. Give each one its width and put them in wire order.
Signals in the timeline
| Signal | Width | Role |
|---|---|---|
word | 16 | input of each check |
Full specification
| Field | Bits of the word |
|---|---|
| version | 15:14 |
| kind | 13:12 |
| tag | 11:8 |
| length | 7:0 |
typedef struct packed { ... } header_t;
function automatic header_t decode_header(input logic [15:0] word);
header_t must be exactly 16 bits wide, with no padding. Every encoding is accepted; this decoder does not check whether a kind is legal.
Each case also reports $bits(header_t), so a struct of the wrong width shows up directly.
Examples
Example 1
Every field different- Input
word = 16'h6512
- Output
struct_width = 16, version = 1, kind = 2, tag = 5, length = 0x12
0x6512 is 01 10 0101 00010010 in binary: version 1, kind 2, tag 5, length 0x12.
Example 2
Zero is still a header- Input
word = 16'h0000
- Output
struct_width = 16, version = 0, kind = 0, tag = 0, length = 0x0
Every field is 0, and the struct is still 16 bits wide.
Example 3
Every field at its maximum- Input
word = 16'hFFFF
- Output
struct_width = 16, version = 3, kind = 3, tag = 15, length = 0xff
version 3, kind 3, tag 15 and length 0xFF: each field is as wide as the table says.
Constraints and contract
- word is a known 16-bit value.
- Keep the field names version, kind, tag and length, and the names header_t and decode_header.
- All fields are unsigned.
Hints
Hint 1
Which field must come first in the declaration: the one at the top of the word or the one at the bottom?
Hint 2
Add up the widths from the table. The struct must come to exactly 16 bits.
Hint 3
Once the struct matches the wire, a raw 16-bit word and a header_t hold the same bits, so the decoder needs no shifting or masking.
What this judge verifies: Your struct and decoder are run on single-bit words for every bit position, on asymmetric field values and on seeded words; each case also reports the struct width. Passing shows the layout matches the table.
275 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