Loading [MathJax]/jax/output/HTML-CSS/config.js

#8. 행위수준모델링(Behavioral modeling)-always문

Verilog/Verilog HDL강의정리(KOCW) 2023. 7. 21. 02:52
반응형

1. 행위수준 모델링

앞에서 배운 연속할당문(assign문)의 경우 플립플롭이나 래치가 없는 형태의, 즉 데이터를 저장하지 못하는 형태의 조합논리회로를 작성하는데 사용되었다. 절차할당문의 경우, 조합회로와 순차회로 모두에서 쓰일 수 있으며, 테스트 벤치에서도 사용이 가능하다. 절차할당문의 경우 대표적으로 always 구문과 initial 구문(testbench)이 있으며, task, function 등의 구문도 가능하다.


1-1. always문

a먼저 always문을 사용하는 구문의 구조에 대해서 살펴보자

always [@(sensitivity_list)] begin
	blocking or nonblocking statement;
end

[@(sensitivity_list]) : 괄호안의 조건에 따라 begin문이 실행되게 된다. 즉, 신호의 변화를 감지하는 부분

blocking or nonblocking statement : 이곳에 할당문이 작성되게 되는데, 앞에서 잠시 언급한 blocking statement의 경우 =, non blocking 의 경우 <= 를 사용하여 할당하게 된다.

D플립플롭의 예시코드를 살펴보자. D 플립플롭은 클럭과 입력값이 input으로 존재하고, output으로 Q값을 설정한다. 그리고 클럭이 발생할 때마다, 입력값이 출력값으로 나가는 형태의 회로를 갖는다. 이를 코드로 작성해보면

module D_flipflop(clk, din, qout)
    input clk, din; //input 설정
    output qout;
    reg qout;	// always 구문에서 쓰이므로 reg 선언
always@(posedge clk)begin
	qout<= din; //non blocking 할당문
end
endmodule

posedge의 경우 클럭이 0,X,Z->1인 경우에 조건에 만족하게 되고(상승엣지), 반대의 경우는 negedge가 된다.

1-2. sensitivity list에 들어갈 수 있는 조건들

@posedge clk 처럼, @뒤에는 sensitivity list를 작성할 수 있는데, 여기에는 여러가지 조건들이 들어갈 수 있다.

그 중에서도 많이 쓰이는 것 한가지가 바로, 모든 신호의 변화의 감지를 인식하는 * 표시를 추가하면 모듈에 연결된 신호가 바뀔 경우 동작하게 된다. 즉, @(*) 표현이 가능하다. 또한, 동기식/비동기식 리셋 방법에 대한 이야기도 있지만, 이는 나중에 추가로 blocking/non- blocking 에 대한 이야기와 합쳐서 하나의 글로 작성하도록 하겠다.

 


2. always 구문으로 테스트벤치 작성하기

테스트벤치에서 클럭을 생성하는 방법으로 always문을 사용할 수 있다.

always
    clk = ~clk; //무한히 반복되는 0<->1 전환 클럭, delay가 없으므로 교착상태에 빠지게 됨


always
    #20 clk = ~clk; //20ns마다 0과 1이 전환 되므로 총 40ns 주기의 클럭


initial
    clk = 1'b0;
always
    #20 clk = ~clk;  //초기 클럭값을 1로 설정한 뒤 20ns마다 전환되는 클럭(주기 40ns)

위 코드에서는 클럭을 생성하는 세가지 예시를 설명하였다. 첫번째 클럭처럼 작성할 경우 정상적인 클럭동작이 되지 않음에 유의하자.

또한, 3번째 clk처럼 기본 초기값을 준 상태에서 클럭을 실행시키는 것이 바람직하다.(reg 형의 변수는 선언시 초기값이 X이기 때문에)

 


3. initial 구문

initial 구문은 시뮬레이션 실행동안 한번만 실행되는 구문이다. 회로 합성에는 영향을 미치지 않으므로, 시뮬레이션에서 사용하게 된다.(testbench에서 사용한다.) 기본적인 사용방법은 다음과 같다.

initial begin
    blocking/non_blocking statement;
end

위 코드와 같이 작성하면 된다. 또한, 초기값을 설정하는 경우에 이렇게 사용하게 된다.

initial begin
      din = 6'b000000;
  #10 din = 6'b001100;
  #10 din = 6'b001110;
  #10 din = 6'b001101;
end

위와 같이 delay를 주면서 din에 값을 주는 방식으로 시뮬레이션을 구성하는데 필요한 값들을 지정할 수 있다.

모듈안에 넣는 예시로도 확인해보면

module clock_test;
    reg a, b;  //always 구문 안에 들어가므로 reg 선언
    
    initial begin; // 초기값 설정
        a = 1'b1;
        b = 1'b0;
    end
    always
      #50 a = ~a;  //100ns주기의 클럭 설정
    always
      #100 b = ~b;  //200ns 주기의 클럭 설정
endmodule

이렇게 클럭을 설정해볼 수 있다.

마지막으로, 가장 중요한 사실은 위 코드에서 initial 구문과 always 구문의 순서가 바뀐다고 하여도 회로 동작에는 차이가 없고,  이는 하드웨어적 특성임을 항상 생각하고 있어야한다.

 

반응형