SystemVerilog 기본 문법 가이드 (2부)

이어서 SystemVerilog의 기본 문법을 살펴보겠습니다.

7. 열거형 (Enumeration)

열거형을 사용하면 상태 기계(state machine)와 같은 용도에 읽기 쉬운 이름을 부여할 수 있습니다.

// 기본 열거형 정의
typedef enum logic [1:0] {
    IDLE  = 2'b00,
    START = 2'b01,
    BUSY  = 2'b10,
    DONE  = 2'b11
} state_t;

// 열거형 사용
state_t current_state, next_state;

always_ff @(posedge clk or posedge reset) begin
    if (reset)
        current_state <= IDLE;
    else
        current_state <= next_state;
end

always_comb begin
    case (current_state)
        IDLE:  next_state = start_signal ? START : IDLE;
        START: next_state = BUSY;
        BUSY:  next_state = process_done ? DONE : BUSY;
        DONE:  next_state = IDLE;
        default: next_state = IDLE;
    endcase
end

8. 구조체 (Structures)

구조체는 관련 데이터를 그룹화하는 데 사용됩니다.

// 패킷 구조체 정의
typedef struct packed {
    logic [7:0]  addr;      // 주소 필드
    logic [31:0] data;      // 데이터 필드
    logic [2:0]  cmd;       // 명령 필드
    logic        parity;    // 패리티 비트
} packet_t;

// 구조체 사용
packet_t tx_packet, rx_packet;

// 구조체 초기화
initial begin
    tx_packet.addr   = 8'h42;
    tx_packet.data   = 32'hA5A5_5A5A;
    tx_packet.cmd    = 3'b010;
    tx_packet.parity = 1'b0;
    
    // 또는 한 번에 초기화
    tx_packet = '{addr: 8'h42, data: 32'hA5A5_5A5A, cmd: 3'b010, parity: 1'b0};
end

// 구조체 필드 접근
always_comb begin
    if (tx_packet.cmd == 3'b010)
        // 명령에 따른 처리...
end

9. 배열 (Arrays)

SystemVerilog는 다양한 유형의 배열을 지원합니다.

// 1차원 배열
logic [7:0] mem [0:255];    // 256개의 8비트 메모리 배열

// 다차원 배열
logic [7:0] matrix [0:3][0:3];  // 4x4 매트릭스

// 배열 초기화
initial begin
    for (int i = 0; i < 256; i++)
        mem[i] = 8'h00;
        
    // 또는 한 번에 초기화
    mem = '{default: 8'h00};
end

// 동적 배열
int dyn_array[];  // 크기가 정해지지 않은 동적 배열

initial begin
    // 동적 배열 크기 할당
    dyn_array = new[100];
    
    // 배열 크기 변경
    dyn_array = new[200](dyn_array);  // 기존 값 유지
end

// 연관 배열(해시 맵)
int addr_map[string];  // 문자열 키를 가진 연관 배열

initial begin
    addr_map["PC"] = 32'h0000_1000;
    addr_map["SP"] = 32'h0000_2000;
    
    // 연관 배열 접근
    if (addr_map.exists("PC"))
        $display("PC address: %h", addr_map["PC"]);
end

// 큐(Queue)
int fifo[$];  // 첫 번째 입력, 첫 번째 출력 큐

initial begin
    fifo.push_back(10);  // 큐 뒤에 추가
    fifo.push_front(5);  // 큐 앞에 추가
    
    int val = fifo.pop_front();  // 큐에서 값 꺼내기
end

10. 패키지 (Packages)

패키지는 재사용 가능한 코드를 그룹화하는 데 사용됩니다.

// 패키지 정의
package my_pkg;
    // 타입 정의
    typedef enum {RED, GREEN, BLUE} color_t;
    typedef struct {
        int x, y;
    } point_t;
    
    // 상수 정의
    localparam int MAX_COUNT = 100;
    
    // 함수 정의
    function automatic int max(int a, int b);
        return (a > b) ? a : b;
    endfunction
endpackage

// 패키지 사용
module top_module;
    // 패키지 가져오기
    import my_pkg::*;  // 모든 심볼 가져오기
    // 또는
    import my_pkg::color_t;  // 특정 심볼만 가져오기
    
    color_t my_color;
    point_t my_point;
    
    initial begin
        my_color = GREEN;
        my_point.x = 10;
        my_point.y = 20;
        
        $display("Max: %d", max(my_point.x, my_point.y));
    end
endmodule

11. 클래스 (Classes)

SystemVerilog는 객체지향 프로그래밍을 지원합니다.

// 클래스 정의
class Packet;
    // 속성(멤버 변수)
    logic [7:0] addr;
    logic [31:0] data;
    static int packet_count = 0;
    
    // 생성자
    function new(logic [7:0] a = 0, logic [31:0] d = 0);
        addr = a;
        data = d;
        packet_count++;
    endfunction
    
    // 메소드
    function void display();
        $display("Packet: addr=0x%h, data=0x%h", addr, data);
    endfunction
    
    // 정적 메소드
    static function int get_count();
        return packet_count;
    endfunction
endclass

// 클래스 사용
module test;
    Packet p1, p2;
    
    initial begin
        p1 = new(8'h42, 32'h1234_5678);
        p2 = new();
        p2.addr = 8'h55;
        p2.data = 32'h9ABC_DEF0;
        
        p1.display();
        p2.display();
        
        $display("Total packets: %d", Packet::get_count());
    end
endmodule

12. 인터페이스 클래스 (Interface Classes)

인터페이스 클래스는 추상화 레벨을 높여 코드 재사용성을 향상시킵니다.

// 인터페이스 클래스 정의
interface class IDisplay;
    // 가상 메소드 선언
    pure virtual function void display();
endclass

// 구현 클래스
class Packet implements IDisplay;
    logic [7:0] addr;
    logic [31:0] data;
    
    // 인터페이스 메소드 구현
    virtual function void display();
        $display("Packet: addr=0x%h, data=0x%h", addr, data);
    endfunction
endclass

class Status implements IDisplay;
    bit [3:0] status_code;
    
    // 인터페이스 메소드 다른 방식으로 구현
    virtual function void display();
        $display("Status: code=0x%h", status_code);
    endfunction
endclass

// 다형성 활용
module test;
    IDisplay disp_arr[2];
    Packet p;
    Status s;
    
    initial begin
        p = new();
        p.addr = 8'h42;
        p.data = 32'h1234_5678;
        
        s = new();
        s.status_code = 4'h7;
        
        disp_arr[0] = p;
        disp_arr[1] = s;
        
        // 인터페이스를 통한 다형성 호출
        foreach (disp_arr[i])
            disp_arr[i].display();
    end
endmodule

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다