如何理解「一個always裡面只輸出一個信號,避免互相干擾」?
每個always都是同時發生的,那怎麼一個always輸出一個信號就避免互相干擾了?
這個關乎代碼風格,不會影響實際綜合結果。
有三種可能的代碼組織方式:(1)每個always文只寫一個時序信號的邏輯。(2)每個always文寫一組功能相關的時序信號的邏輯。(3)所有時序信號的邏輯都寫在一個always文內。
優劣:
(1)和(2)都是我了解的日本半導體行業推薦的規範。之所以要按信號分開,是因為把相關的信號集中在一起編寫、閱讀、調試都比較方便。(1)粒度分太細也會造成代碼臃腫,所以個人推崇(2)。(3)當然也可以。想想如果代碼多起來,比如某個信號可能會出現在25、80、300行處,閱讀、調試上不太便利。至於按哪種方式編寫代碼,有的公司會有規範,有時候可以自己把握。無論如何,一定要避免把一個信號的賦值寫在多個always文內,尤其always還包含了各種同步、非同步的觸發信號。上面幾位說的挺好了。我們實驗室的代碼風格跟馮大 @馮敬堯的差不多,也結合了 @JonsonXP的第二種方法
組合邏輯寫在一組always @(*)塊中(此組合邏輯是阻塞賦值,不相關並行邏輯放到不同always 中,一組相關邏輯放到一個always塊中),實現具體的電路邏輯;時序邏輯寫到另一組always 塊中,主要就是將組合邏輯的值存入寄存器中,輸入到reg中。如下://信號定義
reg [3:0] reg_A, rin_A;
reg [3:0] reg_B, rin_B;
always @(posedge clk or negedge rst)begin
if(! rst) begin
reg_A &<= 4"h0;
reg_B &<= 4"h0;
end
else begin
reg_A &<= rin_A;
reg_B &<= rin_B;
end
end
//組合邏輯,實現具體的電路邏輯,相關信號放在一起,與此組信號並行的放在其他always中
always @(*)begin
//將寄存器存儲的內容作為初值
rin_A = reg_A;
rin_B = reg_B;
//具體邏輯實現
if(A)begin
rin_A = (reg_A+C)| B;
rin_B = rin_A+D+E;
end
end
這時就出現一個有趣的現象,雖然rin_A ,rin_B是reg型,但因為只是中間信號,綜合後成了一個wire線型信號。
PS.解釋下邏輯實現用組合邏輯寫的好處:因為組合邏輯採用阻塞賦值,是順序執行,更容易理解控制;而時序邏輯並行執行控制起來比較麻煩。沒看到題主所說的代碼,猜想你看到的可能是一下兩種之一1. 一個reg只在一個always中被賦值2. always中不要對敏感列表中的變數賦值
無所謂的吧,只是比較清楚、修改方便,可以避免把其他的輸出值改壞掉
這個是胡扯。一個always只輸出一個信號,是一種非常噁心的coding風格。最好的coding風格應該在一個module把所有的非阻塞賦值一個always寫完。組合邏輯集中寫在一塊,時序邏輯集中寫在一塊,並且時序邏輯只做最簡單的wire到reg的賦值。所有的寄存器以reg做後綴,與寄存器做賦值的以nxt做後綴,類似這種:
//----------以下是組合邏輯,所有的邏輯都在這裡實現
assign A_nxt = B ? C : A_reg;assign D_nxt = E ? F : H ? G : D_reg;assign K=L M;//----------以下為時序邏輯,只做nxt給reg賦值,不包含任何邏輯。always @(posedge clk or negedge rst_)begin if(! rst_) begin A_reg &<= xx"h0;D_reg &<= xx"h0;
else begin A_reg &<= A_nxt; D_reg &<= D_nxt; endend百度一下三段式狀態機怎麼寫吧,按那樣寫就行。
我說一句「有1000個信號,就要寫1000個always塊嗎?」
也許沒人說你錯,但肯定有人說你笨。這不是一個好的coding style,代碼臃腫難看,放眼望去全是always,而且敲起來費勁不
個人比較推崇的是,首先組合邏輯和時序邏輯一定要分開;其次,具有相同行為的一組信號放在一起;最後,學知乎,用好分割線,稍微注釋下,避免信號太多時自己邏輯混亂我想這句話的意思應該是 一個信號只能由在一個always賦值吧?
沒有說明敏感表就說每個always都是同時發生,我想題主應該還對邏輯設計接觸不深吧。其實題主所說的是一種注重對電路的描述,這種方法的好處是,如果給你一段代碼,你照著代碼可以直接畫出對應的電路圖,反之亦然,簡單明了。這種方式在小量級的邏輯中是可行而且方便的,例如基於ram的fifo啦,用cpld控制十幾個上電和複位信號啦。但是一旦涉及到較複雜的邏輯,這種方式寫出來的代碼就會變得無比龐大,如果沒有詳細的設計文檔和注釋,簡直就是要命。PS 其實碼代碼只佔了邏輯設計工作不到10分之1,更多的時候,是無休無止的方案設計和調試。如果遇到了性能上的瓶頸,優化起來才真是一種折磨。這明顯是一個 程序員效率vs程序效率 的問題:
1:如果你有無限的時間(這是在過去),每個模塊都在心中/visio中畫好。然後每個pipline的data信號寫一塊,clockgating信號寫一塊,flipflop寫一塊。注意,是per pipeline。這樣保證做出來就是你想要的。
2:因為compiler越來越智能,所以現在我的準則基本是比較相關的logic寫一塊。所有同clock下的flipflop寫一塊:
always @(clk): if nblock_foo1: foo1_0 &<= foo0_next; ..... if nblock_foo2: foo12&<= foo0_next; .....3:未來我準備flipflop都不寫了。就是寫成c語言那樣。因為基本上看來compiler確實很聰明了。RTL會變得越來越軟。用諸如:
always @(clk): if nblock_foo1: foo1_0 &<= foo1_0 * foo1_0 + a *c - d + c ;這種寫法。反思自己最近太過於追求程序效率了。得到的類似30%效率提升其實等一代scaling就可以。所以不是數量級的差別不必太在乎。關鍵在於新functionality。未來大家應該會從RTL中解放出來吧,目前的c-RTL compiler已經做得不錯了。看了那麼多答案,自己也來答一下。
為什麼會有一個「always裡面只輸出一個信號,避免互相干擾」這樣的說法?因為在很早的時候,綜合器功能還不是很健全,把多個信號寫在一個always塊里,可能會得到與你期待不同的結果。而將每個信號單獨寫在一個always塊里,綜合器可以比較容易識別,得到你想要的結果。
但是,現在不一樣的了,綜合器已經十分智能。所以,在always里寫多個信號也是可以的,但是需要注意,組合邏輯和時序邏輯最好分開,另外不能用程序化的思維去思考。
既然always既可以描述組合邏輯,又可以描述時序邏輯,那麼這就造成了一個讓初學者迷惑的現象。
下面是一個簡單的計數器,在這裡reg型的a,被綜合成了觸發器,實現了時序電路(可以存儲狀態)。注意這裡一定要使用"&<=",而不是"=",去描述一個時序邏輯。reg [7:0] a;
always @(posedge clk) begin
if(rst) begin
a &<= 8"b0;
end else begin
a &<= a + 8"b1
end
end
而下面一段代碼,實現了一個簡單的加法器。實際上,這段邏輯的綜合結果沒有任何觸發器,僅僅是靠組合邏輯實現。對a的reg定義,只是為了滿足Verilog的語法。注意這裡一定要使用"=",而不是"&<=",去描述一個組合邏輯。
reg [7:0] a;
always @(*) begin
a = A + B;
end
所以Verilog提供了另外的wire 型,使用連續賦值,也可以同樣實現上述邏輯
wire [7:0] a;
assign a = A + B;
最好不要"&<=" 和 "=" 混用,那樣的邏輯不夠清晰。
另外說一下用always描述組合邏輯很容易犯錯的地方。reg [7:0] a;
always @(*) begin
if(c) begin
a = A + B;
end
end
上述代碼的綜合結果會產生一個鎖存器,因為上述代碼沒有完整的給出所有條件,實際效果跟下面代碼是一樣的,這樣的代碼可以說在FPGA邏輯設計中是極不推薦的。
reg [7:0] a;
always @(*) begin
if(c) begin
a = A + B;
end
else begin
a = a;
end
這也說明了一點,如 @玉慶所說,敏感信號不要出現在always塊內賦值語句的左側。
永遠記得將所有case,所有else條件列全,這是一個良好的習慣。而System Verilog祭出了大招。- 使用always_comb和always_ff取代普通的always,直接告訴綜合器你的意圖,這也間接說明了不希望你在一個always塊里同時描述組合邏輯和時序邏輯。
- 使用logic數據類型將wire和reg合為一體,讓綜合器去識別去吧。
寫hdl代碼就是在畫電路圖。用結構話語言的形式,而非圖畫圖形。越多的輸出寫在一起,就是把更多的與非門畫在一張圖紙上,太多了,不易後期維護,容易出錯(可能寫出綜合器不理解,誤解的東西)。每個模塊只寫一個輸出,就好比沒張圖紙上只做一個與非門。我了個去,這得寫到哪輩子啊。。。
還有這要求?
其實你好好寫一個FSM就知道了。。裡面包含了組合邏輯和時序邏輯。。。
根據state的控制輸出信號(無時序關係),在一個always(*)中描述邏輯。
根據state變換的控制輸出信號(state dependent),單獨在一個always(posedge clk)中描述根據state變換的FSM自身state, 單獨在一個always(posedge clk)中描述。我之前因為不太care代碼的清晰程度。。。結果現在自己回去看自己寫的代碼就斯巴達了。。。我覺得原來提問的代碼你不要刪掉
避免干擾自己思路吧~
反正我們做些小工程絕對不會這樣寫的
我們是怎麼舒服怎麼寫沒啥參考價值,啊~~大公司里的不了解~~推薦閱讀:
※如何評價復旦大學VIP實驗室范益波教授團隊發布開源H.265視頻編碼IP核?
TAG:現場可編輯邏輯門陣列FPGA | 數字電路 | Verilog | ASIC | 數字IC設計 |