이어서 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
답글 남기기