Home > Final > 2025-08-19

2025-08-19
Study System Verilog

RISC-V I-TYPE Review

alt text

funct3 를 통해 SLTI, SLTIU 구분 해야함
SLTI 경우 부호비트를 생각해서 늘려줘야 함
shift 는 전부 unsigned, 그래서 SLTIU 도 immExtend 에서 같이 처리

/*** immExtend ***/

    `OP_TYPE_I: begin
        case (func3)
            3'b001: immExt = {27'b0, instrCode[24:20]}; // SLLI
            3'b011: immExt = {20'b0, instrCode[31:20]}; // SRLI, SRAI
            3'b101: immExt = {27'b0, instrCode[24:20]}; // SLTIU
            default:immExt = , instrCode[31:20]};
        endcase                
    end 
/*** ROM ***/

    //rom[x]=32'b imm12      _ rs1 _f3 _ rd  _ op // I-Type
    rom[6] = 32'b000000000001_00001_000_01001_0010011;// addi x9, x1, 1 
    rom[7] = 32'b000000000100_00010_111_01010_0010011;// andi x10, x2, 4 
    rom[8] = 32'b000000000001_00010_110_01011_0010011;// ori x11, x2, 1 
    rom[9] = 32'b000000000011_00001_001_01100_0010011;// slli x12, x1, 1 → 2b00001000 << 3 = 11 * 2^3  = 88

왼쪽 쉬프트: x « n = x × 2ⁿ
오른쪽 쉬프트: x » n = floor(x ÷ 2ⁿ)

alt text

RISC-V B-TYPE

alt text

비교해서 점프하겠다. 결국 명령어의 주소를 바꾸겠다는 뜻.
PC의 값을 바꾸면 나오는 명령어가 바뀜 = Branch (C언어: if, for, while, switch 등)
(rs1, rs2로 연산하기 위해) ALU 안에 비교기 처리

/*** ControlUnit ***/

    `OP_TYPE_B: aluControl = operator;
/*** alu ***/

    always_comb begin : branch
        btaken = 1'b0;
        case (aluControl[2:0])
            `BEQ:  btaken = (a == b);
            `BNE:  btaken = (a != b);
            `BLT:  btaken = ($signed(a) < $signed(b));
            `BGE:  btaken = ($signed(a) >= $signed(b));
            `BLTU: btaken = (a < b);
            `BGEU: btaken = (a >= b);
        endcase
    end
/*** DataPath ***/
    logic [3:0] PC_4_AdderResult, PC_Imm_AdderResult, PCSrcMuxOut;
    logic PCSrcMuxSel;
    logic btaken;

    adder U_PC_Imm_Adder (
        .a(immExt),
        .b(PCOutData),
        .y(PC_Imm_AdderResult)
    );

    adder U_PC_4_Adder (
        .a(32'd4),
        .b(PCOutData),
        .y(PC_4_AdderResult)
    );

    assign PCSrcMuxSel = btaken & branch;

    mux_2x1 U_PCSrcMux (
        .sel(PCSrcMuxSel),
        .x0 (PC_4_AdderResult),
        .x1 (PC_Imm_AdderResult),
        .y  (PCSrcMuxOut)
    );

ROM[n] : n*4 씩 이동

ROM[5] 참 -> rom[8] 점프 (20->32)

/*** ROM ***/

    //rom[x]=32'b imm7  _ rs2 _ rs1 _f3 _ imm5_ op // B-Type
    rom[5] = 32'b0000000_00010_00010_000_01100_1100011;  // beq x2, x2, 12 
    //rom[x]=32'b imm12      _ rs1 _f3 _ rd  _ op // L-Type
    rom[6] = 32'b000000001000_00000_010_01000_0000011;  // lw x8, 8(x0)
    //rom[x]=32'b imm12      _ rs1 _f3 _ rd  _ op // I-Type
    rom[7] = 32'b000000000001_00001_000_01001_0010011;  // addi x9, x1, 1 
    rom[8] = 32'b000000000100_00010_111_01010_0010011;  // andi x10, x2, 4 

alt text

ROM[5] 거짓 -> rom[8] (20->24)

/*** ROM ***/

    //rom[x]=32'b imm7  _ rs2 _ rs1 _f3 _ imm5_ op // B-Type
    rom[5] = 32'b0000000_00010_00000_000_01100_1100011;  // beq x2, x0, 12 
    //rom[x]=32'b imm12      _ rs1 _f3 _ rd  _ op // L-Type
    rom[6] = 32'b000000001000_00000_010_01000_0000011;  // lw x8, 8(x0)

alt text

규칙성

alt text

Imm의 공통 bit를 최대한 똑같은 위치에 맞춘다.
L, I, S, B, J, JL Type 에서 최대한 같은 위치의 Imm bit 위치를 같게 한다.
H/W 최적화에 도움이 된다.
B, J Type의 경우 Imm값이 ROM(PC)주소의 offset값이 된다.
ROM의 주소는 항상 짝수가 되므로 imm[0]은 항상 ‘0’값이 된다.
그러므로 B, J Type에서 imm[0]이 없이 강제로 ‘0’을 넣어줘도 된다.
그 효과는 offset 범위값을 넓힐 수 있다.
명령어가 입력된 ROM의 주소 특징은 4의 배수이다.
imm 12bit 고정. 최대값 주소범위를 넓히고 싶다.

RISC-V LU, AU, J, JL-TYPE

C언어로 if문 해서 점프, 컴파일러에서 만들어줌