모듈의 내부는 외부에서 내부 구현을 신경쓰지 않아도 되도록 숨겨져 있다.(OOP 언어에서의 클래스와 비슷한 느낌이라고 생각하면 될 것 같다.)
따라서 모듈이 외부 환경과 소통하기 위한 통로로서 포트(Ports)가 존재한다.
오직 이 포트를 통해서만 모듈과 외부환경이 상호작용할 수 있다.
만약 모듈이 외부 환경과 상호작용하지 않는다면,(예를 들어 최상위 모듈의 경우) 포트를 가지지 않는다.
module fulladd(sum, c_out, a, b, c_in); //포트 리스트 있음
module Top; //포트 리스트 없음
포트 리스트의 모든 포트들은 모듈 정의부 안에서 선언되어야 한다.
포트를 선언할 때에는 다음의 키워드를 사용할 수 있다.
- input : 입력 포트
- output : 출력 포트
- inout : 양방향 포트
모든 포트 선언은 wire(넷)로 선언된다.
따라서 아웃풋 포트가 값을 유지해야 하는 경우에는 다음과 같이 reg로 선언해야 한다. (단, 인풋과 인아웃 포트는 reg로 선언될 수 없다.)
output q;
reg q;
포트리스트와 포트 선언을 분리해서 작성할 수도 있지만, ANSI C 방식을 사용하면 한번에 선언할 수 있다.
module fulladd(output reg [3:0] sum, output reg c_out,
input [3:0] a, b, input c_in);
모듈의 내부와 외부에서 포트에 연결할 때는 다음과 같은 규칙을 따라야 한다.
inputs | outputs | inouts | |
내부 | net | reg / net | net |
외부 | reg / net | net | net |
또한 포트의 내부와 외부 항목의 크기가 서로 다른 것도 허용하지만, 별로 좋지는 않다.
포트는 꼭 모든 포트가 연결될 필요는 없으며, 사용하지 않는 포트는 비워둘 수 있다.
모듈의 인스턴스에 외부 신호를 연결할 때, 각각의 포트에 연결할 신호의 순서를 작성하는 방법은 두 가지가 있다.
첫번째로는 포트 리스트의 위치에 맞게 신호를 작성하여 연결하는 방법이 있다.
module fulladd(sum, c_out, a, b, c_in); //모듈 선언
//생략
fulladd fa(SUM, C_OUT, A, B, C_IN); //모듈의 인스턴스화
즉, 위 코드와 같이 모듈을 정의할 때 사용한 포트리스트의 순서에 맞게 신호 순서를 작성으로써
sum과 SUM, c_out과 C_OUT ... 을 연결하는 것이다.
그러나 이러한 방식은 포트리스트의 수가 많아지면 실수가 발생할 수 있다.
두번째 방법으로는 포트의 이름을 사용하여 연결하는 방식이 있다.
이 방식과 앞의 방식은 혼용할 수 없다.
module fulladd(sum, c_out, a, b, c_in); //모듈 선언
//생략
fulladd fa(.sum(SUM), .c_out(C_OUT), .a(A), .b(B), .c_in(C_IN)); //모듈의 인스턴스화
어떤 모듈의 정의부 안에서 인스턴스화된 다른 모듈은 해당 모듈의 하위 계층이 된다.
이러한 계층 관계를 보여주는 것을 계층적 이름이라고 한다.
만일 stimulus 모듈 안에서 모듈 m1이 인스턴스화되었고, m1의 구성요소중에 아웃풋 Q가 존재한다고 한다면,
Q는 계층적 이름으로써 다음과 같이 표현할 수 있다.
stimulus.m1.Q
이러한 계층적 이름은 $display 태스크에서 %m을 사용하여 볼 수 있다.
Reference: Samir Palnitkar - Verilog HDL 2판
'EE > Verilog' 카테고리의 다른 글
[Verilog] 게이트 지연 (0) | 2023.01.06 |
---|---|
[Verilog] 게이트 수준 모델링 (0) | 2023.01.06 |
[Verilog] 모듈의 구성 요소 (0) | 2023.01.05 |
[Verilog] 컴파일러 지시어 (0) | 2023.01.03 |
[Verilog] System task (0) | 2023.01.03 |