Menu

Verilog wire vs reg: 언제 무엇을 쓸까 (예제 포함)

Verilog의 두 핵심 데이터 타입 - 연속 연결을 위한 wire와 procedural 저장을 위한 reg - 그리고 둘 사이에서 항상 선택할 수 있는 규칙.

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

두 이름, 한 가지 일

Verilog의 모든 신호는 타입을 가집니다. 가장 먼저 만나게 되는 두 타입이 wirereg입니다. 둘 다 값을 보존할 수 있고, 단일 비트나 멀티 비트일 수 있습니다. 차이는 신호 자체가 무엇인가 가 아니라 누가 그것을 구동하느냐 입니다.

  • wire 신호는 procedural block 외부 에서 구동됩니다 - assign 문, 서브모듈의 출력, 또는 모듈 input port.
  • reg 신호는 procedural block 내부 에서 구동됩니다 - initial 또는 always.

규칙은 이게 전부입니다. 키워드 이름이 어색한 이유는 현대 Verilog 작성 방식보다 그 이름들이 먼저 생겼기 때문입니다. reg항상 하드웨어에서 register가 되지는 않습니다. 그 이유는 아래에서 다룹니다.

Wire: 연속 연결

wire는 전기적 wire입니다. 드라이버가 만들어 내는 값을 연속적으로 운반합니다. wire가 구동되는 두 가지 방식.

주목할 세 가지.

  • yz는 모듈에서도 wire로, testbench에서도 다시 wire로 선언됩니다.
  • 그것들은 assign으로 구동됩니다 - continuous-assignment 형태입니다. =의 우변은 그 안의 어떤 신호든 변할 때마다 다시 계산됩니다.
  • ywire로 유지하면서 always 블록 안에서 y = a & b라고 쓸 수는 없습니다. 컴파일러가 거부합니다.

wire 키워드를 잊으면 Verilog이 자동으로 단일 비트 wire로 암시적 선언 해 줍니다 - 편리할 때도 있지만 조용한 버그가 될 때도 있습니다. 많은 팀이 implicit wire에 대해 오류를 내는 도구 옵션을 켭니다. 명시적으로 적고 그 함정을 피하세요.

Reg: procedural block 내부의 저장소

reginitial이나 always 안에서 대입하는 신호입니다. 이 이름은 언어 초창기 "reg"가 "register"처럼 들리던 시절의 유물입니다. 현대적 용법에서 regprocedural 코드가 쓰는 모든 신호의 타입 일 뿐입니다.

count는 모듈 안에서 reg(왜냐하면 always 블록이 그것에 쓰니까)이고, testbench에서는 wire(왜냐하면 DUT의 output port가 그것을 구동하니까)입니다. 같은 신호, 다른 역할, 각 스코프에서 다른 타입.

왜 "reg"가 항상 "register"를 의미하지는 않는가

가장 흔한 초보자의 함정. 이 모듈은 yreg로 선언하지만, synthesize된 하드웨어에는 플립플롭이 없습니다.

always @(*) 블록은 어떤 입력 변화에도 sensitive합니다. 그래서 조합 논리입니다. synthesis 도구는 이 패턴을 보고 AND 게이트를 생성합니다 - 플립플롭도 clock도 없이, 그저 로직입니다. reg 키워드는 yalways 안에서 대입되기 때문에 단지 문법적으로 요구된 것입니다.

실제 플립플롭을 얻으려면 always 블록이 clock edge에 sensitive해야 합니다.

always @(posedge clk) begin
    q <= d;
end

이게 "synthesis 도구야, 플립플롭을 만들어 주렴" 패턴입니다: clocked sensitivity list, non-blocking assignment. 같은 reg 키워드, 완전히 다른 하드웨어. 이 구분은 Always BlockBlocking vs Non-blocking에서 다룹니다.

실제로 결정하는 법

신호를 선언할 때마다 물으세요: 이걸 어떻게 구동할 것인가?

  • assign으로 구동? → wire.
  • 서브모듈 output port에 연결? → wire.
  • 모듈 input port? → wire. (입력은 항상 wire.)
  • initial이나 always에서 구동? → reg.
  • procedural 코드로 구동되는 모듈 output port? → output reg.
  • assign으로 구동되는 모듈 output port? → output wire. (또는 그냥 output - 방향만 적으면 기본이 wire.)

이 결정 트리가 일반 Verilog에서 만날 모든 상황을 다룹니다.

