rtl/imm_decode.sv — Immediate Decode Unit
Extracts and sign-extends the immediate field for all five RV32 instruction formats (I, S, B, U, J) from the raw 32-bit instruction word. Purely combinational, single always-block.
Where it fits
Instantiated once by riscv_core.sv as imm_dec_unit, fed if_id_instr in the ID stage.
Ports
| Direction | Name | Width | Description |
|---|---|---|---|
| in | instr |
32 | Raw instruction word |
| out | imm_ext |
32 | Sign-extended immediate |
Functionality
Icarus-safe by construction: every field (sign_bit, i_imm_10_0, s_imm_4_0, b_imm_11, u_upper, j_imm_10_1, ...) is pre-extracted as a named assign wire before the always @(*) case statement — Icarus Verilog 11 errors on some constant bit-select patterns used directly inside always blocks, so this file avoids that entirely.
| Format | Opcodes | Bit layout |
|---|---|---|
| I-type | 0x13 ADDI/etc, 0x03 LOAD, 0x67 JALR |
{sign×20, instr[30:20]} |
| S-type | 0x23 STORE |
{sign×20, instr[30:25], instr[11:7]} |
| B-type | 0x63 BRANCH |
{sign×19, instr[7], instr[30:25], instr[11:8], 1'b0} |
| U-type | 0x37 LUI, 0x17 AUIPC |
{instr[31:12], 12'b0} |
| J-type | 0x6F JAL |
{sign×11, instr[19:12], instr[20], instr[30:21], 1'b0} |
| default | anything else | 32'b0 |
Example
instr = 0x02A00593 # addi a1, x0, 42 (opcode 0x13, I-type)
i_imm_10_0 = instr[30:20] = 12'd42
sign_bit = instr[31] = 0
imm_ext = {20{0}, 0, 12'd42} = 32'd42
instr = 0xFF010113 # addi sp, sp, -16 (I-type, negative immediate)
i_imm_10_0 = instr[30:20] = 12'hFF0
sign_bit = instr[31] = 1
imm_ext = {20{1}, 1, 12'hFF0} = 0xFFFFFFF0 (-16)
Related
- riscv_core.md — the only instantiation site (ID stage)
- reference.md — opcode map cross-reference