FPGA数字电子技术复习笔记(一)verilog语法规则补充(语法篇2)
目錄
- 數字信號實際波形
- Verilog語法規則(在之前的基礎上補充)
- 間隔符
- 標識符
- 常量表示規則
- 字符串
- 寄存器類型
- 縮位運算符
- 門級原件
- 邏輯功能描述
- 嵌套case語句語法及casez/casex
- 數組
- 字符串中的轉義字符
- 循環語句
- while循環
- for循環
- repeat循環
- forever循環
- 塊語句
- 順序塊
- 并行塊
- 命名塊
- 生成塊
- 循環生成語句
- 條件生成語句
- case生成語句
通過學習數字電子技術(康華光 華中科技大學)總結
大概是第1、2、4節有關Verilog的部分
數字信號實際波形
Verilog語法規則(在之前的基礎上補充)
銜接之前的:FPGA學習筆記(二)Verilog初步入門
間隔符
不在字符串中的空格(\b)、TAB(\t)、換行符(\n)、換頁符被忽略,所以寫程序時可以跨越多行書寫。
標識符
起名字可以用英文字母、下劃線(這兩個能開頭)、數字、$組成的標識符
常量表示規則
+/- 位寬 基數符號 數值
分別對應正負、常量對應二進制數的寬度、定義后面數值的表示形式、數值左邊為最高位,右邊最低位。
+號一般省略
例子:3‘d2
代表數值范圍:0~2的三次方即 0 ~ 8。此時數值為2(十進制)。
字符串
字符串是“ ”中間的字符序列,不允許多行書寫,在表達式和賦值語句中,要轉換成無符號整數,用8位的ASCII表示
例如:“ab”等價為 16’h5758,一個字符是8位,所以n個字符就定義為n*8位
這里使用串口助手要注意:
參考:ASCII碼對照表
寄存器類型
除了我們常見的reg類型,還有其他三種
- integer:32位帶符號的整數型變量
- real:64位帶符號的實數型變量,默認值為0
- time:64位無符號的時間型變量
這三種是純數學的表述,不會生成電路。reg一般是無符號的數來處理的。
例子:
類似c語言,如果把實數類型(real)傳遞給integer時,只能保留整部部分,實數的小數部分會被舍棄。
-
實數型常量的表達方式也可以用科學計數法表示
例:
23.51e2–>2351.0
3.6E-1 —> 0.36 -
time型變量通常用來存儲仿真時間
例:
縮位運算符
縮位運算符是單目運算符有:&、~&、|、 ~|、^、 ~ ^或者 ^ ~
分別是與、與非、或、或非、異或、同或
主要計算過程:第一步先將操作數的第一位與第二位進行或與非運算,第二步將運算結果與第三位進行或與非運算,依次類推,直至最后一位。
例:
A=4b‘1010
~^A=1
過程:(~1)^0=0,
(~0)^1=0,
(~0)^0=1,
門級原件
調用方法:
- 多輸入門:
A1是名字,可以省略。括號第一個參數必須是輸出變量。
例子:
- 多輸出門:
允許有多個輸出,但只有一個輸入,還是那個名字可以省略。
例子: - 三態門:
有一個輸出、一個數據輸入和一個輸入控制。如果輸入控制信號無效,則三態門的輸出為高阻態z。 (l類似之前verilog入門文章里面的inout),調用名還可以省略。
例子:bufif1 B1(out,in,ctrl);
邏輯功能描述
!!!!!
主要是三種:利用基礎門級電路、assign(連續賦值語句,也叫數據流描述方法)、initial/always(過程塊語句結構,也叫行為描述方法)
例如:
第一種:
第二種:assign只能這種數據表達形式,不想always中,有語句可以用
module mux2to1_dataflow(D0, D1, S, Y );input D0, D1, S; output Y;wire Y ; //下面是邏輯功能描述assign Y = (~S & D0) | (S & D1); //表達式左邊Y必須是wire型 endmodule第三種:相當與把電路化出了最簡單的狀態,更高效了
module mux2to1_bh(D0, D1, S, Y );input D0, D1, S; output Y;reg Y ; //邏輯功能描述always @(S or D0 or D1) //任何輸入信號的變化都會進入,括號里面的也叫敏感變量,也可以用*代替if (S == 1) Y = D1; //也可以寫成 if (S) Y = D1;else Y = D0; //注意表達式左邊的Y必須是reg型 endmodule不過現在都用別的方法定義模塊了
例子:
這里面的有位寬定義的一般不能去掉前面的output/input。如下:
module top_seg_led (//global clockinput sys_clk , // 全局時鐘信號sys_rst_n, // 復位信號(低有效)key //按鍵信號output led, //1個LED燈//seg_led interfaceoutput [5:0] seg_sel , // 數碼管位選信號output [7:0] seg_led , // 數碼管段選信號);2022.10.18更新
嵌套case語句語法及casez/casex
嵌套case語句:
case(A)1'b1:case(B)2'b0:begin x1=1'b1;x2=1'b0;end2'b01:begin x3=1'b1;x4=1'b0;end default:.........endcasedefault:..... endcase一個case語句不需要加begin end,像1‘b1里的。但是在具體的分支里面,多個語句還是要有begin end
casex/casez:
casez將比較雙方表達式(分支表達式和case_expr控制表達式)中出現的z的位當作不用關心的位處理,在分支表達式中所有為z的位也可以用?代替。
casex則認為表達式中所有的z和x都是無關項
2022.10.22更新
數組
在 Verilog 中允許聲明reg,integer,time,real,realtime及其向量類型的數組,對數組的維數沒有限制。線網數組也可用于連接實例的端口,數組中的每個元素都可以作為一個標量或向量。
integer count [0: 7] ; //由8個計數變量組成的數組 reg bool[31:0] ; // 由32個1位的布爾( boolean)寄存器變量組成的數組 reg [4:0] port_id[0:7]; //由8個端口標識變量組成的數組,端口變量的位寬為5 integer matrix [4:0][0:255] ; //二維的整數型數組 reg [63:0] array_4d [15:0][7:0][7:0][255:0] ;//四維64位寄存器型數組 wire [7:0] w_array2 [5:0] ;//聲明8位向量的數組下面有一些賦值例子:
matrix[1] [0] = 33559;//把數組中第1行第0列的整數型單元(32位)置為33559 array_4d[0] [0][0][0][15:0] = 0;//把四維數組中索引號為[0][0][0][0]的寄存器型單元的0~15位都置為0 matrix = 0 ; //非法,企圖寫整個數組 matrix [1] = 0;//非法,企圖寫數組的整個第2行,即從matrix[1] [0]直到matrix[1][255]字符串中的轉義字符
就是字符串中的%要寫成%%才行
2022.10.23更新
循環語句
while循環
在while語句中可以使用各種操作符,并且可以用這些操作符構成任意的邏輯表達式。如果循環中有多條語句,則須使用begin和end。
while((i < 16) && continue ) //用操作符的多個條件構成while表達式 beginif (flag[i])begin$display ("Encountered a TRUE bit at element number %d",i);continue = 'FALSE;endi = i + 1; endfor循環
初始條件和完成自加操作的過程賦值語句都包括在 for循環中。
for ( count=0; count < 128; count = count + 1)repeat循環
repeat循環的功能是執行固定次數的循環,它不能根據一個邏輯表達式來確定循環是否繼續進行。repeat循環的次數必須是一個常量、一個變量或者一個信號。如果循環重復次數是變量或者信號,循環次數是循環開始執行時變量或者信號的值,而不是循環執行期間的值。
//說明:從О增加到127計數并顯示integer count; initial begincount = 0 ;repeat (128)begin$display ( "Count = %d",count) ;count = count + 1 ;end endforever循環
關鍵字forever用來表示永久循環。直到遇到系統任務$finish為止。如果需要從forever循環中退出,可以使用disable 語句。
通常情況下forever循環是和時序控制結構結合使用的。如果沒有時序控制結構,那么仿真器將無限次地執行這條語句 ,并且仿真時間不再向前推進,使得其余部分的代碼無法執行。
塊語句
順序塊
即begin end語句
一條一條語句順序執行的,這里指的是阻塞賦值的情況下
在寫仿真的時候,如果語句包括了延時控制,那么延時下一條語句要在前面這條延時處理完才能執行
并行塊
關鍵字fork和join聲明,語句是并行執行的,但是要注意如果兩條語句在同一時刻對同一變量進行操作,可能引起隱含的競爭,因為目前的仿真器無法正確的處理競爭,所以要避免這一寫法。
例子:應用在仿真里面
順序塊和并行塊可以互相嵌套
命名塊
和上面看兩個并不是并列關系,但是同等重要。
命名塊主要指給前面兩種塊起個名字,而且命名后的塊里面的變量可以通過名字引用訪問,也可以被禁用,停止執行。
具體語法就是在之前的額塊語句begin/fork后面加一個:,之后后面再跟上起的名字
Verilog通過關鍵字disable提供了一種終止命名塊執行的方法。使用disable則可以禁用設計中的任意一個命名塊。
//在(向量)標志寄存器的各個位中從低有效位開始查找第一個值為1的位1/從向量標志寄存器的低有效位開始查找第一個值為1的位 reg [15:0] flag; integer i; //用于計數的整數initial beginflag = 16'b 0010_0000_0000_0000;i = 0;begin: block1 // while循環聲明中的主模塊是命名塊block1while(i < 16)beginif(flag[i])begin$display( "Encountered a TRUE bit at element number %d",i) ;disable block1; //在標志寄存器中找到了值為真的位,禁用block1endi = i + 1;endendend end生成塊
當對向量中的多個位進行重復操作時,或者當進行多個模塊的實例引用的重復操作時,或者在根據參數的定義來確定程序中是否應該包括某段Verilog 代碼的時候使用生成塊
循環生成語句
例如:對兩個N位總線變量進行按位異或
//本模塊生成兩條N位總線變量的按位異或 module bitwise_xor (out, i0,i1);//參數聲明語句。參數可以重新定義 parameter N = 32; //默認的總線位寬為32位 //端口聲明語句 output [N-1:o] out; input [N-1:0]i0,il; //聲明一個臨時循環變量,該變量只用于生成塊的循環計算。verilog仿真時該變量在設計中并不存在 genvar j; //用一個單循環生成按位異或的異或門( xor) generate for (j=0; j<N; j=j+1)begin: xor_loop xor gl (out [j], i0[j], i1[j]); end //在生成塊內部結束循環 endgenerate //結束生成塊//另外一種編寫形式 //異或門可以用always塊來替代// reg [N-1:0] out; //generate for (j=0; j<N; j=j+1) begin: bit //always (i0[j] or i1[j]) out [j] = i0[j] ^ i1[j]; // end //endgenerate endmodule在仿真開始之前,仿真器會對生成塊中的代碼進行確立(展平),將生成塊轉換為展開的代碼,然后對展開的代碼進行仿真。
關鍵詞genvar用于聲明生成變量,生成變量只能用在生成塊中;在確立后的仿真代碼中,生成變量是不存在的;
生成變量的值只能由循環生成語句來改變;
循環生成語句可以嵌套使用。但是使用同一個生成變量作為索引的循環生成語句不能相互嵌套;
xor_loop是賦予循環生成語句的名字,目的在于通過它對循環生成語句中的變量進行層次化引用。因此,循環生成語句中各個異或門的相對層次名分別為: xor_loop[0].g1,xor_loop[1].g1,…,xor_loop[31].g1。
條件生成語句
利用if else來選擇執行的模塊
//有條件地調用(實例引用)不同類型的乘法器 //根據參數ao_width和al_width的值,在調用時引用相對應的乘法器實例 generate if (a0_width <8)||(a1_width < 8)cla_multiplier # (ao_width,a1_width) mo (product,a0,ai); elsetree_multiplier #(ao_width, 'a1_width)mo · (product,a0,al); endgenerate //生成塊的結束case生成語句
//根據總線的位寬、調用(實例引用)相應的加法器 //參數衛在調用(實例引用)時可以重新定義 //調用(實例引用)不同位寬的加法器是根據不同的N來決定的generate case (N) //當N=1或2時分別選用位寬為1位或2位的加法器 l: adder_1bit adder1(co,sum,a0,al, ci) ; // 1位的加法器 2: adder_2bit adder2(co,sum,a0, a1,ci) ; //2位的加法器 //默認的情況下選用位寬為N位的超前進位加法器 default: adder_cla #(N) adder3(co,sum,a0,a1,ci); endcase endgenerate //生成塊的結束總結
以上是生活随笔為你收集整理的FPGA数字电子技术复习笔记(一)verilog语法规则补充(语法篇2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python中利用plt显示中文标题解决
- 下一篇: 【图像处理】——Python霍夫变换之直