本文詳細(xì)介紹了Verilog常用的運算符和表達(dá)式,特別是分享了處理“計算位寬溢出”和“負(fù)數(shù)”的可行方式,幫助讀者更加輕松地理解和掌握Verilog語言的運算符。
一、常見運算符以及表達(dá)式
算數(shù)運算符:加(+)、減(-)、乘(*)、除(/)、取余(%)
賦值運算符:非阻塞賦值(=)、阻塞賦值(<=);
關(guān)系運算符:大于(>)、小于(<)、等于(==)、不等于(!=)、大于等于(>=)、小于等于(<=)
邏輯運算符:與(&&)、或(||)、非(!);
條件運算符:(?:);
位運算符 : 取反(~)、或(|)、異或(^)、與(&);
移位運算符:左移(<<)、右移(>>);
拼接運算符:位拼接({}),復(fù)制{n};
二、詳細(xì)介紹
1、算數(shù)運算符
加(+)、減(-)、乘(*)、除(/)、取余(%)
+:加法運算或者正值運算,a+b、+a
— :減法運算或者負(fù)值運算:a—b、—a
* :乘法運算:a*b
/ :除法運算:a/b,b不能等于0
% :求余運算:a%b,%兩側(cè)的數(shù)據(jù)必須為整型數(shù)據(jù),b不能等于0
2、賦值運算符
非阻塞賦值(=)常用于組合邏輯,例如assign語句和always@(*)語句塊。
wire [5:0] data0;
reg [6:0] data1;
?
assign data0 = 'd6;
always@(*) begin
data1 = 'd10;
end
阻塞賦值(<=)常用于時序邏輯,例如always@(posedge clk)語句塊。
reg [6:0] data1;
?
always@(posedge clk) begin
data1 <= 'd10;
end
3、關(guān)系運算符
大于(>)、小于(<)、等于(==)
不等于(!=)、大于等于(>=)、小于等于(<=)
a < b :a小于b
a > b :a大于b
a == b :a等于b
a != b :a不等于b
a <= b :a小于或等于b
a >= b :a大于或等于b
4、邏輯運算符
(1)與(&&)
邏輯與:a&&b,a和b同時為真時才為真,否則為假
(2)或(||)
邏輯或:a||b,a和b同時為假時才為假,否則為真
(3)非(!)
a為真時,!a為假
5、條件運算符
條件表達(dá)式的值為真或假,如果為真,返回值1,否則返回值2。它主要用于簡化if-else語句的書寫和提高代碼的可讀性。
條件表達(dá)式 ? 值1 : 值2
assign a = (b) ? 'b1 : 'b0; 如果b為真,那么a = 'b1,否則a = 'b0。
6、位運算符
(1)與(&)
對兩個數(shù)的二進(jìn)制形式進(jìn)行“與”運算,只有兩個相應(yīng)位的值都為1時,結(jié)果才為1。
(2)或(|)
對兩個數(shù)的二進(jìn)制形式進(jìn)行“或”運算,只要有一個相應(yīng)位的值為1,結(jié)果就為1。
(3)異或(^)
對兩個數(shù)的二進(jìn)制形式進(jìn)行“異或”運算,當(dāng)兩個相應(yīng)位的值不同時,結(jié)果為1,否則為0。
(4)取反(~)
對一個數(shù)的二進(jìn)制形式進(jìn)行取反操作,即0變?yōu)?,1變?yōu)?。
~ :按位取反 a=1001 ~a=0110
& :按位與 a=1001 b=0011 a&b=0001
| :按位或 a=1001 b=0101 a|b=1101
^ :按位異或 a=1001 b=0101 a^b=1100
7、移位運算符
在Verilog中有兩種移位運算符:<< (左移位運算符) 和 >>(右移位運算符)。其使用方法如下:a>>n或a<<n,a是操作數(shù),n表示移動幾位,這兩種移位運算都用0填補移出的空位。
reg [5:0] a,c;
reg [7:0] b;
a = 6'b101001;
b = a<<2; 此時b=8'b10100100
c = a>>2; 此時c=6'b1010
8、拼接運算符
位拼接運算符可以把兩個或多個信號的某些位拼接起來進(jìn)行運算操作,或者把單個信號復(fù)制多份。其使用方法如下:
wire [5:0] a, b;
wire [1:0] c
wire [4:0] d;
wire [11:0] e;
?
assign a = 6'b101101;
assign b = 6'h111000;
assign c = 2'h11;
assign d = {a[5],b[2:0],c};//即d = 100011
assign e = {2}; //即e = {b,b} = 111000111000
?
?
wire aa, bb, cc, dd;
assign {aa, bb, cc, dd} = 4'b1011;
//即 aa = 1,bb = 0,cc = 1,dd = 1;
運算符優(yōu)先級

