Menu

Verilog Module Port: input, output, inout 완전 정리

모듈 포트(input, output, inout)를 선언하는 방법, ANSI 스타일 포트 목록, 그리고 output이 wire여야 하는지 reg여야 하는지의 판단 기준.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

모듈의 인터페이스

모듈의 port list는 그 인터페이스 입니다 - 바깥 세상이 볼 수 있고 만질 수 있는 모든 것. 모듈 내부의 본문은 입력으로부터 출력을 계산합니다. 포트는 그 경계를 넘는 wire입니다.

현대의 ANSI 스타일 선언은 방향, 타입, 너비를 모두 인라인으로 둡니다.

module my_module(
    input  wire        clk,
    input  wire        reset,
    input  wire [7:0]  data_in,
    output reg  [7:0]  data_out,
    output wire        valid
);
    // 본문
endmodule

이게 전체 모양입니다. 각 포트는 다음을 가집니다.

  • 방향: input, output, inout.
  • 타입: wire 또는 reg(SystemVerilog에서는 logic).
  • 너비: [7:0] 같은 범위. 생략하면 단일 비트.
  • 이름: 본문에서 사용할 식별자.

세 가지 방향

input - 바깥에서 구동됨

input은 항상 wire입니다. 구동 측이 모듈 바깥에 있습니다 - 상위 모듈의 신호이거나 testbench의 reg이거나. 이 모듈 안에서는 입력을 식 안에서 읽을 수만 있고 대입할 수는 없습니다.

module reader(input wire [7:0] data);
    initial $display("data = %h", data);
endmodule

모듈 안에서 data = ...라고 쓰면 오류입니다.

output - 안에서 구동됨

output은 이 모듈 안의 무언가가 구동합니다. wire(assign이나 서브모듈 출력으로 구동)일 수도 있고 reg(always/initial로 구동)일 수도 있습니다.

module driver(
    input  wire       a,
    input  wire       b,
    input  wire       clk,
    output wire       y,    // wire - assign으로 구동
    output reg        q     // reg  - always로 구동
);
    assign y = a & b;       // y가 wire이므로 OK

    always @(posedge clk)
        q <= a;             // q가 reg이므로 OK
endmodule

always 안에서 y에 대입하거나, assign으로 q를 구동하려고 하면 컴파일 오류입니다. 키워드 선택이 구동 방식과 일치해야 합니다.

inout - 양방향

inout 포트는 모듈 또는 외부의 무언가가 번갈아 가며 구동할 수 있는 wire입니다. 칩 경계 - I²C SDA 라인, 양방향 GPIO 핀, 공유 데이터 버스 등 - 에서 등장합니다. 모듈 내부에서는 tri-state 패턴으로 방향을 제어합니다.

module bidir_pin(
    input  wire data_out,
    input  wire output_enable,
    output wire data_in,
    inout  wire pin
);
    assign pin     = output_enable ? data_out : 1'bz;
    assign data_in = pin;
endmodule

pin이 공유 wire입니다. output_enable이 high이면 모듈이 pindata_out으로 구동합니다. low이면 핀을 high-impedance(z)로 풀어 줘서 외부 드라이버가 사용할 수 있게 합니다. data_in은 핀 위에 현재 무엇이 있든 그것을 항상 관찰합니다.

순수 내부 로직에서는 inout이 드뭅니다. 메모리 컨트롤러, CPU 코어, 이미지 처리 파이프라인을 만든다면 한 번도 필요하지 않을 수 있습니다. 칩 경계의 I/O ring을 위한 기능입니다.

단일 비트 vs 멀티 비트 포트

너비 범위는 선택입니다 - 단일 비트 포트라면 생략합니다.

input wire valid,         // 1비트
input wire [7:0] data,    // 8비트
input wire [31:0] addr,   // 32비트

parameter를 너비로 사용할 수도 있습니다. 이게 매개변수화 모듈이 동작하는 방식입니다.

