블록 다이어그램

Immediate Generator 이론
RISC-V의 경우 instruction 자체가 imm 비트가 여기저기 뿌려져있다. 아래 이미지를 보자

type에 따라 imme비트의 위치가 달라진다.
이는 하드웨어가 명령어를 해독하는 속도를 높이기 위해 레지스터 번호 등의 특정 비트 위치를 고정하다보니 나타난 현상이다.
상대적으로 덜 중요한 immediate 값들은 남는 자리에 쪼개져서 배치된다.
ImmGen 모듈은 이렇게 흩어진 조각들을 모아서 계산에 쓸 수 있는 완전한 32 bit 숫자로 만들어주는 역할을 한다.
그럼 이제 구현은 뻔하다.
입력으로 32 bit instruction과 이 instr이 무슨 타입인지를 알기 위한 signal을 받는다.
R-type은 보면알겠지만 imm이 없기에, 우리는 I, S, B, U, J를 구분해야한다.
물론 5개이므로 3bit signal이 필요하다.
출력은 당연당연하게 쪼개졌던 imm 값이다. 32bit이다.
Type 별 설명
I Type
I Type은 inst[31:20]의 12 bit 데이터를 LSB 쪽으로 채우고, 부호 비트를 나머지 MSB 20 bit에 복사한다.
S Type
S Type은 inst[31:25]와 inst[11:7]을 concat 한 후 I type 같은 방식으로 상위 비트를 채운다.
B Type
B type은 beq, bne 등의 branch 관련 instruction이다. branch addr은 항상 2 byte (16 bit) 단위이다.
이 점을 주의하자. CA 공부를 열심히 하면....
Alignment를 배울 수 있고, 홀수 번째에는 addr이 올 수가 없다. 항상 2칸씩 이동하기 때문에...
이를 이진수로 바꾸면 어떻게 되겠는가?
B type의 imm[0]은 항상 0이 온다.
imm을 여기저기 concat한 12 bit의 값을 imm[11:0]으로 넣는게 아닌, {imm[12:1], 0} 으로 13bit를 만든다.
MSB까지 상위 19 bit는 부호 확장.
U Type
U Type은 부호 확장이 아닌 상위 비트 채우기이다.
instr에서 뽑은 20bit를 MSB부터 채운 후 하위 12 bit를 모두 0으로 채운다.
J Type
J Type은 B type 처럼 imm[0]에 0이 온다. 이후 부호 확장.
ImmGen 설계
이론은 복잡하지만! concat 문법을 알고 instruction 구조를 알면 쉽다~
`timescale 1ns / 1ps
module imm_gen(
input wire [31:0] inst ,
input wire [2:0] imm_src ,
output reg [31:0] imm_ext
);
always @(*) begin
case (imm_src)
// I Type
3'b000: imm_ext = { {20{inst[31]}}, inst[31:20] };
// S Type
3'b001: imm_ext = { {20{inst[31]}}, inst[31:25], inst[11:7] };
// B Type
3'b010: imm_ext = { {19{inst[31]}}, inst[31], inst[7], inst[30:25], inst[11:8], 1'b0 };
// U Type
3'b011: imm_ext = { inst[31:12], 12'b0 };
// J Type
3'b100: imm_ext = { {11{inst[31]}}, inst[31], inst[19:12], inst[20], inst[30:21], 1'b0 };
default: imm_ext = 32'b0;
endcase
end
endmodule
EZ.
TB
`timescale 1ns / 1ps
module tb_imm_gen();
reg [31:0] inst;
reg [2:0] imm_src;
wire [31:0] imm_ext;
// ImmGen 모듈 인스턴스화 (DUT: Device Under Test)
imm_gen uut (
.inst(inst),
.imm_src(imm_src),
.imm_ext(imm_ext)
);
initial begin
// 1. I-type 테스트 (addi t0, t1, -1)
// 명령어: 111111111111_00000_000_00101_0010011 (0xFFF00293)
inst = 32'hFFF00293; imm_src = 3'b000;
#10;
$display("I-type: Result = %h (Expected: ffffffff)", imm_ext);
// 2. B-type 테스트 (beq x0, x0, offset)
// 명령어의 비트들을 섞어서 offset 4(실제로는 8)를 표현
inst = 32'h00000463; imm_src = 3'b010;
#10;
$display("B-type: Result = %h (Expected: 00000008)", imm_ext);
// 3. U-type 테스트 (lui x5, 0x12345)
inst = 32'h123452B7; imm_src = 3'b011;
#10;
$display("U-type: Result = %h (Expected: 12345000)", imm_ext);
$finish;
end
endmodule
이것 또한 제미나이...

TCL Console 결과는 아주 이쁘게 나온다.
(다크모드가 된 이유는 버전을 올려서입니다 ㅎㅎ)
다음 포스팅에서는 Control Unit에 들어갈게요.
'Project > RISC-V CPU Architecture Design' 카테고리의 다른 글
| [8] RISC-V Control Unit 설계 (2) - ALU Decoder (0) | 2026.01.06 |
|---|---|
| [7] RISC-V Control Unit 설계 (1) - Main Decoder (0) | 2026.01.05 |
| [5] ALU 설계 (0) | 2026.01.02 |
| [4] Single-Cycle 프로세서 Register File 설계 (0) | 2026.01.02 |
| [3] RISC-V 프로젝트 기획 (0) | 2026.01.02 |