Semiconductor, Embedded/작성 중...

컴퓨터 구조 및 CPU 동작 원리 (3) - 32 Bit RISC CPU(Pipeline) RTL 설계 ~ING

잇(IT) 2024. 10. 14. 19:58

 

https://insoobaik.tistory.com/717

 

컴퓨터 구조 및 CPU 동작 원리 (1) - 기본 개념

목차컴퓨터의 구성요소 5가지Absractions and ISADefining PerformanceInstruction SetMIPS Arithmetic OperationRegister OperandsMemory OperandsImmediate Operands컴퓨터의 구성요소 5가지1. Datapath : 데이터에 대한 연산 수행2. Contr

insoobaik.tistory.com

 

https://insoobaik.tistory.com/718

 

컴퓨터 구조 및 CPU 동작 원리 (2) - CPU 동작 구조 (Pipelining)

9개의 Instruction을 통해 CPU 동작 원리를 설명할 것이다. - Insturction Memory Reference : lw, swArithmetic / Logical : add, sub, and, or, slt(Set on Less Than : 두 레지스터를 비교하여 결과를 설정하는 명령어)Control Tran

insoobaik.tistory.com

위 두 가지 내용을 바탕으로 32비트 RISC CPU의 RTL 설계를 진행할 예정이다.


첫번째 사진을 통해 Pipeline을 구성하기 위해 4단계 위치 각각에 FF이 필요하다.

두번째 사진을 통해 (1)Instruction Memory, (2)Control, (3)Registers, (4)ALU, (5)ALU Control, (6)Data Memory 총 6개의 Moudle을 구성할 것이다.

 

Control의 경우 RegDst, Branch, MemRead, MemToReg, ALUOp, MemWrite, ALUSrc, RegWrite 7개의 Flag와 ALUOp 1개의 Opcode의 값을 결정하게 된다.


Instruction

32bit RISC CPU의 32bit Instruction의 각 Bit는 위와 같이 구분할 것이다.

 

Cotrol을 통해 전달되는 Opcode에 따라 Output Flag를 위와 같이 설정할 것이다.

 

- R-Format : 6'h00

add $t0, $t1, $t2

(funct에 의해 add, sub, and가 정해진다.) $t1과 $t2의 값을 더하여 결과를 레지스터 $t0에 저장한다.

 

- LW : 6'h24

lw $t0, 4($t1)

$t1 + 4의 메모리 주소에서 데이터를 읽어 레지스터 $t0에 저장한다.

 

- SW : 6'h2B

sw $t0, 8($t1)

레지스터 $t0의 데이터를 메모리 주소 $t1 + 8에 저장한다.

 

- BEQ : 6'h04

beq $t0, $t1, target

$t0와 $t1의 값이 같으면, PC를 target 주소로 분기한다.

 

- addi : 6'h08

addi $t0, $t1, 10

$t1의 값에 즉시 값 10을 더하여 결과를 레지스터 $t0에 저장한다.

 

- andi : 6'h0C

andi $t0, $t1, 15

$t1의 값과 즉시 값 15를 AND 연산하여 결과를 레지스터 $t0에 저장한다.


각 Flag별 의미 

 

- RegDst : R, I-Type 결정 R-Type의 1일 경우 rd 레지스터에, I-Type의 0일 경우 rt에 레지스터에 결과값이 저장된다.

- ALUSrc : ALU에서 계산될 src2 값의 출처를 정하기 위해 사용된다. (1일 경우 Sign-extend 이후 32bit OR 2일 경우Registers의 Read Data 2 중 하나)

- MemToReg : Registers의 Write data 값의 출처를 정하기 위해 사용된다. (0일 경우 ALU result OR 1일 경우 Write Back)

- RegWrite : 1일 경우 Registers의 내부 메모리에 Data 저장, 0일 경우 저장 x

- MemRead : Opcode가 lw일 때 1로 사용되며, Data memory에서 데이터를 읽어온다.

- MemWrite : Opcode가 sw일 때 1로 사용되며, Data memory에 값을 입력한다.

- Branch : ALU에서 Branch를 위해 사용되는 신호이며, ALU의 Zero output과 함께 & 연산을 통해 Branch 수행을 결정한다. (ALU 연산 결과가 0인 경우 zero output이 1로 나오고,  Branch 신호도 1일 경우 Branch를 수행하게 된다.)

- ALUOp [1:0] : Rtype, lw, sw, beq, addi, andi를 구분하기 위한 2bit register

 

위와 같이 6개의 Opcode를 설정할 것이다.


Control Module 설계

Instruction으로 들어온 32bit 중 상위 6bit는 위와 같이 타입에 따라 구분하고 있다.

 

R-Format : 6'h00

LW : 6'h23

SW : 6'h2B

BEQ : 6'h04

+

addi : 6'h08

andi : 6'h0C

 

* R-Type의 경우 위에서 반복적으로 설명하였지만 rs, rt, rd 각각의 레지스터가 funct 값에 따라 연산하게 된다.

I-Type의 경우 하위 16bit가 직접적으로 연산을 수행하기 위한 값에 해당하면 최상위 1비트가 부호 비트이며, 이후 Sign-Extend에 의해 32bit로 확장된다.

