베릴로그

 

'''하드웨어 기술 언어(HDL)'''
베릴로그
VHDL
[image]
1. 개요
2. 역사
3. 예제
3.1. 조합 논리(Combinational Logic)
3.2. 순차 논리(Sequential Logic)
4. 문법
4.1. 상수
4.2. 연산자
4.3. 시스템 태스크(System tasks)
4.4. 반복문


1. 개요


베릴로그(Verilog)는 전자 회로 및 시스템에 쓰이는 하드웨어 기술 언어(HDL, Hardware Description Language)다. 베릴로그 HDL이라고도 부를 수 있으나, 이 경우 VHDL과 헷갈리기 때문에 베릴로그라고만 부른다. 회로 설계, 검증, 구현 등 여러 용도로 사용된다. VHDL은 과거에는 많이 사용되었지만 지금은 대부분 베릴로그를 기반으로 디자인 한다. 통계적으로는 유럽을 제외하면 베릴로그의 점유율이 VHDL을 압도하였다.
Ada기반인 VHDL과 달리 C언어와 비슷한 문법을 가진 것이 특징이다. 'if'나 'for', 'while' 같은 제어 구조도 동일하며, 출력 루틴 및 연산자들도 거의 비슷한 것 등 사용자들이 쉽게 접근할 수 있다. 다만, case문의 형태와 블록의 시작과 끝을 중괄호 대신 Begin과 End를 사용하는 것은 파스칼(Pascal)언어와 유사하다. 그러나 하드웨어 설계와 소프트웨어 설계에는 본질적인 차이가 있기 때문에 문법이 비슷하다고 C언어 프로그래밍 하듯이 베릴로그를 짜게 되면 엉터리 코드가 나오게 된다. HDL에 입문하는 사람들이 많이 고생하는 부분인데, 디지털 회로에 대한 충분한 지식을 갖고, 작성한 코드가 하드웨어로 어떻게 합성될지에 대한 감을 키워나가야 한다.
HDL이 일반 프로그래밍 언어와 크게 다른 점은 시간, 클럭으로 대표되는 이벤트, 아주 작은 프로세스 개념이며, 각각 #, @, fork/join 등의 키워드로 지원한다.
다음과 같이 10의 주기를 가지는 클럭을 시뮬레이션에서 만들 수 있다.
initial clk = 0;
always #5 clk = ~clk;
8비트 다운 카운터 예
module counter (clk, load, Q);
   parameter WIDTH = 8;
   input    clk;
   input    load;
   output   [WIDTH-1:0]   Q;
   reg      [WIDTH-1:0]   cnt;

   always @(posedge clk) begin
      if (load)
         cnt <= {WIDTH{1’b1}};
      else
         cnt <= cnt - 1’b1;
   end

   assign Q = cnt;

endmodule

2. 역사


본래는 Phil Moorby가 모의시험용 언어로 개발하였다. 이후 Cadence Systems에 인수되어 업계표준 HDL로 자리를 잡았다.
이후 95년 IEEE표준이 만들어졌고, 2001년 변경이 있었다(Verilog-2001). 그러나 디지털 시스템의 설계에서 검증의 필요성이 커짐에 따라 이를 지원하기 위해 대대적인 확장이 필요하게 되었다. 이를 위해 2005년 SystemVerilog가 IEEE 표준으로 만들어 졌다.
그러나 SystemVerilog는 검증용 테스트벤치 작성시 외엔 실제 업계에서는 잘 쓰이지 않는데, C에서 쓰이는 enum, class, struct, union등의 data type은 실제 하드웨어 합성시 결과물로 나오게 될 netlist[1]를 직관적으로 예측하기 어렵게 하고 툴 간에 문법 해석 차이가 있는 경우 netlist 기반의 시뮬레이션을 토대로 RTL[2] 디버깅을 하기 상당히 까다로워진다. 물론 베릴로그의 wire, reg data type도 소스코드에 선언된 그대로 wire와 register로 합성되는 것은 아니지만 SystemVerilog의 추상화에 비하면 사실상 하드웨어에 매우 가까운 편이라 소스코드에 존재하는 버그를 찾더라도 netlist를 직접 고치는 것이 가능할 정도. 또한 SystemVerilog는 툴체인에서 지원을 하지 않는 경우가 있기 때문에 더더욱 사용도가 떨어진다.[3]

3. 예제



3.1. 조합 논리(Combinational Logic)



3.2. 순차 논리(Sequential Logic)


module flip_flop(input clk, input d, output reg q);

   always @(posedge clk) begin
      q <= d;
   end
   
   endmodule
non-blockinig assignment인
<=
를 사용해야 한다.

4. 문법



4.1. 상수


[bit 수]'[진수][숫자]
4'b0110 - 4 bit 이진수 0110
32'd2020 - 32 bit 십진수 2020
8'ha12 - 8 bit 16진수 a12
16'o20 - 16 bit 8진수 20

4.2. 연산자



4.3. 시스템 태스크(System tasks)


간단한 I/O 기능을 제공하는 함수들로 주로 '''시뮬레이션''' 과정에서 활용한다. 다른 함수와 구분하기 위해 모든 시스템 태스크는 '''$'''를 접두사로 사용한다.
  • $display
문자열과 지정한 신호의 값을 화면에 출력한다. 자동으로 개행된다.
$display("Hello World!");
$display("%b, %d", a, b);
{{{

}}}
  • $write
기능은
$display
와 동일하나 개행 없이 출력한다.
  • $monitor
지정한 신호의 값이 바뀌면 화면에 출력한다.
  • $stop
시뮬레이션을 중단한다.
$finish
와 달리 control이 여전히 simulator에 있으며 simulator가 Interative Mode가 된다.
  • $finish
시뮬레이션을 종료한다.
$stop
과 달리 control이 OS로 돌아온다.
  • $time
현재의 시뮬레이션 시간
$display($time);


  • $random
랜덤값을 반환한다.
$display($random);



4.4. 반복문


베릴로그에서는 for, while의 루프문을 지원하지만 초심자의 경우 테스트벤치 작성을 위한 경우 말고는 사용을 지양하는 것이 좋다. 베릴로그는 일반적인 프로그래밍 언어와는 다르게 하드웨어 수준의 구조를 코드로 작성하는 것이기 때문에 루프문의 무분별한 오용은 하드웨어의 합성 과정에서 문제를 일으킬 가능성이 높다. 보수적인 엔지니어의 경우 for문의 사용 자체를 금기시 하기도 할 정도이다. 따라서 설계할 루프문이 하드웨어로 합성 가능한 구조인지 잘 따져가면서 사용하는게 중요하다. 반복문이 다이나믹하다면 당연히 합성 불가능하고, 생각하기 힘든 다양한 함정들이 존재하므로 단순한 규칙적인 구조를 기술하는 수준이 아닌[4], 루프 끼리 복잡한 상호작용이 있는 구조를 기교를 부려서 기술하는 것은 지양하는 것이 좋다.

[1] 쉽게 말해서 gate-level[2] 물론 이 경우 SystemVerilog 소스코드에 해당[3] 칩을 제대로 하나 내보내려면, 단순 설계만 아니라 각종 합성부터 해서 backend작업까지 Pass를 시켜야 되는데, 이 backend 작업들 중에서 SystemVerilog를 지원하지 않거나 추가 라이센스비용을 내게하는 경우가 많다.[4] 이것도 초심자의 경우 경우에 따라 생각치도 못한 문제가 발생할 수 있다.