Verilog HDL 入門

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 在硬件上被設計成導線wire(或輸出引腳output)。
assign y = (s == 0) ? a : b; 這句表示:s如果為0,那么等號左邊就是a,否則就是b。將這個表達式的輸出結果接在輸出引腳 y 上。 這就是一個簡單的Verilog程序,不需要我們去設計與非門,直接表達你的你想要的功能就好了。編譯下載到FPGA硬件,功能就實現了。

assign “導線” = “表達式”(也可以是數值、寄存器等能代表高低電平的量);

上面的2選1數據選擇器,內部實現結構如下:

邏輯門表述

上面的assign語句還可以直接使用邏輯表達式: assign y = (a & (~ s)) | (b & s); 這個表明了門級結構連接關系(數據流描述方式),近乎結構描述

很明顯,這種結構描述比行為描述要費力得多,而且不太容易讀懂程序功能。

來看看行為描述方法:

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后面不能接reg型,只能接wire型前面已經說過了。 為什么不能?因為寄存器的賦值除了需要輸入信號,還需要一個觸發信號(例如:D觸發器),assign?sorry,he can’t。

always @(a, b, s)中,括號里面的輸入信號a,b,s表示敏感信號;這句表示,敏感信號列表中的任何一個信號發生變化,將會引發 begin …… end 之間的行為。 Verilog用begin和end包圍代碼段,相當于c語言中大括號{ }的功能。

always @( ) 是一種固定用法,括號內填寫行為觸發條件。

if(!s) y = a; 這里的“=”,書上叫做“阻塞賦值”,和C語言里的賦值語句意思差不多,使用也差不多。 比如,有這么一段代碼:

input clk;//時鐘信號
reg a,b,c; 

//觸發動作:時鐘上升沿
always@(posedge clk) 
begin  
  b = a;  
  c = b;  
end

那么時鐘上升沿出現后,c的值就等于a,b的值也是a,這個行為在描述的時候,語句先后順序,決定了賦值的先后,值是立即更新的。

Verilog還有一個“非阻塞賦值”,表示方法是 <=,我把這種賦值稱為“并行賦值”,在always@ 代碼塊內書寫時,沒有先后順序。一般用于設計時序邏輯電路,舉個例子:

always@(posedge clk) 
begin  
  b <= a;  
  c <= b;  
end

含義:時鐘上升沿出現前a,b的值,在上升沿結束后分別賦給b,c.

非阻塞賦值“<=”符號,
右側所有變量,代表的是這些變量上升沿前的值,
左側變量表示,上升沿后該變量將要更新為右側表達式的值。

所以,這兩句書寫沒有先后順序,調換次序后表達的含義是一樣的,新寄存器的值是在always塊結束后同時更新的。調換次序后如下,仍然表示同樣的含義:

always@(posedge clk) 
begin  
  c <= b; 
  b <= a;   
end

最后提一句:

阻塞和非阻塞賦值,都只能寫在always@()代碼塊內。
assign后面的=是和assign一起連用的,并不是阻塞賦值。

更詳細的分析,請參考另一篇文章:阻塞賦值和非阻塞賦值

結語

本文使用多種方式描述了一個數據選擇器,來介紹Verilog的基本書寫結構。其間,涉及了一部分語法和關鍵詞:
1、module …… endmodule
2、assign
3、always @( )
4、阻塞賦值 = 非阻塞賦值<=

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • fpga規范 工作過的朋友肯定知道,公司里是很強調規范的,特別是對于大的設計(無論軟件還是硬件),不按照規范走幾乎...
    Michael_Johnson閱讀 1,924評論 1 4
  • form表單有什么作用?有哪些常用的input 標簽,分別有什么作用? 回答:用來提交數據給服務器的。常用的inp...
    Komolei閱讀 178評論 0 0
  • 關于要不要加入讀書營的問題,我說我想得比別人有點多,結果最后的答案是,我參加,因為,思來想去,如果不參加讀書營,我...
    林妖妖的盛夏光年閱讀 241評論 5 13
  • 我喜歡花,不管是荷花、菊花、桂花、茉莉......還是小野花,我都喜歡,我想,既然都是花,為什么一定要分個...
    楊益辰閱讀 129評論 0 0