今天給大俠帶來的是一周掌握FPGA Verilog HDL 語法,今天開啟第五天。
上一篇提到了case語句、循環(huán)語句(forever、repeat、while、for)、結(jié)構(gòu)說明語句(initial、always、task、 function)等,此篇我們繼續(xù)來看編譯預(yù)處理,結(jié)合實例理解理論語法,會讓你理解運用的更加透徹。下面咱們廢話就不多說了,一起來看看吧。
編譯預(yù)處理
Verilog HDL語言和C語言一樣也提供了編譯預(yù)處理的功能?!熬幾g預(yù)處理”是Verilog HDL編譯系統(tǒng)的一個組成部分。Verilog HDL語言允許在程序中使用幾種特殊的命令(它們不是一般的語句)。Verilog HDL編譯系統(tǒng)通常先對這些特殊的命令進行“預(yù)處理”,然后將預(yù)處理的結(jié)果和源程序一起在進行通常的編譯處理。
在Verilog HDL語言中,為了和一般的語句相區(qū)別,這些預(yù)處理命令以符號“ `”開頭(注意這個符號是不同于單引號“ '”的)。這些預(yù)處理命令的有效作用范圍為定義命令之后到本文件結(jié)束或到其它命令定義替代該命令之處。Verilog HDL提供了以下預(yù)編譯命令:
`accelerate,`autoexpand_vectornets,`celldefine,`default_nettype,`define,`else,`endcelldefine,`endif,`endprotect,`endprotected,`expand_vectornets,`ifdef,`include,`noaccelerate,`noexpand_vectornets , `noremove_gatenames , `noremove_netnames ,`nounconnected_drive , `protect , `protecte , `remove_gatenames , `remove_netnames ,`reset,`timescale,`unconnected_drive
在這里只對常用的`define、`include、`timescale進行介紹,其余的請自行查閱資料。
宏定義 `define
用一個指定的標(biāo)識符(即名字)來代表一個字符串,它的一般形式為:
`define 標(biāo)識符(宏名) 字符串(宏內(nèi)容)
如:`define signal string
它的作用是指定用標(biāo)識符signal來代替string這個字符串,在編譯預(yù)處理時,把程序中在該命令以后所有的signal都替換成string。這種方法使用戶能以一個簡單的名字代替一個長的字符串,也可以用一個有含義的名字來代替沒有含義的數(shù)字和符號,因此把這個標(biāo)識符(名字)稱為“宏名”,在編譯預(yù)處理時將宏名替換成字符串的過程稱為“宏展開”。`define是宏定義命令。
例1:
`define WORDSIZE 8 module reg[1:`WORDSIZE] data;//這相當(dāng)于定義 reg[1:8] data; ……
關(guān)于宏定義的八點說明:
1) 宏名可以用大寫字母表示,也可以用小寫字母表示。建議使用大寫字母,以與變量名相區(qū)別。
2) `define命令可以出現(xiàn)在模塊定義里面,也可以出現(xiàn)在模塊定義外面。宏名的有效范圍為定義命令之后到原文件結(jié)束。通常,`define命令寫在模塊定義的外面,作為程序的一部分,在此程序內(nèi)有效。
3) 在引用已定義的宏名時,必須在宏名的前面加上符號“`”,表示該名字是一個經(jīng)過宏定義的名字。
4) 使用宏名代替一個字符串,可以減少程序中重復(fù)書寫某些字符串的工作量。而且記住一個宏名要比記住一個無規(guī)律的字符串容易,這樣在讀程序時能立即知道它的含義,當(dāng)需要改變某一個變量時,可以只改變 `define命令行,一改全改。如例1中,先定義WORDSIZE代表常量8,這時寄存器data是一個8位的寄存器。如果需要改變寄存器的大小,只需把該命令行改為:`define WORDSIZE 16。這樣寄存器data則變?yōu)橐粋€16位的寄存器。由此可見使用宏定義,可以提高程序的可移植性和可讀性。
5) 宏定義是用宏名代替一個字符串,也就是作簡單的置換,不作語法檢查。預(yù)處理時照樣代入,不管含義是否正確。只有在編譯已被宏展開后的源程序時才報錯。
6) 宏定義不是Verilog HDL語句,不必在行末加分號。如果加了分號會連分號一起進行置換。如:
例2:
moduletest; reg a, b, c, d, e,out; `defineexpression a+b+c+d; assignout=`expression+e; ... endmodule
經(jīng)過宏展開以后,該語句為:
assign out = a+b+c+d;+e;
顯然出現(xiàn)語法錯誤。
7) 在進行宏定義時,可以引用已定義的宏名,可以層層置換。如:
例3:
moduletest; reg a, b, c; wireout; `defineaa a+b `definecc c+`aa assignout=`cc; endmodule
這樣經(jīng)過宏展開以后,assign語句為:
assign out = c + a + b;
8) 宏名和宏內(nèi)容必須在同一行中進行聲明。如果在宏內(nèi)容中包含有注釋行,注釋行不會作為被置換的內(nèi)容。如:
例4:
module `define typ_nand nand #5//define a nand with typical delay `typ_nandg121(q21,n10,n11); ……… endmodule
經(jīng)過宏展開以后,該語句為:
nand #5 g121(q21,n10,n11);
宏內(nèi)容可以是空格,在這種情況下,宏內(nèi)容被定義為空的。當(dāng)引用這個宏名時,不會有內(nèi)容被置換。
注意:組成宏內(nèi)容的字符串不能夠被以下的語句記號分隔開的。
注釋行
數(shù)字
字符串
確認符
關(guān)鍵詞
雙目和三目字符運算符
如下面的宏定義聲明和引用是非法的。`define first_half "start of string$display(`first_half end of string");
注意在使用宏定義時要注意以下情況:
1) 對于某些 EDA軟件,在編寫源程序時,如使用和預(yù)處理命令名相同的宏名會發(fā)生沖突,因此建議不要使用和預(yù)處理命令名相同的宏名。
2) 宏名可以是普通的標(biāo)識符(變量名)。例如signal_name 和 'signal_name的意義是不同的。但是這樣容易引起混淆,建議不要這樣使用。
“文件包含”處理`include
所謂“文件包含”處理是一個源文件可以將另外一個源文件的全部內(nèi)容包含進來,即將另外的文件包含到本文件之中。Verilog HDL語言提供了`include命令用來實現(xiàn)“文件包含”的操作。其一般形式為:如下圖1
上圖表示“文件包含”的含意。(a)為文件File1.v,它有一個`include "File2.v"命令,然后還有其它的內(nèi)容(以A表示)。(b)為另一個文件File2.v,文件的內(nèi)容以B表示。在編譯預(yù)處理時,要對`include命令進行“文件包含”預(yù)處理:將File2.v的全部內(nèi)容復(fù)制插入到 `include "File2.v"命令出現(xiàn)的地方,即File2.v 被包含到File1.v中,得到(c)所示的結(jié)果。在接著往下進行的編譯中,將“包含”以后的File1.v作為一個源文件單位進行編譯。
“文件包含”命令是很有用的,它可以節(jié)省程序設(shè)計人員的重復(fù)勞動??梢詫⒁恍┏S玫暮甓x命令或任務(wù)(task)組成一個文件,然后用`include命令將這些宏定義包含到自己所寫的源文件中,相當(dāng)于工業(yè)上的標(biāo)準(zhǔn)元件拿來使用。另外在編寫Verilog HDL源文件時,一個源文件可能經(jīng)常要用到另外幾個源文件中的模塊,遇到這種情況即可用`include命令將所需模塊的源文件包含進來。
例1:(1)文件aaa.v
moduleaaa(a,b,out); input a, b; outputout; wireout; assignout= a^b; endmodule(2)文件bbb.v
`include"aaa.v" modulebbb(c,d,e,out); input c,d,e; outputout; wire out_a; wireout; aaaaaa( .a(c), .b(d), .out(out_a) ); assignout=e&out_a; endmodule
在上面的例子中,文件bbb.v用到了文件aaa.v中的模塊aaa的實例器件,通過“文件包含”處理來調(diào)用。模塊aaa實際上是作為模塊bbb的子模塊來被調(diào)用的。在經(jīng)過編譯預(yù)處理后,文件bbb.v實際相當(dāng)于下面的程序文件bbb.v:
moduleaaa(a,b,out); input a, b; outputout; wireout; assignout= a ^ b; endmodule
modulebbb(c, d, e,out); input c, d, e; outputout; wire out_a; wireout; aaaaaa( .a(c), .b(d), .out(out_a) ); assignout= e & out_a; endmodule
關(guān)于“文件包含”處理的四點說明:
1) 一個`include命令只能指定一個被包含的文件,如果要包含n個文件,要用n個`include命令。注意下面的寫法是非法的`include"aaa.v""bbb.v"
2) `include命令可以出現(xiàn)在Verilog HDL源程序的任何地方,被包含文件名可以是相對路徑名,也可以是絕對路徑名。例如:'include"parts/count.v"
3) 可以將多個`include命令寫在一行,在`include命令行,只可以出空格和注釋行。例如下面的寫法是合法的。 'include "fileB" 'include "fileC" //including fileB and fileC
4) 如果文件1包含文件2,而文件2要用到文件3的內(nèi)容,則可以在文件1用兩個`include命令分別包含文件2和文件3,而且文件3應(yīng)出現(xiàn)在文件2之前。例如在下面的例子中,即在file1.v中定義:
`include"file3.v" `include"file2.v" moduletest(a,b,out); input[1:`size2] a, b; output[1:`size2]out; wire[1:`size2]out; assignout= a+b; endmodule
file2.v的內(nèi)容為:
`define size2 `size1+1 . . .
file3.v的內(nèi)容為:
`define size1 4 . . .
這樣,file1.v和file2.v都可以用到file3.v的內(nèi)容。在file2.v中不必再用 `include "file3.v"了。
5) 在一個被包含文件中又可以包含另一個被包含文件,即文件包含是可以嵌套的。例如上面的問題也可以這樣處理,見下圖2、圖3。
它的作用和下圖,圖3的作用是相同的。
時間尺度 `timescale
`timescale命令用來說明跟在該命令后的模塊的時間單位和時間精度。使用`timescale命令可以在同一個設(shè)計里包含采用了不同的時間單位的模塊。例如,一個設(shè)計中包含了兩個模塊,其中一個模塊的時間延遲單位為ns,另一個模塊的時間延遲單位為ps。EDA工具仍然可以對這個設(shè)計進行仿真測試。
`timescale 命令的格式如下:
`timescale<時間單位>/<時間精度>
在這條命令中,時間單位參量是用來定義模塊中仿真時間和延遲時間的基準(zhǔn)單位的。時間精度參量是用來聲明該模塊的仿真時間的精確程度的,該參量被用來對延遲時間值進行取整操作(仿真前),因此該參量又可以被稱為取整精度。如果在同一個程序設(shè)計里,存在多個`timescale命令,則用最小的時間精度值來決定仿真的時間單位。另外時間精度至少要和時間單位一樣精確,時間精度值不能大于時間單位值。
在`timescale命令中,用于說明時間單位和時間精度參量值的數(shù)字必須是整數(shù),其有效數(shù)字為1、10、100,單位為秒(s)、毫秒(ms)、微秒(us)、納秒(ns)、皮秒(ps)、毫皮秒(fs)。這幾種單位的意義說明見下表。
下面舉例說明`timescale命令的用法。
[例1]: `timescale 1ns/1ps
在這個命令之后,模塊中所有的時間值都表示是1ns的整數(shù)倍。這是因為在`timescale命令中,定義了時間單位是1ns。模塊中的延遲時間可表達為帶三位小數(shù)的實型數(shù),因為 `timescale命令定義時間精度為1ps.
[例2]:`timescale 10us/100ns
在這個例子中,`timescale命令定義后,模塊中時間值均為10us的整數(shù)倍。因為`timesacle 命令定義的時間單位是10us。延遲時間的最小分辨度為十分之一微秒(100ns),即延遲時間可表達為帶一位小數(shù)的實型數(shù)。
例3:
`timescale10ns/1ns moduletest; regset; parameterd=1.55; initial begin #dset=0; #dset=1; end endmodule
在這個例子中,`timescale命令定義了模塊test的時間單位為10ns、時間精度為1ns。因此在模塊test中,所有的時間值應(yīng)為10ns的整數(shù)倍,且以1ns為時間精度。這樣經(jīng)過取整操作,存在參數(shù)d中的延遲時間實際是16ns(即1.6×10ns),這意味著在仿真時刻為16ns時寄存器set被賦值0,在仿真時刻為32ns時寄存器set被賦值1。仿真時刻值是按照以下的步驟來計算的。
1) 根據(jù)時間精度,參數(shù)d值被從1.55取整為1.6。
2) 因為時間單位是10ns,時間精度是1ns,所以延遲時間#d作為 時間單位的整數(shù)倍為16ns。
3) EDA工具預(yù)定在仿真時刻為16ns的時候給寄存器set賦值0 (即語句 #d set=0;執(zhí)行時刻),在仿真時刻為32ns的時候給 寄存器set賦值1(即語句 #d set=1;執(zhí)行時刻),
注意:如果在同一個設(shè)計里,多個模塊中用到的時間單位不同,需要用到以下的時間結(jié)構(gòu)。
1) 用`timescale命令來聲明本模塊中所用到的時間單位和時間精度。
2) 用系統(tǒng)任務(wù)$printtimescale來輸出顯示一個模塊的時間單位和時間精度。
3) 用系統(tǒng)函數(shù)$time和$realtime及%t格式聲明來輸出顯示EDA工具記錄的時間信息。
條件編譯命令`ifdef、`else、`endif
一般情況下,Verilog HDL源程序中所有的行都將參加編譯。但是有時希望對其中的一部分內(nèi)容只有在滿足條件才進行編譯,也就是對一部分內(nèi)容指定編譯的條件,這就是“條件編譯”。有時,希望當(dāng)滿足條件時對一組語句進行編譯,而當(dāng)條件不滿足時則編譯另一部分。
條件編譯命令有以下幾種形式:
1)
`ifdef 宏名 (標(biāo)識符) 程序段1
`else
程序段2
`endif
它的作用是當(dāng)宏名已經(jīng)被定義過(用`define命令定義),則對程序段1進行編譯,程序段2將被忽略;否則編譯程序段2,程序段1被忽略。其中`else部分可以沒有,即: 2)
`ifdef 宏名 (標(biāo)識符)
程序段1
`endif
這里的 “宏名” 是一個Verilog HDL的標(biāo)識符,“程序段”可以是Verilog HDL語句組,也可以是命令行。這些命令可以出現(xiàn)在源程序的任何地方。
注意:被忽略掉不進行編譯的程序段部分也要符合Verilog HDL程序的語法規(guī)則。
通常在Verilog HDL程序中用到`ifdef、`else、`endif編譯命令的情況有以下幾種:
? 選擇一個模塊的不同代表部分。
? 選擇不同的時序或結(jié)構(gòu)信息。
? 對不同的EDA工具,選擇不同的激勵。
總結(jié)
Verilog HDL的語法與C語言的語法有許多類似的地方,但也有許多不同的地方。我們學(xué)習(xí)Verilog HDL語法要善于找到不同點,著重理解如:阻塞〔Blocking〕和非阻塞〔Non-Blocking〕賦值的不同;順序塊和并行塊的不同;塊與塊之間的并行執(zhí)行的概念;task和function的概念。Verilog HDL還有許多系統(tǒng)函數(shù)和任務(wù)也是C語言中沒有的如:$monitor、$readmemb、$stop等等,而這些系統(tǒng)任務(wù)在調(diào)試模塊的設(shè)計中是非常有用的,我們只有通過閱讀大量的Verilog調(diào)試模塊實例,經(jīng)過長期的實踐,經(jīng)常查閱理論知識才能逐步掌握。
Day 5 就到這里,到這里,經(jīng)過五天的Verilog HDL基礎(chǔ)語法的學(xué)習(xí),基本語法差不多都在這里了,從Day 6 繼續(xù)開始,最后兩天將推出思考題(附參考答案),大俠可以自行思考,檢測一下自己這一周的語法學(xué)習(xí)效果,大俠保重,告辭。
-
FPGA
+關(guān)注
關(guān)注
1638文章
21859瀏覽量
609797 -
Verilog
+關(guān)注
關(guān)注
28文章
1360瀏覽量
111100 -
C語言
+關(guān)注
關(guān)注
180文章
7622瀏覽量
139068 -
HDL語言
+關(guān)注
關(guān)注
0文章
48瀏覽量
9022
原文標(biāo)題:一周掌握FPGA Verilog HDL語法 day 5
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術(shù)江湖】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
深入理解FPGA Verilog HDL語法(一)
深入理解FPGA Verilog HDL語法(二)
[下載]cpld\fpga\verilog hdl視頻教程
FPGA-Verilog HDL語法參考
FPGA雙沿發(fā)送之Verilog HDL實現(xiàn) 精選資料推薦
FPGA雙沿采樣之Verilog HDL實現(xiàn) 精選資料分享
Verilog_HDL的基本語法詳解(夏宇聞版)

評論