搭建Modelsim SE模擬環境-使用do檔案模擬
本章我們介紹模擬環境搭建是基於Modelsim SE的。Modelsim有很多版本,比如說Modelsim-Altera,但是筆者還是建議大家使用Modelsim-SE,Modelsim-Altera實際是針對Altera 的OEM版本,它事先將Altera的一些IP核模擬庫新增到了工具中,但功能上有一些縮減。而Modelsim-SE需要自己手動新增這些模擬庫,但是功能更全,而且工作中,工程師更傾向用SE版本,因為今後的FPGA開發中我們會接觸更多其他廠商的FPGA,比如Xilinx、Lattice的,遇到這些FPGA時,我們同樣需要將他們的IP核的模擬庫新增到Modelsim 中。
1.1.1.模擬基本概念
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_even
2. (
3. input i_clk , //模組輸入時鐘 ,50mhz
4. input i_rst_n , //復位訊號,低電平有效
5. outputreg o_clk_div //偶數分頻輸出
6. );
7.
8. parameter DIV_EVEN =10 ; //10分頻,輸入50MHz,輸出頻率為
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分頻。
最後我們總結整個模擬過程中,各個部分之間的關係,如下圖。
1.1.2. 建立Modelsim模擬工程
本節我們介紹如何建立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,這個時間根據具體設計所需時間來決定,再點選旁邊的,執行模擬。這樣我們就可以看到輸出的波形訊號了,從而驗證設計的正確性。
1.1.3. 使用do檔案進行Modelsim模擬
上一節我們介紹了通過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”,即可執行模擬。