老師說沒電路就不要寫代碼,但我寫個乘法器在綜合前都想不出它電路啥樣,全加器還行。


首先,你們老師說的是正確的,但可能是說的不夠詳細,或者你表達的不全。

準確的說,在寫Verilog前,要做到心中有數字電路。

數字電路設計主要就是,選擇器、全加器、比較器,乘法器,幾個常用邏輯門,再加個D觸發器,電路基本都能實現了。這些器作為基本單元,對於工程設計來說,並不需要過多的關注它更底層的門或晶體管的樣子。

我在學生時代剛開始學數字電路設計的時候,很長一段時間都是眼裡只有代碼和功能時序,沒有一個良好的正向設計思路。比如,知道要實現的功能,二話不說開始新建.v寫代碼,邊寫邊想,這樣導致的結果,準確的來說時序都是調出來的,而不是設計出來的。

寫的代碼幾乎全使用

always @(posedge clk or negedge rst_n)

從不考慮消耗的資源和面積,學生階段的項目用FPGA也很難把晶元資源用爆,全用的寄存器肯定不會出現時序不滿足的情況。

而實際上做設計最應該關注的是PPA(Performance, Power, Area),寄存器多面積必然大,處理必然延時大,功耗怎麼小。寄存器打拍是因為組合邏輯路徑過長,才往中間插一拍,而不是隨便打。

在寫Verilog前,不光要心中有電路,還要有關鍵時序圖,有一個硬體的詳細設計方案。而且不光在心裡,還得寫下來,畫下來,整理成文檔。在動手寫代碼前,心中就有了譜,清楚的知道,我這個設計能成。

而一個正確的正向設計流程應該是,首先確定設計模塊的功能需求,劃分整體的硬體結構,可以大致分為幾個部分。每一個部分實現一個獨立的功能,不同部分之間介面交互確定。

設計分為數據通路和控制通路。

數據通路決定了整體數據流的走向,整個模塊計算分為哪幾部分,哪些是可以排成流水線,中間的數據流是否需要斷掉,用RAM存還是RegFile存儲。數據通路中數乘法器單元的面積最大,一般都是採用的是分時復用的方式。整個數據通路的計算流整理出來後,基本上乘法的最大個數也統計出來,然後控制計算模塊在不同的時間復用。乘法器的數量和復用程度決定了一個設計是否更優,好的設計是整個數據通路中乘法器幾乎空閑不下來。

到了單個計算模塊,每個模塊都能畫出一個簡單的計算電路圖,

上面這個圖的意思是,a * b或c * d的結果進行累加,最後飽和截位進行輸出。

畫出了電路圖,就可以大體估算出,整個設計需要的寄存器的數量,乘法器的數據。乘法器和寄存器的量級估算基本上就可以確定整個設計的面積單位量級。

控制通路就是玩時序設計,畫出時序圖,具體的實現就是各種大大小小的計數器、enable、start、end、valid、flag信號。系統整體的調度,就記住一句話,狀態機大法好。當然雖然說狀態機可以實現一切時序電路,但並不是所以時序功能都適合用狀態機。比如,整個設計的處理都是連續流水處理,那麼對於狀態機的來說就是一個狀態,不需要用狀態機了。

控制通路的設計就不是畫電路圖了,而是畫時序圖,狀態機的跳轉,各種控制信號的時序交互,握手,ram的讀寫控制等等關鍵時序圖,都需要畫出來。控制通路上的資源佔比很少,一個10bit的計數器就可以計到1023,一個數據打拍就32bit,各種flag就1bit,更不值一提。所以設計中評估資源和優化主要關注的數據通路。

數據通路和控制通路整理完成後,整個設計的處理時間和佔用資源基本上就可以估算出來。上面的工作都完成後,然後就是照圖施工,你會發現,寫代碼就完全是個體力活的事情。只要你方案設計的好,圖畫的好,文檔寫的清晰,隨便找幾個會寫Verilog的代碼都能寫出來(誇張的表述)。

回到我們說的Verilog HDL的HDL的全稱是Hardware Description language,是硬體描述語言,不是design,是在描述之前,你就得想好要描述的東西。做設計的時候按照這樣的思路和套路去想,去做。

再來說說做設計時的描述方式,一些更底層的描述方式,比如

