프로젝트 & 경진대회

RISC-V Single-Cycle Processor Design

htaekjung 2024. 10. 12. 19:50

ISC-V Single cycle processor 회로를 verilog로 설계하는 과정에 대한 포스트이며 다음 강의를 참고하였습니다.

다음 강의에서 제공하는 회로는 그대로 사용하였지만, 코드는 생각없이 베끼지 않고 다 이해를 하며 수정하며 작성했음을 알려드립니다. 

Github는 맨 아래에 첨부하였습니다.

RISC-V Single Cycle Core in Verilog - YouTube

 

RISC-V Single Cycle Core in Verilog

In this playlist, we explore the design and implementation of a RISC-V single-cycle processor core using Verilog. Designed for both beginners and experienced...

www.youtube.com

 

RISC-V 설명

RISC(Reduced instruction Set Computer)은 CISC(Complex Instruction Set Computer)에 비해 가지고 있는 장점을 설명하겠습니다.  

  • Instruction length 고정됨 : 32비트(4바이트)를 사용
    • 따라서 명령어 주소의 하위 2비트는 항상 00이므로 상위 30비트만으로 비교 가능
  • 명령어 처리 속도 빠름 : 한 클록 사이클 내에서 완료
  • 파이프라이닝 : 병렬 처리 가능 -> 처리 속도 빠름
  • 복잡성 : 비교적 단순한 명령어 구조(이름에서 알 수 있듯이 Reduced instruction 이기 때문)

Instruction format

Instruction format은 R,I,S,B,U,J type이 있으며 각각의 특성은 다음과 같습니다.

R - type(Register type) - 레지스터 간 연산 수행하는 명령어

R - type

  • 위 사진에서 rs2, rs1,rd는 operand를 위해 필요한 레지스터입니다
  • op(op code), funct7, funct3은 해당 R-type instruction format이 무슨 연산을 하는지에 따라 값들이 정해져 있습니다.

I - type (Immediate type) - 레지스터와 immediate을 사용한 연산을 수행하는 명령어

I-type

  • op, rs1, rd는 R - type과 동일
  • imm [11:0] = immediate operand
  • funct3은 명령어를 구분하고 구체적인 연산을 정의하는 역할을 합니다.
    I - type funct3 역할

S - type ( Store type) - 메모리 주소에 레지스터 값을 저장하는 명령어

S- type

  • op, rs1, rs2, rd는 R - type과 동일
  • imm [11:5], imm[4:0] = immediate operand
  • funct3은 I - type과 동일

B-type(Branch type) - 조건을 기반으로 프로그램 흐름을 제어하는 분기 명령어

B - type

  • op, rs1, rs2, rd는 R - type과 동일
  • imm[12:0] = immediate operand
  • funct3은 I - type과 동일

U type(Upper Immediate Type) Instruction - 상위 20비트의 immediate 값을 레지스터에 로드하거나 PC에 더하는 명령어

J type(Jump type) Instuction - 점프 명령어 수행하는 명령어

Top Architecture

Top Architecture


RISC-V의 동작 과정

1. PC

먼저 Clock이 posedge가 되면 PC(Program Counter)가 instruction memory에 전달되며, 해당 PC 값에 위치한 명령어가 읽히게 됩니다. 

또한 입력으로 PCNext 신호를 받기 때문에 posedge clk일 때마다 PC 값이 갱신됩니다.

PC,PC_NEXT changes

2. Instruction Memory

PC의 주소값이 Instruction Memory에 들어오게 된다면 Instruction Memory내에서 PC 주소값에 있는 명령어를 output으로 출력합니다. 

 

2. Control Unit

Instruction Memory의 output인 Instr 신호 중 일부가 각각 Control unit, Register File, Extend(bit extension)로 들어가게 되며 Control Unit에서는 PCSrc, ResultSrc, MemWrite, ALUControl, ALUSrc, ImmSrc, RegWrite 신호를 출력하게 됩니다. 

이 각각의 신호들은 Register file, mux, ALU, Data Memory 등등 여러 유닛들을 제어하는 역할을 합니다.

 

