Verilog讀書筆記---數據類型、系統任務、`define、parameter、localparam三者的區別

本文目的

主要梳理之前學習Verilog的疏漏內容,系統瞭解Verilog語法。

Verilog的數據類型:

Verilog有兩組主要的數據類型:網絡數據類型(Net Data Type)和寄存器數據類型(Register Data Type)。其他的數據類型有:事件(Event)、參數(Parameter)和範圍(Specparam)以及其他數據類型。

Verilog還是用強度值來解決數字電路中不同強度的驅動源之間的賦值衝突
在這裏插入圖片描述
如果兩個具有不同強度的信號驅動同一個線網,則競爭結果值爲高強度信號的值。

如果兩個強度相同的信號之間發生競爭,則結果爲不確定值。

整數、實數和時間寄存器類型

整數

是一種通用的寄存器數據類型,用於對數量進行操作,使用integer進行聲明。

integer counter;       //一般用途的變量用作計數器

initial

     counter = -1;    //把-1存儲到寄存器中

實數:

實常量和實數寄存器數據類型使用關鍵字real來聲明,可以用十進制或科學計數法
來表示。實數聲明不能帶有範圍,其默認值爲0.如果將一個實數賦予一個整數,
那麼實數將會被取爲最接近的整數。

real delta;         //定義一個名爲delta的實型變量

時間寄存器

仿真是按照仿真時間進行的,verilog使用一個特殊的時間寄存器數據類型來保存仿真時間。
時間變量通過使用關鍵字time來聲明,其寬度與具體實現無關,最小爲64位。通過調用系統
函數$time可以取得當前的仿真時間。

數組

Verilog中允許聲明reg、integer、time、real、realtime及其向量類型的數組,對數組的維數沒有
限制,即可聲明任意維數的數組。線網數組也可用於連接實例的端口,數組中的每個元素都可以
作爲一個標量或者向量,以同樣的方式來使用,形如<數組名>[<下標>]。
Integer     count[0:7];       //由八位計數變量組成的數組

reg  bool [31:0];              //由32個1位的布爾寄存器變量組成的數組

wire [7:0] w_array2 [5:0];        //聲明8位向量的數組

注意:不要把數組和線網或寄存器向量混淆起來。向量是一個單獨的元件,它的位寬是n,數組由多個元件組成,其中每個元件的位寬爲n或1.

nets型

wire型數據常用來表示用於以assign關鍵字指定的組合邏輯信號。

Verilog程序模塊中輸入輸出信號類型默認爲wire型。

wire型信號可以用做方程式的輸入,也可以用做”assign”語句或者實例元件的輸出
在這裏插入圖片描述

reg型

reg是寄存器數據類型的關鍵字。

寄存器是數據存儲單元的抽象,通過賦值語句可以改變寄存器存儲的值,其作用相當於改變觸發器存儲器的值。

reg型數據常用來表示always模塊內的指定信號,代表觸發器。

通常在設計中要由always模塊通過使用行爲描述語句來表達邏輯關係。在always塊內被賦值的每一個信號都必須定義爲reg型,即賦值操作符的右端變量必須是reg型

reg型號數據的格式:

reg[n-1:0]數據名1,數據名2,…,數據N;
//定義了N個寄存器變量,每個數據位寬爲n

reg型數據的默認值是不定的。reg型數據可以爲正值或負值。當一個reg型數據是一個表達式中的操作數時,它的值被當做無符號值,即正值(如果一個4位的reg型數據被寫入-1,在表達式中運算時,其值被認爲是+15)

reg型和wire型的區別:reg型保持最後一次的賦值,而wire型需要持續驅動。

Memory型

在這裏插入圖片描述
儘管memory型數據和reg型數據的定義格式很相似,但是要注意不同之處。Memory描繪的是深度,reg描繪的是寬度。

Reg [ n-1:0 ] rega;  //一個n位寄存器

Reg mema [ n-1 ]  //一個由n個一位寄存器組成的存儲器組

       一個n位的寄存器可以在一條賦值語句裏進行賦值。而一個完整的存儲器不行

       Rega = 0;//合法的賦值語句

       Mema=0;//非法的賦值語句

       Mema[3]=0;//合法,給memory中的第三個單元賦值爲0

數組

Verilog中允許聲明reg、integer、time、real、realtime及其向量類型的數組,對數組的維數沒有限制,即可聲明任意維數的數組。線網數組也可用於連接實例的端口,數組中的每個元素都可以作爲一個標量或者向量,以同樣的方式來使用,形如<數組名>[<下標>]。

Integer count[0:7]; //由八位計數變量組成的數組

reg bool [31:0]; //由32個1位的布爾寄存器變量組成的數組

wire [7:0] w_array2 [5:0]; //聲明8位向量的數組

=注意:不要把數組和線網或寄存器向量混淆起來。向量是一個單獨的元件,它的位寬是n,數組由多個元件組成,其中每個元件的位寬爲n或1.==

向量

線網和寄存器類型的數據均可聲明爲向量(位寬大於1)。如果在聲明中沒有指定位寬,則默認爲標量(1位)

wire a;      //標量線網變量,默認

wire [7:0] bus;          //8位的總線

reg clock  ;                 //標量寄存器,默認

reg   [0:40]        virtual_addr;    //向量寄存器,41位寬的虛擬地址

向量通過[high#:low#]進行說明,方括號中左邊的數總是代表向量的最高有效位。

可變向量域選擇

在這裏插入圖片描述

Verilog的系統任務

系統任務也屬於行爲級建模,系統任務的調用要出現在initial與always結構中。所有的任務都已$開頭。

1、display,display,write用於信息的顯示和輸出。

%b或%B 二進制
%o或%O 八進制
%d或%D 十進制
%h或%H 十六進制
%e或%E 實數
%c或%C 字符
%s或%S 字符串
%v或%V 信號強度
%t或%T 時間
%m或%M 層次實例
===
\n 換行
\t 製表符
\ 反斜槓\
" 引號”
%% 百分號%
調用方式:eg:$display("%b+%b=%b",a,b,sum);

                         $write("%b+%b=%b",a,b,sum);

注:如果沒有在指定變量的顯示格式,不會輸出數值。如果沒有指定變量顯示的位置,變量值會在字符串部分之後直接顯示出來,變量之間是沒有間隔的,只是一次簡單的顯示。

顯示任務displaydisplay默認顯示的格式是十進制的,還有displayb,displayo,displayo,displaybh的顯示格式分別是二進制,八進制,十六進制。同理有writewrite,writeo,writebwriteb,writeh。

displaydisplay與write的區別是:displaydisplay會在每次顯示信息後自動換行,write不會換行.

2、$strobe探測任務

探測任務的語法和顯示任務完全相同,也是把信息顯示出來。也有strobe,strobe,strobeb,strobeo,strobeo,strobeh四種。

兩者的區別在於:strobestrobe命令會在當前時間部結束時完成;而display是隻要仿真器看到就會立即執行。

3、$monitor監測任務

監測任務用於持續監測指定變量,只要這些變量發生了變化,就會立即顯示對應的輸出語句,並且在仿真中只能進行一次調用,後面的調用會覆蓋前面的。

eg:

initial begin

$monitor("x=%b,y=%b,cin=%b",x,y,cin);

end

同理,有monitor,monitor,monitorbmonitoromonitoromonitorh。
可用$monitoroff,monitoeron關閉監事和打開監視。

4、stop,stop,finish仿真控制任務
區別:stopstop暫停當前方針,finish終止值當前方針。

`define:作用 -> 常用於定義常量可以跨模塊、跨文件;

                        範圍 -> 整個工程;