위 표와 위에서 제시한 Flag를 조합하여 case문을 작성

 

핵심 Code

더보기

...

case(opcode)
                R_Type:begin
                    ALUOp = 2'b10;
                    RegDst = 1'b1;
                    RegWrite = 1'b1;
                end
                lw:begin
                    ALUOp = 2'b00;
                    RegWrite = 1'b1;
                    // ALUSrc는 I-Type에서 주로 사용된다. 
                    ALUSrc = 1'b1;
                    MemRead = 1'b1;
                    MemToReg = 1'b1;
                end
                sw:begin
                    ALUOp = 2'b00;
                    ALUSrc = 1'b1;
                    MemWrite = 1'b1;
                end
                beq:begin
                    ALUOp = 2'b01;
                    Branch = 1'b1;
                end
                addi, andi:begin
                    ALUOp = 2'b11;
                    RegWrite = 1'b1;
                    ALUSrc = 1'b1;
                end
            endcase

...


ALUContorl Module 설계

ALU Module을 통한 연산을 위해 ALUControl Module에서 Control Module로부터 전달받은 ALUOp 값과 Instruction 32bit 중 opcode와 funct 값을 통해 ALUCtrl 값을 ALU Module에 전달하여 특정 연산을 진행할 수 있도록 한다.

 

Control Module은 아래 ALUOp를 Output으로 전달한다.

 

ALUOp

10 R_Type
00 lw, sw
01 beq
11 addi, andi

위와 같이 값을 Output로 전달하기로 정의하였다.

 

ALUControl Module은 아래 ALUCtrl을 Output으로 전달한다.

 

ALUCtrl

00 add
01 sub
10 and

ALUCtrl의 경우 위와 같이 연산을 하도록 구현할 것이다.

 

* lw, sw는 Load, Store을 하기 위해서는 레지스터에 대한 add가 필요하고, Branch의 경우 레지스터의 값이 일치하는지 판별하기 위해 sub를 사용한다. 

 

핵심 Code

더보기

always @ * begin
        ALUCtrl = 0;
        case(ALUOp)
            2'b10:case(funct)
                add_r : ALUCtrl = 4'b00; //add
                sub_r : ALUCtrl = 4'b01; //sub
                and_r : ALUCtrl = 4'b10; //and
            endcase
            2'b11:case(opcode)
                add_i : ALUCtrl = 4'b00; //add
                and_i : ALUCtrl = 4'b10; //and
            endcase
            2'b00 : ALUCtrl = 4'b00; //lw, sw는 Add Operation이 필요
            2'b01 : ALUCtrl = 4'b01; //Branch는 Sub Operation이 필요
        endcase
    end


ALU Module 설계

ALU Module은 연산을 수행하기 위한 Module이다. Control, Registers, ALUControl로 부터 전달받은 레지스터 주소 값, Operation 등을 조합하여 연산을 수행한다.

 

zero Pin의 경우 Branch 명령을 수행하기 위해 두개의 레지스터 주소 값의 차이를 확인하여 Branch를 수행할지에 대한 Flag 신호에 해당한다.

 

ALUCtrl

00 add
01 sub
10 and

ALUControl Module에서 전달한 위 값을 그대로 실행한 뒤 result Pin을 통해 결과를 Data Memory에 전달하거나 Registers Module의 Write Data로 전달하게 된다.

 

핵심 Code

assign zero = result == 0;

마지막에 위와 같이 연산 결과 result가 0일 경우 sub 연산에 의해 두 레지스터의 주소가 동일한 경우에 해당하기 때문에 (물론 아예 동작하기 않은 상태에서도 result가 0일 수 있다.) zero Flag를 1로 전달한다.


DataMemory Module 설계

DataMemory의 경우 실제 Data를 포함하고 있는 Moduled에 해당한다. 전달 받은 레지스터의 주소값을 받아 해당 주소에 lw Load 값을 불러오거나, sw Store 값을 저장하기 위한 공간이다.

 

DataMemory Module의 경우 Data Memory를 가지고 있고 이는 순차 논리 회로로 이루어져 있기 때문에 Clock에 따라 동작한다.

clk, rstn 두개의 Port는 Clock에 필요하며, MemRead, MemWrite는 lw, sw 선택에 따라 결정된다.

그 외 Address, WriteData, ReadData 또한 Read, Write에 따라 해당 레지스터 주고에 접근하여 Data를 Read하거나 Write하게 된다.

WriteData의 경우 sw에 의해 레지스터 주소에 전달되 Data를 내부 Memory에 저장한다.

ReadData의 경우 lw에 의해 레지스터 주소에서 값을 읽을 때 Data가 입력되며, 그 외에 경우에는 x(unknown)을 전달한다.

 

핵심 Code

더보기

always @(posedge clk, negedge rstn)
if (!rstn) for (int i=0;i<64;i++) mem[i] <= 0;
else if (MemWrite) mem[Address[5:0]] <= WriteData;

assign ReadData = MemRead? mem[Address[5:0]]: 'bX;


Registers Module 설계


InstMem Module 설계


cpu(top) Module 설계

728x90