Verilog HDL
由于該語言與C語言比較接近,因此在FPGA的學習里面我先選擇學習它,在后面如果有時間還需要學習VDHL。而且國內一般用Verilog用的比較多。
它具有一下的描述能力:設計的行為特性、設計的數據流特性、設計的結構組成、包含響應監控和設計驗證方面的時延和波形產生機制。
基礎
標識符
可以由任意順序的字母、數字、美元符號和下劃線組成,但第一個字符不能是數字或者美元符號,只能是字符或下劃線,因為以美元符開始的標識符與系統的保留字沖突。
并且大小寫相關,關鍵詞全部小寫。
轉義標識符:與C中一致。
空白符:包括空格(\b)、制表符(\t)、換行和分頁符(\n)。它們出現在字符串里面不可忽略,其他時候都會編譯為分隔標識符,在編譯階段被忽略。

注釋:1.單行注釋:// 2.多行注釋/* … */
關鍵字包括關鍵字、系統任務、編譯指令。
數據類型
邏輯值
與我們一般理解的不一樣,在VerilogHDL語言中,有四個邏輯值:0、1、X、Z。
X:代表邏輯不確定
Z:代表高阻懸浮態。
在16進制基數中代表4位,在8進制中代表3位,在2進制中代表1位
在 Verilog 語言約定的常數表示中,間 號 “?” 是 z 的另一種表示- 使用間號的目的在于增強
casex 和 casez 語旬的可讀性。在這兩條語 旬中,"?” ( 即高阻抗)表示“不必關心 ”的 情況 斗
強度等級
為了解決數字電路中不同強度驅動源之間的賦值沖突引入了強度值的概念:
驅動為supply,strong,pull,weak,強度依次遞減
存儲為Large\Medium\Small依次遞減
Highz(高阻)在整個強度中等級最低
在各種類型的線網中,只 有 trireg 類型的線網可以具有存儲強度。
線網
表示硬件單元之間的連接,線網由其連接器件的輸出端連續驅動。如線網a
在Verilog中的線網包括:wire(默認) tri tri0 supply0 wand triand tril supply1 wor trior trireg uwire. wire作為一般的電路連線,而剩下的幾種用于構建總線,即多個驅動源連到一條線網的情況,或搭建電源、接地等。
線網與實際電線比較線,是連續賦值的,由賦值符右側的驅動源決定,在初始化前值為x(trireg類型的相當于一個寄存器),未賦值時相當于z。
寄存器
不需要驅動源、也不需要像硬件寄存器那樣需要時鐘信號。關鍵詞位reg,默認值是x
它和線網的區別是可以保存當前的數值,直到另一個數值被賦值給它。給它賦值必須在一個過程中進行。這與我們一般認為的寄存器不是完全一樣的概念。
需要注意的是:在兩個模塊的信號連接點,提供信號的一方可以是寄存器或者線網,但是接收信號的一方必須是線網。并且,在**過程(always\initial)**中進行賦值的一定是寄存器類型,而連續賦值的一定是線網類型。
數字表示
<位寬>’<進制><數值>:4’b1111
進制:b\o\d\h
位寬默認32 ;進制默認十進制 ;負號加最前面即可
有時候位數較長:12’b1111_0011_1110,下劃線的存在方便顯示。
有時候數字的表示會用到?,它是“z”的另一種表示,可以增強casex和casez語句的可讀性。
x/z:在二進制中表示1位,在8進制中表示3位,在16進制中表示4位。
向量表示
位寬大于1的網線或者寄存器類型的量就是向量。如:
reg[3:0] c;這樣就可以使用向量的分量如:
c[3] 、c[2:0]等等。·
向縣通過[high# : low#]或{low#: high#]進行說明,方括號中左邊的數總是代表向量的最高有效位。在調用時要保持一致。
可變向量域的選擇:
[ +: width]: 從起始位開始遞增, 位寬為w idth 。
[-: width]: 從起始位開始遞減, 位寬為 w idth 心
其他類型
除 re g 類型之外, Verilog 還支持 inte g e r , re a l (類似浮點數)和 tim e 寄存器數據類型。
整數默認位寬為PC機的位數。 $time可以得到當前的仿真時間。時間聲明如下:
time save_sim_time
但是雖然單位表示相同,其對應關系需要用戶自定義
數組
可以聲明reg、integer、time、real、realtime及其向量類型的數組,定義時在后面加上位數即可,如:
reg [7:0] meme[255:0]
參數
參數代表常數。不能像變量那么賦值。但是每次在實例化時可以重載。通過模塊實例化或使用 defparam 語句改變參數值。但localparam不能重載。
全局常數:parameter
局部常數:localparam
如:
parameter msa=7;
字符串
與C一樣,“adcd…”
字符串是由雙引號括起來的一個字符隊列_,對于字符串的限制是,它必須在一行中書寫完, 不能書寫在多行中,即 不能包 含回車符 。 Verilog 將宇符串當做一個單字節的ACSII 字符隊列。
字符串保存在 reg 類型的變蜇 屯 每個字符占用 8 位(一個字節 )勺因此寄存器變量的寬度
應足夠大 , 以保證容納全部字符。如果寄存器變世的寬度大于字符串的 大小(位), 則 Verilog使用 0 來填充左邊的空余位 ;如 果寄存器變星的寬度小于字符串的大小(位 ), 則
Verilog 截去字符串最左邊的位 因此呵在聲明保存字符串的 reg 變量時, 其位寬應當比字符串的位長稍大。
存儲器量
在數字電路仿真中,人們常常需要對寄存器文件, RAM 和 ROM 建模。在 Verilog 中.使用
寄存器的一維數組來表示存儲牲。數組的每個元素稱為一個元素或一個字( word )氣由一個數組索引來指定, 每個宇的位寬 為 1 位或多位。注意 n個1位寄存器和一個n位寄存器是不同的尸如果需要訪間存儲器中的一個特定的字令則可以通過將字的地址作為數組的下標來完成
。
系統任務和編譯指令
系統任務
也稱系統函數,包括屏幕顯示、
線網值動態監視,暫停和結束仿真等 所有的系統任務都具有$ <keyword> 的形式。
$display(p1,p1,…),它會自動在末尾插入一個換行符。
$monitor(p1,p1,…)可以監視,只需要調用一次可一直使用。
$stop:用來暫停仿真以檢查信號 如 #100 $stop
$finish:用來結束仿真
編譯指令
用法:’<keyword>
'define:宏定義
'define S $stop
'include:
使用 inc lude 可以在諞譯期間將一個 Verilog 源文件包含在另一個 Verilog 文件中今作用類似于 C 語言中的# include 結構。 該指令通常用于將內含全局或公用定義的頭文件包含在設計文件:
'include header.v
還有常用的’ifdef 和’timescale
運算符
模塊和端口
模塊
在Verilog HDL 的編程中,總是需要將復雜的功能自頂而下進行模塊化設計。
如
模塊名:區分大小寫,多個模塊時模塊名稱要唯一
端口列表:按上述代碼中模塊命令格式寫就行(過去可以是先定義名稱,再定義端口(括號后面,每一個以分號結尾))
端口聲明:如上面代碼一樣是和端口列表放在一起的。
關鍵字一般默認為unsigned。
上述代碼為帶有參數的模塊聲明,這樣在例化的的時候可以不用重新定義模塊的位寬。
端口
端口是模塊與外界環境交互的接口.例如 IC 芯片的輸人,輸出引腳就是它的端口。對于外部環境來講,模塊內部是不可見的,對模塊的調用(實例引用)只能通過其端口進行。這種特點 為設計者提供了很大的靈活性:只要接口保持不變,模塊內部的修改并不會影響到外部環境::我們也常常將端口稱為終端 ( terminal )。端口類型及其聲明:
在 Verilog 中, 所有的端口隱含地聲明為wire 類型, 因此如果希望端口具有wire 數據類型.將其聲明為三種類型之一即可;如果輸出類型的端口需要保存數值,則必須將其顯式地聲明為reg類型。需要注意輸入端口不能聲明為reg類型。
端口的連接規則
要注意相應的位寬匹配。有未連接端口時也需要空出相應的端口定義位。
模塊的例化
- 端口連接規則:就是按兩個連接點連接時的端口定義規則進行
- 位寬匹配:模塊的內外部位寬最好匹配
- 未連接端口:允許有未連接
- 端口和外部信號的連接:1.按順序 2.按名字
(下面代碼特指調用的那一行,括號里面的是新的連接名)
add_sub add_sub_01(clk_01 ,ret_m_01 ,....);按名字
add_sub add_sub_02(.clk (clk_01) ,.ret_m (ret_m_01) ,....);帶參數模塊的例化
add_sub #(.DATAWIDTH(16) ) add_sub_03(clk_01 ,ret_m_01 ,....);層次命名
在前面的章節中 ,我們講述了如何使用 Verilog 進行層次化設計。每一個模塊實例、信號或變量都使用一個標識符進行定義; 在整個設計層次中.每個標識符都具有惟一的位置3 層次命名允許設計者在整個設計中通過惟一的名字表示每個標識符0 層次名由一連串使用 “,”
分隔的標識符組成,每個標識符代表一個層次令這樣設計者就可以在設計中的任何地方通過指定完整的層次名 對每個標識符進行訪問。
過程語句initial和always
initial只運行一次
always如果沒有遇到$finish將不斷執行
過程賦值
initial/always @ (posedge 。。。)
過程賦值有兩種:阻塞賦值"=“和非阻塞賦值”<="
在順序代碼塊中使用阻塞賦值,如果這一語句沒有完成后面的語句不會執行,但如果使用非阻塞,相當于"同時進行".
數據流:
對寄存器變量連續賦值:使用assign和force關鍵字即可.
對線網變量的連續賦值:用assign
assign y=a&b;
時序控制
- 延時時序控制:用一個**#**表示,如:
#5 x=3
表示等待5個系統周期后開始賦值
z=#10 (x+y)
先計算再賦值
- 事件時序控制
關鍵字為 @,同樣的,需要根據@所在的位置來判斷執行和延時的順序。 - 電平敏感時序控制:wait(a),等到a為true,執行后面的語句
順序和并行
begin...end fork ... in條件語句(未寫完)
if…else if…else結構
case結構
任務和函數
任務:相當于C中的子過程,不帶返回值,任務中的賦值的變量只能是寄存器類型,而且只能用過程賦值語句。可以調用函數和任務。通過task聲明。
函數:相當于C中的子函數,帶返回值,不能包含時序結構,只有一個邏輯功能,只能調用函數。通過function聲明。
如果任務或函數同時在多個地方被調用,則需要使用automatic.
系統任務
帶有 $ 符號,可以用來執行一些系統設計所需的輸入、輸出、時序檢查、仿真控制操作。如:
$display 用于顯示指定的字符串,然后自動換行(類似c語言printf)
$monitor 用于監視變量,一旦被監視變量發生變化,會顯示指定的字符串
$time 提取可以提取當前的仿真時間。
編譯指令
`<keyword…>,如:
`define
阻塞與非阻塞
必須在 過程 initial 和 always中進行
總結
以上是生活随笔為你收集整理的Verilog HDL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 潮位标识物笔记
- 下一篇: 手写操作系统之helloOS