[Verilog 문법] 5.1 Testbench

YUN·2026년 1월 23일

디지털 회로 설계

목록 보기
17/20

테스트벤치(Testbench)

설계한 모듈을 검증하기 위한 시뮬레이션 환경

(1) 구성 요소

  • DUT(Design Under Test) : 검증 대상 모듈
  • 입력, 출력
    • 입력 : Procedural block에서 값 바꿔야하니 reg 로 선언
    • 출력 : 내가 주는 입력에 의해서 그냥 continuous하게 값이 바뀌면되니 wire로 선언
  • 클럭 생성기 : 주기적인 클럭 신호
  • 리셋 생성기 : 초기화 신호
  • 자극 생성기 : 입력 패턴
  • 모니터/체커 : 출력 검증

(2) 기본 구조

`timescale 1ns / 1ps

module tb_my_module;    // 포트 없음

    // 1. 신호 선언
    reg        clk;
    reg        rst;
    reg  [7:0] data_in;
    wire [7:0] data_out;

    // 2. DUT 인스턴스
    my_module u_dut (
        .clk      (clk),
        .rst      (rst),
        .data_in  (data_in),
        .data_out (data_out)
    );

    // 3. 클럭 생성
    always #5 clk = ~clk;

    // 4. 테스트 시퀀스
    initial begin
        clk     = 0;
        rst     = 1;
        data_in = 0;

        #20 rst = 0;

        #10 data_in = 8'hAA;
        #10 data_in = 8'h55;
        #10 data_in = 8'hFF;

        #100 $finish;
    end

endmodule

(3) timescale 지시자

형식은 아래와 같다.

`timescale 시간단위/정밀도

(4) 클럭 생성

reg clk; //클럭 변수 선언
initial clk = 0; //클럭을 0으로 설정
always #5 clk = ~clk; //5 시간단위 간격으로 clk을 Toggle

(5) 리셋 생성

동기 리셋

reg rst;

initial begin
    rst = 1;
    @(posedge clk);  // clk의 첫 번째 양의 에지(0->1)가 올 때까지 대기
    @(posedge clk); // clk의 두 번째 양의 에지가 올 때까지 추가로 대기
    rst = 0;
end

비동기 리셋

reg rst;

initial begin
    rst = 1;
    #25 rst = 0;
end

Active Low 리셋

reg rst_n;

initial begin
    rst_n = 0;
    #25 rst_n = 1;
end

(6) DUT 인스턴스 연결

my_module #(
    .WIDTH (16),
    .DEPTH (32)
) u_dut (
    .clk      (clk),
    .rst      (rst),
    .data_in  (data_in),
    .data_out (data_out)
);

기존에 상위 모듈에서 하위 모듈 쓸 때 인스턴스 생성하고 연결하는것과 동일하다.

(7) 테스트 시퀀스 작성

initial begin
    // 초기화
    rst     = 1;
    enable  = 0;
    data_in = 0;

    // 리셋 해제 대기
    #100;
    rst = 0;
    #20;

    // 테스트 실행
    @(posedge clk); //posedge 대기
    enable  = 1; 
    data_in = 8'hAB;

    // 반복 테스트
    repeat (10) begin
        @(posedge clk);
        data_in = data_in + 1;
    end

    #100;
    $finish;
end

(8) 예시 (8비트 카운터)

DUT

module counter (
    input            clk,
    input            rst,
    input            enable,
    output reg [7:0] count
);
    always @(posedge clk or posedge rst) begin
        if (rst)
            count <= 8'd0;
        else if (enable)
            count <= count + 1'b1;
    end
endmodule

Testbench

`timescale 1ns / 1ps

module tb_counter;

    reg        clk;
    reg        rst;
    reg        enable;
    wire [7:0] count;

    counter u_dut (
        .clk    (clk),
        .rst    (rst),
        .enable (enable),
        .count  (count)
    );

    parameter CLK_PERIOD = 10;
    initial clk = 0;
    always #(CLK_PERIOD/2) clk = ~clk;

    initial begin
        $dumpfile("counter.vcd");
        $dumpvars(0, tb_counter);

        rst    = 1;
        enable = 0;

        #25 rst = 0;

        #50;
        if (count !== 8'd0)
            $display("FAIL: Test 1");
        else
            $display("PASS: Test 1");

        @(posedge clk);
        enable = 1;

        repeat (10) @(posedge clk);

        if (count !== 8'd10)
            $display("FAIL: Test 2");
        else
            $display("PASS: Test 2");

        @(posedge clk);
        enable = 0;

        repeat (5) @(posedge clk);

        if (count !== 8'd10)
            $display("FAIL: Test 3");
        else
            $display("PASS: Test 3");

        @(posedge clk);
        rst = 1;
        @(posedge clk);

        if (count !== 8'd0)
            $display("FAIL: Test 4");
        else
            $display("PASS: Test 4");

        #50;
        $display("All tests completed");
        $finish;
    end

endmodule
profile
안녕하세요. 전자공학부 학부생의 공부 기록입니다.

0개의 댓글