Skip to content
DevBJ
Go back

Verilog blocking과 non-blocking은 언제 나눠 써야 하나

Advertisement
Updated:
Editor

Verilog 할당 구문을 다시 정리해 본다.

일단 조합회로 절차 블록은 =, clock 기반 순차회로 블록은 <=를 사용한다. 연산자 하나만 보고 합성되는 회로가 결정되는 것은 아니다.

일단 결론

// 조합회로
always @* begin
  y = (a | b) & (~c ^ d);
end

// 순차회로
always @(posedge clk) begin
  q <= d;
end

always 블록 안에서 blocking과 non-blocking 할당을 섞지 않는 편이 좋다. AMD Vivado 합성 가이드도 두 방식을 섞으면 simulation 오류가 생길 수 있다고 설명한다.

continuous assignment

assign은 연속 할당이다. 우변이 바뀌면 좌변 값도 다시 계산된다.

wire y;

assign y = b & c;

Verilog 기준으로 assign의 좌변은 net type을 사용한다. 여기서는 wire로 선언했다.

blocking assignment

=는 문장이 실행되는 즉시 좌변을 갱신한다. 조합회로를 표현하는 always @* 블록에서 주로 사용한다.

always @* begin
  temp = a & b;
  y = temp | c;
end

아래 문장은 갱신된 temp를 사용한다. 그래서 블록 안의 문장 순서가 simulation 결과에 영향을 줄 수 있다.

조합회로 블록에서는 모든 경로에서 출력값을 할당해야 한다. 빠진 경로가 있으면 latch가 만들어질 수 있다.

non-blocking assignment

<=는 우변을 먼저 평가하고 좌변 갱신을 현재 simulation time step의 뒤쪽에 예약한다. clock edge에서 여러 register를 함께 갱신할 때 사용한다.

always @(posedge clk) begin
  a <= b;
  b <= a;
end

clock edge 직전의 a, b 값을 각각 읽은 뒤 두 값을 갱신한다. blocking 할당처럼 첫 문장에서 바뀐 a를 두 번째 문장이 바로 읽는 구조가 아니다.

blocking과 non-blocking 할당의 값 갱신 시점을 비교한 설명 그림

위 그림은 실제 simulator waveform이 아니다. 값 평가와 갱신 순서를 설명하려고 만든 그림이다.

회로는 문맥으로 확인

=이면 무조건 조합회로, <=이면 무조건 flip-flop이라는 뜻은 아니다. sensitivity list, clock edge, 모든 분기의 할당 여부를 함께 봐야 한다.

// clock edge가 있으므로 순차회로를 의도한 블록
always @(posedge clk) begin
  q <= d;
end
// 모든 입력 변화에 반응하고 모든 경로를 할당하는 조합회로
always @* begin
  if (sel)
    y = a;
  else
    y = b;
end

나는 조합 블록과 순차 블록을 나누고, 한 블록에서는 한 종류의 할당만 사용한다. 머 이 정도로 정해두면 다시 볼 일이 많이 줄어든다.

delay는 합성용으로 보지 않는다

assign #10 y = b & c;

#10 같은 delay는 simulation 모델에서는 의미가 있지만 Vivado 합성에서는 무시된다. 합성할 RTL의 실제 timing을 이 값으로 지정하면 안 된다.

확인하지 않은 부분

현재 이 저장소 환경에는 HDL simulator가 설치되어 있지 않아 예제를 직접 실행하지 않았다. 특정 simulator의 event queue 표시나 waveform 차이는 아직 확인하지 않았다.

공식 문서

원문 기록

한 줄 요약

조합회로 절차 블록은 =, clock 기반 순차회로 블록은 <=로 나누고 실제 회로는 블록 전체 문맥으로 확인한다.

끝.


Share this post on:

Next Post
Windows PowerShell에서 pnpm 10 설치하고 실행하기