Project/RISC-V CPU Architecture Design

[10] Single Cycle Processor Datapath 분석

by 한PU 2026. 1. 6.
반응형

Processor Datapath

gemini가 그린 블록 다이어그램입니다.

Single Cycle

single cycle processor stage

아시다시피 single cycle은 위 5단계의 명령어 처리 구조를 한 clock cycle에 완료한다는 의미입니다.

 

각 Stage 별 내용을 한번 봅시다.

Datapath 분석

IF Stage

목표: "다음에 실행할 명령어를 메모리에서 가져오자."

  • pc_reg에서 현재 실행할 명령어의 주소(pc_o)를 출력합니다.
  • instr_mem에서는 pc_o를 받아, 그곳에 저장된 32bit instruction(instr_o)를 출력합니다.
  • 이와 동시에 PC + 4를 pc_plus4에서 진행합니다. 이는 다음 명령어를 의미합니다. 메모리 주소는 4byte씩 이동합니다.
  • PCSrc Mux는 다음 cycle의 PC 값을 결정합니다. 기본적으로는 pc+4이지만, Branch, Jump 발생 시 EX Stage에서 계산된 타깃 주소를 선택합니다.

ID Stage

목표: "가져온 명령어를 해석하고 필요한 Data를 준비하자."

  • instr_o를 여러 조각으로 나눕니다.
    • 소스 레지스터 주소 (rs1, rs2): reg_file로 들어가 읽을 data의 위치를 알려줍니다.
    • 목적지 레지스터 주소 (rd): 결과를 저장할 위치를 지정합니다.
    • Imm: 상수입니다. 짧은 상수값을 imm_gen을 통해 32bit 크기로 확장합니다.
    • Opcode / Funct: controller로 들어가서 명령어에 대한 제어 신호를 출력합니다. 

EX Stage

목표: "실질적인 계산을 수행하자"

  • ALUSrc B MUX: ALU의 두번째 입력으로 무엇을 쓸지 결정합니다.
    • register data (예: ADD 등)
    • imm data (예: ADDI, LW 등)
  • ALU: 실제 연산을 수행합니다. 결과값의 상태를 알려주는 Flag 신호를 출력합니다.
    • 저희는 우선 Z Flag(결과값이 0일 때)만 만들었습니다.
    • 이 외에도 N, C, V가 있습니다. 앞으로 확장하겠습니다.
  • Branch Adder: branch가 발생할때 현재 PC 값에 offset을 더해 점프할 목적지 주소를 계산합니다.
    • 이 값은 IF 영역의 PCSrc Mux로 연결됩니다.

MEM

목표: "필요하다면 data memory에 data를 쓰거나 읽어오자."

  • LW, SW 등의 명령어만 현재 Stage를 사용합니다.

WB

목표: "최종 결과를 register에 저장하여 작업을 마무리하자."

  • ResultSrc Mux: register에 최종적으로 저장할 값을 선택합니다.
    • ALU의 연산 결과
    • memory에서 읽은 값
  • 피드백 루프: 선택된 최종 값은 ID Stage의 wr_data_i 포트로 돌아갑니다.
    • 이 값이 ID Stage에서 지정된 rd에 저장되면서 Instruction 실행이 완료됩니다.

시뮬레이션

TB 코드

`timescale 1ns / 1ps

module tb_single_cycle_processor();

    // ---------------------------------------------------------
    // Signal Declaration
    // ---------------------------------------------------------
    reg         clk_r                  ;
    reg         rst_nr                 ;

    // ---------------------------------------------------------
    // Clock Generation (100MHz)
    // ---------------------------------------------------------
    always #5 clk_r = ~clk_r           ;

    // ---------------------------------------------------------
    // DUT Instantiation
    // ---------------------------------------------------------
    // 사용자가 만든 최상위 모듈 이름에 맞춰 SingleCycle_Top 또는 single_cycle_processor 사용
    SingleCycle_Top u_dut (
        .clk_i  (clk_r                 ),
        .rst_ni (rst_nr                )
    );

    // ---------------------------------------------------------
    // Test Procedure
    // ---------------------------------------------------------
    initial begin
        // Initialize signals
        clk_r  = 0                     ;
        rst_nr = 0                     ; // Assert reset

        // Release reset after 20ns
        #22;
        rst_nr = 1                     ;

        $display("==================================================");
        $display("   Starting Single Cycle Processor Simulation      ");
        $display("==================================================");

        // 시뮬레이션 시간 동안 실행 (예: 200ns)
        #200;

        $display("==================================================");
        $display("   Simulation Finished                            ");
        $display("==================================================");
        $finish;
    end

    // ---------------------------------------------------------
    // Monitor Register values (Debugging)
    // ---------------------------------------------------------
    // 시뮬레이션 중에 특정 레지스터 값이 변할 때마다 출력하여 확인
    initial begin
        $monitor("Time: %0t | PC: %h | Instr: %h | x1: %h | x2: %h | x3: %h | x4: %h",
                 $time, u_dut.pc_w, u_dut.instr_w,
                 u_dut.u_register_file.regs_r[1],
                 u_dut.u_register_file.regs_r[2],
                 u_dut.u_register_file.regs_r[3],
                 u_dut.u_register_file.regs_r[4]);
    end

endmodule

Program.hex

00a00093
01400113
002081b3
00302023
00002203

프로젝트 폴더에 넣도록 하겠습니다.

 

현재 코드의 내용은 아래와 같습니다.

1. addi x1, x0, 10 (x1 = 10)

2. addi x2, x0, 20 (x2 = 20)

3. add x3, x1, x2 (x3 = 10 + 20 = 30)

4. sw x3, 0(x0) (mem[0] = 30)

5. lw x4, 0(x0) (x4 = mem[0] = 30)

 

5번째 cycle이 끝나는 순간 x4의 값이 30이 되겠죠? 확인해보겠습니다.

결과

시뮬레이션 결과

완전 잘됐네용~

 

schematic 올리고 이번 포스팅 끝내겠습니다.

다음에는 자세한 성능분석을 해보겠습니다.

오늘도 읽어주셔서 감사합니다!

 

Schematic

 

반응형