verilog 튜토리얼
Verilog 시작하기
수색…
비고
Verilog는 행동 또는 등록 전송 수준에서 디지털 회로를 설계, 시뮬레이션 및 검증하는 데 사용되는 하드웨어 설명 언어 (HDL)입니다. "전통적인"프로그래밍 언어와 구별되는 이유는 주목할 만하다.
- 차단 및 비 차단이라는 두 가지 유형의 할당이 있으며, 각각 고유 한 용도와 의미가 있습니다.
- 변수는 단일 비트 폭 또는 명시 적 폭으로 선언해야합니다.
- 디자인은 계층 적이며 원하는 동작을하는 모듈을 인스턴스화 할 수 있습니다.
- 시뮬레이션에서 (일반적으로 합성이 아닌)
wire
변수는 0, 1, 부동 (z
) 및 정의되지 않은 (x
)의 4 가지 상태 중 하나에있을 수 있습니다.
버전
번역 | 출시일 |
---|---|
Verilog IEEE-1364-1995 | 1995-01-01 |
Verilog IEEE-1364-2001 | 2001-09-28 |
Verilog IEEE-1364.1-2002 | 2002-12-18 |
Verilog IEEE-1364-2005 | 2006-04-07 |
SystemVerilog IEEE-1800-2009 | 2009-12-11 |
SystemVerilog IEEE-1800-2012 | 2013-02-21 |
설치 또는 설정
Verilog 설정 또는 설치에 대한 자세한 지침은 많은 Verilog 도구가 있으므로 사용하는 도구에 따라 다릅니다.
소개
Verilog는 전자 시스템을 모델링하는 데 사용되는 하드웨어 설명 언어 (HDL)입니다. 가장 일반적으로 추상화의 레지스터 전송 레벨 (RTL)에서 전자 시스템을 설명합니다. 아날로그 회로 및 혼합 신호 회로의 검증에도 사용됩니다. 그 구조와 주요 원칙 (아래에 설명)은 전자 시스템을 기술하고 성공적으로 구현하도록 설계되었습니다.
- 엄격
전자 회로는 고정 된 구조를 가진 물리적 개체이며 Verilog가이를 위해 채택되었습니다. 모듈 (모듈), 포트 (입력 / 출력 / 출력), 연결 (와이어), 블록 (@ 항상), 레지스터 (reg)는 모두 컴파일시 고정됩니다. 엔티티 및 상호 연결 수는 동적으로 변경되지 않습니다. 칩 구조 (합성 용)를 나타내는 최상위 레벨과 검증을 위해 시스템 레벨에 항상 "모듈"이 있습니다. - 병행
물리적 칩의 본질적인 동시 동작은 항상 (대부분의 commmon), 초기 및 fork / join 블록에 의해 언어에서 모방됩니다.
module top();
reg r1,r2,r3,r4; // 1-bit registers
initial
begin
r1 <= 0 ;
end
initial
begin
fork
r2 <= 0 ;
r3 <= 0 ;
join
end
always @(r4)
r4 <= 0 ;
endmodule
위의 모든 명령문은 동일한 시간 단위 내에서 병렬로 실행됩니다.
타이밍 및 동기화
Verilog는 회로의 시간적 특성을 설명하는 다양한 구조를 지원합니다. 회로의 타이밍과 지연은 #delay 구문과 같이 Verilog에서 구현할 수 있습니다. 마찬가지로 Verilog는 동기 및 비동기 회로와 플롭, 래치, 조합 로직 (예 : "항상"블록)을 사용하는 조합 로직을 수용합니다. 블록 세트는 공통 클럭 신호를 통해 동기화되거나 특정 입력 세트를 기반으로 블록이 트리거 될 수 있습니다.#10 ; // delay for 10 time units always @(posedge clk ) // synchronous always @(sig1 or sig2 ) // combinatorial logic @(posedge event1) // wait for post edge transition of event1 wait (signal == 1) // wait for signal to be 1
불확실성
Verilog는 전자 회로에 내재 된 불확실성의 일부를 지원합니다. "X"는 회로의 알려지지 않은 상태를 나타내는 데 사용됩니다. "Z"는 회로의 비 구동 상태를 나타내는 데 사용됩니다.reg1 = 1'bx; reg2 = 1'bz;
추출
Verilog는 서로 다른 수준의 추상화를 지원합니다. 디자인의 가장 높은 수준의 추상화는 Resister transfer Level (RTL)이며, 다음은 게이트 레벨이며 셀 레벨이 가장 낮습니다 (User Define Primitives). RTL 추상화가 가장 보편적으로 사용됩니다. Verilog는 또한 주로 검증에 사용되는 디자인의 구조적 구현과 상관없이 추상화의 행동 수준을 지원합니다.
// Example of a D flip flop at RTL abstraction
module dff (
clk , // Clock Input
reset , // Reset input
d , // Data Input
q // Q output
);
//-----------Input Ports---------------
input d, clk, reset ;
//-----------Output Ports---------------
output q;
reg q;
always @ ( posedge clk)
if (~reset) begin
q <= 1'b0;
end else begin
q <= d;
end
endmodule
// And gate model based at Gate level abstraction
module and(input x,input y,output o);
wire w;
// Two instantiations of the module NAND
nand U1(w,x, y);
nand U2(o, w, w);
endmodule
// Gate modeled at Cell-level Abstraction
primitive udp_and(
a, // declare three ports
b,
c
);
output a; // Outputs
input b,c; // Inputs
// UDP function code here
// A = B & C;
table
// B C : A
1 1 : 1;
0 1 : 0;
1 0 : 0;
0 0 : 0;
endtable
endprimitive
Verilog에는 세 가지 주요 사용 사례가 있습니다. 이들은 코드의 구조와 해석을 결정하고 사용 된 도구 세트를 결정합니다. Verilog 디자인을 성공적으로 구현하려면 세 가지 애플리케이션이 모두 필요합니다.
- 물리적 디자인 / 백엔드
여기서 Verilog는 디자인을 논리적 설계를 구현하는 상호 연결 게이트의 매트릭스로 주로 보는 데 사용됩니다. RTL / 로직 / 디자인은 합성 -> 배치 -> 클록 트리 구성 -> 라우팅 -> DRC -> LVS -> 테이프 아웃까지 다양한 단계를 거칩니다. 정확한 단계와 순서는 구현의 정확한 특성에 따라 다릅니다. - 시뮬레이션
이 유스 케이스에서 주요 목적은 테스트 벡터를 생성하여 스펙별로 설계를 검증하는 것입니다. 이 유즈 케이스에서 작성된 코드는 합성 할 필요가 없으며 검증 영역 내에 남아 있습니다. 여기서 코드는 for / while / do 루프와 같은 일반적인 소프트웨어 구조와 매우 유사합니다. - 디자인
디자인은 일반적으로 추상화의 RTL 수준에서 회로 사양을 구현하는 것을 포함합니다. 그런 다음 Verilog 코드가 검증을 위해 제공되며 실제 구현을 위해 완전히 검증 된 코드가 제공됩니다. 이 코드는 Verilog의 합성 가능한 구문 만 사용하여 작성됩니다. 특정 RTL 코딩 스타일은 시뮬레이션 대 합성 불일치를 유발할 수 있으며이를 피하기 위해주의를 기울여야합니다.
주요 구현 흐름에는 두 가지가 있습니다. 또한 Verilog 코드가 작성되고 구현되는 방식에도 영향을 미칩니다. 특정 스타일의 코딩 및 특정 구조가 한 흐름에서 다른 흐름보다 적합합니다.
- ASIC 흐름 (특정 용도의 집적 회로)
- FPGA 플로우 (Field-programmable gate array) - FPGA 및 CPLD 포함
안녕하세요 세계
이 예제는 icarus verilog 컴파일러를 사용합니다.
1 단계 : hello.v라는 파일 만들기
module myModule();
initial
begin
$display("Hello World!"); // This will display a message
$finish ; // This causes the simulation to end. Without, it would go on..and on.
end
endmodule
2 단계. icarus를 사용하여 .v 파일을 컴파일합니다.
>iverilog -o hello.vvp hello.v
-o 스위치는 출력 개체 파일에 이름을 지정합니다. 이 스위치가 없으면 출력 파일은 a.out이라고합니다. hello.v는 컴파일 할 소스 파일을 나타냅니다. 오류가없는 한,이 소스 코드를 컴파일 할 때 실제로 출력이 없어야합니다.
3 단계.이 Hello World Verilog 프로그램을 시뮬레이션 할 준비가되었습니다. 이렇게하려면 다음과 같이 호출하십시오.
>vvp hello.vvp
Hello World!
>
Mac OSX Sierra 용 Icarus Verilog 컴파일러 설치
- App Store에서 Xcode를 설치하십시오.
- Xcode 개발자 도구 설치
> xcode-select --install
이렇게하면 gcc
및 make
와 같은 기본 명령 줄 도구가 제공됩니다.
- Mac 포트 설치
https://www.macports.org/install.php
OSX Sierra 설치 패키지는 Mac 플랫폼에 추가 소프트웨어 패키지를 설치하고 업그레이드하는 오픈 소스 방법을 제공합니다. Think yum
또는 apt-get
for Mac.
- Mac 포트를 사용하여 icarus 설치하기
> sudo port install iverilog
- 명령 줄에서 설치 확인
$ iverilog
iverilog: no source files.
Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]
[-g1995|-g2001|-g2005] [-g<feature>]
[-D macro[=defn]] [-I includedir] [-M depfile] [-m module]
[-N file] [-o filename] [-p flag=value]
[-s topmodule] [-t target] [-T min|typ|max]
[-W class] [-y dir] [-Y suf] source_file(s)
See the man page for details.
$
이제 Mac에서 Verilog 파일을 컴파일하고 시뮬레이션 할 준비가되었습니다.
Mac OS X Sierra에서 시뮬레이션 데이터의 그래픽 디스플레이를위한 GTKWave 설치
GTKWave는 여러 가지 그래픽 데이터 저장 표준을 지원하는 완전한 기능의 그래픽보기 패키지이지만 vvp
가 출력 할 형식 인 VCD도 지원합니다. 그래서 GTKWave를 선택하려면 몇 가지 옵션이 있습니다.
- http://gtkwave.sourceforge.net/gtkwave.zip으로 이동 하여 다운로드하십시오. 이 버전은 일반적으로 최신 버전입니다.
- MacPorts ( https://www.macports.org/ )를 설치했다면 간단히
sudo port install gtkwave
를 실행하십시오. 이것은 아마도 의존성에 설치하려고 할 것이다. 이 방법은 일반적으로 이전 버전을 얻게됩니다. MacPorts가 설치되어 있지 않으면이 페이지에서이 작업을 수행 할 수있는 설치 설정 예가 있습니다. 예! 이 방법은 소스에서 GTKWave를 "빌드"하기 때문에 모든 xcode 개발자 도구가 필요합니다.
설치가 완료되면 Python 버전을 선택하라는 메시지가 표시 될 수 있습니다. 이미 2.7.10을 설치 했으므로 새로운 것을 선택하지 않았습니다.
이 시점에서 명령 행에서 gtkwave 시작할 수 있습니다 gtkwave
. 시작되면 XQuarts를 설치하거나 업데이트하라는 메시지가 나타날 수 있습니다. 그렇게해라. 필자의 경우 XQuarts 2.7.11이 설치되어있다.
참고 : 실제로 XQuart를 올바로 사용하려면 재부팅해야합니다. 그런 다음 gtkwave
다시 입력하면 응용 프로그램이 나타납니다.
다음 예제에서는 테스트 할 테스트 벤치와 모듈이라는 두 개의 독립적 인 파일을 만들고 gtkwave를 사용하여 디자인을 보겠습니다.
Icarus Verilog와 GTKWaves를 사용하여 디자인을 그래픽으로 시뮬레이션하고 봅니다.
이 예제는 Icarus와 GTKWave를 사용합니다. OSx에있는 도구에 대한 설치 지침은이 페이지의 다른 곳에서 제공됩니다.
모듈 디자인부터 시작하자. 이 모듈은 BCD - 7 세그먼트 디스플레이입니다. 나는 쉽게 우리에게 무언가를 제공하기 위해 무딘 방식으로 디자인을 코딩했으며 언젠가는 그래픽으로 고정시키는 데 쓸 수 있습니다. 그래서 우리는 시계, 리셋, BCD 값을 나타내는 4 개의 데이터 입력, 7 개의 세그먼트 디스플레이를 나타내는 7 비트 출력을 가지고 있습니다. bcd_to_7seg.v라는 파일을 만들고 그 아래에 소스를 놓습니다.
module bcd_to_7seg (
input clk,
input reset,
input [3:0] bcd,
output [6:0] seven_seg_display
);
parameter TP = 1;
reg seg_a;
reg seg_b;
reg seg_c;
reg seg_d;
reg seg_e;
reg seg_f;
reg seg_g;
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
seg_a <= #TP 1'b0;
seg_b <= #TP 1'b0;
seg_c <= #TP 1'b0;
seg_d <= #TP 1'b0;
seg_e <= #TP 1'b0;
seg_f <= #TP 1'b0;
seg_g <= #TP 1'b0;
end
else
begin
seg_a <= #TP ~(bcd == 4'h1 || bcd == 4'h4);
seg_b <= #TP bcd < 4'h5 || bcd > 6;
seg_c <= #TP bcd != 2;
seg_d <= #TP bcd == 0 || bcd[3:1] == 3'b001 || bcd == 5 || bcd == 6 || bcd == 8;
seg_e <= #TP bcd == 0 || bcd == 2 || bcd == 6 || bcd == 8;
seg_f <= #TP bcd == 0 || bcd == 4 || bcd == 5 || bcd == 6 || bcd > 7;
seg_g <= #TP (bcd > 1 && bcd < 7) || (bcd > 7);
end
end
assign seven_seg_display = {seg_g,seg_f,seg_e,seg_d,seg_c,seg_b,seg_a};
endmodule
다음으로이 모듈이 올바르게 작동하는지 확인하기위한 테스트가 필요합니다. 테스트 벤치의 case 문은 사실 내 의견으로는 읽기 쉽고 그것이하는 일에 대해서는 더 분명합니다. 그러나 나는 디자인과 테스트에 같은 판례를 넣는 것을 원하지 않았다. 그것은 나쁜 습관입니다. 오히려 서로를 검증하기 위해 두 개의 독립적 인 설계가 사용되고 있습니다.
아래 코드를 사용하면 $dumpfile("testbench.vcd");
및 $dumpvars(0,testbench);
. 이 선은 디자인의 그래픽 분석을 수행하는 데 사용되는 VCD 출력 파일을 만드는 것입니다. 그들을 버리면 VCD 파일이 생성되지 않습니다. testbench.v라는 파일을 만들고 그 아래에 소스를 놓습니다.
`timescale 1ns/100ps
module testbench;
reg clk;
reg reset;
reg [31:0] ii;
reg [31:0] error_count;
reg [3:0] bcd;
wire [6:0] seven_seg_display;
parameter TP = 1;
parameter CLK_HALF_PERIOD = 5;
// assign clk = #CLK_HALF_PERIOD ~clk; // Create a clock with a period of ten ns
initial
begin
clk = 0;
#5;
forever clk = #( CLK_HALF_PERIOD ) ~clk;
end
initial
begin
$dumpfile("testbench.vcd");
$dumpvars(0,testbench);
// clk = #CLK_HALF_PERIOD ~clk;
$display("%0t, Reseting system", $time);
error_count = 0;
bcd = 4'h0;
reset = #TP 1'b1;
repeat (30) @ (posedge clk);
reset = #TP 1'b0;
repeat (30) @ (posedge clk);
$display("%0t, Begin BCD test", $time); // This displays a message
for (ii = 0; ii < 10; ii = ii + 1)
begin
repeat (1) @ (posedge clk);
bcd = ii[3:0];
repeat (1) @ (posedge clk);
if (seven_seg_display !== seven_seg_prediction(bcd))
begin
$display("%0t, ERROR: For BCD %d, module output 0b%07b does not match prediction logic value of 0b%07b.",$time,bcd, seven_seg_display,seven_seg_prediction(bcd));
error_count = error_count + 1;
end
end
$display("%0t, Test Complete with %d errors", $time, error_count);
$display("%0t, Test %s", $time, ~|error_count ? "pass." : "fail.");
$finish ; // This causes the simulation to end.
end
parameter SEG_A = 7'b0000001;
parameter SEG_B = 7'b0000010;
parameter SEG_C = 7'b0000100;
parameter SEG_D = 7'b0001000;
parameter SEG_E = 7'b0010000;
parameter SEG_F = 7'b0100000;
parameter SEG_G = 7'b1000000;
function [6:0] seven_seg_prediction;
input [3:0] bcd_in;
// +--- A ---+
// | |
// F B
// | |
// +--- G ---+
// | |
// E C
// | |
// +--- D ---+
begin
case (bcd_in)
4'h0: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
4'h1: seven_seg_prediction = SEG_B | SEG_C;
4'h2: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D;
4'h3: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_C | SEG_D;
4'h4: seven_seg_prediction = SEG_F | SEG_G | SEG_B | SEG_C;
4'h5: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_C | SEG_D;
4'h6: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D;
4'h7: seven_seg_prediction = SEG_A | SEG_B | SEG_C;
4'h8: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
4'h9: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_B | SEG_C;
default: seven_seg_prediction = 7'h0;
endcase
end
endfunction
bcd_to_7seg u0_bcd_to_7seg (
.clk (clk),
.reset (reset),
.bcd (bcd),
.seven_seg_display (seven_seg_display)
);
endmodule
이제 우리는 testbench.v와 bcd_to_7seg.v의 두 파일을 가지고 있습니다. 우리는 이카루스를 사용하여 컴파일하고 정교하게 만들 필요가 있습니다. 이것을하기 위해:
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
다음으로 시뮬레이션해야합니다.
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
8000, Test Complete with 0 errors
8000, Test pass.
이 시점에서 파일이 실제로 테스트되고 있는지 확인하려면 bcd_2_7seg.v 파일로 이동하여 일부 논리를 이동하고 처음 두 단계를 반복하십시오.
예를 들어, seg_c <= #TP bcd != 2;
~ seg_c <= #TP bcd != 4;
. 재 컴파일 및 시뮬레이션은 다음을 수행합니다.
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
6600, ERROR: For BCD 2, module output 0b1011111 does not match prediction logic value of 0b1011011.
7000, ERROR: For BCD 4, module output 0b1100010 does not match prediction logic value of 0b1100110.
8000, Test Complete with 2 errors
8000, Test fail.
$
이제 GTKWave를 사용하여 시뮬레이션을 볼 수 있습니다. 명령 행에서 a
gtkwave testbench.vcd &
GTKWave 창이 나타나면 왼쪽 상단 상자에 모듈 이름 testbench가 표시됩니다. 클릭하세요. 이렇게하면 해당 파일과 관련된 하위 모듈, 작업 및 기능이 표시됩니다. 전선과 레지스터는 왼쪽 아래 상자에 나타납니다.
이제 clk, bcd, error_count 및 seven_seg_display를 파형 창 옆의 신호 상자로 드래그하십시오. 이제 신호가 플롯됩니다. Error_count는 잘못된 seven_seg_display 출력을 생성 한 특정 BCD 입력을 표시합니다.
Verilog 버그를 그래픽으로 해결할 준비가되었습니다.