[TOC]
## 前言
` `在linux下做FPGA開發驗證模塊功能時我們需要仿真,但是我們使用IDE工具會拉低效率,因為無論是quartus還是xilinx的開發工具,其設計本來就比較全面,運行的時候有很多東西都在運行,如果我們只需要仿真一個簡單的模塊,有可能整套走下來需要幾分鐘,源文件更改后再次仿真又要耗時幾分鐘,因此會影響我們的效率。
` `這個時候我們可以使用iverilog這塊輕量級的綜合工具來做好這個工作,搭建好環境后反復調試將會很節約時間。
## 準備工作
` `首先我們需要安裝必要的工具。我的環境是deepin15.11。
* 安裝iverilog
```
sudo apt-get install iverilog
```
* 安裝查看波形的工具GTKwave
```
sudo apt-get install gtkwave
```
` `linux下的verilog編輯器推薦使用**VS Code**,VS Code是一款非常好用的編輯器,基本各種語言使用中都可以得到很好的體驗。一款編輯器,搞定linux下大部分開發。注意要支持verilog語法,請到VSCode的插件中搜索verilog然后選擇一款進行安裝。


## 基本參數說明
Icarus Verilog編譯器主要包含3個工具:
* iverilog:用于編譯verilog和vhdl文件,進行語法檢查,生成可執行文件
* vvp:根據可執行文件,生成仿真波形文件
* gtkwave:用于打開仿真波形文件,圖形化顯示波形
在終端輸入`iverilog`回車,可以看到常用參數使用方法的簡單介紹:

