1. CPU의 기본적인 구조
컴퓨터의 연산과 데이터 처리를 담당하는 CPU를 Verilog로 구현하기 전에 기본적인 구조에 대해 알아보자. CPU는 크게 제어유닛(Control Unit), 산술논리장치(ALU, Arithmetic Logic Unit), 레지스터(Registers) 로 나눌 수 있다. 먼저 제어 유닛에서 처리해야할 데이터를 순서를 결정하고, 처리를 위한 신호를 발생시킨다. 그리고 각 값은 레지스터에 저장되어, 주어진 값을 이용하여 산술논리장치가 연산을 처리한다. 오늘은 먼저 사진 왼쪽 상단에 있는 제어 유닛의 핵심인 PC(Program Counter)에 대한 구현을 해볼 예정이다.
2. PC(Program Counter)란?
제어 유닛으로 동작하는 레지스터 중 하나인 프로그램 카운터(Program Counter, PC)는 CPU 내부의 레지스터 중 하나로, 다음 실행할 명령어의 주소를 저장하는 역할을 한다. PC는 일반적으로 1씩 증가하면서 메모리에서 다음 명령어의 주소를 참조하는 방식으로 동작한다. 즉, CPU가 명령어를 실행할 때마다 PC 값이 증가하여 메모리에서 다음 명령어를 읽어온다.
PC는 결국 실행할 명령어의 주소를 저장하는 레지스터이지만, 프로그램이나 어떤 작업을 수행할 때, 분기문이나 반복문이 필요한 경우가 있다. 이를 고려하기 위해 동작을 수행할 다음 주소를 계산해야한다. 따라서 기존의 작업을 덧셈기(Adder)로 처리하다가, 갑작스럽게 처리해야할 데이터의 주소 값을 넣어주기 위한 MUX, 그리고 이를 저장할 몇 개의 레지스터가 필요하다. 아래 회로도를 보자.
위 모듈인 program_addr_counter은 입력으로 clk(클럭 신호), reset_p(비동기 리셋 신호), pc_inc(프로그램 카운터를 증가시킬 신호), load_pc(프로그램 카운터에 새로운 값으로 로드할 신호), pc_o_en(프로그램 카운터 출력을 활성화할 신호), 그리고 pc_in(새로운 프로그램 카운터 값)을 받고, 출력으로는 현재 프로그램 카운터 값을 나타내는 pc_out을 출력한다.
모듈 안에서 8bit adder 모듈이 사용되며, pc_inc와 p_addr_out(이전 주소 값)를 더해 data_out을 출력한다. 이후 p_addr에는 load_pc가 활성화되면 pc_in(새로운 프로그램 카운터 값)을, 그렇지 않으면 data_out을 할당한다.
마지막으로 resister_N_bit_posedge 모듈을 통해 p_addr 값을 p_addr_out에 저장하고, pc_out으로 출력한다. resister_N_bit_posedge 모듈은 양의 에지(posedge)에서 입력 신호를 레지스터에 저장하고, 출력 신호로 p_addr_out을 내보낸다. tri_state_Q는 3상 버퍼를 통해서 O_en값에 따라 출력을 할지 말지 결정하고, 출력이 되면 pc_out을 내보낸다.
전체적인 설명이 끝났으므로 Verilog를 통해 구현해보자.
3. Verilog를 이용한 PC(Program Counter) 구현
`timescale 1ns / 1ps
module program_addr_counter(
input clk,
input reset_p,
input pc_inc,
input load_pc,
input pc_o_en,
input [7:0] pc_in,
output [7:0] pc_out
);
wire [7:0] data_out, p_addr, p_addr_out;
hadder_n_bit #(.N(8)) ha8bit(.A(pc_inc), .data_in(p_addr_out), .data_out(data_out));
//8비트 adder 모듈
assign p_addr = (load_pc) ? pc_in : data_out; //mux를 쓰는 간단한 방법
//MUX를 거쳐 나온 값을 레지스터의 입력중 하나로 넣어줌
resister_N_bit_posedge #(.N(8)) sum_reg(.D(p_addr), .clk(clk), .reset_p(reset_p), .wr_e_p(1'b1), .rd_e_p(pc_o_en), .Q(p_addr_out), .tri_state_Q(pc_out));
//positive edge에서 동작하는 8bit 레지스터
endmodule
위 회로도를 그대로 Verilog에서 구현하였다. 한 가지 특징이 있다면, 2x1 mux의 경우, assign문을 통해서 모듈을 따로 불러오지 않더라도 간단하게 조건 연산자를 사용하여 mux 구현이 가능하다.
4. PC 모듈 테스트 및 동작 확인
PC 모듈은 상승 엣지에서 1씩 카운터 된다. 상위 input값에 따라 output값인 pc_out의 값을 지켜보자. 상승 엣지가 될 때마다 1씩 증가하는 것을 볼 수 있다. adder와 8bit resister 사이의 mux의 신호 선택선을 제어하는 load_pc의 값이 1일 때, 클락이 상승하고 곧바로 pc_out의 값이 mux에 따라서 값이 pc_in값인 19로 출력는 것을 볼 수있다. 또한 3상 버퍼를 제어하는 pc_o_en의 값이 0으로 떨어질 때, pc_out의 값이 임피던스로 출력된다. 그리고 reset값이 상승 엣지가 될 때 pc_out의 값이 0으로 출력되는 것을 알 수 있다.
'Projects' 카테고리의 다른 글
FPGA 프로젝트 : Verilog를 이용한 CPU 제작 / ACC(Accumulator)와 ALU의 연결 (4) (0) | 2023.05.18 |
---|---|
AVR 통신 분석 : ATmega128A에서의 AVR 통신 및 기능 분석(UART, I2C, PWM) (0) | 2023.05.16 |
FPGA 프로젝트 : Basys3에서 Cook Timer와 Stop Watch 구현 PPT(멀티 타이머) (0) | 2023.05.16 |
FPGA 프로젝트 : Verilog를 이용한 CPU 제작 / ACC(Accumulator) (3) (0) | 2023.05.11 |
FPGA 프로젝트 : Verilog를 이용한 CPU 제작 / ALU(Arithmetic Logic Unit) (2) (0) | 2023.05.10 |