13. 문자열 처리 (String Processing)
SystemVerilog는 강력한 문자열 처리 기능을 제공합니다.
module string_example;
string str1 = "Hello";
string str2 = "World";
string result;
initial begin
// 문자열 연결
result = {str1, " ", str2};
$display("Combined: %s", result); // "Hello World" 출력
// 문자열 비교
if (str1 == "Hello")
$display("Strings match");
// 문자열 길이
$display("Length: %d", str1.len()); // 5 출력
// 문자열 조작
result = str1.toupper(); // "HELLO"
result = str1.substr(1, 3); // "ell"
result = str1.putc(2, "X"); // "HeXlo"
// 문자열에서 문자 가져오기
byte c = str1.getc(0); // 'H'의 ASCII 코드
// 정수를 문자열로 변환
int value = 12345;
result.itoa(value); // "12345"
// 16진수 문자열로 변환
result = $sformatf("%h", value); // "3039"
end
endmodule
14. 프로그램 블록 (Program Block)
프로그램 블록은 테스트 코드를 설계 코드와 분리하는 데 사용됩니다.
// 프로그램 블록 정의
program automatic test;
// 테스트 변수들
logic [7:0] test_data;
int error_count = 0;
// 테스트 코드는 일반적으로 initial 블록에 작성
initial begin
// 테스트 시퀀스
repeat (10) begin
test_data = $random;
check_data(test_data);
#10;
end
$display("Test completed with %0d errors", error_count);
end
// 테스트 태스크
task check_data(logic [7:0] data);
if (data == 0)
error_count++;
endtask
endprogram
// 모듈과 프로그램 연결
module top;
// 클럭 생성
logic clk = 0;
always #5 clk = ~clk;
// DUT 인스턴스화
counter dut (
.clk(clk),
.reset(1'b0),
.count()
);
// 테스트 프로그램 인스턴스화
test t1();
endmodule
15. 태스크와 함수 (Tasks and Functions)
태스크와 함수는 코드 재사용을 위한 중요한 요소입니다.
module task_function_example;
logic [7:0] data, result;
// 함수 정의 - 즉시 값 반환, 딜레이 불가
function logic [7:0] add_one(input logic [7:0] val);
return val + 1;
endfunction
// 자동 함수 - 함수 호출 간 로컬 변수가 유지되지 않음
function automatic int factorial(input int n);
if (n <= 1)
return 1;
else
return n * factorial(n-1); // 재귀 호출
endfunction
// 태스크 정의 - 시간 지연 가능, 반환값 없음
task automatic process_data(input logic [7:0] in_data, output logic [7:0] out_data);
#10; // 시간 지연 (10 시간 단위)
out_data = in_data * 2;
endtask
// 기본 인수를 가진 태스크
task display_value(input logic [7:0] val = 8'hFF);
$display("Value: %h", val);
endtask
initial begin
data = 8'h10;
// 함수 호출
result = add_one(data);
$display("Result: %h", result); // 0x11 출력
// 재귀 함수 호출
$display("5! = %0d", factorial(5)); // 120 출력
// 태스크 호출
process_data(data, result);
$display("After task: %h", result); // 0x20 출력
// 기본 인수를 사용한 태스크 호출
display_value(); // 기본값 0xFF 사용
display_value(8'h42); // 명시적 값 0x42 사용
end
endmodule
16. 어서션 (Assertions)
어서션은 설계의 동작을 검증하는 강력한 도구입니다.
module assertion_example(
input logic clk,
input logic reset,
input logic req,
input logic ack,
input logic [7:0] data
);
// 즉시 어서션 (Immediate Assertion)
always_comb begin
// 데이터가 특정 범위 내에 있는지 확인
assert(data inside {[0:100]})
else $error("Data out of range: %d", data);
end
// 병행 어서션 (Concurrent Assertion)
// req 신호 후 1~3 클럭 내에 ack 신호가 와야 함
property req_ack_protocol;
@(posedge clk) disable iff (reset)
req |-> ##[1:3] ack;
endproperty
// 어서션 인스턴스화
assert property (req_ack_protocol)
else $error("Protocol violation: ack not received within 3 cycles after req");
// 병행 커버 포인트 (Concurrent Cover)
cover property (@(posedge clk) req ##1 ack)
$info("Req-Ack sequence covered");
// 시퀀스 정의 (Sequence)
sequence data_seq;
data == 8'h55 ##1 data == 8'hAA;
endsequence
// 시퀀스 기반 어서션
assert property (@(posedge clk) data_seq)
else $error("Expected data sequence not detected");
endmodule
17. 랜덤화 (Randomization)
랜덤화는 효과적인 검증을 위한 핵심 기능입니다.
class RandomPacket;
// 랜덤화할 변수
rand bit [7:0] addr;
rand bit [31:0] data;
rand bit [1:0] prio;
// 제약 조건
constraint valid_addr {
addr inside {[10:20], [30:40]}; // 주소는 10-20 또는 30-40 범위 내
}
constraint data_c {
data < 100; // 데이터는 100보다 작음
data % 2 == 0; // 데이터는 짝수
}
// 우선순위에 따른 제약 조건
constraint prio_c {
(prio == 0) -> data < 30; // 우선순위 0이면 데이터 < 30
(prio == 1) -> data < 60; // 우선순위 1이면 데이터 < 60
(prio == 2) -> data < 90; // 우선순위 2이면 데이터 < 90
}
// 배타적 제약 조건(DIST)
rand bit [1:0] mode;
constraint mode_dist {
mode dist {0 := 40, 1 := 40, 2 := 20}; // 0,1은 각각 40%, 2는 20% 확률
}
function void post_randomize();
$display("Randomized: addr=%0d, data=%0d, prio=%0d, mode=%0d",
addr, data, prio, mode);
endfunction
endclass
module rand_example;
initial begin
RandomPacket pkt = new();
// 랜덤화 실행
repeat (5) begin
if (pkt.randomize()) // 랜덤화 성공하면 true 반환
$display("Randomization succeeded");
else
$display("Randomization failed");
end
// 특정 필드를 고정하고 랜덤화
if (pkt.randomize() with {addr == 15; prio == 2;})
$display("Constrained randomization succeeded");
// 인라인 제약 조건
if (pkt.randomize() with {data > 50; data < 80;})
$display("Inline constraint succeeded");
end
endmodule
18. 커버리지 (Coverage)
커버리지는 검증의 완성도를 측정하는 데 사용됩니다.
module coverage_example(
input logic clk,
input logic reset,
input logic [1:0] mode,
input logic [7:0] data
);
// 함수적 커버리지
covergroup cg_modes @(posedge clk);
option.per_instance = 1; // 인스턴스별 통계
// 커버 포인트 - mode 신호 커버
cp_mode: coverpoint mode {
bins mode_0 = {0};
bins mode_1 = {1};
bins mode_2 = {2};
bins mode_3 = {3};
bins mode_trans[] = (0,1,2,3 => 0,1,2,3); // 모든 전환 커버
}
// 데이터 범위 커버
cp_data: coverpoint data {
bins low = {[0:63]};
bins mid = {[64:127]};
bins high = {[128:255]};
}
// 크로스 커버리지 - mode와 data의 조합
cross_mode_data: cross cp_mode, cp_data;
endcovergroup
// 커버그룹 인스턴스화
cg_modes cg = new();
// 명시적 커버 그룹 샘플링도 가능
always @(posedge clk) begin
if (!reset)
cg.sample(); // 명시적 샘플링
end
// 코드 커버리지는 컴파일러 지시문으로 제어됨
// 라인 커버리지, 조건 커버리지, FSM 커버리지, 토글 커버리지 등
endmodule
답글 남기기