프로그래밍/Verilog

베릴로그 문법 (3) 인스턴스와 계층 구조

베린이 2024. 6. 12. 13:56
반응형

- 인스턴스

인스턴스화는 이미 완성된 모듈을 가져오는 것을 말합니다. 어떤 경우에 인스턴스화를 할까요??

 

1. testbench

이전 글에서 testbench는 시뮬레이션을 하기 위한 환경이라고 말씀을 드렸습니다. 시뮬레이션을 하는 이유는 DUT(Device Under Test)의 기능을 확인하거나 검증하기 위해서 합니다. 그러기 위해서는 testbench에 DUT를 가져와야겠죠?? 이럴 때 모듈을 인스턴스화합니다.

 

2. 구조 설계

아래 그림은 UART라고 하는 통신 IP의 block diagram 예시입니다.

 

 

UART 모듈 내부에 기능별로 여러 component들이 있죠?? 이러한 구조를 계층 구조(hierarchy)라고 합니다. 하나의 모듈의 위의 component를 모두 구현할 수 있지만, 이럴 경우 코드가 너무 길어지고 재사용에도 용이하지 않습니다. 그래서 각 component들 마다 module을 만들어주고 uart_top에서 위의 모듈들을 인스턴스화하여 구조적 설계를 합니다.

그럼 이 글에서는 testbench에서 인스턴스화 예시를 보겠습니다.

 

- 인스턴스화 예시

EDA playground의 왼쪽 testbench.sv에 top module을 작성합니다.

module top ();
  
  //자료형 선언, 초기화
  reg  [3:0] a; initial a = 4'h0;
  reg  [3:0] b; initial b = 4'h0;
  
  wire [7:0] c;
  
  //시뮬레이션 time
  initial begin
    #500
    $display("////////////////");
    $display("///sim_finish///");
    $display("////////////////");
    $finish;
  end
  
  //dump file 만들기
  initial begin
    $dumpfile("dump.vcd");
    $dumpvars;
  end

endmodule

 

여기서 $display는 $finish와 마찬가지로 베릴로그 시스템 task로, log에 괄호 안의 문자를 display 해달라는 의미입니다. 위의 코드를 실행하면 선언된 reg들은 initial 값인 4'h0을, wire는 할당되지 않았기 때문에 z를 나타내고 500ns 뒤에 display 한 뒤 시뮬레이션이 종료됩니다.

 

그리고 오른쪽에 있는 design.sv에 multiplier 모듈을 작성합시다.

module multiplier (x,y,out);
  input  [3:0] x, y;
  output [7:0] out;
  
  assign out = x * y;
  
endmodule

 

단순한 곱셈기로 4비트 x, y를 input으로 받아 둘을 곱한 뒤 8비트 out으로 출력하는 간단한 모듈입니다. input output은 reg로 선언하지 않으면 wire로 선언됩니다.

port 선언을 아래와 같이 해줘도 됩니다, 회사에 있을 때는 항상 아래와 같이 했습니다.

module multiplier (
   input  wire [3:0] x
  ,input  wire [3:0] y
  ,output wire [7:0] out
);
  
  assign out = x * y;
  
endmodule

 

이제 이 모듈을 testbench의 DUT로 인스턴스화해봅시다. 이제 시뮬레이션 time과 dump 파일을 만드는 initial 구문은 생략하겠습니다. 여러분은 써주셔야합니다.

module top ();
  
  //자료형 선언, 초기화
  reg  [3:0] a; initial a = 4'h0;
  reg  [3:0] b; initial b = 4'h0;
  
  wire [7:0] c;
  
  //dut 인스턴스화
  multiplier u_dut (
     .x   (a)
    ,.y   (b)
    ,.out (c)
  );
  
  //reg control
  initial begin
    #100
    a = 4'h3;
    b = 4'h5;
    #100
    a = 4'h7;
    b = 4'h6;
    #100
    a = 4'h0;
    b = 4'hf;
    #100
    a = 4'hd;
    b = 4'hc;
  end
  
endmodule

 

먼저 위 testbench 코드를 diagram으로 표현하고 분석해 보겠습니다.

 

 

Diagram을 보시면 이해가 쉬울 텐데요, testbench인 top 모듈에서 선언된 reg a, b가 u_dut라는 이름으로 인스턴스화된 multipler 모듈의 x, y port에 연결됐습니다. 그리고 wire c가 out port에 연결된 구조입니다.

그러면 시뮬레이션을 돌려서 a, b가 변함에 따라 c의 결과를 확인해 보겠습니다.

 

 

Waveform에서 x, y, out은 지웠습니다. 위의 결과를 검토해 볼까요?? 참고로 아래 수들은 모두 16진법의 수입니다.

#0

4'h0 x 4'h0 = 8'h0

#100

4'h3 x 4'h5 = 8'hf

#200

4'h7 x 4'h6 = 8'h2a

#300

4'h0 x 4'hf = 8'h0

#400

4'hd x 4'hc = 8'h9c