module bus #(
    parameter WIDTH = 32
)(
    input  wire [WIDTH-1:0] in,
    output wire [WIDTH-1:0] out
);
    assign out = in;
endmodule

ANSI vs Verilog-1995 스타일

가끔 port list와 선언을 나눠 둔 옛 코드가 보일 수 있습니다.

// 옛 Verilog-1995 스타일 - 새 코드에서는 쓰지 마세요
module foo(clk, data_in, data_out);
    input clk;
    input [7:0] data_in;
    output reg [7:0] data_out;
    // ...
endmodule

port list에는 이름만 있고, 각 포트는 본문 안에서 따로 선언됩니다. 장황하고, "port list에는 있는데 선언되지 않음" 오류가 잘 나며, 타이핑이 두 배입니다. ANSI-2001 스타일(이 문서 전반에 나오는 스타일)이 이를 대체합니다.

module foo(
    input  wire       clk,
    input  wire [7:0] data_in,
    output reg  [7:0] data_out
);
    // ...
endmodule

ANSI 스타일을 사용하세요. 도구들은 2001년부터 이 스타일을 지원해 왔습니다.

완전한 예시

이 한 모듈에는 다음이 있습니다.

  • parameter(WIDTH).
  • clock, reset, load enable, data, shift enable 입력.
  • always 블록 안에서 구동되는 reg 출력(data_out).
  • continuous assignment로 구동되는 wire 출력(msb_out).
  • 각 포트의 방향, 타입, 너비를 인라인으로 적은 완전한 ANSI 스타일 선언.

여러분이 작성할 거의 모든 synthesis 가능 모듈이 이런 형태입니다.

다음에 볼 내용

다음 문서 - Module Instantiation - 은 이 모듈을 가져다가 더 큰 설계 안에서 사용하는 방법을 보여 줍니다. 방금 작성한 shifter는 그 자체로는 쓸모가 없습니다. 무언가가 그것을 인스턴스화해 시스템에 연결할 때 비로소 값어치를 합니다.

자주 묻는 질문

Verilog에는 어떤 포트 방향이 있나요?

input, output, inout 세 가지입니다. input은 모듈 바깥에서 구동됩니다. output은 모듈 내부에서 구동됩니다. inout은 양방향입니다 - 모듈이 같은 핀을 구동하기도 하고 읽기도 하는 tri-state bus에 유용합니다. 내부 포트의 대부분은 input이나 output이고, inout은 칩 핀에서만 등장합니다.

output wire와 output reg의 차이는 무엇인가요?

output wire는 출력이 continuous assignment나 서브모듈 출력 같은 - always 블록 외부의 무언가 - 가 구동한다는 뜻입니다. output reg는 procedural block(initial이나 always)에서 구동한다는 뜻입니다. 키워드는 always 안에서 그 신호를 대상으로 삼을 수 있는지를 결정하는 것이지, synthesize된 하드웨어에 플립플롭이 들어가는지를 결정하는 게 아닙니다.

Verilog 포트의 ANSI 스타일이란 무엇인가요?

ANSI 스타일은 각 포트의 방향과 타입을 port list 안에서 인라인으로 선언합니다: module foo(input wire [7:0] data, output reg [7:0] result);. 이전의 Verilog-1995 스타일은 port list에 이름만 적고 모듈 안에서 다시 선언했습니다. 새 코드에서는 항상 ANSI 스타일을 사용하세요 - 짧고, 오류가 적고, 현대적인 환경에서는 어디서나 표준입니다.

Verilog 모듈에 input과 output을 여러 개 둘 수 있나요?

네 - 모듈은 필요한 만큼의 포트를, 어떤 방향 조합으로든 가질 수 있습니다. port list에서 쉼표로 구분합니다. port list의 순서는 인스턴스화 시 positional connection 순서를 결정하지만, 순서에 의존하지 않기 위해 거의 항상 named connection(.port(signal))을 사용합니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기