三、常見問題和誤區(qū)
1、位寬溢出問題
加法和乘法的計算結(jié)果需要擴展位寬,如果定義的結(jié)果變量位寬未做擴展,則計算結(jié)果將丟失最高位,導(dǎo)致結(jié)果異常。
簡單處理辦法:結(jié)果賦值的寄存器或wire的位寬引入進(jìn)位即可。
module test
(
input clk,
output reg [7:0] a,c,d,
output reg [8:0] b
);
?
reg [7:0] d0= 8'd145, d1= 8'd128;
?
always @ (posedge clk) begin
a <= d0+ d1;
b <= d0+ d1;
c <= (d0+ d1) >> 1;
d <= (d0+ d1 + 0) >> 1;
end
?
endmodule
說明:
a <= d0+ d1,表達(dá)式中最大位寬是8bit,因此運算結(jié)果丟掉了進(jìn)位,得到17;
b <= d0+ d1,整個表達(dá)式中最大位寬是9bit,因此運算結(jié)果保留了進(jìn)位,得到273
c <= (d0+ d1) >> 1 ,表達(dá)式中最大位寬只有8bit,因此d0+ d1的中間結(jié)果也是8bit(丟掉進(jìn)位后的17),這樣不能起到保留最高有效位的效果。
d <= (d0+ d1+ 0) >> 1,表達(dá)式中多了一個未聲明位寬的常數(shù)0,其默認(rèn)位寬為32bit,這樣加法的中間結(jié)果便不會丟掉進(jìn)位。
2、負(fù)數(shù)問題
表達(dá)式中如果有一個操作數(shù)是“負(fù)數(shù)”,整個表達(dá)式的運算需要特別考慮,其實處理起來也很簡單。
(1)如果只涉及到加法和減法,負(fù)數(shù)與表達(dá)式中最大操作數(shù)的位寬必須保持一致,如下處理:
reg [8:0] a = -128;
reg [9:0] b = 512;
reg [9:0] c;
reg [10:0] d;
?
assign c = {a[8], a} + b;
assign d = {{2{a[8]}}, a} - {a[9], a}};
(2)如果涉及乘法,則將負(fù)數(shù)轉(zhuǎn)換為絕對值與符號位。
reg [8:0] a = -128;
reg [9:0] b = 512;
reg [17:0] c_abs;
reg [18:0] c;
reg a_sign;
reg [7:0] a_abs;
?
assign a_sign = a[8];
assign a_abs = a[8] ? (~a[7:0] + 1'b1) : a[7:0];
assign c_abs = a_abs*b;
assign c = a_sign ? (~{1'b0, c_abs} + 1'b1') : {1'b0, c_abs};
本文將不斷定期更新中,關(guān)注,收藏,不走丟哦
有任何問題,都可以在評論區(qū)和我交流哦
本文由FPGA入門到精通原創(chuàng),公眾號為“FPGA入門到精通”,github開源代碼:“FPGA知識庫”文章來源:http://www.zghlxwxcb.cn/news/detail-475025.html
您的支持是我持續(xù)創(chuàng)作的最大動力!如果本文對您有幫助,還請多多點贊、評論和收藏。文章來源地址http://www.zghlxwxcb.cn/news/detail-475025.html
到了這里,關(guān)于Verilog常用運算符及表達(dá)式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!