?
實(shí)際上,HDL 語言肯定要比《玩轉(zhuǎn) IP core》或者《IP 核芯志》(業(yè)界著名的和尚書)這樣的講系統(tǒng)設(shè)計(jì)的書來的基礎(chǔ)。按照從簡單到復(fù)雜的思想,應(yīng)該先說說 Verilog 方為合適。當(dāng)年老衲也是低估了搞笑的吶喊的先知(jiaoshou)們的毀人不倦,覺得“語言嘛,應(yīng)該會(huì)的了”。結(jié)果坊間出現(xiàn)了不少 C Style 的和尚書的實(shí)現(xiàn),老夫就出離憤怒了:是可忍孰不可忍!實(shí)際上私下說,老衲不想涉及教語言也有私心雜念:語言莫過于刻板的規(guī)則,講起來也是單調(diào):講的不喜歡,聽的也不喜歡。看看前面兩講的內(nèi)容,僅僅就幽默感而言,比起和尚書差遠(yuǎn)了。但是,沒辦法啊,與其叫語法黨、邏輯派橫行,不如老夫的電路門一統(tǒng)江湖。我們接著聊!
數(shù)字邏輯的了分為組合電路和時(shí)序電路兩種。組合電路就是即來即服務(wù),信號(hào)來了,理論上結(jié)果立即呈現(xiàn)。時(shí)序電路呢,則對(duì)于員工比較人道:在固定時(shí)間工作,其他時(shí)間可以歇著。
1. 組合邏輯,線型實(shí)現(xiàn)
組合邏輯在 Verilog 語言體系里面分兩類,分別采用 wire 類型變量和 reg 類型變量來完成。本講主要介紹第一類:wire 類型變量型組合邏輯描述方法。在下一講里面,會(huì)介紹 reg 的情況。
提到 wire 類型變量型組合邏輯描述方法,一個(gè)不能會(huì)的關(guān)鍵詞就是“assign”。它用于對(duì)于 wire 類型變量的賦值。assign 賦值的一般形式為:
assign [drive_strength] [delay] net_lvalue = expression;
其中:drive_strength 為信號(hào)強(qiáng)度,delay 為設(shè)定時(shí)延,net_lvalue 為 wire 型變量名,expression 為表達(dá)式;方括號(hào)對(duì)“[ ]”表示可省略,而且這兩個(gè)內(nèi)容與電路邏輯設(shè)計(jì)無關(guān),在此不詳細(xì)論述。
例 1 給出了一個(gè)直通模塊的完整代碼。這段代碼沒有實(shí)際意義,就是輸出時(shí)時(shí)刻刻等于輸入的功能。各位聽眾需要掌握的只是完整模塊代碼的格式。
【例 1】直通模塊的完整代碼
/***********************************************
Module Name:?? Bypass
Feature:?????? Input bypass to output
Coder:???????? Garfield
Organization:? XXXX Group, Department of Architecture
------------------------------------------------------
Input ports:?? Input_Data, 8 bits
Output Ports:? Output_Data, 8 bits, equales Input_Data
------------------------------------------------------
History:
11-27-2015: First Version by Garfield
11-27_2015: Verified by Garfield with Bypass_test in ISE/Modelsim
***********************************************/
module Bypass
? (
??? input[7:0] Input_Data,
??? output wire[7:0] Output_Data
? );
//Definition for Variables in the module
//None for this module
//Logical
assign Output_Data =? Input_Data;
endmodule
說明一下,因?yàn)檫@個(gè)模塊實(shí)際上不具有邏輯功能,所以一般綜合軟件都會(huì)在給出警告(Warning)后,把這個(gè)模塊優(yōu)化掉。
?
2. 門級(jí)電路,語言呈現(xiàn)
電路這個(gè)東西也屬于妖魔鬼怪的,會(huì)七十二變,變來變?nèi)プ兂闪?Verilog 語言。學(xué)習(xí)者只有學(xué)會(huì)了如何使用照妖鏡,認(rèn)得語言的本質(zhì),才算學(xué)好了 Verilog。
數(shù)字電路里面,所有組合單元都可以用與非門做出來。不是在下的結(jié)論,是《布爾代數(shù)》里面的結(jié)論。所以,在上課的時(shí)候老師們總喜歡“圈圈圓圓圈圈”地化簡“卡諾圖”。數(shù)學(xué)基礎(chǔ)在哪里呢,他們不講的,不曉得為什么?!昂诎迳侠蠋煹姆酃P,還在拼命唧唧喳喳寫個(gè)不?!币孕∪酥亩戎?,也不是好事,顯得老衲也不那么光明偉岸了,吾有權(quán)保持沉默!
對(duì)于標(biāo)量信號(hào)的邏輯運(yùn)算有:
表 .1 邏輯運(yùn)算操作符、真值表與對(duì)應(yīng)電路符號(hào)
?
對(duì)于向量存在按照比特操作(一般語法書里面叫做“按位操作”)和信號(hào)各個(gè)比特一起操作(一般語法書里面叫做“縮減操作”)兩個(gè)類型。
按位操作包含:
表 2 按位運(yùn)算操作符、真值表與對(duì)應(yīng)電路符號(hào)
?
縮減操作包含:
表 3 縮減運(yùn)算操作符、真值表與對(duì)應(yīng)電路符號(hào)
請(qǐng)注意,這里把電路符號(hào)也同時(shí)提供給施主們了。電路是基礎(chǔ),毋庸置疑。以后,再?zèng)]有運(yùn)算的對(duì)應(yīng)電路符號(hào)了,為了節(jié)約紙張。
?
3. 加減乘除,四則運(yùn)算
算術(shù)運(yùn)算全部打包也沒有幾個(gè),見表 4 所示。
表 4 Verilog 語言中的算術(shù)運(yùn)算
符號(hào) |
例子 |
含義 |
注釋 |
+ |
a + b |
a 加 b |
可綜合 |
- |
a - b |
a 減 b |
可綜合 |
* |
a * b |
a 乘以 b |
可綜合 |
/ |
a / b |
a 除以 b |
不可綜合 整數(shù)除法,結(jié)果取靠近 0 的整數(shù) b 為 0 的時(shí)候,輸出為 x |
% |
a %b |
a 對(duì) b 取模 |
不可綜合 結(jié)果與 a 的符號(hào)相同 |
** |
a **b |
a 的 b 次冪 |
不可綜合 操作數(shù)的類型為實(shí)數(shù)、整數(shù)或者帶符號(hào)數(shù),結(jié)果返回實(shí)數(shù) 操作數(shù)的類型為無符號(hào)數(shù),結(jié)果返回?zé)o符號(hào)數(shù) 如果 a 為 0 同時(shí) b 非正,輸出 x 如果 a 為負(fù)數(shù)同時(shí) b 不失整數(shù),輸出 x |
請(qǐng)注意,這些運(yùn)算的可綜合性,很重要。
到了 Verilog 2001,運(yùn)算結(jié)果和 a 和 b 的定義有關(guān)。如果它們是無符號(hào)數(shù),則按照無符號(hào)數(shù)輸出;如果它們是帶符號(hào)數(shù),則獲得帶符號(hào)數(shù)的輸出。
算術(shù)運(yùn)算不是簡單的門可以解決的,簡單講講無符號(hào)數(shù)加法的樣子。這里以 4 比特、無符號(hào)數(shù)加法器作為例子。最基本的、組合邏輯的加法器如圖 1。這個(gè)叫逐次進(jìn)位的加法器,建立時(shí)間為各級(jí)半 / 全加器的建立時(shí)間之和。在位寬很大的時(shí)候,這種單元可以允許的最高工作時(shí)鐘頻率是很低的。
圖 1 無符號(hào)加法器的全加器(4 比特)鏈結(jié)構(gòu)
下來,和大伙兒嘮嘮 Verilog 語言中有關(guān)移位的操作。按照邏輯層面上說,移位操作和算術(shù)運(yùn)算是兩類完全不同的東西,似乎分別來講更為合適。一則,移位涉及的內(nèi)容不多,作為一回來過于短了,講聽眾值不回票價(jià);二來,數(shù)字設(shè)計(jì)中移位用的最多的場合還是乘以或者除以 2 的冪的運(yùn)算。所以,老比丘把移位的內(nèi)容,也放到算術(shù)運(yùn)算里面了。如果哪位施主有意見,請(qǐng)找和尚辯理,老道這里只是照本宣科。
移位操作分為:
? 邏輯右移(>>):1 個(gè)操作數(shù)向右移位,產(chǎn)生的空位用 0 填充
? 邏輯左移(<<):1 個(gè)操作數(shù)向左移位,產(chǎn)生的空位用 0 填充
? 算術(shù)右移(>>>):1 個(gè)操作數(shù)向右移位。如果是無符號(hào)數(shù),則產(chǎn)生的空位用 0 填充;有符號(hào)數(shù)則用其符號(hào)位填充
? 算術(shù)左移(<<<):1 個(gè)操作數(shù)向左移位,產(chǎn)生的空位用 0 填充
?
4. 大小比較,關(guān)系運(yùn)算
關(guān)系操作都是對(duì)于兩個(gè)數(shù)值進(jìn)行的,所謂的“雙目操作”。關(guān)系操作符包括表 5 中的幾個(gè),其中的操作數(shù)可以是無符號(hào)數(shù),也允許是有符號(hào)數(shù)。
表 5 關(guān)系操作符
符號(hào) |
名稱 |
結(jié)果 |
備注 |
>? |
大于 |
比較 2 個(gè)操作數(shù),如果前者大于后者,結(jié)果為真 |
可綜合 |
<? |
小于 |
比較 2 個(gè)操作數(shù),如果前者小于后者,結(jié)果為真 |
可綜合 |
>= |
大于或等于 |
比較 2 個(gè)操作數(shù),如果前者大于或等于后者,結(jié)果為真 |
可綜合 |
<= |
小于或等于 |
比較 2 個(gè)操作數(shù),如果前者小于或等于后者,結(jié)果為真 |
可綜合 |
== |
邏輯相等 |
2 個(gè)操作數(shù)比較,如果各位均相等,結(jié)果為真 如果其中任何一個(gè)操作數(shù)中含有 x 或 z,則結(jié)果為 x |
可綜合 |
!= |
邏輯不等 |
2 個(gè)操作數(shù)比較,如果各位不完全相等,結(jié)果為真 如果其中任何一個(gè)操作數(shù)中含有 x 或 z,則結(jié)果為 x |
可綜合 |
=== |
case 相等 |
2 個(gè)操作數(shù)比較,如果各位(包括 x 和 z 位)均相等,結(jié)果為真 |
不可綜合 |
!== |
case 不等 |
2 個(gè)操作數(shù)比較,如果各位(包括 x 和 z 位)不完全相等,結(jié)果為真 |
不可綜合 |
5. 特殊描述,拼接選取
歡迎大家來到 Verilog 語言的絕對(duì)領(lǐng)域;這是本語言的一畝三分地;俗話說:我的地盤我做主!瞧瞧把老衲興奮地,都不知道說什么好了。嘴皮子這個(gè)利落啊,就是涂了三十層潤唇膏的感覺。老和尚說了半天,客官問什么意思?就是本回書介紹的內(nèi)容 ---- 位拼接與選取,是 Verilog 語言特有的內(nèi)容。穆仙長,您可以瞑目了。您終于不用擔(dān)心大伙兒不知死活,拿 Verilog 語言和其他語言類比了。理由嘛,八個(gè)字:“獨(dú)此一家,別無分號(hào)”;現(xiàn)代漢語就是:獨(dú)家特許經(jīng)營權(quán)。
拼接操作用來完成前面說到的打包工作,其主要功能是把多個(gè)信號(hào),按照一定的順序,合并成為一個(gè)信號(hào)。拼接的操作符是大括號(hào)對(duì)“{ }”,一般格式是:
{signal1, signal2, ……}
其中,信號(hào)(signal)可以是常數(shù)也可以是變量,但是位寬必須已知且不可變。在例 3.13 里面,給出了一個(gè)簡單的例子。
在 Verilog 語言中,拼接運(yùn)算符是很好用很常用的,但是用法比較苛刻,所以常常會(huì)遇到編譯不過的問題。
上面提到的“位寬必須已知且不可變”,這個(gè)要求是非常重要的,實(shí)踐中無數(shù)次拼接運(yùn)算符的報(bào)錯(cuò)就是不滿足上面的要求。例 2 里面就給出了一些出錯(cuò)的情況。
【例 2】錯(cuò)誤的拼接操作
錯(cuò)誤寫法 |
原因 |
正確表達(dá) |
{4, a[2:0]} |
1 沒有指定位長 |
{32’b1,a[2:0]} |
{8’b0000_0010, b} b 是 integer |
b 沒有指定位長 |
{8’b0000_0010, b[2:0]} |
與拼接操作經(jīng)常一起使用的是重復(fù)操作,也用拼接的操作符是大括號(hào)對(duì)“{ }”,一般格式是:
replication_time{signal}
其中,信號(hào)(signal)可以是常數(shù)也可以是變量,但是位寬必須已知且不可變;重復(fù)次數(shù)(replication_time)必須是常數(shù)。
對(duì)于拼接操作,一個(gè)自然而然的運(yùn)用場景就是把一些邏輯上有聯(lián)系的信號(hào),結(jié)合成“總線”。
例如,可以這樣把很多控制信號(hào)搜集成控制總線:
Control_Bus = {enable, wr_enable, rd_enable, configure_enable }
這是數(shù)據(jù)總線,依次包含芯片使能信號(hào) enable,寫使能信號(hào) wr_enable,讀使能信號(hào) rd_enable,和配置使能信號(hào) configure_enable。這些信號(hào)的具體含義是系統(tǒng)設(shè)計(jì)的時(shí)候,接口定義規(guī)定的,與目前的內(nèi)容無關(guān),不詳細(xì)介紹。實(shí)際系統(tǒng)中的控制總線一般都比這個(gè)復(fù)雜的多,客觀莫要抬杠,這里只是例子,能說明概念就好了。
?
6. 左右逢源,選擇操作
到目前為止,大家遇到的還是“自古華山一條路”的運(yùn)算,直來直去的操作。這種不夠靈活局面到此為止,雖然在 Verilog 語言操作的優(yōu)先級(jí)里面“? :”忝居末位,但是它在各種操作里面的作用卻決不可小覷。沒有選擇操作,系統(tǒng)的功能永遠(yuǎn)是“一根筋”;有了這個(gè)玩意這就成了“兩頭堵”了。系統(tǒng)的智能,那是嘩嘩嘩的上升,都可以去做機(jī)器人和工業(yè) 4.0 了。牛吧?
選擇操作的一般形式是:
condition ? value1 : value2
其中,condition 是判決條件,一般是信號(hào)或者如第三講里面的判決表達(dá)式;value1 和 value2 是兩個(gè)信號(hào),當(dāng)條件 condition 為真時(shí),表達(dá)式結(jié)果為 value1,當(dāng)條件 condition 為假時(shí),表達(dá)式結(jié)果為 value2??辞宄?,這就是一個(gè)基于條件的選擇。
當(dāng)條件 condition 為不確定“x”或者高阻“z”的時(shí)候,表達(dá)式的值同時(shí)取決于 value1 和 value2 的值,見表 6 所示。
表 6“? :”條件為“x”或者“z”時(shí),輸出結(jié)果
? : Condition = x/z |
0 |
1 |
x |
z |
0 |
0 |
x |
x |
x |
1 |
x |
1 |
x |
x |
x |
x |
x |
x |
x |
z |
x |
x |
x |
x |
上表只是一個(gè)仿真的用途,實(shí)際中既然電路里面信號(hào)不能能是“x”或者“z”,所以無論如何電路的輸出是一個(gè)確定的值,大家可以放心。話說到這里,“? :”到底對(duì)應(yīng)什么電路里面的元件呢?很簡單,地球人都知道:選擇器,而且是最簡單的雙路選擇器。其電氣原理圖,如圖 2 所示。按照一般習(xí)慣,把條件為真的取值畫在上面,把條件為假的取值畫在下面,符號(hào)內(nèi)的“1”和“0”表示條件值的“真”和“假”。有時(shí)候,為了簡化,符號(hào)內(nèi)的“1”和“0”也可以不畫。這時(shí)候更需要個(gè)遵守值的上下位置的約定。
圖 2 “? :”對(duì)應(yīng)的選擇器
還有,就是表達(dá)式 value1 和 / 或者 value2 也可以是“? :”選擇操作,這個(gè)時(shí)候?qū)崿F(xiàn)的電路就是判斷鏈。
?
7. 高阻應(yīng)用,接口風(fēng)采
“出來混,遲早是要換的”,這句話太好了。前文書,給大伙說了高阻的事情,老沙門講到“高阻一般會(huì)在輸入輸出管腳處使用”,貧道也只是說“只有和真實(shí)物理芯片管腳鏈接的信號(hào),才能被定義為 inout 類型”。但是如何在代碼中體現(xiàn),卻是沒有提到,又是一個(gè)爛尾樓。
這是一個(gè)和這回書話題相關(guān)的題外話,順便也聊聊。那就是對(duì)于 inout 這種類型的變量的處理。這種數(shù)據(jù)類型主要用于類似上面介紹的數(shù)據(jù)總線的場合?,F(xiàn)在定義以對(duì)于芯片的操作定義讀寫。也就是說,讀操作意味著芯片向外輸出數(shù)據(jù),寫操作意味著向芯片內(nèi)寫入數(shù)據(jù)。依照上面的描述,定義片內(nèi)的讀使能信號(hào) RD_IN 和寫使能信號(hào) WR_IN,高電平有效。片外的數(shù)據(jù)總線設(shè)為 PCB_DATA_BUS。輸出數(shù)據(jù)在輸出信號(hào) DATA_ENABLE 高電平時(shí)刻有效,輸入數(shù)據(jù)在輸入信號(hào) WR_IN 為高電平時(shí)有效。具體時(shí)序如圖 3,例程關(guān)鍵部分例 3 所示。
圖 3 數(shù)據(jù)總線接口時(shí)序
【例 3】數(shù)據(jù)總線接口關(guān)鍵代碼
module BUS_interface
? (
?????? inout[15:0] PCB_DATA_BUS,
??????? input WR_IN, RD_IN,
……
?????? output DATA_ENABLE? //Data_enable flag from the state-machine
……
? );
?
//Load other module(s)
//DATA_ENABLE assignment here
//Definition for Variables in the module
wire[15:0] in_data;
//Buffer for input data
wire[15:0] out_data;
//Data for output
//Logical
assign in_data = PCB_DATA_BUS;
//Input direction
assign PCB_DATA_BUS = (DATA_ENABLE) ? out_data : 16’hzzzz;
//Output direction
endmodule
簡單一句話:輸入時(shí)時(shí)可讀,使能有效采樣;輸出使能賦值,其他時(shí)刻高阻。
這正是:
“
操作符號(hào)是笑談,運(yùn)用巧妙功力現(xiàn)。門級(jí)運(yùn)算有主見,加減乘除結(jié)構(gòu)看。
拼接關(guān)系書寫間,條件來把數(shù)值選。電路代碼兩不厭,太白遇到敬亭山。
”
與非網(wǎng)原創(chuàng)內(nèi)容,謝絕轉(zhuǎn)載!
系列匯總: