Verilog HDL 快速入門

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Alexanderrr/article/details/51615463

Verilog HDL 快速入門

Verilog HDL是一種硬件描述語言(HDL:Hardware Description Language),它是以文本形式來描述數字系統硬件的結構和行爲的語言。 世界上最流行的兩種硬件描述語言是Verilog HDL和VHDL。

注意,VerilogHDL是一種描述語言,它和常見的編程語言C有根本的不同。C語言,讓計算機的CPU從上往下按順序執行每一條指令,執行完程序就結束了。

而,VerilogHDL主要是描述了一個數字模塊的結構,或者行爲。有點像商業合同,合同裏面也會描述產品的結構,產品的功能等等。合同的每一個條款,並不需要嚴格的先後順序,只要把項目的方方面面都考慮完整,寫下來就OK了。VerilogHDL也是這樣。

我們用VerilogHDL描述數字模塊的功能,剩下的交給編譯器(如,Quartus),編譯器會根據我們的要求設計重構FPGA內部硬件。對於大批懶人來說,這技術簡直碉堡了。這就是EDA(Electronic Design Automation,電子設計自動化)。


好,下面就來認識一下VerilogHDL
我們先設計一個“數據選擇器”:
s是數據選擇控制端,
a,b是輸入信號,y是輸出信號
這裏寫圖片描述
代碼如下:

module mux2_1(a, b, s, y); //模塊名、模塊接口名
    input a, b, s;        // 定義輸入端口
    output y;              // 定義輸出端口

    /* s爲0時,選擇a輸出;
        s爲1時,選擇b輸出。*/  
    assign y = (s == 0) ? a : b;  //輸出信號
endmodule

每個Verilog文件中都有一個module 開始,endmodule 結束的代碼塊。
這個代碼塊的定義了一個名字叫 mux2_1 的模塊,模塊名後面緊跟的括號內寫明瞭該模塊的接口信號,相當於數字器件的引腳。
但是括號內沒有說明接口的信號方向,所以緊跟着另起一行用inputoutput 再說明一下。註釋和C語法一樣,可以用// 或 /* */ 。
assign 是Verilog的關鍵詞,書上稱爲連續賦值。我一般把他視爲“連線”操作,assign後面的緊跟的 y 在硬件上是一根導線(或輸出引腳)。
assign  y = (s == 0) ? a : b;
這句話的意思是:s如果爲0,那麼等號左邊就是a,否則就是b。將這個表達式的輸出結果接在輸出引腳 y 上。
這就是一個簡單的Verilog程序,不需要我們去設計與非門,直接表達你的你想要的功能就好了。然後,編譯下載到FPGA,功能就實現了。

要注意的是,assign 後面永遠跟着一個 =,它們是一起使用的。
即,assign xx = zz;


上面的2選1數據選擇器,內部實現結構如下:
這裏寫圖片描述
所以,上面的assign語句還可以這樣寫,直接使用邏輯表達式:
assign y = (a & (~ s)) | (b & s);
這個是在門級對邏輯關係進行描述,所以不屬於行爲描述,算是結構描述吧。下面這種描述方式,叫做門原語,算結構描述。這裏的關鍵詞wire 表示電路中的導線(信號線)。

module mux2_1(a, b, s, y);
    input a, b, s;
    output y;
    wire ns, as, bs;

    not(ns, s);//這裏使用了一個非門,輸出是ns,輸入是s
    and(as, a, ns);//使用一個與門,輸出as,輸入a和ns
    and(bs, b, s);//使用與門,輸出bs,輸入b和s
    or(y, as, bs);//使用或門,輸出y,輸入as和bs
endmodule

看,這是告訴我們電路中有什麼元器件,又是怎麼連接的,所以這個屬於結構描述。
很明顯,有時候結構描述比行爲描述要費力得多,而且不太容易理解程序功能。
另外,上面的這個程序中,這4個邏輯門的順序,可以隨便寫,不用管先後順序。


這個數據選擇器,還可以使用如下行爲描述方法:

module mux2_1(a, b, s, y);
    input a, b, s; 
    output y; 
    reg  y; //reg 表示寄存器

    always @(a, b, s)
    begin
        if(!s) y = a;
        else y = b;
    end
endmodule

這裏reg表示寄存器(存儲器),需要提醒一下的是,assign後面只能接wire型,不能接reg型。(當然output從物理上也是wire)
爲什麼不能?因爲寄存器的賦值除了需要輸入信號,還需要觸發信號(例如D觸發器寄存器),assign?sorry,he can’t。

always @(a, b, s)中,括號裏面的輸入信號a,b,s表示敏感信號。
always @( ) 是連在一起使用的。
這句話的意思是,敏感信號列表中的任何一個信號發生變化,將會引發
begin …… end 之間的行爲。
Verilog用begin和end包圍代碼段,相當於c語言中的大括號{ }的功能。
if(!s) y = a;
這裏的“=”單獨使用,叫做“阻塞賦值”。我把他理解爲“串行賦值”。
比如,有這麼一段代碼:
b=a;
c=b;
那麼最後,c的值就等於a,這個行爲在描述的時候,語句的先後順序,決定了賦值的先後。
在Verilog中,和它對應的還有一個“非阻塞賦值”,表示方法是 <=,我把這種賦值稱爲“並行賦值”。具體區別,請參考另一篇短文阻塞賦值和非阻塞賦值


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章