parameter:     作用 -> 常用於模塊間參數傳遞;

                       範圍 -> 本module內有效的定義;

localparam       作用 -> 常用於狀態機的參數定義;

                       範圍 -> 本module內有效的定義,不可用於參數傳遞;

                                  localparam cannot be used within the module port parameter list.

2、應用舉例

`define、parameter、localparam三者的區別及舉例

`define

概念:可以跨模塊的定義,寫在模塊名稱上面,在整個設計工程都有效。
           一旦`define指令被編譯,其在整個編譯過程中都有效。例如,通
           過另一個文件中的`define指令,定義的常量可以被其他文件調用,
           直到遇到 `undef;
    舉例:定義 `define UART_CNT 10'd1024
               使用 `UART_CNT

parameter

概念:本module內有效的定義,可用於參數傳遞;
           如果在模塊內部定義時無法進行參數傳遞,
           若在模塊名後照下面這樣寫則可以進行傳遞

舉例:定義

module video_in
           #(
          parameter MEM_DATA_BITS = 64,
          parameter INTERLACE     = 1      // 0
          )
          (
           input     clk,
           input     rst_n,
          
           output    burst_finsh
          );

使用 -> 調用此模塊的時候可以像端口信號傳遞一樣進行參數傳遞

video_in

       #( .MEM_DATA_BITS ( 64 ),
          .INTERLACE     ( 1  )
        )
       u_video_in (
        .clk             (clk_50m),
        .rst_n          (rst_n),
        
        .burst_finsh (burst_finsh)
        );

localparam:

概念:本module內有效的定義,不可用於參數傳遞;
           localparamcannot be used within the module port parameter list.
           一般情況下,狀態機的參數都是用localparam的。

舉例:

 
          localparam BURST_LEN               = 10'd64;     /*一次寫操作數據長度 */
          
          localparam BURST_IDLE              = 3'd0;       /*狀態機狀態:空閒 */
          localparam BURST_ONE_LINE_START    = 3'd1;       /*狀態機狀態:視頻數據一行寫開始 */
          localparam BURSTING                = 3'd2;       /*狀態機狀態:正在處理一次ddr2寫操作 */
          localparam BURST_END               = 3'd3;       /*狀態機狀態:一次ddr2寫操作完成*/
          localparam BURST_ONE_LINE_END      = 3'd4;       /*狀態機狀態:視頻數據一行寫完成*/
          
          reg[2:0]  burst_state              = 3'd0;       /*狀態機狀態:當前狀態 */
          reg[2:0]  burst_state_next         = 3'd0;       /*狀態機狀態:下一個狀態*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章