ModelSim入门及Testbench编写——合理利用仿真才是王道
在入職之前曾自學了一段時間的Verilog,后來因為工作的緣故鮮有接觸,就擱置下來了。后來因偶然的機會需要參與一個CPLD的小項目,又開始從零學起,有些諷刺的是,不知道如何入手工具的我又回到EDN上翻之前自己寫的博文,才重新熟悉了Quartus的使用流程。現在得了些空閑,最重要的是有了些許想法,終于重新打起精神來料理一個博客。
重溫了基本的Quartus操作和語法后,需要對手頭的工作進行仿真驗證,這時候抖去塵土才發現世界已變,Quartus 9.x自帶的Vector Waveform已經淘汰掉了,所以又硬著頭皮來學ModelSim。預備工作在上篇文章中介紹了,不再累述。
現在就開始一步步入手ModelSim,并通過與Quartus無縫銜接實現仿真。本文使用了ModelSim10.0c + QuartusII 10.0,其他版本基本雷同,請自行研究。
看不清圖的點開看大圖!
1.設置第三方EDA工具
在Tools -> Options中設置ModelSim的安裝路徑,注意要設置到win32文件夾(64位軟件對應的就是win64)。
?
建立一個工程(依然以加法器為例)。在Assignments -> Settings中設置仿真工具為ModelSim。這樣Quartus就能無縫調用ModelSim了。
?
當然也可以在建立工程的時候就設置仿真工具。
?
2.編寫Testbench
說到Testbench,你可以叫它Testbench,或者Testbenches,但不是Test Bench。說起來,就連Quartus也沒注意這個問題,至于原因嘛參見Common Mistakes In Technical Texts一文。文章中還列舉了些別的錯誤用語,包括Flip-flop不能寫成Flipflop,等等。文章鏈接:
http://www.sunburst-design.com/papers/Technical_Text_Mistakes.pdf
?
我們可以通過Quartus自動生成一個Testbench的模板,選擇Processing -> Start -> Start Test Bench Template Writer,等待完成后打開剛才生成的Testbench,默認是保存在simulation\modelsim文件夾下的.vt格式文件。?
?
打開vt文件后可以看到Quartus已經為我們完成了一些基本工作,包括端口部分的代碼和接口變量的聲明,我們要做的就是在這個做好的模具里添加我們需要的測試代碼。
一個最基本的Testbench包含三個部分,信號定義、模塊接口和功能代碼。
‘timescale 1ns/ 1ps表示仿真的單位時間為1ns,精度為1ps。想要進行仿真首先要規定時間單位,而且最好在Testbench里面統一規定時間單位,而不要在工程代碼里定義,因為不同的模塊如果時間單位不同可能會為仿真帶來一些問題,而timescale本身對綜合也就是實際電路沒有影響。
?
其實Testbench本身可以看做一個模塊或者設備(本例中的模塊名為add_vlg_tst),和你自己編寫的模塊進行通信。通過Testbench模塊向待測模塊輸出信號作為激勵,同時接收從待測模塊輸出的信號來查看結果。因此,在待測模塊中的reg型信號在Testbench中就變成了wire,待測模塊中的wire型信號在Testbench中則對應為reg型。那么inout怎么辦呢,inout型信號也要設成wire,同時要用一個reg型信號作為輸出寄存器,同時設置一個三態門,由一個使能信號控制,如:assign?inout_sig = out_en ? out_reg : 1’bz;
?
處理完接口和聲明之后,需要自己設置一些激勵信號,激勵信號的內容就是肯能會輸入到待測模塊中的波形。下面我們就來寫一個簡單的測試程序。
首先需要一個復位信號:
initial
begin
?? rst_n = 0;
?? #100 rst_n = 1;
end
initial開頭的這個過程在Testbench中只執行一次,#100表示延時了100個時間單位,我們之前已經通過timescale進行了設置,這里延時了100ns。這就有點類似于C語言了,代碼通過延時被順序執行,rst_n在0時刻為低電平(也就是邏輯0),100ns后變成高電平,從而形成了一個上電復位。
?
其次是時鐘,使用always模塊來完成:
initial
begin
?? mclk = 0;
end
?
always
begin
#10 mclk = ~mclk;
end
always模塊中的代碼會不斷重復執行,利用這個特點,每10ns翻轉一次mclk,只是這樣還不行,還要給mclk一個初值,就是上面的initial語句。如此便可以生成一個周期為20ns,頻率50MHz的方波信號,作為本例的系統時鐘。
?
當然,這個時鐘也可以通過initial模塊實現。只需添加一個while(1),即死循環。
initial
begin
mclk = 0;
???while(1)
#10 mclk = ~mclk;
end
Testbench中的很多操作都是不可綜合的,同時它的風格也可以比較隨意。
?
設置完時鐘和復位,就需要設置輸入信號:
initial
begin
?? a_in = 1;
?? b_in = 3;
?? #200 a_in = 2;
?? b_in = 0;
?? #200 a_in = 3;
?? b_in = 3;
end
注意這里a_in = 1和b_in = 3是同時發生的,也就是并行的,之后延時200ns,a_in = 2同時b_in = 0,如前面所說,想要實現順序操作,就需要使用延時,如果兩個語句間沒有延時,就表示同時執行。還有一點,這個initial語句塊和負責復位的initial語句塊也是并行的,并且都是從0時刻開始。也就是說,0時刻后經過100ns rst_n復位,再經過100ns(從0時刻起),a_in = 2被執行。
至此,測試程序也完成了,讓我們開始仿真吧
?
3.設置Quartus并調用仿真工具
運行仿真之前,還要設置一下。在Simulation選項卡中配置仿真選項,可以配置仿真語言、仿真時間的格式以及輸出目錄。選中mpile test bench,點擊Test Benches打開Test Benches對話框。
?
點擊New新建一個Test BenchSetting,填入Testbench模塊的名稱(這里是add_vlg_tst),酌情設置仿真運行的時間(這里設為800ns,只是進入ModelSim后仿真自動執行的時間,不設或隨意設置也行),并將剛才編寫的Testbench添加進來。
?
一路OK后,選擇Tools -> Run EDA Simulation Tools,有兩個選項,RTL Simulation是RTL行為級仿真,只驗證功能是否正確,與在哪個芯片上運行無關,仿真前至少需要執行一次Analysis&Synthesis;Gate Level Simulation是門級仿真,涉及到具體的芯片,并且仿真前需要編譯工程,在門級仿真中ModelSim會將布局布線后的門級延時體現在波形中,在測試一個具體的工程模塊時,應當先進行RTL仿真,之后還要進行門級仿真。
?
4.ModelSim工具的基本操作
運行RTL Simulation進入ModelSim界面。在這里介紹幾個比較重要的部分。
在view菜單中,可以顯示和隱藏各種工具窗口。其中Structure窗口顯示了測試模塊和待測模塊的結構:
?
點擊不同的模塊,在Objects窗口中可以查看選中模塊中的信號,因為除了端口(port)以外,還有很多內部信號默認是不顯示波形的,通過將需要的信號拖到Wave窗口中,就能夠顯示。
?
工具欄中的??部分是用來控制仿真運行的,左側紅框中的是復位,在文本框里設置要執行的時間,點擊右側紅框中的按鈕就可以執行了。其他的請自行摸索或參看Help文件。
如果面對一大堆0101感覺很暈,可以在信號列表里選中信號,右鍵選擇要顯示的數據格式。
而Wave窗口的左下角有幾個小按鈕,是用來設置游標的,通過添加游標,可以測量相應的時間,也可以在這里配置時間刻度的格式。
在Wave波形圖中,使用滾輪和鼠標右鍵可以很方便的縮放或選擇波形區域,下圖就是這個全加器工程的波形圖,在復位之后,c_out的值等于a_in與b_in的和,并在時鐘上升沿輸出。
總結
以上是生活随笔為你收集整理的ModelSim入门及Testbench编写——合理利用仿真才是王道的全部內容,希望文章能夠幫你解決所遇到的問題。