sel[1:0] 等效於 sel[1:0] == 2b11
~(|sel[1:0])等效於 sel[1:0] == 2b0
~a[3:0] + 1b1 等效於 -a[3:0]
c[4:0] = {a[3], a[3:0]} + {b[3], b[3:0]}等效於c[4:0] = $signed(a[3:0]+b[3:0])

變數乘以一個常數用移位加

assign data_out[5:0] = ({6{data_vld0}} data0[5:0])
| ({6{data_vld1}} data1[5:0])
| ({6{data_vld2}} data2[5:0])
| ({6{data_vld3}} data3[5:0]);

這是一個4選1的數據選擇器,並且要求四個vld不能同時為1。

實際上,拋開代碼的可讀性,很多代碼的寫法,並不需要多此一舉用更底層的描述方法,高級的描述只要語法和工具支持,就可以直接使用,更底層的描述,我們以為會用更少邏輯,但是工具可能也會優化的更好,比如,變數乘以常數,a * 2『d3,工具會幫你優化成 a &

當然也不能過分依賴工具,能復用的邏輯盡量復用,先選後比,先選後加,先選後乘。畢竟自己寫出來的邏輯是確定的,而交給工具並不一定會按你想的方向去優化綜合。而做一個設計在確保代碼功能實現的前提下,還需要考慮的是代碼可調試性和可維護性。

最後再扯一段我用過好幾次的話

學習Verilog的五個階段

00:心中無電路,代碼無電路

01:心中有電路,代碼無電路

10:心中有電路,代碼有電路

11:心中無電路,代碼有電路

00:心中無電路,代碼無電路

達到10就可以了,這時候你就是高手了,再往後就開始玩玄學了。

歡迎糾正,歡迎補充。


不太同意那個說不需要深入到邏輯門的答案。對於一般的開發者來說,如果僅是希望能夠比較快速順利的完成功能,確實EDA能夠完成不少優化工作。但EDA不是萬能的,有許多EDA解決不了,只有對底層電路了如指掌的開發者才能完成的設計。舉一個個人認為比較有代表性的例子,5g nr ldpc 的提升值(lifting size)設計成如今這種 [公式] 形式,一個很重要的因素是設計准循環電路中,如果是 [公式] 的形式可以使用banyan switch+QSN的電路結構,比單純QC-LDPC shift network(QSN)(提升值可以為任意值),要節約大概30%的2-1MUX。這一改動在保證了LDPC碼的靈活性的前提下節約了相當數量的晶元面積,順帶簡化了之後LDPC矩陣的設計,這種結合了演算法和實現的優化不是靠EDA能夠做到的。高端的晶元,比拼的就是這一點一滴的細節,對於一個追求卓越的工程師來說,滿足於rtl層的設計是遠遠不夠的


主要是「電路」這個概念現在被異化得比較嚴重。傳統上電路應該是電感、電阻、電容、導線再加上晶體管等。而數字電路出來以後,就直接從晶體管級抽象成邏輯門,再進一步抽象成各種中規模集成電路級別的模塊。雖然也可以把這些個模塊稱為電路,但其實更多的是關心它們的邏輯功能而已。

其實對於使用Verilog來描述硬體,基本上是在RTL這一層做的。除非你特定情況需要自己從門級甚至晶體管級自己定義一個特殊的電路結構。所以在大多數時候根本不用關心那麼底層,別說晶體管了,門級結構也不用想。這也是很多搞模擬/射頻電路的老師認為我們這些「搞數字的」根本不算「搞電路的」。

在RTL這一層做事,沒必要去想最後門級電路長什麼樣,不然就如同 @Podes 知友說的,失去了使用Verilog的意義。不過,熟悉常見的中規模集成電路級別的基本功能以及利用這些經典模塊來構建小系統的能力要具備,尤其是對於入門的新手而言。不然就成了腳踩西瓜皮,滑到哪裡算哪裡。

至於什麼乘法器之類的,有學生來問我我一律回答直接調用IP核,根據需求看IP核的手冊加以設置。重點不在這裡。

最後說一句:要麼是你的老師沒有教過你們從功能分析到Spec/架構定義再到RTL建模/編碼的全流程,要麼就是你那節課逃掉了沒去。前者,鍋由你的老師背;後者,自己好好反省,錯過了最重要的一課。如果沒有這一課,講再多的什麼語法細節之類的,都是浪費時間。


