零基礎教你學FPGA之Verilog語法基礎(中)

2021-02-13 電子技術應用ChinaAET

我們接著上篇文章繼續學習,上次提到了兩種賦值語句,讓我們接著往下學。

  1、塊語句

  塊語句包括兩種,一個是順序塊,一個是並行塊。

  (1)順序快

  順序快就好比C語言裡的大括號「{ }」,在Verilog語法中,用begin…end代替。這裡只需要知道,在begin…end中間的語句是順序執行的就行了。

  (2)並行塊

  並行塊可以算是一個新的知識點,與順序塊最大的不同就是並行塊中的語句是同時開始執行的,要想控制語句的先後順序,可以加延時語句控制。這種並行塊是用fork…join語句描述。

  2、條件語句

  條件語句這裡不說,和C語言一樣。就說一點主意事項。

  在使用條件語句時,要注意語句的嚴整與封閉性。和C語言不同,舉個例子

  always @(al or d)

  begin

  if(al==1) q=d;

  end

  這個例子是說,當al上升沿到來時,d的值賦給q,那麼當al=0時又是什麼情況呢,事實上,在always塊中,如果沒有給變量賦值,這個變量就會保持原值,也就是生成了一個鎖存器。為了避免這種情況的發生,我們一般這樣寫

  always @(al or d)

  begin

  if(al==1) q=d;

  else q=0;

  end

  同樣在case語句中也要加上default語句避免鎖存器的生成,這樣可以使設計者更加明確的設計目標,也提高了程序的可讀性。

  3、case語句

  

  case語句要注意幾點,只挑幾點重要的,其他的不說了

  (1)case語句分項後的表達式的值必須相同,否則就會出現問題,例如上面圖片上的result。

  (2)與C語言不同,與某一項case語句匹配後,就會跳出case語句,這裡沒有break語句。

  (3)case語句的所有表達式位寬必須相等,例如上圖都是16位整型,如果不加以說明,系統會以默認值32位控制表達式位寬。

  下面是case,casez,case語句的真值表

  

  這個表其實還是很好記的

  case語句,只有匹配才出「1」

  casez語句除了匹配出「1」之外,另外只要遇到「z」就出「1」

  case語句除了匹配出「1」之外,另外只要遇到「z」或「x」就出「1」

  

  上圖就用到了casez語句來處理不必要考慮的值,這樣就可以靈活的設置對信號的默寫位進行比較。

  下面寫了一個小例子來練習一下

  使用case語句實現一個四選一多路選擇器

  module xiaomo(a1,a2,a3,a4,out,s1,s2);

  input a1,a2,a3,a4;

  input s1,s2;

  reg out; //把輸出變量聲明為寄存器類型

  always @(s1 or s2 or a1 or a2 or a3 or a4 or out) //任何信號的變化都會引起輸出變量的重新計算

  begin

  case ({s1,s2}) //位拼接運算

  2'b00: out=a1;

  2'b01: out=a2;

  2'b10: out=a3;

  2'b11: out=a4;

  default: out=1'bx; //保持語句的嚴整性

  endcase

  end

  endmodule

