Menu

Verilog Continuous Assignment: assign 문

assign이 어떻게 동작하는지 - 그것이 기술하는 항상 참인 관계, 무엇을 구동할 수 있고 없는지, 그리고 procedural 코드와 비교해 어떤 패턴에 빛을 발하는지.

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

assign은 영구적 진리를 기술한다

wire 선언은 신호를 만듭니다. assign그것을 무엇이 구동하는지 를 기술합니다. 관계는 연속적입니다: 우변이 무엇이든 좌변은 모든 시뮬레이션 시점에 그것과 같습니다.

wire y;
assign y = a & b;

이 두 줄이 함의하는 것.

  • 회로에 y라는 wire가 존재합니다.
  • y는 모든 시점에 ab의 비트와이즈 AND입니다. 어느 쪽이든 바뀌면 y가 따라갑니다.

clock도 이벤트도 없습니다. 시뮬레이터는 a 또는 b가 변하는 것을 보고 y를 dirty로 표시하고 식을 다시 평가합니다. 하드웨어에서는 AND 게이트 몇 개로 매핑됩니다: 조합, stateless, 즉각적.

암시적(implicit) 형태

선언과 대입을 한 줄로 합칠 수 있습니다.

wire y = a & b;

위의 두 줄과 동일합니다. 이 스코프 바깥에서 신경 쓰는 사람이 없는 인라인 wire에 유용합니다. 많은 스타일 가이드가 선언과 식을 바로 옆에 두기 때문에 implicit 형태를 선호합니다.

assign이 구동할 수 있는 것

assign의 타겟은 net 타입 이어야 합니다 - 일반 Verilog에서는 wire(또는 더 드문 사촌인 tri, wand, wor)입니다. reg는 될 수 없습니다. 실수로 타겟을 reg로 선언하면

reg y;
assign y = a & b;   // 오류: assign으로 reg를 구동할 수 없음

컴파일러가 알려 줍니다. 타겟을 wire로 바꾸거나, 로직을 reg가 합법인 always @(*) 블록으로 옮기세요.

우변은 값으로 평가되는 어떤 것이든 될 수 있습니다: 리터럴, 신호, parameter, 연산자 식, 함수 호출. 여러 입력 너비를 섞을 수 있고 표준 너비 확장 규칙이 적용됩니다.

assignalways 중 무엇을 쓸까

둘 다 조합 논리를 만들 수 있습니다. 선택은 주로 코드 가독성의 문제입니다.

  • assign은 관계가 단일 식일 때 좋습니다. 가산기, ?:로 만든 단순 mux, mask, parity bit 등 한 줄로 쓸 수 있는 모든 것.
  • always @(*)는 procedural 문이 필요할 때 좋습니다. 다중 분기 case, 중첩 if/else if, 이름 있는 중간 reg로 도움받는 모든 것. 이건 Always Block에서 다룹니다.

같은 4-to-1 mux를 양쪽 방식으로 작성한 예시입니다.

두 모듈 모두 본질적으로 같은 멀티플렉서로 synthesize됩니다. assign 버전은 한 줄이고, always 버전은 여섯 줄입니다. 분기가 네 개라면 차이가 크지 않지만 열여섯 개라면 case 블록이 분명히 더 읽기 쉽습니다.

흔한 패턴

평범한 조합 논리

