?
自打說了《玩轉(zhuǎn) IP Core》和寫了《IP 核芯志》之后,老衲就沉淪了,沉迷于“秋風(fēng)功”修煉。俗話說:“坐吃山空”,見到荷包漸漸干癟,和尚我不得不再次出山了。施主們多多捧場為好。本想說說理論的事情,奈何在下道行還淺,就只得簡單的講講 Verilog 語言這個事情了,大伙兒見諒。
這個語言本不難,道和歪嘴念經(jīng)的太多,念著念著就成了 C 語言的附屬了,這個著實的大謬也??纯凑讜念}目便知:從電路里來,到 Verilog 里去!
老僧一貫不喜歡說古,對于 Verilog 語言的歷史,施主只需要知道幾個事實:
1)1983 年誕生,此時 EDA 設(shè)計尚處于幼年,難免有很多誤區(qū)。所以,Verilog 語言里面也存在許多“擰巴”的地方。
2)1995 年,首次被 IEEE 標(biāo)準(zhǔn)化,這就是所謂的 Verilog 95 版本。
3)2001 年,IEEE 對于 Verilog 重大更新,Verilog? 2001 面世。
4)2005 年,IEEE 又進(jìn)行了細(xì)微更正,出品了 Verilog 2005。
本書里面介紹了 2001 版本,也就是應(yīng)用最廣、軟件兼容性最強的版本。
1. 模塊為本,鏈接系統(tǒng)
在概念設(shè)計過程中,設(shè)計人員總是將復(fù)雜的功能劃分為簡單的功能,模塊是提供每個簡單功能的基本結(jié)構(gòu)。設(shè)計人員可以采取“自頂向下”的思路,將復(fù)雜的功能模塊劃分為低層次的模塊。這一步通常是由系統(tǒng)級的總設(shè)計師完成,而低層次的模塊則由下一級的設(shè)計人員完成。自頂向下的設(shè)計方式有利于系統(tǒng)級別層次劃分和管理,并提高了效率、降低了成本。在實際代碼編寫過程中,會采用“自下向上”的工作流程。也就是先從前面劃分好的最下層的模塊開始寫作代碼以及完成相應(yīng)的單元測試,逐次聯(lián)線打包和測試,直至完成最高層模塊及其測試。這個“自頂向下”再“自下向上”的過程,是項目管理研究的范疇,這里稍帶提一下。
Verilog 語言被設(shè)計用來描述復(fù)雜的硬件電路。由于上述項目管理模式的普遍采用,使用 Verilog 描述硬件的基本設(shè)計單元是模塊(module)。構(gòu)建簡單的子電路,然后通過子電路的連接形成較為復(fù)雜的上層電路,最終達(dá)到系統(tǒng)的設(shè)計需求。實際的自電路元件,Verilog 語言能夠提供輸入、輸出端口,可以實例調(diào)用其他模塊,也可以被其他模塊實例調(diào)用。模塊中可以包括組合邏輯部分、過程時序部分。
一個模塊如圖 1 所示,模塊一般用方框表示,但是也有例外。圖中,方框內(nèi)的名字為模塊名,指向模塊的帶肩頭線表示輸入信號,由模塊向外的箭頭線表示模塊的輸出信號。輸入信號和輸出信號上面一般標(biāo)記信號名稱。例如,圖 1.3 中就是一個具有三個輸入信號(“輸入 11”,“輸入 12”和“輸入 13”)和兩個輸出信號(“輸出 11”和“輸出 12”)的模塊,模塊被命名為“模塊 1”。
圖 1 模塊的圖例
模塊之間的連接如圖 2 所示,如果模塊的輸出為另一個模塊的輸入,在圖中會合并兩個聯(lián)線(也就是說,用一個從第一個模塊指向第二個模塊的帶箭頭線來表示)。例如,圖 2 中“模塊 1”的兩個輸出連接到了“模塊 2”的兩個輸入。沒有在模塊之間連接的信號,則表示該信號是外部信號,例如“模塊 2”的輸入 3 信號。
圖 2 模塊之間的連接
多個模塊可以打包為一個上層的模塊,如圖 3 所示。圖中,把圖 3 里面的兩個模塊打包成為了一個上層模塊:“模塊 3”。生成的上層模塊的輸入和輸出一定包含低層模塊之間未連接的信號,但是也可以包括低層模塊之間的連接信號。
圖 3 模塊打包為上層模塊
具體這些模塊設(shè)計、模塊連接以及模塊打包如何完成,后文書自有交待。
?
2. 電路設(shè)計,二虎擋道
在任何一本《數(shù)字電子技術(shù)》教材的某個犄角旮旯,總有類似下面的論述。
“組合邏輯電路中,同一信號經(jīng)不同的路徑傳輸后,到達(dá)電路中某一會合點的時間有先有后,這種現(xiàn)象稱為邏輯競爭,而因此產(chǎn)生輸出干擾脈沖的現(xiàn)象稱為冒險。
競爭(Competition)定義為:在組合邏輯電路中,某個輸入變量通過兩條或兩條以上的途徑傳到輸出端,由于每條途徑延遲時間不同,到達(dá)輸出門的時間就有先有后,這種現(xiàn)象稱為競爭。把不會產(chǎn)生錯誤輸出的競爭的現(xiàn)象稱為非臨界競爭。把產(chǎn)生暫時性的或永久性錯誤輸出的競爭現(xiàn)象稱為臨界競爭。
冒險(Risk)定義為:信號在器件內(nèi)部通過連線和邏輯單元時,都有一定的延時。延時的大小與連線的長短和邏輯單元的數(shù)目有關(guān),同時還受器件的制造工藝、工作電壓、溫度等條件的影響。信號的高低電平轉(zhuǎn)換也需要一定的過渡時間。由于存在這兩方面因素,多路信號的電平值發(fā)生變化時,在信號變化的瞬間,組合邏輯的輸出有先后順序,并不是同時變化,往往會出現(xiàn)一些不正確的尖峰信號,這些尖峰信號稱為‘毛刺’。如果一個組合邏輯電路中有‘毛刺’出現(xiàn),就說明該電路存在冒險。
競爭冒險都是由于延遲時間的存在,當(dāng)一個輸入信號經(jīng)過多條路徑傳送后又重新會合到某個門上,由于不同路徑上門的級數(shù)不同,或者門電路延遲時間的差異,導(dǎo)致到達(dá)會合點的時間有先有后,從而產(chǎn)生瞬間的錯誤輸出?!?/p>
為什么每次讀教科書,都覺得是大筒木輝夜的驚天陰謀呢?有一種不讓讀者進(jìn)入無限月讀,誓不罷休的霸氣外露(典故見《火影忍者疾風(fēng)傳》)。當(dāng)然這是題外話,大家一樂一樂(非拉面廣告啊)。列位稍安勿躁,待貧道說人話解釋一番。
競爭就是三字經(jīng)“人之初,性本善。性相近,習(xí)相遠(yuǎn)”的道理。同一個服務(wù)器的數(shù)據(jù)包,有的是電驢 P2P(點對點,point? to point)幾乎及時到達(dá),有的卻莫名其妙被發(fā)配去糧食基地米國周游了一圈五分鐘才到您老的計算機(jī)網(wǎng)口。如果這個是上網(wǎng)瀏覽一點網(wǎng)頁,還倒罷了,這就是非臨界的。假使這個是看視頻,這個就卡那里了,用戶會很不爽,這就算臨界競爭了。
冒險的情況,壞就壞在“分進(jìn)合擊”上面。一組本來好好的輸入,非要經(jīng)過不同道路到達(dá)器件,結(jié)果可好有了時間差了,再被已處理后果不堪設(shè)想。
3. 時序器件,建立保持
問題從最簡單的開始解決,這是一個原則。先來瞧瞧一個 D 觸發(fā)器對于輸入信號的要求,就是耳朵都聽出繭子的建立時間和保持時間問題。建立時間(英文 Set up time,簡寫 Tsu),是指觸發(fā)時鐘沿(一般為時鐘信號的上升沿,本書中也沿用這個約定)到達(dá) D 觸發(fā)器之前,要求輸入信號必須已經(jīng)達(dá)到穩(wěn)定的時間。對應(yīng)的,保持時間(英文 Hold time,簡寫 Th),是指觸發(fā)時鐘沿到達(dá) D 觸發(fā)器之后,要求輸入信號還需要保持必須穩(wěn)定的時間。建立時間、保持時間相對于觸發(fā)時鐘沿的關(guān)系,如圖 4 所示。
圖 4 建立時間、保持時間相對于觸發(fā)時鐘沿的關(guān)系
“我們都是木頭人,不許說話不準(zhǔn)動”,建立時間和保持時間就是輸入信號的“木頭人時間”。做游戲的時候,“木頭人時間”內(nèi)有了晃動或者出聲,那游戲就輸了。電路里面,如果輸入信號在建立時間或者保持時間里面發(fā)生了變化,那就是仿真(尤其是時序仿真)里面所謂“全國山河一片紅”了,那個絕對是災(zāi)難(聲明:貧道與中國臺灣沒有關(guān)系)。
不推導(dǎo)“復(fù)雜”公式,直接給結(jié)論:要滿足建立與保持時間,時序系統(tǒng)才能穩(wěn)定工作。
對于 FPGA 設(shè)計,這個“滿足”是靠寫時序約束,來教導(dǎo)綜合軟件和布局布線軟件實現(xiàn)的。
首先,這里解答“什么是布局布線”這個問題。簡單理解,“布局布線”就是在器件(FPGA/ASIC)里面畫 PCB。布局是把器件放到相應(yīng)的位置上,布線是把有關(guān)聯(lián)的器件連接起來。
?
機(jī)器都是笨的,即使是號稱“電腦”的計算機(jī),需要人來操作才能完成需要的任務(wù)。如果僅僅把設(shè)計給了設(shè)計環(huán)境,不做任何設(shè)計上的說明(也即所謂的“時序約束”),機(jī)器絕對會搞出一些工程師不希望的結(jié)果出來。記?。喝魏喂ぞ叨疾粫⒅貒L試尋找到達(dá)最快的布局布線結(jié)果。這個正如畫 PCB 的工程師絕對不會使用軟件提供的所謂“自動功能”。
最常用的時序約束有時鐘、輸入輸出時延和“虛假路徑”幾種,下面一一介紹:
時鐘的頻率和性質(zhì)決定了其他時延的上限。時鐘頻率越高、時鐘抖動越大,允許的布局布線時延以及組合邏輯時延也就越小。
時鐘信號包括三個性質(zhì):周期與占空比、時鐘間的偏移和時鐘的抖動。如圖 5 所示,時鐘的周期定義為理想時鐘的兩個觸發(fā)沿之間的時間間隔;時鐘的占空比定義為一個周期內(nèi),理想時鐘高電平“1”信號占整個時鐘周期的比例;時鐘之間的偏移定義為兩個同源時鐘之間的、固定的出發(fā)沿的時間差;時鐘的抖動定義為一個時鐘信號相對于理想時鐘,上升沿與下降沿可能變換的前后范圍。最后多嘴一句,這些實際系統(tǒng)中的時鐘與理想時鐘的差別是芯片內(nèi)的“時鐘樹”造成的。
圖 5? 時鐘的時序約束參數(shù)
下面兩折比較類似,現(xiàn)在合并演出(臺下:偷工減料,退票?。狠斎?/ 輸出路徑時延表標(biāo)記芯片的前端 / 后端芯片的時序特性 / 要求。這個基本上就是,把前端芯片看作 D 觸發(fā)器,告訴工具前端芯片的輸出時延,這樣可以保證系統(tǒng)對于輸入可以可靠采樣。同樣的,把后端芯片看作 D 觸發(fā)器,通知工具后端芯片的建立時間和保持時間,可以保證可靠的信號輸出。整個系統(tǒng)的鏈接情況,如圖 6 所示。
圖 6 輸入 / 輸出路徑時延
下一出是《珍珠塔》,“皇帝家也有三門草鞋親,謝謝”(這就完了???臺下騷動:“退票!退票!”)。實際系統(tǒng)中,很少有必須工作時間都一致的,總會存在一些“急先鋒”遇到的“慢郎中”的。別抬杠,您老沒遇到,只能說明您還毛嫩。多周期的時序約束,實際上是減少布局布線壓力的,這個和前面 存在差異。對于這些需要計算較慢的單元 / 路徑,可以降低要求,把好的資源讓渡給需要快速的部分使用。圖 7 就是一個例子,上面是需要快速解決的單元們,下面是可以“慢慢來”的部分。多周期約束定義了到底可以多慢做完這個工作。
圖 7 多路徑約束
最后出場的就是“虛假路徑”這個草包,主要表現(xiàn)時鐘域之間路徑和測試邏輯,工具對這類任務(wù)也采取不聞不問、聽之任之的態(tài)度。
?
4. 定制器件,細(xì)節(jié)入手
FPGA 才是“上得廳堂,下得廚房,安得系統(tǒng),打得流氓”的多面手,其結(jié)構(gòu)如圖 8 所示。
圖 8 某 FPGA 的功能結(jié)構(gòu)圖
其中包括可編程輸入輸出單元(IOB,Input Output Block)、可配置邏輯塊(CLB,Configurable Logic Block)、數(shù)字時鐘管理模塊(DCM,Digital Clock Management) 和嵌入式塊 RAM(BRAM,Block RAM) 等部分。這個里面與 Verilog 語言設(shè)計電路有關(guān)的部分是 CLB,揭開 CLB 的蓋頭來,您老將會看到如圖 9 所示的一副尊容。以 Xilinx 公司的 FPGA 器件為例,CLB 由多個(一般為 2 個或 4 個)相同的 Slice(這個詞還真不好翻譯,查了半天度娘,看到唯一靠點譜的說法是邏輯片)和附加邏輯構(gòu)成。其中,Slice 是基本的邏輯電路實現(xiàn)單元,屬于中等后面介紹;外圍電路中,開關(guān)網(wǎng)絡(luò)主要完成一般信號的可配置連接,快速連接線進(jìn)行時鐘和復(fù)位等關(guān)鍵信號的連接。
圖 9 Xilinx 公司 FPGA 中 CLB 的結(jié)構(gòu)圖
Slice 的結(jié)構(gòu)如圖 10 所示,一個 Slice 由兩個 4/6 輸入的 LUT(查找表,Look Up Table)、進(jìn)位算術(shù)邏輯、D 觸發(fā)器和函數(shù)復(fù)用器組成。算術(shù)邏輯包括一個異或門和一個專用與門,一個異或門可以使一個 Slice 實現(xiàn) 2bit 全加操作,專用與門用于提高乘法器的效率(這個后文書有詳細(xì)講解,這里屬于“看熱鬧”的內(nèi)容);進(jìn)位邏輯由專用進(jìn)位信號和函數(shù)復(fù)用器(MUXC)組成,還包括兩條快速進(jìn)位鏈,用于提高 CLB 模塊的處理速度,用于實現(xiàn)快速的算術(shù)加減法操作。4 輸入 LUT 用于實現(xiàn)組合邏輯運算。
圖 10 Xilinx 公司某款 FPGA Slice 的結(jié)構(gòu)
同學(xué)們有沒有感到驚訝呢?如果有,說明你的《數(shù)字電子技術(shù)》的學(xué)費沒白交。說好的用于組合邏輯的門級電路呢?還有編碼器、譯碼器等等,等等?這些器件都沒有,怎么設(shè)計組合邏輯???“風(fēng)蕭蕭兮易水寒,虞兮虞兮奈若何?”
LUT 本質(zhì)上就是一個 RAM,里面存著真值表。目前 FPGA 中,多數(shù)采用 4 輸入的 LUT,所以每一個 LUT 可以看成一個有 4 位地址線的 的 RAM。 當(dāng)用戶通過原理圖或 HDL 語言描述了一個邏輯電路以后,EDA 軟件會自動計算邏輯電路的所有可能結(jié)果,并把真值表事先寫入 RAM。這樣,每輸入一個信號進(jìn)行邏輯運算就等于輸入一個地址進(jìn)行查表,找出地址對應(yīng)的內(nèi)容,然后輸出即可。對于輸入高于 4 比特的輸入,EDA 軟件會自動把輸入拆分成若干 LUT,最后聯(lián)合輸出。(真值表是什么,這個不用講了吧。不懂的人,數(shù)電考試肯定作弊的,回去重修?。┕俜秸f法是:“由于基于 LUT 的 FPGA 具有很高的集成度,其器件密度從數(shù)萬門到數(shù)千萬門不等,可以完成極其復(fù)雜的時序與邏輯組合邏輯電路功能,所以適用于高速、高密度的高端數(shù)字邏輯電路設(shè)計領(lǐng)域” 。所以本書介紹的結(jié)構(gòu)竟然是流行趨勢,好極好極!
最后來看一看開發(fā)流程里面的“綜合”這個過程,那些“優(yōu)化”什么的亮瞎鈦合金狗眼的概念,對于 FPGA 的組合邏輯方面還存在嗎?我們估計獨立思考。貧道聞到了退化的味道。這也不是說 EDA 軟件沒用,LUT 組合方面的算法還是可圈可點的嘛。
?
5. 語言缺陷,電路子集
Verilog 設(shè)計之初就號稱可以一次打兩只鳥:設(shè)計和驗證,殊不知這兩個方向的思路卻相差很大。數(shù)字邏輯的設(shè)計是基于數(shù)電的,受限制于電路器件的特性;反觀數(shù)字邏輯系統(tǒng)的驗證,這是一個純粹軟件仿真的活計,工程師更加喜歡一般程序設(shè)計語言的思路。在老衲參與的很多技術(shù)討論里面發(fā)現(xiàn),這“兩鳥”不僅僅沒有打到,這把“米”是一定“蝕”了。大多數(shù)初學(xué)者完全分不清那些可以綜合,那些不可以。
老僧也在總結(jié)這個現(xiàn)象的原因,吾稱之為:“教不得法,學(xué)不得法”。“教不得法”是指,很多關(guān)于 Verilog 的書繼承了程序語言教材的結(jié)構(gòu),把語句分為:算術(shù)運算、條件判斷和循環(huán)等等部分,完全不區(qū)分可綜合性,這樣有誤導(dǎo)的嫌疑;“學(xué)不得法”是一個歷史原因,大多數(shù)學(xué)習(xí)者實際上具有很強的程序語言,例如 C 語言,的基礎(chǔ),這反而是有害的。人的思維是有習(xí)慣性的,Verilog 的形式又與 C 語言很類似,所以多數(shù)人都把 C 語言設(shè)計里面的習(xí)慣不自覺的帶入了 Verilog 語言的電路實現(xiàn)。于是乎,綜合軟件上報的錯誤“如滔滔江水,綿綿不絕”,實現(xiàn)與想象不一致也是“如黃河泛濫,一發(fā)不可收拾”。以上是一家之言啊,切勿對號入座,否則必有受傷者,老衲不負(fù)責(zé)醫(yī)藥費!
數(shù)字電路和程序語言的區(qū)別,別告訴我您不知道。下面姑且總結(jié)幾條,叫大家以后面試的時候,可以說得頭頭是道。
1. 對應(yīng)于仿真:C 語言的代碼是一行一行執(zhí)行的,屬于順序結(jié)構(gòu);而 Verilog 是一種硬件描述語言,語句同時進(jìn)行,屬于并行結(jié)構(gòu)。
這個特點說起來有點抽象,我們舉一個例子吧。就對于某家上面舉出的代碼,減震器記得時刻到了。
表 1 兩種語言的仿真方式差別
? |
|
Verilog |
代碼 |
int a, b, c; …… c? = a; a = b; b = c; …… |
reg [0:7] a, b, c; …… always @ (posedge Clock) begin …… c <= a; a <= b; b <= c; …… end |
初始值 |
a = 1; b = 2; c =3 |
|
結(jié)果 |
a = 2; b = 1; c = 1 |
第一節(jié)拍:a = 2; b = 3; c = 1; 第二節(jié)拍: a = 3; b = 1; c = 2; 第三節(jié)拍:? a = 1; b = 2; c = 3; 第四節(jié)拍:a = 2; b = 3; c = 1; …… |
“不看不知道,世界真奇妙”,套用以前《正大綜藝》的臺詞。見到黃河了?佛主說:回頭是岸,南無阿彌陀佛。
避繁就簡,結(jié)合網(wǎng)上度娘出來的資料,老衲針對 Verilog 可綜合性設(shè)計,分別 FPGA 和 ASIC 的情況,給列位總結(jié)出了表 2(內(nèi)部資料,注意保密)。表里面可能有一些超前的概念,例如 always、循環(huán)和阻塞 / 非阻塞賦值等,這些會在后文書里面介紹,這里先說聲對不起。
表 2 Verilog 可綜合性設(shè)計原則匯總表
原則 |
FPGA 適用 |
ASIC 適用 |
不使用初始化賦值 |
不適用 |
適用 |
不使用時延 |
適用 |
適用 |
不使用循環(huán)次數(shù)不確定的循環(huán)語句 |
適用 |
適用 |
不使用移位次數(shù)不確定的移位操作 |
不適用 |
適用 |
不使用復(fù)雜運算,如乘法、除法,冪等 |
依賴于綜合軟件 |
適用 |
不使用用戶自定義原語 |
適用 |
適用 |
盡量使用同步方式設(shè)計電路 |
適用 |
適用 |
除非是關(guān)鍵路徑的設(shè)計,一般不采用調(diào)用門級元件來描述設(shè)計的方法,建議采用行為語句來完成設(shè)計 |
適用 |
不適用 一些組合邏輯優(yōu)化可使用門電路簡化 |
用 always 過程塊描述組合邏輯,應(yīng)在敏感信號列表中列出所有的輸入信號 |
僅適用于 Verilog 95 |
僅適用于 Verilog 95 |
所有的內(nèi)部寄存器都應(yīng)該能夠被復(fù)位,在使用 FPGA 實現(xiàn)設(shè)計時,應(yīng)盡量使用器件的全局復(fù)位端作為系統(tǒng)總的復(fù)位 |
適用 |
適用 |
對時序邏輯描述和建模,應(yīng)盡量使用非阻塞賦值方式 |
適用 |
適用 |
對組合邏輯描述和建模,既可以用阻塞賦值,也可以用非阻塞賦值 |
適用 |
適用 |
同一個過程塊中,最好不要同時用阻塞賦值和非阻塞賦值 |
適用 |
適用 |
不能在一個以上的 always 過程塊中對同一個變量賦值 |
適用 |
適用 |
對同一個賦值對象不能既使用阻塞式賦值,又使用非阻塞式賦值 |
適用 |
適用 |
避免混合使用上升沿和下降沿觸發(fā)的觸發(fā)器 |
適用 |
適用 |
同一個變量的賦值不能受多個時鐘控制,也不能受兩種不同的時鐘條件(或者不同的時鐘沿)控制 |
適用 |
適用 |
避免在 case 語句的分支項中使用 x 值或 z 值 |
與綜合軟件有關(guān) |
與綜合軟件有關(guān) |
話說兩頭,老衲從來不提倡先寫代碼,然后去看能不能綜合的設(shè)計步驟。老僧把那叫做“C Style”、“邏輯派”或者“語法黨”,某家提倡的是“電路門”。早在《IP 核芯志》里面,吾就說過了:“看圖說話基本法,電路映射程序中?!?,這是不二法門。聽不懂嗎?就是先畫電路 / 時序 / 狀態(tài)轉(zhuǎn)移圖,再去寫代碼的意思!還不懂?完全無語了,容我冷靜一下。
這正是:
“
遠(yuǎn)看石塔黑乎乎,上面細(xì)來下面粗。有朝一日翻過來,下面細(xì)來上面粗。
都曉倒著很懸乎,重心不穩(wěn)難以扶。不知語言學(xué)習(xí)路,也要數(shù)電加基礎(chǔ)。
”
?
與非網(wǎng)原創(chuàng)內(nèi)容,謝絕轉(zhuǎn)載!
如果有任何技術(shù)問題,歡迎留言提問~~