Skip to content

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)