?
施主們辛苦了,學(xué)習(xí)語言一貫是一個苦差事。學(xué) Verilog 還算好的,到底還是人工語言,有規(guī)律,還有《數(shù)字電子技術(shù)》這門課墊底(沒學(xué)好這門功課的同學(xué) ---- 學(xué)好與否,與您老的考試成績無關(guān) ---- 趕快回去找本教材好好看看)。如果是學(xué)習(xí)自然語言,那就更麻煩了。除了記憶還是記憶,這就是學(xué)習(xí)的規(guī)律,沒有捷徑的。
前面講解了組合邏輯的事情,從今天起老衲來說說時序邏輯的端倪。
在數(shù)字電路理論中,時序邏輯電路是指電路任何時刻的穩(wěn)態(tài)輸出不僅取決于當(dāng)前的輸入,還與前一時刻輸入形成的狀態(tài)有關(guān)。 這跟組合邏輯電路相反,組合邏輯的輸出只會跟目前的輸入成一種函數(shù)關(guān)系。 換句話說,時序邏輯擁有儲存器件(內(nèi)存)來存儲信息,而組合邏輯則沒有。換句話說,是否存在存儲器件是判斷一個電路是否是時序邏輯電路的關(guān)鍵。
時序邏輯按照其中信號變化的時機(jī),又分為同步時序和異步時序兩種。
同步電路是一種由定時器產(chǎn)生的時鐘信號驅(qū)動的電路。在一個同步電路中,它的各個期間中,邏輯信號的每一個變化都是同時的。所有信號變化都服從一個特別的同步信號,稱為“時鐘”。不管邏輯的規(guī)模有多大,都假設(shè)對于時鐘信號而言,其他邏輯部分的變化的時延是微小的。所以,整個電路的行為 -- 無論任何一個信號—都可以在任何速度上精確地被預(yù)見。在實際電路中,時鐘源到達(dá)各個觸發(fā)器的網(wǎng)線長度不同,因此需要使用時鐘緩存單元來盡量降低時鐘偏移的影響。
異步電路邏輯更加體現(xiàn)邏輯的本質(zhì),但是由于它的彈性關(guān)系,其也是設(shè)計上困難度最高的。 最基本的儲存組件是鎖存器。 鎖存器可以在任何時間改變它的狀態(tài),依照其他的鎖存器信號的變動,他們新的狀態(tài)就會被產(chǎn)生出來。 異步電路的復(fù)雜度隨著邏輯級數(shù)的增加,而復(fù)雜性也快速的增加,因此他們大部分僅僅使用在小的應(yīng)用。
在一般的設(shè)計中,會采用同步電路進(jìn)行設(shè)計。這是方便分析和設(shè)計的要求,一般設(shè)計人員的大腦只能把握這樣的范圍了。在自己可以控制的范圍內(nèi)設(shè)計,這是一個行之有效的策略。
很多情況下,目前大規(guī)模的數(shù)字電路系統(tǒng)里面,對應(yīng)不同功能部分,可能存在多個時鐘。但是,每一個部分一般由一個時鐘驅(qū)動,這個范圍內(nèi)可以視為同步電路。但是,因為不同時鐘的頻率與相位的差別,不同部分之間的信號有無法滿足“邏輯信號的每一個變化都是同時”的要求。這是一種特殊的,但是常用的異步電路邏輯。對于這種電路后文書將會詳細(xì)介紹,但是這種電路的分析過程倒是更類似于同步邏輯。
1. 時鐘啟動,節(jié)拍控制
在時序電路里面,再強(qiáng)調(diào)時鐘的作用也不為過的。一般而言,在一個系統(tǒng)里面只會采用一種類型的器件。這樣設(shè)計起來簡單,而且不會存在不能實現(xiàn)的情況。最常用的器件呢,就算是 D 觸發(fā)器了。這個器件使用起來,類似于對于信號的采樣,最簡單不過。
D 觸發(fā)器的電氣符號里面,一般常用的有三組輸入信號:數(shù)據(jù)輸入 D、復(fù)位 / 初值輸入 S 和 R 以及時鐘信號 CLK。忽略掉復(fù)位 / 初值輸入 S 和 R 的影響,D 觸發(fā)器的真值表如表 1。其中,Qnext 為下一個有效時鐘沿的 Q 的值。從信號處理的角度,可以將 D 觸發(fā)器理解為在時鐘有效沿對于輸入采樣,并且延遲一個時鐘節(jié)拍輸出的單元。D 觸發(fā)器的時序圖如圖 1 所示。
表 1 D 觸發(fā)器的真值表
D |
CLK |
Q |
Qnext |
0 |
↑ |
x |
0 |
1 |
↑ |
x |
1 |
x |
0/1 |
0 |
0 |
x |
0/1 |
1 |
1 |
圖 1 D 觸發(fā)器的時序圖
正因為 D 觸發(fā)器有延時的作用,有時候為了一些相關(guān)的數(shù)據(jù)到達(dá)時間對齊,會使用 D 觸發(fā)器對一些先到達(dá)的數(shù)據(jù)的延時操作。注意,D 觸發(fā)器能夠完成的時延一定是時鐘周期的整數(shù)倍。這個時候,工程上經(jīng)常說的術(shù)語是“打 X 拍子”,X 是一個整數(shù)。這個嚴(yán)格來說就是延遲 X 個時鐘周期的意思。打一拍子就用一個 D 觸發(fā)器,打兩拍子就用兩個 D 觸發(fā)器串聯(lián),以此類推。打多個拍子的代碼實現(xiàn)方法,會在下一講中介紹,這里僅僅給大伙兒建立一個概念。
?
作為一個簡單的例子,老衲推薦計數(shù)器。計數(shù)器,很多人見過:大家坐飛機(jī)的時候,進(jìn)門前,空姐手里拿的,見一個人“咯嗒”按一下,上面的數(shù)字加一。這個計數(shù)器,用來統(tǒng)計最終進(jìn)入飛機(jī)的人數(shù)的,以備后用(某家就不再多說了,不能烏鴉嘴。方丈告誡我:嘴下留德,勝造七級浮屠)。這里的計數(shù)器,功能和空姐手里的差不多,只不過她那是機(jī)械的,這里的是電子的。她那里的按鍵,在這里是使能信號“enable”。計數(shù)器的結(jié)構(gòu)如圖 2 所示,其中加入了溢出保護(hù)機(jī)制。其代碼如例 1,其中給出了帶溢出保護(hù)和不帶溢出保護(hù)的兩套代碼。
圖 2 計數(shù)器的結(jié)構(gòu)圖
上圖中沒有給出時鐘 CLK 和復(fù)位 RST 信號的處理,這是一般時序邏輯結(jié)構(gòu)圖的慣例。這兩個信號的處理太一般了,所以被偷懶地省略了。
【例 1】計數(shù)器代碼
無溢出保護(hù) |
具有溢出保護(hù) |
module counter ? ( ??? input CLK, input RST, ??? input enable, ??? output reg[7:0] counter, ? ); //Load other module(s) //Definition for Variables in the module //Logical always @(posedge CLK, negedge RST) begin ??? if (!RST) ??? //Reset ??? begin ?????? counter <= 8'h00; ??? end ??? else if(enable) ??? //Counter enabled ??? begin ??? ????counter <= ??counter + 8'h001; end else begin end end endmodule |
module counter ? ( ??? input CLK, input RST, ??? input enable, ??? output reg[7:0] counter, ? ??output reg overflow_flag ? ); //Load other module(s) //Definition for Variables in the module //Logical always @(posedge CLK, negedge RST) begin ??? if (!RST) ??? //Reset ??? begin ?????? {overflow_flag, counter} <= 9'h000; ??? end ??? else if (overflow_flag) ??? //Over flew and reset ??? begin ??????? {overflow_flag, counter} <= 9'h000; ??? end ??? else if(enable) ??? //Counter enabled ??? begin ??? {overflow_flag, counter} <= {overflow_flag, counter} + 9'h001; end else begin end end endmodule |
不具有溢出保護(hù)的功能的計數(shù)器,在實際工程中是有問題的。就按例子中 8 比特寬度的計數(shù)寬度為例,其最大計數(shù)值是 255。如果來了 256 個乘客,沒有溢出保護(hù)的代碼會顯示計數(shù)值為 0,這顯然會帶來誤解。
還有代碼中利用了組合操作“{ }”來簡化的書寫,也請讀者注意這個技巧。
?
2. 循環(huán)串接,鏈狀傳遞
最簡單的 D 觸發(fā)器組成的電路是什么?那一定是只有一個 D 觸發(fā)器的、延遲一個時鐘節(jié)拍的電路了。這個老和尚上一講已經(jīng)介紹了,現(xiàn)在貧道在深入一步。“稍稍難一點(diǎn)的電路是什么呢?”參考圖 3.1 里面的一般化的數(shù)字邏輯系統(tǒng)架構(gòu),去掉各種組合邏輯之后,就是一個非常單調(diào)的、也是很簡單的 D 觸發(fā)器鏈了。聰明!這就是這一節(jié)給大家介紹的第一種千層面:只有面。
這樣的一個 D 觸發(fā)器鏈,在信號處理上也叫作延時鏈,結(jié)構(gòu)如圖 3 所示。
圖 3 延時鏈的結(jié)構(gòu)
大家會發(fā)現(xiàn)只是 4 個 D 觸發(fā)器的例子,代碼已經(jīng)很長了。那么如果是很多 D 觸發(fā)器呢,例如 16 個 D 觸發(fā)器或者 32 個 D 觸發(fā)器,那不就成了累傻孩子的活計了嗎?這里就要介紹唯一可以被綜合成電路的循環(huán)了:常數(shù)循環(huán)次數(shù)的 for 循環(huán)。
關(guān)鍵詞 for 的一般形式是:
for (variable = start_value; end_condition; circle_express)
begin
??? operations
end
其中,variable 是一個變量名;start_vlue 是變量的初始值;end_condition 是循環(huán)的條件;circle_expree 是每個循環(huán)的步進(jìn)操作;operations 是每次循環(huán)的操作。要想這個循環(huán)能被綜合,for 的循環(huán)次數(shù)必須確定,。捎帶說明一下,最常見的是第一行的形式。
例 2 里面給出了 4 級觸發(fā)器鏈用 for 實現(xiàn)的代碼。只要改變里面的常數(shù),就是 1024 級 D 觸發(fā)器鏈也不難實現(xiàn)。
【例 2】4 級 D 觸發(fā)器鏈的 for 實現(xiàn)
module DFF_link_4_for
? (
??? input CLK, input RST,
??? input input_data,
??? output output_data
? );
?
//Load other module(s)
//Definition for Variables in the module
reg dff[3:0];
integer loop;
//Logical
assign output_data = dff[3];
always @(posedge CLK, negedge RST)
begin
??? if (!RST)
??? //Reset
??? begin
?????? for (loop = 0; loop <= 3; loop = loop + 1)
?????? begin
??????? dff[loop] <= 1'b0;
?????? end
??? end
??? else
??? begin
??? dff[0]<= input_data;
??? for (loop = 1; loop <= 3; loop = loop + 1)
??? begin
??????? dff[loop] <= dff[loop - 1];
???? end
??? end
end
endmodule
看到這里,很多人會把 Verilog 里面的 for 和其他程序語言里面的 for 混淆掉。這是一個十分嚴(yán)重的錯誤。循環(huán)變量在電路的哪里體現(xiàn)呢?任憑您老“眼睛瞪的像銅鈴”,也找不到半分 loop 的影子吧?實話告訴您,這個循環(huán)變量是在綜合里面起作用的,告訴綜合軟件要重復(fù)幾遍 for 里面的操作。
如果大伙兒覺得一串 D 觸發(fā)器只能做個時延玩玩,那就錯了。這里貧道給諸位一個例子:不用 RAM 來存儲一組數(shù)據(jù)。當(dāng)然了,這個存儲也是有代價的。數(shù)據(jù)不能像 RAM 一樣隨機(jī)讀寫,只能按照一定的時序讀取。
?
3. 各取所長,分工合作
完成一個組合邏輯的操作,會有時延嗎?這里的時延是指從輸入信號穩(wěn)定到獲得正確結(jié)果的時間間隔。對于行為仿真,宗師和黨魁說的沒錯,還真是沒有時延的。但是到了時序仿真這里,就老母雞變鴨了,結(jié)果里面明明白白地出現(xiàn)了時延。有時延倒是叫一般人感覺靠譜一點(diǎn):天下沒有免費(fèi)的午餐。這個時延包含兩個部分,也就是前文書說的可以優(yōu)化的兩個部分:降低布局布線造成的時延(DW)或者降低組合邏輯的時延(DC)。叫大伙兒建立一個概念:做任何事情都是要代價的,這才是天道。
回憶一下數(shù)電課程里面介紹過的 4 比特加法器鏈。假設(shè):每個 1 比特的加法環(huán)節(jié)需要的處理時間是 5 ns(當(dāng)然,實際電路如果這么慢,估計老夫敲一個字母計算機(jī)都要等上一分鐘來處理了。這個雖然不符合實際,但是計算方便啊。大伙兒就別抬杠了。)。那么,4 個 1 比特加法器環(huán)節(jié),一個 4 比特加法器的處理時間應(yīng)該是 20 ns 了。換句話說,在 20 ns 里面如果輸入輸出有變化,那么結(jié)果肯定有問題。再換句話說,這個 4 比特加法器允許輸入數(shù)據(jù)的變化周期大于 20 ns,對應(yīng)最高的數(shù)據(jù)變化頻率為 50 MHz。注意這里還都是組合邏輯,不存在時鐘和時鐘頻率的概念。
如何能夠加快數(shù)據(jù)變化的頻率呢?
首先,“偷工減料”是不可取的。這位說:4 比特加法器是 50 MHz,那么 2 比特加法器就提高到 100 MHz 了。話是沒錯,但是這個比特位寬的減少,卻不是您老說了算的。這個是一對算法什么的工程師計算、仿真的結(jié)果,減少了系統(tǒng)性能肯定受影響。
其次,“忍經(jīng)”在這里唱不得。這位又說了:50 MHz 也不慢了,忍了吧。這話也沒錯,但是系統(tǒng)的數(shù)據(jù)輸入速度,是依賴于外部要求的,也不能變。
最后,依賴于模塊結(jié)構(gòu)的變化以及時序控制的引入,可以解決這個問題。現(xiàn)在我們就開始這個過程。這里會很詳細(xì)的介紹設(shè)計過程,啰嗦是啰嗦了一點(diǎn),但是利于大伙兒把握和以后舉一反三。忍了吧!
忽略全加器和半加器的區(qū)別,圖里面一共有四個一樣的 1 比特加法單元。一個簡單、實用的想法是把這些加法器都隔離開,這樣每次運(yùn)算的時間就是 5 ns 了。那么自然而然的問題來了:用什么器件來隔離呢?又是一個簡單、實用的想法:D 觸發(fā)器。這個就是基本的思路了。這就是所謂流水線的思想了。
To be continued!
后面內(nèi)容更加精彩,大伙兒明晚早來占位!
與非網(wǎng)原創(chuàng)內(nèi)容,謝絕轉(zhuǎn)載!
系列匯總:
之二:Verilog 編程無法一蹴而就,語言層次講究“名正則言順”