|
初學Verilog HDL被那個“=”與“<=”整迷糊啦,然后找度娘,一篇文章寫得不錯嘛,不迷糊啦。如下,還迷糊的小伙伴湊個熱鬧吧,file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wpsC738.tmp.png,另外,感謝作者嘍。 首先我們要理解兩種變量類型 Net Type(連線型)和 Register Type (寄存器型)。(有些參考書上有分為3種類型,這個無關緊要)Net Type(連線型),從名字上理解就是“導線”唄,導線的這頭和導線的另一頭始終是直接連通的,這頭是什么值,那頭就是什么值,所以輸出隨著輸入隨時變化的。連線型中 wire 最常見。 更多詳情可咨詢劉老師:電話18365409359,QQ3311615775 Register Type(寄存器型),寄存器就不像普通導線了,它可以把值給存住,你只要給它賦一次值,它都會存住那個值,直到你給它賦一個新的值它才會改變。寄存器型中 reg 最常見。 最常用到的是 wire 和 reg 這兩種類型,其他的對我們初學者來說一般很少用到,可以暫時跳過,以后慢慢學下去自然會理解。 注意:wire型變量如果沒有賦予初始值,默認初始值為高阻態“Z”。 reg 型變量如果沒有賦予初始值,默認初始值為不定態“X”。 在理解這兩種基本的數據類型之后,我們來看看verilog語言中的賦值語句。verilog語言中的賦值語句有兩種,一種是持續賦值語句(assign語句),另一種是過程賦值語句(always語句)。 持續賦值語句(assign語句)主要用于對wire型變量的賦值,因為wire(線型)的值不能存住,需要一直給值,所以需要用持續賦值。 例如:assign c = a + b; 只要a和b有任意變化,都可以立即反映到c上,也就是說c的值是根據a,b的值隨時變化的。 過程賦值語句(always語句)主要用于reg 型變量的賦值 ,因為always語句被執行是需要滿足觸發條件的,所以always過程塊里面的內容不是每時每刻都被執行,因此需要將被賦值的對象定義成寄存器類型,以便這個值能被保持住。 過程賦值又分為 阻塞賦值 “=” 和 非阻塞賦值 “<=” 兩種。這里的非阻塞賦值符號 “<=” 與 “小于等于” 符號相同,他們在不同的語境下表示不同含義,要注意區分,例如在“if-else”等判斷語句中,一般都表示為“小于等于”。 接下來對這兩種賦值作具體講解... ① 阻塞賦值 “=“ 。 阻塞賦值和我們平時理解的賦值差不多,不用太多解釋,就是按照語句的順序,一句句往下順序執行。一個賦值語句執行完,然后執行下一個賦值語句。 ② 非阻塞賦值 “<=” 。非阻塞賦值就比較特別了,在同一個always過程塊中,非阻塞賦值語句都是同時并發執行的,并且在過程塊結束時才執行賦值操作。也就是說,在同一個always過程塊中,非阻塞賦值語句被執行沒有先后順序,在過程快結束時,大家一起被賦值。 給大家舉一個具體的例子: module test (clk, a1, a2, b1, b2, c1, c2); // test為module名稱,括號內的是端口列表,包含所有輸入輸出的變量名稱 input clk, a1, a2; // 定義輸入變量,這里沒有定義位寬,默認為1位寬度 output b1, b2, c1, c2; // 定義輸出變量,這里沒有定義位寬,默認為1位寬度 reg b1 = 0 , b2 = 0, c1 = 0 , c2 = 0; // 注意!因為這些變量將會在always過程塊中被賦值,所以必須定義成 reg 型 // 注意!這里省略了對輸入信號clk, a1, a2 的類型定義,它們默認為1位的wire 型(因為輸入信號是隨時要變化,所以必須用wire型) always @ (posedge clk) // always 用 clk 上升沿觸發 begin b1 = a1; // 這里采用的是阻塞賦值 c1 = b1; end always @ (posedge clk) // always 用 clk 上升沿觸發 begin b2 <= a2; // 這里采用的是非阻塞賦值 c2 <= b2; end endmodule // endmodule 別忘了,與 module 成對使用 仿真輸入值設置圖如下: 我們只需給輸入信號賦值,輸出信號根據輸入信號的變化而變化。 下面請看用quartus 2 軟件仿真的波形圖 首先請看這兩張圖的區別,第一張是時序仿真波形圖(timing),黃色標記部分因為延時而產生,第二張圖為功能仿真波形圖(function),不考慮器件的延時。 在①時刻,第一個時鐘上升沿到來(posedge clk), 兩個always過程塊同時被觸發(這就是PFGA器件強大的一點,可以并發執行) a1,b1,c1采用的是阻塞賦值。阻塞賦值語句順序執行,先執行 b1 = a1; 由于 a1 此刻的值為 1,所以b1 變為 1,然后執行 c1 = b1;由于b1的值剛才已經變成 1 了,所以c1也變成了 1 。 a2,b2,c2采用的是非阻塞賦值。非阻塞賦值語句并發執行, 也就是說 b2 <= a2; c2 <= b2; 這兩句同時執行。由于a2 此刻的值為1,所以 b2 變為1,與此同時,b2 的當前值也將賦值給 c2 , b2 的當前值是是多少呢? 這里一定要分清楚了,b2 的當前值是 0,并不是 1 ,因為在 b2 還沒有變為 1 之前,b2 的值就要賦值給 c2 了,所以 c2 的值仍然是 0 。 直到在②時刻,第二個時鐘上升沿到來,兩個always再一次被同時觸發,這次在執行 c2 <= b2; 這條賦值語句時,b2 的當前值為 1 ,所以 c2 才被賦值為 1 。 大家可以根據上面的分析方法,自己分析一下在③、④時刻 b1,b2,c1,c2 應該分別為什么值,與波形圖對照著理解一下。 其實verilog語言和 c語言大同小異,比較著來學習,會比較容易...... 更多詳情可咨詢劉老師:電話18365409359,QQ3311615775 |