本章咱們介紹仿真環境搭建是基於Modelsim SE的。Modelsim有不少版本,好比說Modelsim-Altera,可是筆者仍是建議你們使用Modelsim-SE,Modelsim-Altera實際是針對Altera 的OEM版本,它事先將Altera的一些IP核仿真庫添加到了工具中,但功能上有一些縮減。而Modelsim-SE須要本身手動添加這些仿真庫,可是功能更全,並且工做中,工程師更傾向用SE版本,由於從此的FPGA開發中咱們會接觸更多其餘廠商的FPGA,好比Xilinx、Lattice的,遇到這些FPGA時,咱們一樣須要將他們的IP核的仿真庫添加到Modelsim 中。函數
FPGA的仿真實際就是一個驗證設計的過程,驗證在「模擬的輸入」的狀況下,設計文件的輸出是否和咱們指望是一致的。這裏的「模擬的輸入」就是「測試激勵」,設計文件就是待測設計,最終經過對輸出結果的分析來驗證設計的正確性。這就構成了仿真的三個基本組成部分:測試激勵(Test_bench)、待測設計(DUT)和最終結果的輸出驗證。工具
上面介紹可能仍是有些抽象,咱們經過一個簡單的仿真例子來介紹仿真中的各個部分。你們打開咱們的例程《05_clk_div_even》。測試
待測設計(DUT):首先看src文件夾下的clk_div_even.v就是咱們待測設計(DUT)。這個比較好理解,就是咱們設計的模塊。這是一個偶數分頻的例子,每次計數從0-4,計數5次,計數器clk_div_cnt會清零一次,同時輸出分頻信號o_clk_div翻轉一次,這樣每五個時鐘週期,輸出信號都會翻轉一次,十個時鐘週期後又恢復到初始狀態,使得輸出信號10分頻。這裏你們須要額外關注一下這個模塊的輸入和輸出,輸入未來是咱們激勵信號進來的地方。優化
1. module clk_div_evenspa
2. (設計
3. input i_clk , //模塊輸入時鐘 ,50mhz3d
4. input i_rst_n , //復位信號,低電平有效code
5. outputreg o_clk_div //偶數分頻輸出orm
6. );blog
7.
8. parameter DIV_EVEN =10 ; //10分頻,輸入50MHz,輸出頻率爲5Mhz
9. reg [3:0]clk_div_cnt ; //分頻計數器
10.//-------------------------------------------------------------------
11.// 分頻計數器,每次計數到N-1時歸零
12.//-------------------------------------------------------------------
13. always @ (posedge i_clk ornegedge i_rst_n)
14. begin
15. if(!i_rst_n)
16. clk_div_cnt <=4'd0;
17. else if(clk_div_cnt ==DIV_EVEN/2-1)
18. clk_div_cnt <=4'd0;
19. else
20. clk_div_cnt <=clk_div_cnt + 4'd1;
21. end
22.//-------------------------------------------------------------------
23.// 分頻計數器,每次計數N/2-1時,輸出分頻信號翻轉
24.//-------------------------------------------------------------------
25. always @ (posedge i_clk ornegedge i_rst_n)
26. begin
27. if(!i_rst_n)
28. o_clk_div <=1'b0;
29. else if(clk_div_cnt ==DIV_EVEN/2-1)
30. o_clk_div <=~o_clk_div;
31. end
32.endmodule
測試激勵(Testbench):Testbench是FPGA仿真的關鍵,Testbench能夠理解爲一個激勵產生器。你們能夠看到咱們的待測設計的輸入是i_clk和i_rst_n,實際在開發板上,板子上的晶振輸出50MHz激勵時鐘信號給FPGA,一樣電路中的復位電路給FPGA提供了i_rst_n的激勵信號。在仿真過程當中,Testbench就代替了實際的電路,經過Verilog模擬實現這些外部電路的激勵信號,提供給DUT,從而經過輸出驗證設計。工程目錄的sim文件夾下的tb_clk_div_even.v 就是咱們已經編寫好的Testbench。以下就是一個基本Testbench的設計。
下面從上圖所示5個部分介紹Testbench基本寫法。
1、`timescale 1ns/1ps 決定整個仿真中的時間單位信息,在文件中任何關於時間的信息都是基於此的,1ns表示仿真中的基本時間單位,1ps則表示仿真精度能夠達到1ps。例如 #10.005表示的就是延時10.005ns。實際仿真中,精度是能夠控制到0.005ns的,即5ps。
2、tb_clk_div_even() 是實際testbench的名稱,一樣用module定義,可是注意testbenc是沒有端口描述的,這與咱們待測文件DUT是不同的。
3、激勵信號和輸出信號的定義,細心的同窗應該能夠看出,激勵信號就是咱們DUT文件的輸入,輸出信號也就是咱們DUT文件的輸出。不一樣的是在Testbench中,咱們將激勵信號定義爲reg類型,輸出信號定義爲了wire類型。
4、第四部分就是產生激勵信號,具體詳細實現咱們就不介紹了,你們能夠閱讀咱們的文檔《Testbench經常使用語法及技巧》,閱讀以後這個地方就很容易理解了。
5、最後一部分是待測設計的實例化,在FPGA設計中,模塊的實例化就相似C語言中的函數調用,咱們在其餘模塊中調用當前模塊時,就須要以實例化的方式來實現。不一樣的是,Verilog文件模塊實例化時,咱們須要標明每個端口信號。在咱們設計的Testbench中,經過模塊實例化,將咱們的激勵信號最終傳遞給了待測設計文件。
輸出驗證:下圖是咱們仿真的最終輸出的波形文件,能夠看出輸出信號o_clk_div是輸入信號i_clk的10分頻。
最後咱們總結整個仿真過程當中,各個部分之間的關係,以下圖。
本節咱們介紹如何創建Modelsim仿真工程,瞭解Modelsim仿真工具的使用。
第一步:打開Modelsim SE,點擊菜單欄「File—>New—>Project」,準備新建工程。
第二步:彈出「Create Project」對話框,按下圖填寫仿真工程名稱,以及工程的存儲路徑,以及默認庫的的名稱,這裏默認庫名爲「work」,咱們一般叫做工做庫。設置好後點擊OK。
這裏介紹一下庫的概念,即library。庫是Modelsim仿真的載體,Modelsim會將仿真工程中的設計文件(DUT)和激勵文件(Testbench)的編譯(Compile)結果存放在work庫中,在咱們新建工程的時候就會帶着生成一個work庫,以下圖在Modelsim工做區,選擇Library選項卡,咱們能夠看到生成的work庫,此時work庫是空的,由於咱們尚未添加並仿真設計文件和激勵文件。
第三步:新建或添加設計文件,這裏咱們已經寫好的testbench和待測模塊,因此選擇直接添加已存在文件便可。
第四步:依次添加testbench和待測模塊文件。
第五步:編譯咱們的DUT和Testbench文件,以下圖在工做區域選擇Project選項卡,右鍵選擇Compile—>Compile All,編譯全部。
第六步:切回到Library,此時再看work庫就不是空的了,work庫裏的clk_div_even和tb_clk_div_even分別是tb_clk_div_even.v(Testbench)和clk_div_even.v(DUT)的編譯結果。選中Testbench仿真結果tb_clk_div_even,右鍵—>Simulate without Optimization,啓動無優化仿真。
第七步:彈出仿真波形窗口(wave窗口),可是窗口內沒有任何信號波形,工做區域多了一個sim選項卡,進入sim選項頁,能夠看到仿真實例clk_div_even和tb_clk_div_even。選擇相應的實例,右鍵—>add wave,添加信號到wave窗口。
第八步:切到wave 窗口,以下圖,設置仿真運行時間爲100us,這個時間根據具體設計所需時間來決定,再點擊旁邊的,運行仿真。這樣咱們就能夠看到輸出的波形信號了,從而驗證設計的正確性。
上一節咱們介紹了經過Modelsim創建仿真工程的方法,可是這種方法咱們須要使用界面操做,這樣會很費時很麻煩。這裏咱們介紹一種快捷的方法,經過do文件快速搭建仿真環境,只須要雙擊批處理文件modelsim_run.bat,就能夠自動調用Modelsim,並自動完成對Testbench和待驗證設計文件的編譯和仿真,而且能夠自動將要觀察的信號添加到wave窗口。
首先打開「02_Project_Examples\05_clk_div_even\sim」文件夾,能夠看到以下文件。
咱們主要介紹一下前兩個文件,最後一個是咱們的testbench:
modelsim_run.bat文件:這是一個批處理文件,裏面就一行「modelsim -do sim.do」,這是一條DOS命令,意思就是調用Modelsim工具,並在Modelsim工具中執行sim.do這個文件。
sim.do:do文件是由tcl腳本語言編寫的,這個參考例程中的do文件是最基本的tcl腳本語言。下面介紹一下關鍵腳本語言的用法。如下是do文件的內容。
1. vlib work
2. vlog ../sim/*.v
3. vlog ../src/*.v
4. vsim-t ns -novopt +notimingchecks work.tb_clk_div_even
5. radix hex
6. addwave -position insertpoint sim:/tb_clk_div_even/clk_div_even_inst/*
7. run -all
vlib work:創建work庫,至關於在上一節中新建工程時所生成的work庫,後期咱們編譯的結果信息存放到work庫中。
vlog ../sim/*.v:vlog至關於modelsim工具中的compile,「../sim/*.v 」表示編譯05_clk_div_even\sim路徑下全部的verilog文件。vlog ../src/*.v表示編譯05_clk_div_even /src/路徑下的全部verilog文件。
vsim -t ns -novopt +notimingchecks work.tb_clk_div_even:編譯完成全部verilog文件後,就要啓動仿真了,vsim就是啓動仿真功能,vsim後面有許多關鍵詞,這裏簡單說明一下,-t表示仿真時間單位爲ns,-novopt表示仿真時無優化,+notimingchecks表示無時序檢查,work.tb_clk_div_even表示對work庫中的tb_clk_div_even進行仿真,實際至關於在界面操做時,展開work庫,右鍵—>Simulate without Optimization,啓動仿真。
radix hex :表示要添加wave窗口的信號,以16進制的顯示。
add wave–position insertpoint sim:/tb_clk_div_even/clk_div_even_inst/*:表示將clk_div_even_inst中的全部信號添加到wave窗口中去,執行這句之後,咱們每次仿真時,就不用每次都手動去添加仿真波形了。可是這句話實際是Modelsim生成的,不須要咱們本身編寫。最開始咱們寫的do文件是不包含這條語句的,當咱們運行到以下圖狀態時,選擇要添加的信號,右鍵—>add wave後,下面的腳本窗口會彈出相應操做的tcl腳本語句。這樣咱們把這條語句賦值到咱們的do文件中便可。第二次再調用sim.do文件時,就不用再手動添加波形了。
run –all : 運行全過程。固然也能夠運行一段時間。run 10us 表示運行10us。
掌握這些最基本的tcl腳本,使用do文件仿真會爲咱們節省不少時間。後續的教程裏咱們都會默認以這種方式進行仿真。固然這裏只是介紹了最基本的仿真腳本語言,從此咱們仿真時可能還會有第三方的IP核文件,如altera的PLL、FIFO、RAM等須要添加到仿真用例中,這些咱們後面在介紹IP核使用時會給你們介紹如何利用do文件仿真含有IP核的設計。
如今咱們能夠體驗一下do文件仿真所用的時間,雙擊「modelsim_run.bat」,便可運行仿真。