3. Register File

Instr 신호를 받아 output RD1, RD2는 각각 A1, A2의 값을 읽어 ALU로 보내는 역할을 합니다.

Instruction format에 나눠 설명하겠습니다.

  • R type인 경우에는 A1에는 rs1, A2에는 rs2, A3에는 rd가 입력됩니다.
  • I type인 경우에는 A1에는 rs1, A2는 immediate 값이므로 보통 사용 안함, A3에는 rd가 입력됩니다.
  • S type인 경우에는 A1에는 rs1, A2에는 rs2가 입력되며, A3에는 immediate 값이므로 보통 사용 안합니다. 

WE3(Write Enable)신호가 있는 경우에는 A3의 주소에 WD3의 데이터 값이 쓰기 동작을 통해 입력됩니다.

 

4. ALU

ALU에서는 Register file에서 받은 SrcA 신호와 SrcB 신호가 들어와 두 신호 간 sum, substract, AND, OR 등 연산을 수행합니다.

Overflow, Carry, 부호 판별, Zero 등 flag 판별하는 기능도 추가하였다.

또한 ALU의 연산 결과가 음수인 경우에는 1을 출력하고 양수인 경우에는 0을 출력하는 기능도 추가하였습니다. 

5. Data Memory

ALU에서 연산된 값들을 읽거나 쓰기 동작을 수행합니다. 

 

6. Data Store

연산 결과는 레지스터 파일이나 데이터 메모리로 저장되며 PCNext 명령어가 다시 수행되며 1~6이 반복됩니다.

 

 

Digital design

1. ALU

2. Control unit

3.Microarchitecture Design ( Program Counter & Register File & Instruction Memory & Data Memory)

4. Testbench


1. ALU

ALU simplified figure
ALU figure

설계해야 할 ALU는 2개의 input(A와 B)이 3비트 ALUControl 신호를 통해 AND gate, OR gate, sum, subtract, zero extension 동작을 수행하도록 합니다.

