산술 논리 장치(ALU) 구현 상세

ALU 입력 피연산자 선택기 설계

중앙 처리 장치(CPU)의 핵심 구성 요소인 산술 논리 장치(ALU)는 산술 및 논리 연산을 담당합니다. 효율적인 ALU를 설계하려면 먼저 연산에 사용될 피연산자(operand)를 적절히 선택하는 메커니즘이 필요하며, 이후 실제 연산을 수행하는 로직이 구현되어야 합니다. 이 글에서는 RISC-V 기반 프로세서의 ALU 유닛 설계에 대해 다루며, 특히 피연산자 선택기와 기본적인 산술 연산(덧셈, 뺄셈)을 수행하는 ALU 모듈의 구현을 살펴봅니다.

ALU는 레지스터, 즉시값(immediate value), 프로그램 카운터(PC) 등 다양한 소스로부터 데이터를 입력받을 수 있습니다. 따라서 ALU의 입력으로 어떤 데이터를 사용할지 결정하는 선택 로직이 필요합니다. 아래 Verilog 코드는 세 가지 주요 시나리오에 따라 ALU의 두 입력 피연산자(alu_operand_a, alu_operand_b)를 선택하는 모듈을 보여줍니다. 현재 프로젝트의 RISC-V 구현은 특정 명령어 세트(예: U-타입 명령어 중 lui만 구현)에 최적화되어 있으므로, PC + 4와 같은 특정 상황을 제외하고는 레지스터 또는 즉시값을 주된 입력으로 사용합니다.

module OperandSelector (
    input  wire [`CONTROL_SIG_WIDTH-1:0] select_control,       // 피연산자 선택 제어 신호
    input  wire [`DATA_PATH_WIDTH-1:0]   reg_data_a,           // 레지스터 A의 값
    input  wire [`DATA_PATH_WIDTH-1:0]   reg_data_b,           // 레지스터 B의 값
    input  wire [`DATA_PATH_WIDTH-1:0]   immediate_val,        // 즉시값
    input  wire [`DATA_PATH_WIDTH-1:0]   current_pc,           // 현재 프로그램 카운터(PC) 값

    output reg  [`DATA_PATH_WIDTH-1:0]   alu_operand_a,        // ALU 입력 1
    output reg  [`DATA_PATH_WIDTH-1:0]   alu_operand_b         // ALU 입력 2
);

    // 데이터 경로의 너비 (예: 32비트)
    localparam DATA_PATH_WIDTH    = 32;
    // 제어 신호의 너비 (예: 2비트)
    localparam CONTROL_SIG_WIDTH  = 2;

    // 피연자 선택 모드 정의
    localparam SRC_SELECT_REG_REG = 2'b00; // ALU 입력: 레지스터 A, 레지스터 B
    localparam SRC_SELECT_REG_IMM = 2'b01; // ALU 입력: 레지스터 A, 즉시값
    localparam SRC_SELECT_PC_ADD4 = 2'b10; // ALU 입력: 4, 현재 PC (PC + 4 계산용)

    always @(*) begin
        // 기본값 설정: 레지스터 A와 B를 사용
        alu_operand_a = reg_data_a;
        alu_operand_b = reg_data_b;

        case (select_control)
            SRC_SELECT_REG_REG: begin
                // 레지스터 A와 B를 그대로 사용 (기본값으로 이미 설정됨)
            end
            SRC_SELECT_REG_IMM: begin
                // 레지스터 A는 유지하고, 레지스터 B 대신 즉시값 사용
                alu_operand_b = immediate_val;
            end
            SRC_SELECT_PC_ADD4: begin
                // PC + 4 계산을 위해 첫 번째 피연산자를 4로, 두 번째 피연산자를 현재 PC로 설정
                alu_operand_a = DATA_PATH_WIDTH'd4;
                alu_operand_b = current_pc;
            end
            default: begin
                // 정의되지 않은 제어 신호의 경우 0으로 초기화
                alu_operand_a = DATA_PATH_WIDTH'b0;
                alu_operand_b = DATA_PATH_WIDTH'b0;
            end
        endcase
    end
endmodule

기본 산술 연산기(ALU) 모듈 구현

피연산자가 선택되면, 다음 단계는 실제 산술 및 논리 연산을 수행하는 ALU 모듈을 구현하는 것입니다. 현재 설계는 간단한 덧셈과 뺄셈 연산만을 지원합니다. 이 모듈은 연산 결과와 함께 결과가 0인지 여부를 나타내는 result_is_zero 플래그를 출력합니다. 오버플로우나 부호 있는/없는 연산에 대한 복잡한 처리는 이 초기 설계 단계에서는 고려하지 않습니다.

module BasicALU (
    input  wire [`OP_CODE_WIDTH-1:0]     operation_code,    // ALU 연산 지정 코드
    input  wire [`DATA_PATH_WIDTH-1:0]   input_val_x,       // 첫 번째 피연산자
    input  wire [`DATA_PATH_WIDTH-1:0]   input_val_y,       // 두 번째 피연산자

    output reg                           result_is_zero,    // 연산 결과가 0이면 1, 아니면 0
    output reg [`DATA_PATH_WIDTH-1:0]    alu_output_result  // ALU 연산 결과
);

    // 데이터 경로의 너비 (예: 32비트)
    localparam DATA_PATH_WIDTH = 32;
    // 연산 코드의 너비 (예: 2비트)
    localparam OP_CODE_WIDTH   = 2;

    // ALU 연산 코드 정의
    localparam ALU_OP_ADD = 2'b00; // 덧셈
    localparam ALU_OP_SUB = 2'b01; // 뺄셈

    always @(*) begin
        // 출력 레지스터 초기화
        alu_output_result = DATA_PATH_WIDTH'b0;
        result_is_zero    = 1'b0;

        case (operation_code)
            ALU_OP_ADD: begin
                alu_output_result = input_val_x + input_val_y;
            end
            ALU_OP_SUB: begin
                alu_output_result = input_val_x - input_val_y;
                // 뺄셈 결과가 0이면 'result_is_zero' 플래그를 설정
                if (alu_output_result == DATA_PATH_WIDTH'b0) begin
                    result_is_zero = 1'b1;
                end
            end
            default: begin
                // 정의되지 않은 연산 코드의 경우 결과 0으로 처리하고 플래그 설정
                alu_output_result = DATA_PATH_WIDTH'b0;
                result_is_zero = 1'b1;
            end
        endcase
    end
endmodule

태그: RISC-V ALU Verilog 디지털_회로_설계 CPU_아키텍처

7월 24일 01:44에 게시됨