“人氣腹語(yǔ)術(shù)師天愿在現(xiàn)場(chǎng)披露了被人偶搭檔奪取靈魂的腹語(yǔ)術(shù)師將妻子殺害的表演節(jié)目,。天愿真的陷入了多重人格,,命令自己殺害妻子和子的人偶的人格出現(xiàn)了。為了不(讓自己)殺害和弟子登川有外遇的妻子,天愿提出委托想要監(jiān)視,,然而第二天早上,和子真的被殺害的事件發(fā)生了,。天愿坦白很可能是在自己的意識(shí)失去的時(shí)候殺害的……”(----“真相只有一個(gè)”《名偵探柯南》一向是老衲喜歡的動(dòng)畫(huà)片)這個(gè)是第806回《腹語(yǔ)師的錯(cuò)覺(jué)》的介紹,。
人有雙重人格,或者叫人格分裂,,那么語(yǔ)言呢,?Verilog語(yǔ)言還真的是人格分裂的語(yǔ)言。前回書(shū)已經(jīng)說(shuō)到了,,不能簡(jiǎn)單地把wire類(lèi)型映射為組合邏輯,,同時(shí)把reg類(lèi)型映射為時(shí)序邏輯。事實(shí)上,這兩個(gè)概念會(huì)交叉的,。也就是說(shuō),,wire類(lèi)型極可能被綜合為組合邏輯也可能綜合為時(shí)序邏輯,reg類(lèi)型也是這樣,。
“‘reg’是什么,?”最微軟的回答是:注冊(cè)表文件。這個(gè)自然沒(méi)錯(cuò),,但是違背了“到哪座山,,唱哪里歌”的原則。一般的“標(biāo)準(zhǔn)”答案是:寄存器型變量,??纯础畆eg’,不就是‘register’(寄存器)的縮寫(xiě)嗎,?大多數(shù)中文教材中都是這樣說(shuō)的,。
下面為了說(shuō)明白這樁事情,請(qǐng)?jiān)试S老僧引用IEEE有關(guān)Verilog語(yǔ)言里面的原文:
“Assignments to a reg are made by procedural assignments (see 6.2 and 9.2). Since the reg holds a value between assignments, it can be used to model hardware registers. Edge-sensitive (i.e., flip-flops) and level sensitive (i.e., RS and transparent latches) storage elements can be modeled. A reg need not represent a hardware storage element since it can also be used to represent combinatorial logic.”
為了強(qiáng)調(diào),,表1里面給出了wire,、reg類(lèi)型和組合邏輯、時(shí)序邏輯之間的映射關(guān)系,。
表1 wire,、reg類(lèi)型和組合邏輯、時(shí)序邏輯之間的映射關(guān)系
wire
reg
組合邏輯
可
可
時(shí)序邏輯
可
可
可見(jiàn)reg是“雙面間諜”的工作性質(zhì),,為了能夠“左右逢源”,,自然用法要比wire來(lái)的復(fù)雜。類(lèi)型wire被綜合為時(shí)序邏輯一般還真是寫(xiě)錯(cuò)了,,不必細(xì)表,。
1. 電平觸發(fā),組合實(shí)現(xiàn)
和reg“孟不離焦,,焦不離孟”的是關(guān)鍵詞always,,這個(gè)要記清楚。人家wire和assign是夫妻,,reg和always是一對(duì),,千萬(wàn)不要搞混了,這不是能拉郎配的季節(jié),。
“always”的語(yǔ)法結(jié)構(gòu)是:
always @(sensitive_tabel)
其中,,sensitive_tabel稱(chēng)作敏感列表,其中包含always內(nèi)部操作的一個(gè)或者多個(gè)觸發(fā)條件,。字符“@”發(fā)音是“艾特”(at),,大伙兒發(fā)電子郵件(e-mail)的時(shí)候常用,,不羅嗦。
正如上面提到的,、標(biāo)準(zhǔn)立面的說(shuō)法可以是邊沿敏感和電平敏感兩種,。對(duì)于組合邏輯電路,這個(gè)敏感列表里面所有條件均為電平敏感,。邏輯上,,當(dāng)敏感列表里面的條件符合的時(shí)候,always內(nèi)部的操作可以進(jìn)行,。但是,,很多邏輯上可行的代碼,由于沒(méi)有實(shí)際電路的支持,,是無(wú)法實(shí)現(xiàn)的。
在Verilog語(yǔ)言95版本里面,,電平觸發(fā)的敏感列表的寫(xiě)法是
triger1 or triger2 or triger3……
其中,,triger1等為觸發(fā)信號(hào)。當(dāng)觸發(fā)信號(hào)電平變化時(shí),,說(shuō)明敏感列表里面條件符合,。如果觸發(fā)信號(hào)是向量,則其中一個(gè)比特的信號(hào)變化,,就認(rèn)為信號(hào)電平有變化,。到了Verilog 2001版本,這個(gè)寫(xiě)法被更加簡(jiǎn)化了:“,”和“or”都可以用來(lái)分割敏感事件,;并且,,可以用“*”代表所有輸入信號(hào),這可以防止遺漏,。例1給出了一些符合語(yǔ)法的always的例子,。
【例1】always與敏感列表
always @ (triger1 or triger2 or triger3) //Version 95 and Version 2001
always @ (triger1 , triger2 , triger3) //Version 2001
always @ (*) //Version 2001
具有完全電平敏感列表的always模塊,總叫人覺(jué)得就是組合邏輯了,。再次強(qiáng)調(diào)數(shù)字電路是并行工作的,,注意不要用“執(zhí)行”這個(gè)詞,不準(zhǔn)確,。對(duì)應(yīng)的所有assign以及always帶領(lǐng)的快都是并行的,,其在代碼中前后順序與輸出結(jié)果無(wú)關(guān)。也就是說(shuō)例2里面的兩段代碼是等效的,。代碼中,,敏感列表sensitive_table1和sensitive_table2對(duì)應(yīng)操作Operation_A和操作Operation_B。
【例2】always所帶操作順序與輸出結(jié)果無(wú)關(guān)
always @(sensitive_table1)
Operation_A
always @( sensitive_table2)
Operation_B
always @( sensitive_table2)
Operation_B
always @(sensitive_table1)
Operation_A
理論上,,assign后面只有一行,,對(duì)于這個(gè)并行工作的理解不難,,不會(huì)產(chǎn)生誤解。到了always這里,,一般其后的代碼就有很多行了,,一不注意就會(huì)出錯(cuò)。
2. 條件判斷,,分枝多多
“用C語(yǔ)言的標(biāo)準(zhǔn)評(píng)價(jià)Verilog,,如同用水果的標(biāo)準(zhǔn)評(píng)價(jià)蜜餞?!?,但是他們的確很多寫(xiě)法有類(lèi)似,這是很容易誤導(dǎo)學(xué)習(xí)者的地方,。
前文書(shū)關(guān)于“? :”選擇操作哪里介紹過(guò),,選擇與分枝在一般系統(tǒng)中是不可少的。那里介紹的代碼方法,,顯然會(huì)產(chǎn)生閱讀困難----尤其是在條件比較多的時(shí)候,。為了改善這一問(wèn)題,也同時(shí)可以更加符合大家以前的習(xí)慣,,這一講書(shū)老朽給貴客介紹“if”和“case”這兩位大家熟悉的陌生人,。
先看眼里的代碼,條件語(yǔ)句if的形式有如表2中的三種,。其中,,condition等表示選擇的條件,operation等表示對(duì)應(yīng)的操作,。請(qǐng)注意,,這里的表達(dá)式“選擇”,目的是和電路對(duì)應(yīng),,不是故意和別人不一樣的嘩眾取寵,。
表2條件語(yǔ)句if的格式
無(wú)分枝
單級(jí)分枝
多級(jí)分枝
形式
if (condition )
begin
operations
end
if (condition )
begin
operations_1
end
else
begin
operations_2
end
if (condition_1 )
begin
operations_1
end
else if (condition_2 )
begin
operations_2
end
else if……
……
begin
operations_m
end
對(duì)應(yīng)電路
時(shí)序電路
時(shí)序電路
組合電路
時(shí)序電路
組合電路
表.2中“對(duì)應(yīng)電路”一行也請(qǐng)施主們注意,if語(yǔ)句中條件的所有路徑覆蓋不全面,,可能會(huì)產(chǎn)生時(shí)序電路的,。對(duì)于reg類(lèi)型的變量,需要滿(mǎn)足“條件不滿(mǎn)足的時(shí)候,,保持原值”,;同時(shí),組合電路不可“自賦值”(也就是類(lèi)似“a <= a”的形式),。當(dāng)需要“保持”的時(shí)候,,純組合電路是無(wú)法滿(mǎn)足的。所以,,綜合器會(huì)引入“鎖存器”,。不是綜合器自作主張,,這是代碼的要求?!疤熳髂酹q可恕,,自作孽不可活”,只能怪你自己了,,哭吧,!這個(gè)對(duì)應(yīng)的器件是鎖存器,不是這里的重點(diǎn),,會(huì)在以后介紹,。這里要說(shuō)的是:要產(chǎn)生組合邏輯,if的條件路徑必須全覆蓋,。
if語(yǔ)句中條件的所有路徑覆蓋不全面,,可能會(huì)產(chǎn)生時(shí)序電路的。這個(gè)對(duì)應(yīng)的器件是鎖存器,,不是這里的重點(diǎn),,以后介紹。這里要說(shuō)的是:要產(chǎn)生組合邏輯,,if的條件路徑必須全覆蓋。
例3是一個(gè)單級(jí)條件語(yǔ)句if應(yīng)用的例子,,其功能是求有符號(hào)數(shù)絕對(duì)值,。其中,輸入為8比特有符號(hào)數(shù),,編碼方式為補(bǔ)碼,;輸出是輸入數(shù)值的絕對(duì)值。具體算法是:
【例3】絕對(duì)值運(yùn)算模塊
module abs
(
input[7:0] signed_value,
output reg[6:0] result
);
//Definition for Variables in the module
//Load other module(s)
//Logical
always @(signed_value)
begin
if ( signed_value[7])
//Negative number input
begin
result <= (~signed_value[6:0]) + 7'h01;
end
else
//Positive number or zero input
begin
result <= signed_value[6:0];
end
end
endmodule
3. 多種情況,,并列判決
在條件很多的時(shí)候,,用if語(yǔ)句來(lái)寫(xiě)還是很麻煩的,搞不好就是是一個(gè)條件路徑覆蓋不完全,。這個(gè)時(shí)候,,可以選擇case套餐。case語(yǔ)句是一種多分支選擇語(yǔ)句,, Verilog語(yǔ)言提供的case語(yǔ)句直接處理多分支選擇,。多分支的case有三種形式,如表3所示,。
表3條件語(yǔ)句case的形式
case
casex
casez
比較方式
敏感表達(dá)式與各項(xiàng)值之間的比較,,是一種全等比較
如果分支表達(dá)式某些位的值為高阻z,那么對(duì)這些位的比較就會(huì)忽略,,不予考慮,,而只關(guān)注其他位的比較結(jié)果,。
casez會(huì)把z/?匹配成任意,也會(huì)把任意匹配成z/?
在casex語(yǔ)句中,,則把這種處理方式進(jìn)一步擴(kuò)展到對(duì)x的處理,,即如果比較雙方有一方的某些位的值是z或x,那么這些位的比較就不予考慮,。
casex會(huì)把z/?x匹配成任意,,也會(huì)把任意匹配成z/?/x,即直接忽略z/?/x
形式
case (variable)
costant_1:
begin
operations_1
end
costant_2:
begin
operations_2
end
……
default:
begin
operations_m
end
endcase
case (variable)
costant_1:
begin
operations_1
end
costant_2:
begin
operations_2
end
……
default:
begin
operations_m
end
endcase
case (variable)
costant_1:
begin
operations_1
end
costant_2:
begin
operations_2
end
……
default:
begin
operations_m
end
endcase
constant項(xiàng)
各個(gè)constant項(xiàng)為確定寬度的常數(shù)值,不包含x和z,;
可以用“?”表示不關(guān)心該位數(shù)值
各個(gè)constant項(xiàng)為確定寬度的常數(shù)值,,可包含x但不能包含z
各個(gè)constant項(xiàng)為確定寬度的常數(shù)值,可包含z但不能包含z
constant例子
3’b000:3比特寬度全0,;
3’b0?0:3比特寬度第二比特不關(guān)心,,其他比特為0
3’b000:3比特寬度全0;
3’b0?0:3比特寬度第二比特不關(guān)心,,其他比特為0,;
3’b00x:3比特寬度最低比特為x,其他比特為0
3’b000:3比特寬度全0,;
3’b0?0:3比特寬度第二比特不關(guān)心,,其他比特為0;
3’b00z:3比特寬度最低比特為不關(guān)心,,其他比特為0
可綜合性
可綜合
依賴(lài)綜合軟件
依賴(lài)綜合軟件
case括弧內(nèi)的變量稱(chēng)為控制表達(dá)式,,case分支項(xiàng)中的常數(shù)稱(chēng)為分支表達(dá)式??刂票磉_(dá)式通常表示為控制信號(hào)的某些位,,分支表達(dá)式則用這些控制信號(hào)的具體狀態(tài)值來(lái)表示,因此分支表達(dá)式又可以稱(chēng)為常量表達(dá)式,。當(dāng)控制表達(dá)式的值與分支表達(dá)式的值相等時(shí),,就執(zhí)行分支表達(dá)式后面的語(yǔ)句。如果所有的分支表達(dá)式的值都沒(méi)有與控制表達(dá)式的值相匹配的,,就執(zhí)行default后面的語(yǔ)句,。
default項(xiàng)可有可無(wú),一個(gè)case語(yǔ)句里只能有一個(gè)default項(xiàng),。 當(dāng)分支表達(dá)式可以覆蓋控制表達(dá)式全部分枝路徑時(shí),,default可以不寫(xiě)。但是,,有時(shí)候這個(gè)全覆蓋不是那么容易看出來(lái)的,,所以建議最好寫(xiě)上default,哪怕有冗余這個(gè)default永遠(yuǎn)不可能被實(shí)現(xiàn),。也請(qǐng)大家放心,,這種冗余綜合軟件會(huì)大伙兒去掉的,,不必?fù)?dān)心浪費(fèi)電路資源。
每一個(gè)case分項(xiàng)的分支表達(dá)式的值必須互不相同,,否則就會(huì)出現(xiàn)矛盾現(xiàn)象(對(duì)表達(dá)式的同一個(gè)值,,有多種執(zhí)行方案)。
執(zhí)行完case分項(xiàng)后的語(yǔ)句,,則跳出該case語(yǔ)句結(jié)構(gòu),,終止case語(yǔ)句的執(zhí)行。(精通C語(yǔ)言的大蝦們請(qǐng)?zhí)貏e注意這點(diǎn),,這里case操作執(zhí)行完之后不必寫(xiě)break了,。)
在用case語(yǔ)句表達(dá)式進(jìn)行比較的過(guò)程中,只有當(dāng)信號(hào)的對(duì)應(yīng)位的值能明確進(jìn)行比較時(shí),,比較才能成功,,因此要詳細(xì)說(shuō)明case分項(xiàng)的分支表達(dá)式的值。
case語(yǔ)句的所有表達(dá)式的值的位寬必須相等,,只有這樣控制表達(dá)式和分支表達(dá)式才能進(jìn)行對(duì)應(yīng)位的比較,。一個(gè)經(jīng)常犯的錯(cuò)誤是用'bx、'bz 來(lái)替代n'bx,、n'bz,,這樣寫(xiě)是不對(duì)的,因?yàn)樾盘?hào)x,、z的缺省寬度是機(jī)器的字節(jié)寬度,,通常是32位(此處 n 是case控制表達(dá)式的位寬)。
當(dāng)分支表達(dá)式不完全覆蓋控制表達(dá)式全部分枝路徑時(shí),,您老有偷懶沒(méi)有寫(xiě)default的情況下,可能產(chǎn)生時(shí)序邏輯的鎖存器的,,這點(diǎn)和條件if語(yǔ)句類(lèi)似,。例4是一個(gè)例子,說(shuō)明了default的重要性,。但是,,圖1中的“l(fā)d”是鎖存器已經(jīng)是時(shí)序電路的元件了,超越了本章的范圍,。
【例4】case語(yǔ)句條件覆蓋不全產(chǎn)生會(huì)綜合出鎖存器
代碼1:組合邏輯電路寫(xiě)法
module case_full
(
input[7:0] number,
input[1:0] select,
output reg[7:0] result
);
//Load other module(s)
//Definition for Variables in the module
//Logical
always @(*)
begin
case (select)
2'b00:
begin
result <= number + 8'b0000_0001;
end
2'b01:
begin
result <= number;
end
2'b10:
begin
result <= number - 8'b0000_0001;
end
default:
begin
result <= 8'b0000_0000;
end
endcase
end
endmodule
圖1例4綜合出的電路圖(全部為組合邏輯)