드라이버 충돌

wire 신호는 이론상 여러 드라이버를 가질 수 있습니다 - tri-state bus가 그렇게 동작합니다. 여러 모듈이 같은 wire를 구동할 수 있고 비활성인 모듈은 high-impedance(z)로 갑니다. 일반 로직에서는 같은 wire에 두 assign 문이 쓰면 정의되지 않은 동작이 됩니다.

assign y = a;
assign y = b;   // BAD - y에 드라이버 둘

시뮬레이터가 하나를 고를 수도, 신호를 X로 만들 수도 있습니다 - 도구에 따라 다릅니다. 어쨌든 버그입니다. 명시적으로 버스를 만드는 게 아니라면 wire 하나당 드라이버 하나.

reg 신호는 단 하나의 procedural block에서만 구동될 수 있습니다. 두 always 블록이 같은 reg에 대입하면 synthesis 오류이고 시뮬레이션에서도 기이하게 동작합니다. 같은 규칙: 드라이버 하나.

SystemVerilog의 갱신: logic

SystemVerilog(Verilog이 발전한 superset)는 둘을 모두 대체하는 단일 키워드를 추가합니다: logic. logic 신호는 assign 또는 procedural block으로 구동될 수 있지만 둘 동시는 안 되며, 컴파일러가 실수로 다중 드라이버 버그를 만들지 못하게 막아 줍니다.

module modern(input logic a, input logic b, output logic y);
    assign y = a ^ b;
endmodule

새 프로젝트를 시작하고 도구가 SystemVerilog을 지원한다면(이 페이지의 에디터는 -g2012로 지원), 어디서나 logic을 쓰는 게 규칙을 단순화합니다. 일반 .v 파일은 여전히 wire/reg 분할이 필요하고, 두 스타일 모두 영원히 실무에서 보일 것입니다.

다음에 볼 내용

다음 문서 - Vectors and Arrays - 는 같은 두 타입을 멀티 비트로 만드는 방법을 보여 줍니다. 버스 너비, 범위, packed 차원, 그리고 bit의 vector와 vector의 array의 차이. 1비트 가산기보다 큰 것을 만들기 전에 알아야 할 모든 것입니다.

자주 묻는 질문

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

wirereg 모두 시뮬레이션의 매 순간 신호 값을 보존하지만, 둘 중 무엇을 쓸지는 누가 신호를 구동하는가 로 결정합니다. wire는 procedural block 외부 - assign이나 서브모듈 출력 - 에서 구동됩니다. reginitial이나 always 블록 내부에서 구동됩니다. 이름은 역사적이고 오해를 부르는 측면이 있습니다 - reg가 항상 'register'를 의미하지는 않습니다.

Verilog의 reg는 플립플롭을 의미하나요?

반드시 그렇지는 않습니다. reg는 그 always 블록이 clock edge에 sensitive하고 non-blocking assignment를 쓸 때만 플립플롭으로 synthesize됩니다. 조합 always @(*) 블록 안에서 대입된 reg는 평범한 조합 논리로 synthesize됩니다. 키워드는 Verilog 데이터 타입 을 고를 뿐, 하드웨어를 고르지 않습니다.

wire와 reg 중 무엇을 써야 하나요?

경험칙: 신호를 assign으로 구동하거나 서브모듈 output port에 연결할 거라면 wire. alwaysinitial 블록 안에서 대입할 거라면 reg. 모듈 입력은 항상 wire. 출력은 assign으로 구동하면 wire, procedural block으로 구동하면 reg입니다.

always 블록 안에서 wire에 대입할 수 있나요?

아니요 - 그건 syntax error입니다. wire 신호는 continuous assignment(assign) 또는 서브모듈 인스턴스의 output port로만 구동될 수 있습니다. initial이나 always 안의 모든 것은 reg(SystemVerilog에서는 logic)를 타겟해야 합니다. 컴파일러가 이를 잡아내고 'left-hand side type mismatch'에 대해 불평합니다.

SystemVerilog의 logic이란?

logic은 SystemVerilog가 wirereg를 통합한 것입니다. continuous assignment 또는 procedural block으로 구동될 수 있습니다(둘 동시는 안 됨). 현대 코드는 점점 logic을 어디서나 쓰면서 wire/reg 구분을 잊는 추세입니다. 일반 Verilog 파일에서는 여전히 선택해야 합니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기