ALUControl이 3'b000일 때는 A+B (sum), 3'b001일 때는 A-B(subtract with using 2's complement), 3'b010일 때는 A & B, 3'b011일 때는 A | B 연산이 진행됩니다.

또한 3'b101의 경우 zero extension 동작을 진행하는데 이 동작을 하는 이유는 unsigned 값을 더 큰 비트로 확장할 때 값이 바뀌지 않도록 상위 비트를 0으로 채워야 하기 때문입니다.

Result 뿐 아니라 overflow, carry, negative, zero signal도 output으로 두었습니다.


2. Control Unit

Control Unit Figure
RISC-V Main Decoder & ALU Decoder truth table

 

Top architecture의 Control Unit 부분을 확대하면 위의 왼쪽 사진과 같습니다. 위 R - type instruction format에 있는 사진에서 알 수 있듯이 op에서는 Instr[6:0], funct3에는 Instr[14:12], funct7에는 Instr[31:25]가 들어가야 합니다. 이러한 input 신호들을 통해 다음과 같은 신호들이 출력됩니다. 

  • PCSrc (Program Counter Source) - 다음 명령어 주소 결정하는 신호
  • ResultSrc (Result Source)             - Register File에 쓸 데이터 선택하는 신호
  • MemWrite (Memory Write)            - Data Memory의 쓰기 동작을 제어하는 신호
  • ALUControl                                   - ALU에서 어떠한 연산을 할 지 결정하게 하는 신호
  • ALUSrc (ALU Source)                   - ALU에 입력되는 두 번째 피연산자를 결정하는 신호
  • ImmSrc (Immediate Source)        - Immediate을 확장할 때 어떤 형식으로 확장할지 결정하는 신호 - 
  • RegWrite (Register Write)            -  Register File에서 데이터를 write 동작 여부를 결정하는 신호

 

또한 Control unit을 ALU Decoder과 Main Decoder로 나누어 쉽게 설계할 수 있도록 했습니다.


3. Microarchitecture Design

Program Counter & Instruction Memory & Register File & Data Memory

다음으로는 Program Counter, Instruction Memory, Register File, Data Memory에 대해 설명하겠습니다.

Program Counter

input으로는 PCNext 신호를 통해 4바이트씩 주소값이 증가하며 PC신호가 출력되는 것을 알 수 있습니다.

Instruction Memory

입력신호 A를 통해 PC값이 들어오면 

Instruction Memory - Program Counter에서 명령어의 주소를 input으로 받으면 initial begin ~ end 로 구성된 명령어가 RD로 출력됩니다.

Mem[0] = 32'hFFC4A303; // lw x6, -4(x9)  (I-type) PC=0일 때
Mem[1] = 32'h00832383; // lw x7, 8(x6)   (I-type) PC=4일 때

로 설정했습니다. 

Register File

    initial begin
        Registers[9] = 32'h00000020;
    end

위 코드를 통해 9번 레지스터에 32라는 값을 저장하였습니다.

 

PC = 0일 때, A1 = 5'b01001, A2 =  5'b11100, A3 = 5'b00110이며 RD1 레지스터에 A1주소에 저장된 값을 내보내고, RD2에는 A2가 immediate value이기 때문에 안쓰이기 때문에 필요 없습니다. ALU에 들어갈 SrcB 값은 Extend된 값인 fffffffc가 입력될 것입니다.

ALU를 통해 32-4=28이 출력될 것이며 data memory에서 28번지 주소 값을 32로 설정하였기 때문에 register file에 32가 입력될 것이며 따라서 x6에 32가 입력될 것입니다. 

 

 

PC = 4인 경우에는 A1 = 5'b00110, A2 = 5'b01000, A3 = 5'b00111입니다. RD1 레지스터에 A1주소에 저장된 값을 내보내고, RD2에는 A2가 immediate value이기 때문에 안쓰이기 때문에 필요 없습니다. ALU에 들어갈 SrcB 값은 Extend된 값인 00000008가 입력될 것입니다.

ALU를 통해 32+8 = 40이 출력될 것이며 data memory에서 40번지 주소 값을 2로 설정하였기 때문에 register file에 2가 입력될 것이며 따라서 x6에 2가 입력될 것입니다. 

 

아래 그림에서 볼 수 있듯이 WD3 값이 각각 32, 2가 나온 것을 알 수 있습니다.  

 

 

Data memory

     initial begin
        Data_MEM[28] = 32'h00000020;
        Data_MEM[40] = 32'h00000002;
    end


Register File 부분에서 말했다시피 28번지 값을 32, 40번지 값을 2로 설정하였습니다. 

 

위 과정을 Questa에서 시뮬레이션을 한 결과는 다음과 같습니다. 

Questa simulation figure 1
Questa simulation figure 2

위 사진에서 모든 signal들이 첨부된 것은 아니지만 중요한 것들은 다 첨부했습니다. 


Github : Htaekjung/RISC-V-Single-Cycle-Processor-Design (github.com)

 

GitHub - Htaekjung/RISC-V-Single-Cycle-Processor-Design

Contribute to Htaekjung/RISC-V-Single-Cycle-Processor-Design development by creating an account on GitHub.

github.com

 

 

총평

직접 이 정도 회로를 verilog로 설계하는 것은 처음인 것 같은데 전에 들었던 컴퓨터 구조 과목과 마이크로 프로세서 응용 과목에서 배운 RISC와 지금 배우고 있는 디지털 시스템 설계 과목을 접목하여 이런 설계를 한 것은 매우 뜻 깊다고 생각하고 뿌듯하다.

RISC-V single cycle processor을 설계하며 컴퓨터 구조와 verilog, Questa에 대해 더 자세히 이해할 수 있었던 것 같고 이 분야로 내 진로를 정해도 재밌게 할 수 있겠다는 확신이 어느정도 들었던 것 같다. 


이 블로그의 내용 중 일부는 MERL_DSU님의 YouTube와 GitHub 자료를 참고한 것이며, 해당 자료에 대한 저작권은 MERL_DSU에게 있습니다.