一、電路設計的語法
1.設計不用的語法
a)initial 【設計不用,**時使用】
b) #5 【設計不用,**時使用】
下面的均設計不用,**時亦不用
task/function
for/while/repeat/forever
integer
ca***/casez
force/wait/fork
模組內部不能有x態(不定態)、z態(高阻態),內部不能有三態介面
2.設計使用的語法
a)reg/wire、parameter
b)assign【建議改名時使用】、always
c)只允許使用if else 和case兩種條件語句
只用a)、b)、c)就能搞定所有的設計
d)算術運算子(+,-,*,/,%)
e)賦值運算子(<=,=)【時序邏輯用<=,組合邏輯用=,其他 情況不存在】
注:不必糾結二者的區別,只需記住時序邏輯用<=,組合邏輯用=
f)關係運算子(>,=,<=)
g)邏輯運算子(&&,||,!)【為避免歧義,邏輯運算子兩邊必須用1bit訊號】
h)位運算子(~,|,^,&)【重點關注異或】
i) 移位運算子(<>)
j)拼接運算子({})
二、電路設計的結構
1.電路設計的3種結構
1)組合邏輯
always @(*) begin
語句end
2)時序邏輯
a)同步復位的時序邏輯
always @ (posedge clk )begin
if(rst_n==1'b0)begin
語句else begin
語句end
endb)非同步復位的時序邏輯
always @ (posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
語句else begin
語句end
end三、電路設計的要點
1.乙個always只產生乙個訊號 例如
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
b <= 1』b0;
a <= 1』b0;
else begin
b <= 1』b1;
a <= b;
end
end
通常的verilog**,乙個 always裡面會設計多個訊號,例如上圖,這個 always 語句同時設計了a和 b兩個訊號。明德揚建議乙個 always只設計乙個訊號,例如上面 **應該改為以下**。
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
b <= 1』b0;
else begin
b <= 1』b1;
end
end
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
a <= 1』b0;
else begin
a <= b;
end
end
a). 一心一用。每段 always 同時只考慮 1 個訊號的設計,不用考慮其他無關的訊號。 例如設計 a 時,就全力想 a 訊號,不用考慮 b 訊號。這樣有助於寫出最簡、最高 效的**。
b). 有助於按照定義實現訊號。設計的第一步是定義訊號,該訊號幹什麼用,什麼時 候為 0,什麼時候為其他值,都在設計前定義好。always 就根據這個定義來寫代 碼,非常簡單。
c). 方便查詢和定位問題。如果**出現問題,方便查詢問題的源頭。只要找到與定 義不一致的那段 always**,修改該段**,就能解決好問題。
d). 修改**影響最小。修改**時,只修改本訊號,而不會對其他訊號造成影響。 否則很有可能修改 1 個訊號,導致其他本來已經正確的訊號又變錯誤。很多同學 設計時,容易反反覆覆,經常按下葫蘆又起瓢,最後是勉勉強強成功,但這樣的 系統,可靠性能有多高呢。
e). 有助於衡量工作進度。做好設計定義後,就非常清楚有多少訊號需要設計。只要 按照定義寫好**,該訊號的設計就基本完成,出錯的概率很低。即使後期有錯 誤,修改相應的那個訊號就解決問題。但如果多個訊號集中到乙個 always,每個 訊號之間相互影響,不到最後時刻,你都不清楚還有多少設計未完成。工作中曾 經出現這樣情景:產品設計號稱進度是 99%,但後期修改 1 個錯誤,進而影響了 其他訊號,基本上其他訊號都要重新設計,進度一下子又退回了 50%。
f). 容易修改**。多個訊號集中在乙個 always,修改**時,你只能見縫插針,還 要極力避免影響其他訊號,非常困難。
g). 有助於硬體思維設計。乙個 always設計 1個訊號,這段 always很容易理解為乙個 電路模組,從而設計出最高效的電路。多個訊號在乙個 always,容易按軟體思維 來進行 fpga設計。
2.乙個訊號只能在乙個always產生
上圖第1個觸發器的輸出值為 0,第2個觸發器的輸出值為 1,由於兩個觸發器輸 出訊號名都是 b,那自然就是同一根線,那麼在這種情況下,b的值到底是 0還是 1呢? 誰也不知道,因此fpga內部不允許有這種不確定的情況出來。所以下面兩段**是 不允許的,b只能在乙個always裡產生,而不能是兩個。
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
b <= 1』b0;
else begin
if(a==1』b1)
b <= 1』b1;
end
end
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
b <= 1』b0;
else begin
if(c==1』b1)
b <= 1』b0;
end
end
3.硬體設計思維
fpga不是一行一行順序執行的,fpga是將**變成 電路後,上電執行的。其 always描述的是乙個訊號在什麼情況下,這個訊號的值為多 少;在其他情況下,值為多少。
下面就是乙個很典型的軟體思維寫出的**。
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
b <= 4』b0;
else begin
b<= b+1; //line_0
if(b==8)
b <= 0;//line_1
end
end
例如某個訊號在三種情況下取不同的值:條件 a滿足時值為2、條件 b滿足時值 為1,以及其他情況時值為 0,如上圖。則對應的always**如下:
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
a <= 0;
else if(條件 a)
a <= 2;
else if(條件b)
a <= 1;
else
a <= 0;
end
fpga設計的步驟:首先考慮這個訊號有多少種值,然後這些值分別在哪幾種情況 獲得。把情況劃分好之後,就可以用 if else語句來寫**了。
前面錯誤的**,其正確的**應該是這樣的,將情況分成 b等於7(值為0)和 b不等於7(值等於上一次值加 1)兩種情況:
always@(posedge clk or negedge rst_n) begin
if(rst_n==1』b0)begin
b <= 4』b0;
else begin
if(b==7)
b <= 0;//line_1
else
b <= b+1;
end
end
4.條件判斷只允許使用if else 和 case ,其他全不用(包括ca***)。
5.含有posedge或negedge的,一定是d觸發器,是時序電路。
6.設計時,如果你想立刻有結果,那就用組合邏輯,如果你想延時一拍有結果,那就用時序邏輯。
重點:1,三種電路
2,兩種條件
3,一一法則
即標紅部分。
明德揚 面試解析
已知某傳輸流的包長為168位元組,其資料格式如下 0x47包頭,0x00,0x00,id,資料 其中0x47為包頭訊號,id為一位元組的資料,取值範圍為0x00到0xff,資料為有效負載負載,負載中不會出現0x47 需要把流中的id對映成新的值,對映表有外部上位機實時設定ram實現。模組介面如下 m...
函式至簡原則
object jianhua println f0 alice println 1.return可以省略,以最後一行為返回值 def f1 name string string println f1 alice println 2.如果函式體只有一行 可以省略花括號 def f2 name stri...
大道至簡至易,亦至精至微
心為君之官 嘗見先生送二三耆宿出門,退坐於中軒,若有憂色。德洪趨進請問。先生曰 頃與諸老論及此學,真圓鑿方枘 rui 此道坦如道路,世儒往往自加荒塞,終身陷荊棘之場而不悔,吾不知其何說也?錢德洪看見先生送兩三個老先生出門,回來坐在走廊上,面有憂色,就走進去問先生怎麼了?王陽明回答說 剛才跟這幾位老先...