4、循環語句

  Verilog語法**有4中循環語句,這裡只簡單說一下C語言裡沒有的兩種

  (1) forever語句

  連續執行語句,這種語句主要用在產生周期性的波形,用來做仿真信號。個人理解和always語句差不多的功能,但是,forever語句只能用在initial塊中。

  (2)repeat 語句後面接常量表達式,可以指定循環次數,例如;

  repeat (8)

  begin

  …

  end

  表示循環8次相應語句。

  5、順序塊和並行塊

  所謂順序塊就是前面說的begin…end,他的作用就是把多條語句組合到一起執行,在順序塊裡面,語句是一條一條順序執行的,如果遇到#10延遲語句,延遲也是相對於上一條語句的延遲,這一點比較重要。

  相對於順序塊的就是並行塊,用fork…end語句表示,並行塊裡的語句是同時執行的。

  順序塊和並行塊可以嵌套使用。

  如果在begin或者fork語句後面加上名字,這個塊語句就成了命名塊,例如

  begin :xiaomo

  ……

  end

  命名塊有什麼好處呢?有了命名塊,我們就可以用verilog提供的disable語句來隨時終止命名塊,例如disable xiaomo;這樣,當程序運行到此時,就會禁用命名塊,就會直接跳出塊語句,相當於C語言裡面的break語句一樣,看下面這個例子:

  

  6、生成塊

  生成塊語句可以動態的生成Verilog代碼,這一聲明語句方面了參數化模塊的生成。黨對矢量中的多個位進行重複操作時,或者進行多個模塊的實力引用時,或者在根據參數的定義來確定程序中是否應該包括末端Verilog代碼的時候,使用生成語句能夠大大簡化程序的編寫過程。

  生成語句可以控制變量的聲明、任務或函數的調用,還能對實力引用進行全面的控制。編寫代碼時必須在模塊中說明生成塊的實例範圍,關鍵字 generate…endgenerate用來指定該範圍。

  Verilog中有三種生成語句的方法,分別是循環生成,條件生成和case生成。

  (1)循環生成

  

  

  註:genvar 是關鍵詞,用於生成生成變量,生成變量只存在於生成塊中,在確立後的方針代碼中,生成變量是不存在的。

  xor_loop是賦予生成語句的名字,目的在於溝通它對循環生成語句之中的變量進行層次化引用。

  當然這個異或門還可用always塊實現

  生成塊程序

  generate

  for (j=0;j

  begin :xiaomo

  always @(i0[ j ] or i1[ j ]) out [ j ]=i0[ j ]^i1[ j ];

  end

  endgenerate

  (2)條件生成

  

  下面是一段生成語句

  

  (3)case生成

  

  下面是一個例子使用case語句生成N位的加法器

  

  

7、結構語句

  (1)initial語句比較簡單,這裡就不多說了。

  (2)always語句

  always語句在仿真過程中是不斷活動的,always語句後面的語句是否執行,這要看always語句是否滿足觸發條件。因此,always語句只有和時序控制語句結合才能使用,否則就會被死鎖。例如:always areg=~areg;

  這個always語句生成一個0延遲的無限跳變過程這時會發生死鎖。但是一旦加上時序控制,這條語句就不一樣了,例如:

  always #10 areg=~areg;

  這樣的語句就描述的一個周期為20毫秒的跳變信號。所以我們常用這種方法來描述時鐘信號,並作為激勵信號來測試硬體電路。

  看下面這個例子

  reg [7:0] counter;

  reg tick;

  always @(posedge areg)

  begin

  tick=~tick;

  counter=counter+1;

  end

  這個例子就是說每當信號areg上升沿到來時,信號tick取反,計數器counter加一,這種時間控制是always語句最常用的。

  always語句的時間控制模板

  

  如果組合邏輯塊語句的輸入變量過多容易漏掉,例如:

  always @(a or b or c or d or e)

  這樣的情況下可以用always@ (*)語句來代替,*號自動將所有輸入變量默認為敏感信號。

  上面所討論的都是等待信號的值發生變化或者觸發時才執行相應語句,我們也可以用wait語句來用電平敏感來控制。例如

  always

  wait (count_enable) #20 count=count+1;

  意思就是說,當count-enable的值為1時,程序延遲20毫秒後計數。

  8、任務與函數

  書上寫了關於任務與函數的區別,寫了好多,我覺得區別這兩個概念主要看一點就夠了,就是看有沒有返回值,函數有,任務沒有。舉個例子

  switch_bytes (old_bytes,new_bytes);這是個任務,沒有返回值,功能是把新舊兩個字節互換位置。

  new_bytes=switch_bytes(old_bytes);這是個函數,功能是把舊字節轉換後賦值給新字節。有返回值。

  下面寫一個交通信號燈的程序來學習一下任務這個概念

  moudle xiaomo_traffic;

  reg clock,red,green,amber;

  //定義時鐘,紅燈,黃燈,綠燈

  parameter on=1,off=0,red_tics=350.amber_tics=30,green_ics=200;

  //定義紅燈等待350個時鐘,黃燈等待30個時鐘,綠燈等待200個時鐘

  initial red=0;

  initial green=0;

  initial amber=0;

  //初始化,這裡用initial語句保證三條語句同時執行

  always

  begin

  red=on; //紅燈亮

  light (red,red_tics); //這裡用到任務,功能是等待350個時鐘的時間,聲明看下面程序

  amber=on; //黃燈亮

  light (amber,amber_tics); //等待30個時鐘

  green=on; //綠燈亮

  light (green,green_tics); //等待200個時鐘

  end

  task:light; //命名任務

  output color;

  input [31:0] tics;

  //注意這裡的兩個變量要與上面的一一對應,也就是說上面的light(red,red_tics);中的red對應color,red_tics對應tics

  begin

  repeat(tics); //重複執行tics次下面的語句

  @(posedge clock); //等待上升沿,因為這裡的tics對應上面的red_tics幾個,所以這裡要等待相應個上升沿

  color=off; //等到相應個上升沿結束時,相應顏色的燈關閉

  end

  endtask

  //下面就是寫時鐘函數了,用always塊

  always

  begin

  #100 clock=0;

  #100 clock=1; //每100毫秒產生一次跳變

  end

  endmoudle

  注意:這個程序要找對一一對應關係,例如脈衝模塊裡的clock對應posedge clock中的clock,程序行與行之間是有聯繫的,不能隨便聲明

(未完待續)


相關焦點

  • 零基礎教你學FPGA之Verilog語法基礎(下)
    本文承接《零基礎教你學FPGA之Verilog語法基礎(中)》  9、關於任務和函數的小結,
  • 零基礎教你學FPGA之Verilog語法基礎(上)
    關於I/O說明有三種格式,即輸入、輸出、輸入輸出,第三種格式代表信號可以雙向傳送。在寫I/O說明的時候要註明信號位寬,即由幾位組成,例 如 input [7:0] xiaomo;代表輸入一個8位的信號「小墨」,注意這裡要用中括號,第一位是位寬減1,接一個冒號,再接數字0,再接埠名;  關於內部信號說明要用到和埠有關的wire和reg類型變量的聲明。
  • 零基礎學FPGA(五)Verilog語法基基礎基礎(下)
    與任務不同,函數具有返回值,而且至少要有一個輸入變量,而且在函數中不能使用延遲、事件和時序控制結構,函數可以條用函數,但是不能調用任務。  (2)在聲明函數時,系統會自動的生成一個寄存器變量,函數的返回值通過這個寄存器返回到調用處。  (3)函數和任務都包含在設計層次中,可以通過層次名對他們實行調用。這句話什麼意思啊?
  • 通過點燈的邏輯體驗FPGA的編程流程以及Verilog語法基礎
    學習FPGA也不例外,不要小瞧這隻小小的LED,它能在你學習的路上帶給你光明,引導一個門外漢跨進可編程邏輯世界的大門!作為「寒假在家一起練」的第二次直播講座,我們今天就基於1個LED做了1個多小時的分享,從創建第一個FPGA項目、寫下第一句Verilog代碼,到調用FPGA的IP Cores,體驗了FPGA的設計流程以及Verilog的基本語法規範。
  • 零基礎學FPGA(四)Verilog語法基基礎基礎(中)
    我們接著上篇文章繼續學習,上次提到了兩種賦值語句,讓我們接著往下學。  (1)順序快  順序快就好比C語言裡的大括號「{ }」,在Verilog語法中,用begin…end代替。這裡只需要知道,在begin…end中間的語句是順序執行的就行了。  (2)並行塊  並行塊可以算是一個新的知識點,與順序塊最大的不同就是並行塊中的語句是同時開始執行的,要想控制語句的先後順序,可以加延時語句控制。
  • 零基礎學FPGA(三)Verilog語法基基礎基礎(上)
    這幾天複習了一下Verilog的語法知識,就藉此寫寫我對這些東西的想法吧。感覺呢,是和C語言差不多,具有C語言基礎的朋友學起來應該沒什麼問題,和C語言相同的地方就不說了吧,重點說一下不同點吧。  小結  在verilog語法中,所有的過程塊(包括initial塊,always塊),連續賦值語句,實例引用都是並行的,也就是說在一個模塊中遇到這些語句就是同時執行的,而且沒有先後次序。只有連續賦值語句assign和實例引用語句可以獨立於過程塊存在於模塊的功能定義部分,即這兩種語句可以不用在那兩個過程塊裡執行,也可以在模塊的功能定義部分執行,例如第一個例子。
  • 細談FPGA之Verilog HDL語法(一)
    前面淺談了一下FPGA(淺談FPGA),有人希望能繼續分享,那麼今天就來簡單講講FPGA的描述語言——Verilog HDL的語法,語法內容比較多
  • ​verilog相關基礎知識
    對於verilog基礎知識,這裡做簡單的介紹,對於已經熟悉verilog語言的讀者可以省略不看此部分。
  • 學日文零基礎
    一、學日文零基礎簡介學日文零基礎,日本語是比較火爆的外語,通常輔導班的授課的周期有暑期班等,針對不同的水準的學員,課程培訓價值在1856-36495
  • FPGA 高手養成記-Verliog語法基礎
    基本的語法略過,主要想寫一些關於框架,規範,技術難點的博文,這樣對於我們養成好的編碼習慣是有好處的,就定這樣一個flag吧.希望大家可以一起好好學習,共同進步.接口時序設計規範模塊和模塊之間的通過模塊的接口實現關聯, 因此規範的時序設計, 對於程序設計的過程, 以及程序的維護, 團隊之間的溝通都是非常必要的。
  • 我想學英語從零開始 零基礎如何學英語
    我想學英語從零開始 零基礎如何學英語很多人說自己想從零開始學英語,那麼零基礎如何學英語呢?從哪些入手學習英語呢?下面小編為大家介紹一下!英語零基礎學習從哪裡入手首先,我們如果英語基礎一點都沒有的話,可以先從學習英語音標開始學,英語音標是學習英語的基礎,通過學音標我們可以知道陌生單詞的發音,也能夠知道怎麼去讀和背英語單詞,音標的學習上能夠更好地幫助我們記憶英語單詞。
  • 拯救英語零基礎最重要的從基礎開始
    ……以上各種症狀,相信英語渣們都感同身受,作為英語零基礎的童鞋們,對於提高自己的英語也是心急如焚,如果像無頭蒼蠅般亂撞,今天這裡學一點,明天那裡聽一點,終究是無法實質性提高自己的英語的。萬丈高樓平地起,拯救英語零基礎最重要的從基礎開始,系統性地進行英語學習。
  • 英語從零開始怎麼學 零基礎怎麼學英語最有效
    英語從零開始怎麼學 零基礎怎麼學英語最有效很多英語零基礎的人想要學習英語,下面小編介紹一些適合零基礎學英語的有效方法!如何從零開始學英語1、首先要參加學習班,循序漸進的,由初級班到高級班,要堅持上課,把基礎打好,基礎是很重要的,例如你所提到的語法和音標有了一定基礎以後,多用英文聊天,加入英語角,英語聊天群,不要怕講錯,多跟別人學習。2、多聽英文廣播,英文歌曲,英文電影,喜歡的電影可以多看幾遍,琢磨電影中對白的英語在講什麼。
  • 人人必備的零基礎日語語法入門課!
    因為光背語法的話,又晦澀難記又不知道它具體的使用方法,背例句的話,我們可以了解這個語法前面的接續情況,這樣讓我們更好使用語言,通過背例句,我們也能知道如何運用這個語法說話,畢竟學語法不能光光學語法,語法是為了之後能夠寫日語句子,日語文章,說日語而學的。
  • 我英語基礎很差,怎麼從零開始學英語?
    同學們,十一月好~轉眼第四季度就快到尾聲了,2020的年度計劃你是否有好好地完成呢?很多同學已經準備開始複習工作了,在教學的過程中,我們收到很多問題,其中有一個問題出現的頻率最多,那就是——我英語基礎很差,如何從零開始學好英語?
  • 成人零基礎怎麼學日語?日語入門先要學什麼?
    1.從零基礎開始學日語,確立目標很重要。  從零基礎開始學日語,首先要明確一個目標,無論做什麼事情,樹立一個明確的目標很重要,學日語是想考級,想去日本留學,還是單純的處於對日劇動漫等方面的興趣。從零開始學日語,比如,如果你從零開始學日語的目的是考級,那麼就可以給自己設定學習半年的時候考過4級,學習兩年的時候考2級...這樣有了學習目標就有了動力。
  • 成人零基礎怎麼學日語?日語入門先要學什麼?
    1.從零基礎開始學日語,確立目標很重要。
  • 如何從零基礎開始學日語?快速學日語的方法
    .今天我們簡單教你從零開始學日語。二、選擇一個適合自己的日語教材教材要求有從零基礎日語到中級、高級的一套,這樣能夠保證從零開始學日語到以後較高級別的學習要求,知識體系是完整的。《標日》雖是眾多日語初學者的首選之一,但《標日》的只是體系對於日語高級階段的學習是比較不利的。
  • 成人零基礎如何科學的自學英語?
    你零基礎,也沒有任何學習第二語言的經驗,自學這個想法我勸你三思。首先基礎的語法知識很可能看不懂。我看過很多本語法書,但是港真,如果我沒有英語基礎的話,很多的語法點我根本繞不過來。其次,自學會浪費你很多時間。
  • 英語學習方法:拯救英語零基礎最重要的從基礎開始
    ……以上各種症狀,相信英語渣們都感同身受,作為英語零基礎的童鞋們,對於提高自己的英語也是心急如焚,如果像無頭蒼蠅般亂撞,今天這裡學一點,明天那裡聽一點,終究是無法實質性提高自己的英語的。萬丈高樓平地起,拯救英語零基礎最重要的從基礎開始,系統性地進行英語學習。