FPGA的Veilog?HDL語(yǔ)法、框架總結(jié)
一、基礎(chǔ)知識(shí)
1、邏輯值
邏輯0:表示低電平,也就對(duì)應(yīng)我們電路GND
;邏輯1:表示高電平,也就是對(duì)應(yīng)我們電路的VCC
;邏輯X:表示未知,有可能是高電平,也有可能是低電平;邏輯Z:表示高阻態(tài),外部沒(méi)有激勵(lì)信號(hào),是一個(gè)懸空狀態(tài)
。2、進(jìn)制格式
Verilog數(shù)字進(jìn)制格式包括二進(jìn)制、八進(jìn)制、十進(jìn)制和十六進(jìn)制。一般常用的為二進(jìn)制、十進(jìn)制和十六進(jìn)制。二進(jìn)制表示如下:4b0101表示4位二進(jìn)制數(shù)字0101十進(jìn)制表示如下:4'd2表示4位十進(jìn)制數(shù)字2(二進(jìn)制0010)十六進(jìn)制表示如下:4ha表示4位十六進(jìn)制數(shù)字a(二進(jìn)制1010)16'b1001 1010 1010 1001=16'h9AA93、標(biāo)識(shí)符
標(biāo)識(shí)符(identifier)用于定義模塊名、端口名、信號(hào)名等。標(biāo)識(shí)符可以是任意一組字母、數(shù)字、$符號(hào)和(下劃線)符號(hào)的組合;但標(biāo)識(shí)符的第一個(gè)字符必須是字母或者下劃線;標(biāo)識(shí)符是區(qū)分大小寫的;4、標(biāo)識(shí)符推薦寫法
不建議大小寫混合使用;普通內(nèi)部信號(hào)建議全部小寫;信號(hào)命名最好體現(xiàn)信號(hào)的含義,簡(jiǎn)潔、清晰、易懂;以下是一些推薦的寫法:- 1、用有意義的有效的名字如
sum
、cpu_addr
等。 - 2、用下劃線區(qū)分詞,如
cpu addr
。 - 3、采用一些前綴或后綴,比如時(shí)鐘采用clk前綴:
clk_50
,clk_cpu
;
二、數(shù)據(jù)類型
在Verilog 語(yǔ)言中,主要有三大類數(shù)據(jù)類型。寄存器數(shù)據(jù)類型、線網(wǎng)數(shù)據(jù)類型和參數(shù)數(shù)據(jù)類型。從名稱中,我們可以看出,真正在數(shù)字電路中起作用的數(shù)據(jù)類型應(yīng)該是寄存器數(shù)據(jù)類型和線網(wǎng)數(shù)據(jù)類型。1、寄存器類型
寄存器表示一個(gè)抽象的數(shù)據(jù)存儲(chǔ)單元,通過(guò)賦值語(yǔ)句可以改變寄存器儲(chǔ)存的值寄存器數(shù)據(jù)類型的關(guān)鍵字是reg,reg類型數(shù)據(jù)的默認(rèn)初始值為不定值x。always語(yǔ)句
和initial語(yǔ)句
中被賦值。如果該過(guò)程語(yǔ)句描述的是時(shí)序邏輯,即always語(yǔ)句帶有時(shí)鐘信號(hào),則該寄存器變量對(duì)應(yīng)為觸發(fā)器;如果該過(guò)程語(yǔ)句描述的是組合邏輯,即always語(yǔ)句不帶有時(shí)鐘信號(hào),則該寄存器變量對(duì)應(yīng)為硬件連線;//計(jì)數(shù)器對(duì)系統(tǒng)時(shí)鐘計(jì)數(shù),計(jì)時(shí)0.2秒always?@(posedge?sys_clk?or?negedge?sys_rst_n)?begin
????if?(!sys_rst_n)
????????counter?<=?24'd0;
????else?if?(counter?24'd999_9999)
????????counter?<=?counter? ?1'b1;
????else
????????counter?<=?24'd0;
end
//通過(guò)移位寄存器控制IO口的高低電平,從而改變LED的顯示狀態(tài)
always?@(posedge?sys_clk?or?negedge?sys_rst_n)?begin
????if?(!sys_rst_n)
????????led?<=?4'b0001;
????else?if(counter?==?24'd999_9999)?
????????led[3:0]?<=?{led[2:0],led[3]};
????else
????????led?<=?led;
end
2、線網(wǎng)類型
線網(wǎng)數(shù)據(jù)類型表示結(jié)構(gòu)實(shí)體(例如門)之間的物理連線。線網(wǎng)類型的變量不能儲(chǔ)存值,它的值是由驅(qū)動(dòng)它的元件所決定的。驅(qū)動(dòng)線網(wǎng)類型變量的元件有門、連續(xù)賦值語(yǔ)句、assign等。如果沒(méi)有驅(qū)動(dòng)元件連接到線網(wǎng)類型的變量上,則該變量就是高阻的,即其值為z。線網(wǎng)數(shù)據(jù)類型包括wire型
和tri型
,其中最常用的就是wire類型。3、參數(shù)類型
參數(shù)其實(shí)就是一個(gè)常量,在Verilog HDL中用parameter定義常量。我們可以一次定義多個(gè)參數(shù),參數(shù)與參數(shù)之間需要用逗號(hào)隔開(kāi)。每個(gè)參數(shù)定義的右邊必須是一個(gè)常數(shù)表達(dá)式。三、運(yùn)算符
1、算數(shù)運(yùn)算符
2、關(guān)系運(yùn)算符
3、邏輯運(yùn)算符
4、條件操作符
5、位運(yùn)算符
6、移位運(yùn)算符
7、拼接運(yùn)算符
8、優(yōu)先級(jí)運(yùn)算符
四、模塊結(jié)構(gòu)
Verilog的基本設(shè)計(jì)單元是“模塊"(block)。一個(gè)模塊是由兩部分組成的,一部分描述接口,另一部分描述邏輯功能。時(shí)鐘信號(hào)的上升沿
或者復(fù)位信號(hào)的下降沿到
來(lái),就執(zhí)行begin
與end
之間的代碼。如果產(chǎn)生了復(fù)位信號(hào)(低電平),計(jì)數(shù)器清0,如果計(jì)數(shù)器的值小于10000000,計(jì)數(shù)器的值就 1,如果沒(méi)有產(chǎn)生復(fù)位信號(hào)和計(jì)數(shù)值不小于10000000,計(jì)數(shù)器的值就為0。在這個(gè)always塊中,邏輯是順序執(zhí)行的。第二個(gè)always塊代碼的意思:如果時(shí)鐘信號(hào)的上升沿
或者復(fù)位信號(hào)的下降沿到
來(lái),就執(zhí)行begin
與end
之間的代碼。如果產(chǎn)生了復(fù)位信號(hào)(低電平),led0點(diǎn)亮,如果計(jì)數(shù)器的值小于10000000,led0-3順序點(diǎn)亮,如果沒(méi)有產(chǎn)生復(fù)位信號(hào)和計(jì)數(shù)值不小于10000000,led燈狀態(tài)保持不變。在這個(gè)always塊中,邏輯是順序執(zhí)行的。但是這個(gè)always塊代碼是并行執(zhí)行的,也就是說(shuō)時(shí)鐘信號(hào)一直在產(chǎn)生。功能定義部分有三種方法:- 1、assign語(yǔ)句描述組合邏輯
- 2、always語(yǔ)句描述組合/時(shí)序邏輯
- 3、例化實(shí)例元件
五、結(jié)構(gòu)語(yǔ)句
1、initial和always語(yǔ)句
initial語(yǔ)句它在模塊中只執(zhí)行一次。它常用于測(cè)試文件的編寫,用來(lái)產(chǎn)生仿真測(cè)試信號(hào)(激勵(lì)信號(hào)),或者用于對(duì)存儲(chǔ)器變量賦初值。always 語(yǔ)句一直在不斷地重復(fù)活動(dòng)。但是只有和一定的時(shí)間控制結(jié)合在一起才有作用。initial語(yǔ)句
常用于測(cè)試文件,在測(cè)試文件中初始化使用。比如上面的代碼首先始終信號(hào)初始化為0,之后在always語(yǔ)句中讓其10個(gè)時(shí)鐘周期翻轉(zhuǎn)一次,就達(dá)到了時(shí)鐘的要求。復(fù)位信號(hào)最開(kāi)始為低電平,然后延時(shí)20個(gè)時(shí)鐘周期就拉高。觸摸按鍵信號(hào)最開(kāi)始為低電平,延時(shí)10和時(shí)鐘周期后拉高,再延時(shí)30個(gè)時(shí)鐘周期再拉低,延時(shí)110個(gè)時(shí)鐘周期再拉高,再延時(shí)30個(gè)時(shí)鐘周期再拉低。always的時(shí)間控制可以是沿觸發(fā),也可以是電平觸發(fā);可以是單個(gè)信號(hào),也可以是多個(gè)信號(hào),多個(gè)信號(hào)中間要用關(guān)鍵字or連接。always 語(yǔ)句后緊跟的過(guò)程塊是否運(yùn)行,要看它的觸發(fā)條件是否滿足。2、組合邏輯和時(shí)序邏輯電路
根據(jù)邏輯功能的不同特點(diǎn),可以將數(shù)字電路分成兩大類:組合邏輯電路和時(shí)序邏輯電路。- 組合邏輯電路中,任意時(shí)刻的輸出僅僅取決于該時(shí)刻的輸入,與電路原來(lái)的狀態(tài)無(wú)關(guān)。
- 時(shí)序邏輯電路中,任時(shí)刻的輸出不僅取決于當(dāng)時(shí)的輸入信號(hào),而且還取決于電路原來(lái)的狀態(tài)?;蛘哒f(shuō)還與以前的輸入有關(guān),因此時(shí)序邏輯必須具備記憶功能。
3、賦值語(yǔ)句
Verilog HDL 語(yǔ)言中,信號(hào)有兩種賦值方式1、阻塞賦值(blocking),如b=a2、非阻塞賦值(Non_Blocking),如b<=a3.1、阻塞賦值
阻塞賦值可以認(rèn)為只有一個(gè)步驟的操作:即計(jì)算RHS(左側(cè))并更新LHS(右側(cè))。所謂阻塞的概念是指,在同一個(gè)always塊中,后面的賦值語(yǔ)句是在前一句賦值語(yǔ)句結(jié)束后才開(kāi)始賦值的。module?block_nonblock(Clk,Rst_n,a,b,c,out)??input?Clk;
??input?Rst_n;
??input?a;
??input?b;
??input?c;
??output?reg?[1:0]?out;
//?out?a? ?b? ?c;最大值為3,所以應(yīng)該定義為2位的位寬
//?d?=?a b;
//?out?=?d c;
??reg?[1:0]d;//定義一個(gè)中間變量
always?@(posedge?Clk?or?negedge?Rst_n)
??if?(!Rst_n)
????out?=?2'b0;
??else??begin?
????d???=?a b;
????out?=?d c;
???end
???
endmodule
??input?Clk;
??input?Rst_n;
??input?a;
??input?b;
??input?c;
??output?reg?[1:0]?out;
??reg?[1:0]d;//定義一個(gè)中間變量
always?@(posedge?Clk?or?negedge?Rst_n)
??if?(!Rst_n)
????out?=?2'b0;
??else??begin?????
????out?=?d c;
????d???=?a b;
???end
???
endmodule
3.2、非阻塞賦值
非阻塞賦值的操作過(guò)程可以看作兩個(gè)步驟(1)賦值開(kāi)始的時(shí)候,計(jì)算RHS(左側(cè));(2)賦值結(jié)束的時(shí)候,更新LHS(右側(cè))。所謂非阻塞的概念是指,在計(jì)算非阻塞賦值的RHS以及更新LHS期間,允許其他的非阻塞賦值語(yǔ)句同時(shí)計(jì)算RHS和更新LHS。非阻塞賦值只能用于對(duì)寄存器類型的變量進(jìn)行賦值,因此只能用在initial塊和always塊等過(guò)程塊中。還是用上面的例子module?block_nonblock(Clk,Rst_n,a,b,c,out)??input?Clk;
??input?Rst_n;
??input?a;
??input?b;
??input?c;
??output?reg?[1:0]?out;
??reg?[1:0]d;//定義一個(gè)中間變量
always?@(posedge?Clk?or?negedge?Rst_n)
??if?(!Rst_n)
????out?=?2'b0;
??else??begin?
????d???<=?a b;??
????out?<=?d c;??
???end???
endmodule
生成效果如下:
??input?Clk;
??input?Rst_n;
??input?a;
??input?b;
??input?c;
??output?reg?[1:0]?out;
??reg?[1:0]d;//定義一個(gè)中間變量
always?@(posedge?Clk?or?negedge?Rst_n)
??if?(!Rst_n)
????out?=?2'b0;
??else??begin?
????out?<=?d c;
????d???<=?a b;????
???end???
endmodule
組合邏輯
(電平觸發(fā))的always 塊中用阻塞賦值=
,綜合成組合邏輯的電路結(jié)構(gòu);這種電路結(jié)構(gòu)只與輸入電平的變化有關(guān)系。2、在描述時(shí)序邏輯
(沿觸發(fā))的always 塊中用非阻塞賦值=
,綜合成時(shí)序邏輯的電路結(jié)構(gòu);這種電路結(jié)構(gòu)往往與觸發(fā)沿有關(guān)系,只有在觸發(fā)沿時(shí)才可能發(fā)生賦值的變化。“注意:在同一個(gè)always塊中不要既用非阻塞賦值又用阻塞賦值
不充許在多個(gè)always塊中對(duì)同一個(gè)變量進(jìn)行賦值!因?yàn)樵诙鄠€(gè)always塊中代碼時(shí)并行執(zhí)行的。”一般在設(shè)計(jì)中掌握以下六個(gè)原則,可解決在綜合后仿真中出現(xiàn)絕大多數(shù)的冒險(xiǎn)競(jìng)爭(zhēng)問(wèn)題。1)時(shí)序電路(沿觸發(fā)的always塊)建模時(shí),用非阻塞賦值;2)鎖存器電路建模時(shí),用非阻塞賦值;3)用always塊建立組合邏輯(電平觸發(fā)的always塊)模型時(shí),用阻塞賦值;4)在同一個(gè)always塊中建立時(shí)序和組合邏輯電路時(shí),用非阻塞賦值:5)在同一個(gè)always塊中不要既用非阻塞賦值又用阻塞賦值;6)不要在一個(gè)以上的always塊中為同一個(gè)變量賦值。4、條件語(yǔ)句
條件語(yǔ)句必須在過(guò)程塊中使用。過(guò)程塊語(yǔ)句是指由initial語(yǔ)句和always語(yǔ)句引導(dǎo)的塊語(yǔ)句。4.1 if_else語(yǔ)句
if(la)等同于if(a!=1)
2、
if語(yǔ)句
對(duì)表達(dá)式的值進(jìn)行判斷,若為0,x,z,則按假處理;若為1,按真處理。3、if和else
后面的操作語(yǔ)句可以用begin和end
包含多個(gè)語(yǔ)句。4、允許if語(yǔ)句的嵌套
。4.1 case語(yǔ)句
case語(yǔ)句(多分支選擇語(yǔ)句)1、分支表達(dá)式的值互不相同;2、所有表達(dá)式的位寬必須相等;不能用’bx
來(lái)代替n'bx
3、casez比較時(shí),不考慮表達(dá)式中的高阻值4、casex不考慮高阻值z(mì)和不定值x注意
if_else
需要配對(duì),一個(gè)if語(yǔ)句就應(yīng)該必須有一個(gè)else語(yǔ)句。好處是避免latch產(chǎn)生。latch
是一個(gè)鎖存器,在數(shù)字電路中l(wèi)atch是一個(gè)電平觸發(fā)的存儲(chǔ)器,觸發(fā)器是一個(gè)邊沿觸發(fā)的存儲(chǔ)器。在編寫veilog語(yǔ)句中應(yīng)避免產(chǎn)生無(wú)畏鎖存器,鎖存器只在組合邏輯電路中產(chǎn)成,而鎖存器會(huì)導(dǎo)致電路生成的毛刺比較多,還會(huì)影響我們對(duì)整個(gè)電路的時(shí)序分析。什么樣的情況下會(huì)產(chǎn)生這個(gè)鎖存器呢?首先在組合邏輯電路中,如果我們有if語(yǔ)句
但是沒(méi)有相應(yīng)的else語(yǔ)句
,他就有可能產(chǎn)生鎖存器。第二點(diǎn),比如case語(yǔ)句,如果我們的case語(yǔ)句沒(méi)有給完全,沒(méi)有列舉完所有應(yīng)該的產(chǎn)生的case語(yǔ)句,就應(yīng)該寫一個(gè)default
,否則也會(huì)生成一個(gè)鎖存器。-END-
|?整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有?|
|?如有侵權(quán),請(qǐng)聯(lián)系刪除?|
往期好文合集(點(diǎn)擊下劃線跳轉(zhuǎn)閱讀)
知乎熱議:嵌入式開(kāi)發(fā)中C 好用嗎?
知乎超熱門話題:為什么要考985?
知乎:硬件和軟件哪個(gè)吃香??