老師說沒電路就不要寫代碼,但我寫個乘法器在綜合前都想不出它電路啥樣,全加器還行,寫Verilog如何做到心中有電路?
首先,你們老師說的是正確的,但可能是說的不夠詳細,或者你表達的不全。
準確的說,在寫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] == 2'b11
~(|sel[1:0])等效于 sel[1:0] == 2'b0
~a[3:0] + 1'b1 等效于 -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 << 2’d1 + a。甚至可能還優化得更好,所以還不如直接用乘法器,*號。
當然也不能過分依賴工具,能復用的邏輯盡量復用,先選后比,先選后加,先選后乘。畢竟自己寫出來的邏輯是確定的,而交給工具并不一定會按你想的方向去優化綜合。而做一個設計在確保代碼功能實現的前提下,還需要考慮的是代碼可調試性和可維護性。
最后再扯一段我用過好幾次的話
學習Verilog的五個階段
00:心中無電路,代碼無電路
01:心中有電路,代碼無電路
10:心中有電路,代碼有電路
11:心中無電路,代碼有電路
00:心中無電路,代碼無電路
達到10就可以了,這時候你就是高手了,再往后就開始玩玄學了。
歡迎糾正,歡迎補充。
審核編輯 :李倩
-
電路
+關注
關注
172文章
5928瀏覽量
172391 -
寄存器
+關注
關注
31文章
5355瀏覽量
120546 -
Verilog
+關注
關注
28文章
1351瀏覽量
110139
原文標題:寫Verilog如何做到心中有電路?
文章出處:【微信號:IP與SoC設計,微信公眾號:IP與SoC設計】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論