因為參與的新項目需要用fpga,所以自己學了一下verilog語言。整理一些比較基礎的內容。
verilog程序最重要的結構就是模塊module,它在形式上與c語言的函數很像,但是由於verilog是面向硬件的語言,因此在設計思想上與c語言是有一定的差別的。
一個verilog模塊通常必須有的變量:clk時鍾,rst置位,input輸入,output輸出
下面是一些verilog中常用的聲明。
Parameter常量
Wire輸入輸出信號缺省時默認是wire,是assign關鍵字指定的組合邏輯信號
Wire [n:1] a1,...,ai 每個總線有n個線路,共i個總線
Reg 在always塊里的指定信號,常代表觸發器寄存器
Reg[4:1] a 一個4位的名為a的reg信號 編號從1到4由低位到高位
Reg變量可以是正數或負數,但是在運算時視為正數
如果需要中間賦值或運算,需聲明成reg類型
一個verilog模塊的主要結構如下
Module 模塊名(端口列表); Wire reg 和其他類型聲明; Assign數據流聲明; Always initial塊,行為語句 #verilog中各個always塊都是並行執行的,不存在誰先誰后的關系 ... 任務和函數... ... Endmodule
always @(posedge clk) #上升沿到來時觸發
verilog數據常量定義:
數字表達式:<位寬><進制><數字>
'b:二進制 4'b1110 表示4位二進制數1110
'h:十六進制 8'hef、4'ha
'd:十進制 2'd3、4'd15(不能寫16,4位寬最大15)等
頂層程序調用底層module和c語言函數格式類似,通過module定義的端口傳遞參數,但是使用思想不同。
模組類名 實例名(端口變量)
端口變量盡量書寫規范
.a(A) #.模組定義端口變量(實際變量)
Case語句的本質是分支比較,兩個值的比較,若分支和case后面的值相等則運行相應分支語句,因此case后面的值可以是常值。
verilog文件開頭一般有timescale
`timescale 仿真時間單位/時間精度
verilog基本運算:
verilog有兩種賦值符號分別是<=和=。
<=是非阻塞賦值,在always塊完成后才賦值;
=是阻塞賦值,賦值完成后才進入下一句;
一般時序邏輯用<=,組合邏輯用=。
~ 按位取反 比如:11110 取反后為00001
!邏輯取反 ,如!非0 為0 !0 為1
&&:代表邏輯與。
&:代表與門運算(按位與)。
^異或處理,對一個變量里面1的個數是奇數偶數的判斷,偶數為0,奇數為1
實際是對該變量相鄰位逐一求異或。
1 組合邏輯:
組合邏輯的特點是任意時刻的輸出僅僅取決於該時刻的輸入,與電路原本的狀態無關,邏輯中不牽涉跳變沿信號的處理,組合邏輯的verilog描述方式有兩種:
(1):always @(電平敏感信號列表)
always模塊的敏感列表為所有判斷條件信號和輸入信號,但一定要注意敏感列表的完整性。在always 模塊中可以使用if、case 和for 等各種RTL 關鍵字結構。由於賦值語句有阻塞賦值和非阻塞賦值兩類,建議讀者使用阻塞賦值語句“=”。always 模塊中的信號必須定義為reg 型,不過最終的實現結果中並沒有寄存器。這是由於在組合邏輯電路描述中,將信號定義為reg型,只是為了滿足語法要求。
(2):assign描述的賦值語句。
信號只能被定義為wire型。
2 時序邏輯:
時序邏輯是Verilog HDL 設計中另一類重要應用,其特點為任意時刻的輸出不僅取決於該時刻的輸入,而且還和電路原來的狀態有關。電路里面有存儲元件(各類觸發器,在FPGA 芯片結構中只有D 觸發器)用於記憶信息,從電路行為上講,不管輸入如何變化,僅當時鍾的沿(上升沿或下降沿)到達時,才有可能使輸出發生變化。
與組合邏輯不同的是:
(1)在描述時序電路的always塊中的reg型信號都會被綜合成寄存器,這是和組合邏輯電路所不同的。
(2)時序邏輯中推薦使用非阻塞賦值“<=”。
(3)時序邏輯的敏感信號列表只需要加入所用的時鍾觸發沿即可,其余所有的輸入和條件判斷信號都不用加入,這是因為時序邏輯是通過時鍾信號的跳變沿來控制的。
(*keep = "true"*)
有時候在chipscope中很難找到你預期的信號,這往往是被綜合器優化掉了,或者更改了信號名.有效的方法是在源代碼中加上約束語句,這樣就不用對代碼做大的改動.
fifo:
Fist in first out。先入先出的數據緩存器,沒有外部讀寫地址線,可同時讀寫。
同步FIFO和異步FIFO。
同步FIFO只有一個時鍾,也就是說寫端和讀端的時鍾是一樣的。
異步FIFO讀端和寫端兩個時鍾則是不一樣的。包括同頻異相,異頻異相。
FIFO用途:
數據緩沖器。比如你寫端burst一個數據,沒有fifo緩沖的話就炸了。Fifo會把寫端的突發數據緩存,讀端可以慢慢的讀出來。
跨時鍾域。異步fifo主要使用在不同時鍾域的邊緣,用來同步數據到另一個時鍾域。
對於異步讀寫時鍾不同的fifo需要求fifo深度,深度是寫需要的時間內讀端沒有讀完的數據量(word),下面是在網上找到的一個比較好的解釋fifo深度的例子