assign sum   = a + b;
assign carry = a[7] & b[7];
assign equal = (data == 8'hFF);

식 하나, wire 하나. assign의 빵과 버터입니다.

2-to-1 Mux

assign out = sel ? a : b;

조건식 하나 - synthesizer가 그것을 2-to-1 mux 하나로 바꿉니다. "a와 b 중 선택"의 가장 깔끔한 표기입니다.

비트 패킹

assign status = {error, overflow, ready, busy, 4'b0};

assign의 우변에서 concatenation을 쓰면 flag를 상태 바이트로 묶을 수 있습니다. 결과는 연속적으로 계산되고 구동됩니다.

Tri-State 출력

assign data_pin = output_enable ? data_out : 1'bz;

output_enable이 high이면 핀을 구동하고, low이면 high impedance로 풉니다. 여러 드라이버가 wire를 공유할 수 있는 칩 핀에서 정석 패턴입니다.

동시성: 여러 assign은 순차가 아니다

계속 강조해도 부족한 사실: 같은 모듈 안의 여러 assign 문은 모두 병렬로 실행됩니다. 시퀀스가 아닙니다.

assign y = a & b;     // 모든 시점에 존재
assign z = a | b;     // 역시 모든 시점에 존재, 독립적

파일 안의 순서는 무관합니다. 두 식이 동시에 참입니다. synthesizer는 AND 게이트를 OR 게이트의 왼쪽에 둘 수도 오른쪽에 둘 수도 있지만 중요하지 않습니다 - 두 게이트가 연속적으로 동작합니다.

순차적으로 보이는 동작을 원한다면 always 블록(아마도 clock과 함께)을 찾게 됩니다. 그건 다른 장의 이야기입니다.

다중 드라이버: 버스 패턴

wire는 여러 assign이 타겟할 수 있지만, tri-state bus가 아니라면 거의 원하지 않을 일입니다. 두 드라이버가 wire를 두고 다투면 정의되지 않은 동작이 나옵니다.

assign y = a;
assign y = b;   // BAD - 드라이버 둘, 시뮬레이터가 하나를 고르거나 X로 만듦

정당한 패턴: 각 드라이버가 비활성일 때 z로 풀고, 동시에 활성인 드라이버는 최대 하나입니다.

assign bus = device_a_active ? data_from_a : 1'bz;
assign bus = device_b_active ? data_from_b : 1'bz;

이게 작동하는 이유는 어떤 시점에든 두 ternary 중 최대 하나만 z가 아닌 값을 만들기 때문입니다. wire의 실제 값은 풀어 주지 않은 드라이버의 값입니다.

내부 로직(칩 핀이나 공유 on-chip bus가 아닌 곳)에서는 wire 하나당 드라이버 하나. 다중 드라이버 버그는 디버그하기 끔찍합니다.

assign이 못 하는 것

assign이 잘못된 도구인 경우.

  • 저장. assign은 조합 관계를 기술합니다 - 플립플롭을 만들지 못합니다. clock 사이클을 가로질러 값을 기억해야 한다면 그건 always @(posedge clk) 블록입니다.
  • 다단계 procedural 로직. assign 안에서는 if/elsecase를 쓸 수 없습니다. 가장 가까운 게 ?: 체인인데, 분기가 셋을 넘으면 보기 흉해집니다.
  • procedural 블록 내부에서 register를 구동. reg 타겟에는 procedural assignment가 필요하지 assign은 아닙니다.

이 한계를 알면 always로 언제 전환할지 결정할 수 있습니다.

다음에 볼 내용

이제 Verilog의 구조적 측면 전체를 봤습니다: 모듈 선언, 인스턴스화, 그리고 assign으로 조합 논리 배선. 다음 장은 procedural block으로 들어갑니다 - 시간과 순서가 의미를 갖기 시작하는 initialalways 구성요소들.

자주 묻는 질문

Verilog의 continuous assignment는 무엇인가요?

assign target = expression;은 영구적이고 연속적인 관계를 선언합니다: target은 항상 expression과 같습니다. 식의 어떤 신호든 변하면 시뮬레이터는 우변을 다시 평가해 target을 갱신합니다. clock도 이벤트도 없습니다 - 관계는 모든 시점에 참입니다.

Verilog에서 assign으로 무엇을 구동할 수 있나요?

assignwire를 구동할 수 있지만 reg는 절대 안 됩니다. 타겟은 net 타입이어야 합니다. 대신 always 블록 내부에서 대입하려면 reg로 선언해야 합니다. 컴파일러는 xreg인데 assign x = ...을 쓰면 거부하고, xwire인데 always 안에서 x = ...를 쓰면 거부합니다.

assign과 always 블록 중 무엇을 써야 하나요?

단순한 조합 논리에는 assign을 사용하세요 - 입력 하나, 출력 하나, if/else가 필요 없는 경우. always @(*)는 procedural 문(case, if/else if 체인, for 루프)이 필요할 때 사용합니다. 둘 다 조합 하드웨어를 만듭니다 - 선택은 가독성에 관한 것입니다.

Verilog에서 같은 wire에 여러 assign을 할 수 있나요?

각 드라이버가 비활성일 때 wire를 z로 풀어 주는 tri-state bus를 모델링할 때만 가능합니다. 동시에 wire를 명확한 값으로 구동하려는 두 assign은 contention을 일으킵니다 - 시뮬레이터가 하나를 선택할 수도 있고 신호를 X로 만들 수도 있고, 도구에 따라 다릅니다. 일반적인 조합 논리에서는 wire 하나당 드라이버 하나입니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기