你老師的確是對的。

只是表述方式有問題,我如果帶小朋友是不會說這些話的,因為我知道他很容易像題主一樣曲解或者壓根理解不了,這些都是些正確的廢話。

在我看來,這句話有極強的誤導性

圖片來自於網路

先聲明一下,作為一個人,我們大多數人的腦子在計算時都比不上電腦CPU,是不可能在你設計數字電路的時候完整的描繪出每個與非門的,如果你能做到的話,建議直接把自己腦子license給S家讓他們研究下看能不能產生技術突破,因為你是「行走的VCS/DC」。

如果讓我比喻,數字電路就是一棟精巧的超大建築,數字電路設計師的工作,是描述這個建築裡面那個房間是什麼功能,通往各個房間的路是怎麼樣排列的,哪裡有個樓梯,哪裡不能拐彎(Design Proposal).......而類似於VCS這樣的模擬工具,相當於是先幫你虛構了這個建築(編譯),然後虛構了一群人去使用這個建築(激勵),並且報告給你,讓你確認是不是達到了你的設計目的(模擬)。DC這樣的工具就是把最後的建築圖紙交給建築公司直到最終成為晶元。

圖片來自於網路

所以你老師的意思是讓你先畫出這個結構圖,並不是要你精準的想到每個房間哪裡用什麼材料(邏輯門)。類似於這樣:

另外,描述本身還是有一些小技巧的,我看來這本書裡面比較詳細吧,供君參考。

Verilog編程藝術京東¥ 75.80去購買?


這是要害死人的節奏啊。

你應該反問一句:「老師,您說的電路具體是什麼意思?」不知道這裡的「電路」是指什麼,就不要人云亦云什麼「心中有電路」啦。

一個數字邏輯裡面最基本的反相器的電路是什麼?或者一個最簡單的時序部件 D觸發器的電路是怎樣的?能回答出來嗎?32bit的全加器的電路你能在腦袋中想像出來嗎?是個正常的人都無法做到心中有這種「電路」!

所謂寫Verilog做數字邏輯設計要做到「心中有電路」,這個電路是指:RTL寄存器傳輸級這一個抽象層次的電路結構,或者說是以時序、節拍為核心要素的電路結構。絕對不是指組合邏輯電路,更不是指晶體管、R、L、C等這種物理層的circuit。

所有複雜的數字邏輯系統都可以歸一化為:1、不同層次的有限狀態機結構組合;2、或者時序邏輯和組合邏輯的組合;3、或者時序控制部件與運算部件的組合。

以上三種說法既代表著構建數字系統的不同思維方式,也直觀地表達了三種不同的verilog描述風格。任何一個基於標準單元庫的數字電路都可以使用三種方式之一描述出來。三種方式不是互斥的,各自都是完備的,只是解析問題的角度不同。這個跟軟體開發裡面的「設計模式」概念有點類似。

三種模式可以單獨使用也可以混合使用。不同的數字功能模塊適合不同的描述風格。比如,一個IIC協議解析使用狀態機描述方式很容易理解也很容易寫出來,使用另外兩種方式就比較麻煩;一個指令系統或者數據流使用控制+運算的風格來描述比較順手,其他的方式就非常痛苦;等等。

所以,結論是:你在設計數字電路時需要想到的是怎麼把時序結構排好,如何把過於複雜的運算邏輯分到不同節拍裡面去,從而達成PPA(Performance,Power,Area)優化和折中。思考的起點就是RTL級而不是門級的結構。

當然,有人會跟我杠說:現實中還是有人基於基本門單元用verilog來做結構化電路描述啊。當然有。但是寫這種電路結構的估計只有兩類人:1. 做全定製設計宏單元庫的人;2.做模擬電路的人。這兩類人都實質上在設計晶體管級電路,他關注的是circuit的特性,比如電流(功耗)和電容(速度)這些參數。這樣做的人還有一種可能是學生吧,我估計他也只是為了完成數字邏輯設計課程題目。

如果你認為自己腦容量足夠大,我做大規模數字系統設計時偏要關注到組合邏輯電路的結構細節,那我只能認為你太自信了,自信到覺得EDA後端工具比你還蠢。記住一點:在RTL抽象級以下的電路優化方面,人在機器面前弱爆了。


推薦閱讀:
相关文章