本文是針對在寫項目中遇到的Verilog代碼寫法錯誤,多對一和一對多賦值問題,從邏輯賦值的角度理解為何會編譯出錯。并在后續討論了if-else和case的電路結構和區別。在此處列出來供大家一起交流學習。
2.對Verilog代碼的理解
2.1 一對多賦值、多對一賦值行為的區別
2.1.1多對一賦值的Verilog代碼:
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
REG1 <= 'd0;
REG2 <= 'd0;
end
else begin
if(write) begin
case(paddr)
'h54321 : REG1 <= ?pwdata; ? //在32'h54321寫入pwdata
'h12345 : REG2 <= ?pwdata; ? //在32'h12345寫入pwdata
default begin
REG1 <= REG1 ;
REG2 <= REG2 ;
end
endcase
//另一種寫法
//REG1 <= (paddr == 'h54321) ? pwdata : REG1; //在32'h54321寫入pwdata
//REG2 <= (paddr == 'h12345) ? pwdata : REG2; ?//在32'h12345寫入pwdata
end
else begin
REG1 <= REG1;
REG2 <= REG2;
end
end
end
·如果將一個信號(如pwdata)對多個信號進行賦值(如REG1、REG2),應該使用譯碼器形式的電路結構。也就是pwdata根據paddr進行譯碼,從而將值賦給REG1/REG2。如下圖所示
#FormatImgID_0#
·譯碼器一般用多個輸入信號,根據padder判斷取值的不同,將輸入信號pwdata賦值給相應的輸出信號。代碼中給出了兩種寫法都可以。
2.1.2一對多賦值的Verilog代碼:
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
prdata <= 'd0;
end
else begin
if(read) begin
case(paddr)
'h54321 : prdata <= REG1; //在32'h54321讀出prdata = REG1 ?
'h12345 : prdata <= REG2; //在32'h12345讀出prdata = REG2
default : prdata <= prdata;
endcase
//注意下面這種寫法是錯誤的(2.1.3中會分析)
//prdata <= (paddr == 'h54321) ? REG1 : prdata;
//prdata <= (paddr == 'h54321) ? REG2 : prdata;
end
else begin
prdata <= prdata;
end
end
end
·如果將多個信號(如REG1、REG2)對一個信號進行賦值(如prdata),應該使用多路選擇器形式的電路結構。也就是REG1/REG2根據paddr進行判斷,從而將值賦給prdata。如下圖所示
#FormatImgID_1#
·多路選擇器的寫法一般是利用case語句進行實現,根據case的條件不同,選擇不同的輸入信號對輸出信號進行賦值。
2.1.3 為什么多對一賦值不能用三目運算符呢?
即寫成:
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
prdata <= 'd0;
end
else begin
if(read) begin
//注意多對一中,下面這種寫法是錯誤的
prdata <= (paddr == 'h54321) ? REG1 : prdata;
prdata <= (paddr == 'h54321) ? REG2 : prdata;
end
else begin
prdata <= prdata;
end
end
end
分析:這時候編譯就會報錯,prdata同時被兩個常量賦值。假如說paddr選中了'h54321,此時 prdata<= REG1成立;但是請注意在第二條語句中,由于paddr≠'h54321,prdata <= prdata。
由此我們可以知道三目運算符和case并不等價,如果改寫成if-else多層嵌套語句,編譯沒有出錯誤。
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
prdata <= 'd0;
end
else begin
if(read) begin
if(paddr == 'h54321)begin
prdata <= REG1;
end
else begin
if(paddr == 'h54321)begin
prdata <= REG2;
end
else begin
prdata <= prdata; ? ?
end
end
end
else begin
prdata <= prdata;
end
end
end
下面進一步分析if-else和case語句的區別來分析。
2.2 if—else語句與case語句的區別
2.2.1 if-else語句的電路結構
每個if-else就是一個2選1mux器。當信號有明顯優先級時,首先要考慮if-else,但是if嵌套過多也會導致速度變慢;if語句結構較慢,但占用面積小。
嵌套的if語句如果使用不當,就會導致設計的更大延時,為了避免較大的路徑延遲,最好不要使用特別長的嵌套if結構。如想利用if語句來實現那些對延時要求苛刻的路徑時,應將最高優先級給最遲到達的關鍵信號。
2.2.2 case語句的電路結構
case語句綜合為 n選1的mux電路。適用于無明顯優先級的邏輯判斷,即這些邏輯條件都處于同一個優先級且互斥;case結構電路速度較快,但占用面積較大。
2.2.3 if語句和case語句中的latch問題
if-else:組合邏輯和時序邏輯中的always語句塊中實現是不同的。
組合邏輯中:if缺少else 時,會有latch;
時序邏輯中:盡管缺少else,依舊是D觸發器,不存在latch。
case語句:case列舉不全并且還沒寫default語句,則會綜合出鎖存器。所以一定寫default,無論是組合還是時序邏輯。
總結:保證if-else對應齊全;case必寫default。
2.2.4 if-else語句和case語句的區別
對于這個的討論,本人認為是以前由于綜合工具落后,導致有區別,但是隨著綜合工具的更新,他們之間的區別越來越小,甚至有人可以用if-else綜合出無優先級的多路選擇器,用case綜合出有優先級的多路選擇器。
“if-else的邏輯判別是有優先級的,而case的邏輯判斷條件是并列的。
舉個例子,如果你用IF實現譯碼器,綜合出的是有優先級的譯碼器。如果用CASE,綜合出的就是一個無優先級的譯碼器。也就是說IF是有優先級的,執行的次序有先后。而CASE執行的時候是沒有先后順序的。”
“隨著綜合工具的進步,已經不需要討論if-else 和case的區別了,兩者可以等同 ”
“Verilog 2001標準(IEEE 1364-2001)第132頁:
The case item expressions shall be evaluated and compared in the exact order in which they are given.
指出了case是串行有優先級。又:
Apart from syntax, the case statement differs from the multiway if-else-if construct in two important ways:
a) The conditional expressions in the if-else-if construct are more general than comparing one expression with several others, as in the case statement.
b) The case statement provides a definitive result when there are x and z values in an expression.
a)是廢話。b)指出了case是四態對比。除此之外和if-else沒有差別。”
審核編輯:黃飛
-
Verilog
+關注
關注
28文章
1351瀏覽量
110162 -
D觸發器
+關注
關注
3文章
164瀏覽量
47961 -
代碼
+關注
關注
30文章
4803瀏覽量
68754 -
Case
+關注
關注
0文章
27瀏覽量
13379 -
多路選擇器
+關注
關注
1文章
22瀏覽量
6545
發布評論請先 登錄
相關推薦
評論