FPGA學(xué)習(xí)筆記day3
modelsimSE、PE、LE、OEM,不同的版本,前三個是最高版本,編譯速度最快。
操作流程:創(chuàng)建工程,添加代碼,編譯,啟動仿真器,運行仿真
tb文件(testbench)
關(guān)鍵字:

對于大型設(shè)計,例如百萬門級的設(shè)計驗證,工程師需要使用一整套規(guī)范的驗證工具
對較小的設(shè)計,使用HDL Testbench的仿真器是沒問題的

然后學(xué)習(xí)怎么寫testbench
新建一個.v文件
上來先建立一個時鐘:
'timescale 1ns/1ns;
'timescale是個關(guān)鍵字,后面的兩個數(shù)字,前面那個是時間長度,后面那個是時間精度。
但是時鐘實際上還需要下面的語句處理一下。always #10 sys_clk=~sys_clk。
module uart_loopback_top_tb;
reg sys_clk;
reg sys_rst_n;
reg uart_txd;
wire uart_txd;
這里面的reg都是輸入信號,wire都是輸出信號。
always #10 sys_clk=~sys_clk
意思是每隔10個1ns,sysclk就取反一次。這樣一來其周期就變成了20ns。所以也就有了一個50Mhz的晶振。時鐘在這里確定完了。
集中學(xué)習(xí)一下FPGA串口波特率與系統(tǒng)時鐘的關(guān)系:
FPGA系統(tǒng)有一個自己的時鐘,比方說有個50mhz的晶振。1/50mhz,所以周期為20ns。
波特率,以9600為例。就是一秒鐘傳送9600個bit。這個傳輸數(shù)據(jù)的周期就是1/9600=104167ns。這就是傳輸一個bit所需要的時間,即傳輸周期。
波特率分頻計數(shù)值:104167/20=5208
因為系統(tǒng)時鐘一般是通過計數(shù)器來實現(xiàn)的,在每個上升沿或者下降沿的時候計數(shù)+1,所以這個5208就是系統(tǒng)時鐘經(jīng)過5208次計數(shù)之后達(dá)到了104167ns
具體關(guān)系如下:

然后搞復(fù)位信號
initial begin
sys_clk<=1'b0;
sys_rst_n<=1'b0;
uart_rxd<=1'b1;
這里設(shè)置其為1的主要原因在于,rxd必須在不工作的時候拉高,需要傳輸數(shù)據(jù)時,給一個低電平,產(chǎn)生一個下降沿。下降沿被捕獲之后再傳輸數(shù)據(jù),所以初始化的時候其值應(yīng)保持為高電平。
#100 sys_rst_n<=1'b1;
然后開始傳輸數(shù)據(jù)
#10 uart_rxd<=1'b0; 這里電平掉下來,產(chǎn)生一個下降沿
#8680?uart_rxd<=1'b1;
#8680?uart_rxd<=1'b0;
#8680?uart_rxd<=1'b1;
#8680?uart_rxd<=1'b0;
#8680?uart_rxd<=1'b1;
#8680?uart_rxd<=1'b0;
#8680?uart_rxd<=1'b0;
#8680?uart_rxd<=1'b1;這八個是傳輸了10101001這個數(shù)據(jù),一共八位
為什么是8680呢
因為這個板子的時鐘是20ns周期,也就是50mhz晶振。波特率設(shè)置為115200了,那么50m/115200=434.
也就是說434個時鐘周期,傳送一個bit。一個時鐘周期20ns,434×20=8680.所以這個數(shù)字是這么來的。8680ns傳送一個bit,一共八位,那就需要8個8680.
#10 uart_rxd<=1'b1;
最后這個就是停止位。表示一個八位的數(shù)據(jù)傳送完畢。把rxd重新拉高。
end
然后最后一步就是需要將設(shè)計模塊“例化”
例化設(shè)計模塊的代碼(模板)長這樣:

flow_led是模塊名,后面那個u0名字隨便起,不重要。
里面的三個信號,左側(cè)帶點的信號為模塊定義的端口信號,右側(cè)括號里面的信號是激勵模塊中定義的信號。(就是剛才自己設(shè)置的reg什么的)這兩個的名字可以重復(fù)。但不是一個含義。命名一致的好處在于便于理解激勵模塊和被測模塊信號之間的對應(yīng)關(guān)系。在實例化被測模塊之后,就可以以endmodule結(jié)束了。
這篇文章很不錯,收藏一下
(14條消息) TestBench基本寫法與語法詳解_testbench怎么寫_ZHE980121的博客-CSDN博客
所以最后整個testbench文件代碼長這樣:
‘timescale 1ns/1ns;
module uart_loopback_top_tb;
reg sys_clk;
reg sys_rst_n;
reg uart_rxd;
wire uart_txd;
initial begin
sys_clk? ?<=1'b0;
sys_rst_n <=1'b0;
uart_rxd? <=1'b1;
#10 uart_rxd<=1'b0;
#8680 uart_rxd<=1'b1;
#8680 uart_rxd<=1'b0;
#8680 uart_rxd<=1'b0;
#8680 uart_rxd<=1'b1;
#8680 uart_rxd<=1'b1;
#8680 uart_rxd<=1'b1;
#8680 uart_rxd<=1'b0;
#8680 uart_rxd<=1'b1;
uart_rxd? <=1'b1;
end
always #10 sys_clk=~sys_clk;
uart_loopback_top uart_loopback_top_u(
.sys_clk? ?(sys_clk),
.sys_rst_n (sys_rst_n),
.uart_rxd? (uart_rxd),
.uart_txd? (uart_txd)
)
endmodule
然后來學(xué)習(xí)怎么使用modelsim
打開之后的界面長這樣:

這軟件比較尷尬的一點就是路徑不可以改變。這個東西的路徑是定死的,比如在c盤做的東西放到d盤可能就不行了。所以這里有一個選項是:
change directory


然后創(chuàng)建新工程

建議命名的時候和testbench文件的名字一致

進去之后找個空白地方單擊右鍵,可以找到這個:

可以創(chuàng)建新文件,或者添加已有文件,或者創(chuàng)建仿真
只需要把quartus工程下的tb文件以及rtl文件里面的.v文件都添加進來

添加完了長這樣,右擊是可以選擇edit修改,改完記得保存
下一步:對這些文件進行編譯

compile selected選中哪個編譯哪個
compile all全編譯

編譯通過之后就可以進行仿真了


design比較常用,下邊這個使能優(yōu)化,enable ooptimization要去掉
設(shè)置成這樣就行了

然后ok,就開始了

然后右鍵單擊仿真文件,添加到仿真波形:

然后就能看到波形了,這里看不到是因為沒有跑起來

在這里可以設(shè)置這個運行時間,可以看到更多的波形
右邊的按鈕就是運行、連續(xù)運行、暫停、等等

然后點一下就可以看到波形了

左側(cè)的東西都是信號名字,然后可以對一對時間:


這里甚至可以對一對數(shù)據(jù),是不是自己發(fā)送的那個數(shù)據(jù)

成功咧
今天先到這里。明天啃書。