### 參數 -o
` `這是比較常用的一個參數了,和GCC中-o的使用幾乎一樣,用于指定生成文件的名稱。如果不指定,默認生成文件名為a.out。如:`iverilog -o test test.v`。
### 參數 -y
` `用于指定包含文件夾,如果top.v中調用了其他的的.v模塊,top.v直接編譯會提示
~~~
led_demo_tb.v:38: error: Unknown module type: led_demo
2 error(s) during elaboration.
*** These modules were missing:
led_demo referenced 1 times.
***
~~~
` `找不到調用的模塊,那么就需要指定調用模塊所在文件夾的路徑,支持相對路徑和絕對路徑。
` `如:`iverilog -y D:/test/demo led_demo_tb.v`
` `如果是同一目錄下:`iverilog -y ./ led_demo_tb.v`,另外,iverilog還支持Xilinx、Altera、Lattice等FPGA廠商的仿真庫,需要在編譯時通過-y參數指定庫文件的路徑,詳細的使用方法可以查看官方用戶指南:
[https://iverilog.fandom.com/wiki/User\_Guide](https://iverilog.fandom.com/wiki/User_Guide)
### 參數-I
` `如果程序使用`include語句包含了頭文件路徑,可以通過-i參數指定文件路徑,使用方法和-y參數一樣。
` `如:`iverilog -I D:/test/demo led_demo_tb.v`
### 參數-tvhdl
` `verilog還支持把verilog文件轉換為VHDL文件,如`iverilog -tvhdl -o out_file.vhd in_file.v`
## 仿真流程
### 綜合
` `通過`iverilog -o tb tp_counter.v counter.v`命令,對源文件和仿真文件,進行語法規則檢查和編譯。由于本示例比較簡單,只有1個文件,如果調用了多個.v的模塊,可以通過前面介紹的-y參數指定源文件的路徑,否則編譯報錯。如果源文件都在同同一個目錄,可以直接通過`./`絕對路徑的方式來指定。
` `如果編譯成功,會在當前目錄下生成名稱為tb的文件。

### 生成波形文件
` `使用`vvp -n tb -lxt2`命令生成lxt波形文件,運行之后,會在當前目錄下生成.lxt文件。

` `如果沒有生成,需要檢查testbench文件中是否添加了如下幾行:
```
initial begin
$dumpfile("tb.lxt");
$dumpvars(0, counter);
end
```
### 使用GTKwav查看波形
` `使用命令`gtkwave tb.lxt`,可以在圖形化界面中查看仿真的波形圖



verilog轉換為VHDL
` `雖然VHDL和Verilog都誕生于20世紀80年代,而且都屬于硬件描述語言(HDL),但是二者的語法特性卻不一樣。Icarus Verilog 還有一個小功能就是支持把使用Verilog語言編寫的.v文件轉換為VHDL語言的.vhd文件。
` `如把led_demo.v文件轉換為VHDL文件led_demo.vhd,使用命令`iverilog -tvhdl -o led_demo.vhd led_demo.v`。
### VHDL文件編譯和仿真
` `如果你還和編譯Verilog一樣,使用`iverilog led_dmeo.v`來編譯VHDL文件的話,那么會提示有語法錯誤,這是正常的,因為Verilog和VHDL是不同的語法規則,不能使用Verilog的標準來檢查VHDL文件的語法。需要添加`-g2012`參數來對VHDL文件進行編譯,如`iverilog -g2012 led_demo.vhd`,和Verilog一樣,同樣也支持Testbech文件的編譯和仿真,當然需要編寫對應的VHDL Testbench文件。
## 搭建工程
` `開始搭建工程,首先新建一個文件夾,并在VS Code中打開該文件夾。
* step1:建立verilog模塊文件“counter.v”
```
`timescale 1ns/1ps
module counter(
input clk,
input rst_n,
output reg [4:0] ocnt
);
always@(posedge clk or negedge rst_n)
if (!rst_n) begin
ocnt <= 5'd0;
end
else ocnt <= ocnt + 5'd1;
endmodule
```
* step2:建立testbech文件"top_counter.v"
```
//`include "counter.v"
`timescale 1ns/1ps
module tp_counter;
reg clk;
reg rst_n;
wire [4:0]od;
counter counter
(
.rst_n (rst_n),
.clk (clk),
.ocnt(od)
);
localparam CLK_PERIOD = 2;
always #(CLK_PERIOD/2) clk=~clk;
initial begin
$dumpfile("tb.lxt"); //生成lxt的文件名稱
$dumpvars(0, counter); //tb中實例化的仿真目標實例名稱
end
initial begin
#1 rst_n<=1'bx;clk<=1'bx;
#(CLK_PERIOD*3) rst_n<=1;
#(CLK_PERIOD*3) rst_n<=0;clk<=0;
repeat(5) @(posedge clk);
rst_n<=1;
repeat(64) @(posedge clk);
$dumpflush;
$stop;
end
endmodule
```
` `注意testbench文件中有幾行iverilog編譯器專用的語句,如果不加的話后面不能生成lxt文件。
```
initial begin
$dumpfile("tb.lxt"); //生成lxt的文件名稱
$dumpvars(0, counter); //tb中實例化的仿真目標實例名稱
end
```
* step3:編寫makefile文件
` `采用makefile的方式,可以在我么第一次搭建好工程之后,之后進行綜合的時候方便一些。我們可以使用`make`命令就能進行綜合仿真,一步到位。
` `該工程的makefile文件如下:
```
tb: tp_counter.v counter.v
iverilog -o tb tp_counter.v counter.v
vvp -n tb -lxt2
clean:
rm -rf tb tb.lxt2
```
* step4:編寫運行腳本“run.sh”,方便直接查看波形
```
#!/bin/bash
make
gtkwave tb.lxt
```
` `為腳本添加運行權限
```
chmod +x tb.lxt
```
* step5:開始仿真
` `上述文件都準備好后,我們可以使用`make`命令來綜合工程并生成波形文件,若出現錯誤,在終端將會有相應的提示。
` `沒有錯誤后,在終端輸入`./run.sh`將會再次進行綜合一次,并在gtkwave中打開波形文件。然后就可以使用上面查看波形的方法查看信號。
## $dumpfile() $ dumpvars()的用法
` `$dumpfile和$dumpvar是verilog語言中的兩個系統任務,可以調用這兩個系統任務來創建和將指定信息導入VCD文件. (什么是VCD文件? 答:VCD文件是在對設計進行的仿真過程中,記錄各種信號取值變化情況的信息記錄文件。EDA工具通過讀取VCD格式的文件,顯示圖形化的仿真波形,所以,可以把VCD文件簡單地視為波形記錄文件.)下面分別描述它們的用法并舉例說明之。
` `$dumpfile系統任務:為所要創建的VCD文件指定文件名。
` `舉例("//"符號后的內容為注釋文字):
```
initial
$dumpfile ("myfile.dump"); //指定VCD文件的名字為myfile.dump,仿真信息將記錄到此文件
```
` `$dumpvar系統任務:指定需要記錄到VCD文件中的信號,可以指定某一模塊層次上的所有信號,也可以單獨指定某一個信號。
` `典型語法為$dumpvar(level, module\_name); 參數level為一個整數,用于指定層次數,參數module則指定要記錄的模塊。整句的意思就是,對于指定的模塊,包括其下各個層次(層次數由level指定)的信號,都需要記錄到VCD文件中去。
```verilog
舉例:
initial
$dumpvar (0, top); //指定層次數為0,則top模塊及其下面各層次的所有信號將被記錄
initial
$dumpvar (1, top); //記錄模塊實例top以下一層的信號
//層次數為1,即記錄top模塊這一層次的信號
//對于top模塊中調用的更深層次的模塊實例,則不記錄其信號變化
initial
$dumpvar (2, top); //記錄模塊實例top以下兩層的信號
//即top模塊及其下一層的信號將被記錄
```
` `假設模塊top中包含有子模塊module1,而我們希望記錄top.module1模塊以下兩層的信號,則語法舉例如下:
```
initial
$dumpvar (2, top.module1); //模塊實例top.module1及其下一層的信號將被記錄
```
` `假設模塊top包含信號signal1和signal2(注意是變量而不是子模塊), 如我們希望只記錄這兩個信號,則語法舉例如下:
```
initial
$dumpvar (0, top.signal1, top.signal2); //雖然指定了層次數,但層次數是不影響單獨指定的信號的
//即指定層次數和單獨指定的信號無關
```
` `我們甚至可以在同一個$dumpvar的調用中,同時指定某些層次上的所有信號和某個單獨的信號,假設模塊top包含信號signal1,同時包含有子模塊module1,如果我們不但希望記錄signal1這個獨立的信號,而且還希望記錄子模塊module1以下三層的所有信號,則語法舉例如下:
```
initial
$dumpvar (3, top.signal1, top.module1); //指定層次數和單獨指定的信號無關
//所以層次數3只作用于模塊top.module1, 而與信號
top.signal1無關
```
` `上面這個例子和下面的語句是等效的:
```
initial
begin
$dumpvar (0, top.signal1);
$dumpvar (3, top.module1);
end
$dumpvar的特別用法(不帶任何參數):
initial
$dumpvar; //無參數,表示設計中的所有信號都將被記錄
```
> 最后,我們將$dumpfile和$dumpvar這兩個系統任務的使用方法在下面的例子中綜合說明,假設我們有一個設計實例,名為i\_design,此設計中包含模塊module1,模塊module1下面還有很多層次,我們希望對這個設計進行仿真,并將仿真過程中模塊module1及其以下所有層次中所有信號的變化情況,記錄存儲到名為mydesign.dump的VCD文件中去,則例示如下:
initial
begin
` `$dumpfile ("mydesign.dump"); //指定VCD文件名為mydesign.dump
` `$dumpvar (0, i_design.module1); //記錄i_design.module1模塊及其下面層次中所有模塊的所有信號
end
最后提供一個iverilog搭建好的模板:https://gitee.com/yuan_hp/iverilog_template.git
- 序
- 第1章 Linux下開發FPGA
- 1.1 Linux下安裝diamond
- 1.2 使用輕量級linux仿真工具iverilog
- 1.3 使用linux shell來讀寫串口
- 1.4 嵌入式上的linux
- 設備數教程
- linux C 標準庫文檔
- linux 網絡編程
- 開機啟動流程
- 1.5 linux上實現與樹莓派,FPGA等通信的串口腳本
- 第2章 Intel FPGA的使用
- 2.1 特別注意
- 2.2 高級應用開發流程
- 2.2.1 生成二進制bit流rbf
- 2.2.2 制作Preloader Image
- 2.2.2.1 生成BSP文件
- 2.2.2.2 編譯preloader和uboot
- 2.2.2.3 更新SD的preloader和uboot
- 2.3 HPS使用
- 2.3.1 通過JTAG下載代碼
- 2.3.2 HPS軟件部分開發
- 2.3 quartus中IP核的使用
- 2.3.1 Intel中RS232串口IP的使用
- 2.4 一些問題的解決方法
- 2.4.1 關于引腳的復用的綜合出錯
- 第3章 關于C/C++的一些語法
- 3.1 C中數組作為形參不傳長度
- 3.2 匯編中JUMP和CALL的區別
- 3.3 c++中map的使用
- 3.4 鏈表的一些應用
- 3.5 vector的使用
- 3.6 使用C實現一個簡單的FIFO
- 3.6.1 循環隊列
- 3.7 C語言不定長參數
- 3.8 AD采樣計算同頻信號的相位差
- 3.9 使用C實現棧
- 3.10 增量式PID
- 第4章 Xilinx的FPGA使用
- 4.1 Alinx使用中的一些問題及解決方法
- 4.1.1 在Genarate Bitstream時提示沒有name.tcl
- 4.1.2 利用verilog求位寬
- 4.1.3 vivado中AXI寫DDR說明
- 4.1.4 zynq中AXI GPIO中斷問題
- 4.1.5 關于時序約束
- 4.1.6 zynq的PS端利用串口接收電腦的數據
- 4.1.7 SDK啟動出錯的解決方法
- 4.1.8 讓工具綜合是不優化某一模塊的方法
- 4.1.9 固化程序(雙核)
- 4.1.10 分配引腳時的問題
- 4.1.11 vivado仿真時相對文件路徑的問題
- 4.2 GCC使用Attribute分配空間給變量
- 4.3 關于Zynq的DDR寫入byte和word的方法
- 4.4 常用模塊
- 4.4.1 I2S接收串轉并
- 4.5 時鐘約束
- 4.5.1 時鐘約束
- 4.6 VIVADO使用
- 4.6.1 使用vivado進行仿真
- 4.7 關于PicoBlaze軟核的使用
- 4.8 vivado一些IP的使用
- 4.8.1 float-point浮點單元的使用
- 4.10 zynq的雙核中斷
- 第5章 FPGA的那些好用的工具
- 5.1 iverilog
- 5.2 Arduino串口繪圖器工具
- 5.3 LabVIEW
- 5.4 FPGA開發實用小工具
- 5.5 Linux下繪制時序圖軟件
- 5.6 verilog和VHDL相互轉換工具
- 5.7 linux下搭建輕量易用的verilog仿真環境
- 5.8 VCS仿真verilog并查看波形
- 5.9 Verilog開源的綜合工具-Yosys
- 5.10 sublim text3編輯器配置verilog編輯環境
- 5.11 在線工具
- 真值表 -> 邏輯表達式
- 5.12 Modelsim使用命令仿真
- 5.13 使用TCL實現的個人仿真腳本
- 5.14 在cygwin下使用命令行下載arduino代碼到開發板
- 5.15 STM32開發
- 5.15.1 安裝Atollic TrueSTUDIO for STM32
- 5.15.2 LED閃爍吧
- 5.15.3 模擬U盤
- 第6章 底層實現
- 6.1 硬件實現加法的流程
- 6.2 硬件實現乘法器
- 6.3 UART實現
- 6.3.1 通用串口發送模塊
- 6.4 二進制數轉BCD碼
- 6.5 基本開源資源
- 6.5.1 深度資源
- 6.5.2 FreeCore資源集合
- 第7章 常用模塊
- 7.1 溫濕度傳感器DHT11的verilog驅動
- 7.2 DAC7631驅動(verilog)
- 7.3 按鍵消抖
- 7.4 小腳丫數碼管顯示
- 7.5 verilog實現任意人數表決器
- 7.6 基本模塊head.v
- 7.7 四相八拍步進電機驅動
- 7.8 單片機部分
- 7.8.1 I2C OLED驅動
- 第8章 verilog 掃盲區
- 8.1 時序電路中數據的讀寫
- 8.2 從RTL角度來看verilog中=和<=的區別
- 8.3 case和casez的區別
- 8.4 關于參數的傳遞與讀取(paramter)
- 8.5 關于符號優先級
- 第9章 verilog中的一些語法使用
- 9.1 可綜合的repeat
- 第10章 system verilog
- 10.1 簡介
- 10.2 推薦demo學習網址
- 10.3 VCS在linux上環境的搭建
- 10.4 deepin15.11(linux)下搭建system verilog的vcs仿真環境
- 10.5 linux上使用vcs寫的腳本仿真管理
- 10.6 system verilog基本語法
- 10.6.1 數據類型
- 10.6.2 枚舉與字符串
- 第11章 tcl/tk的使用
- 11.1 使用Tcl/Tk
- 11.2 tcl基本語法教程
- 11.3 Tk的基本語法
- 11.3.1 建立按鈕
- 11.3.2 復選框
- 11.3.3 單選框
- 11.3.4 標簽
- 11.3.5 建立信息
- 11.3.6 建立輸入框
- 11.3.7 旋轉框
- 11.3.8 框架
- 11.3.9 標簽框架
- 11.3.10 將窗口小部件分配到框架/標簽框架
- 11.3.11 建立新的上層窗口
- 11.3.12 建立菜單
- 11.3.13 上層窗口建立菜單
- 11.3.14 建立滾動條
- 11.4 窗口管理器
- 11.5 一些學習的腳本
- 11.6 一些常用的操作語法實現
- 11.6.1 刪除同一后綴的文件
- 11.7 在Lattice的Diamond中使用tcl
- 第12章 FPGA的重要知識
- 12.1 面積與速度的平衡與互換
- 12.2 硬件原則
- 12.3 系統原則
- 12.4 同步設計原則
- 12.5 乒乓操作
- 12.6 串并轉換設計技巧
- 12.7 流水線操作設計思想
- 12.8 數據接口的同步方法
- 第13章 小項目
- 13.1 數字濾波器
- 13.2 FIFO
- 13.3 一個精簡的CPU( mini-mcu )
- 13.3.1 基本功能實現
- 13.3.2 中斷添加
- 13.3.3 使用中斷實現流水燈(實際硬件驗證)
- 13.3.4 綜合一點的應用示例
- 13.4.5 使用flex開發匯編編譯器
- 13.4.5 linux--Flex and Bison
- 13.4 有符號數轉單精度浮點數
- 13.5 串口調試FPGA模板