未聞verilog---表達式的賦值即位寬和符號的確定


表達式的位寬和符號

計算表達式的步驟

計算表達式的步驟如下

  1. 基於表達式位長確定的規則,確定表達式的位長。
  2. 基於表達式符號確定的規則,確定表達式的符號。
  3. 把表達式( 或者self-determined subexpression ) 的類型和位長向下傳播到表達式的上下文決定( context-detemined) 的操作數上。通常,上下文決定操作數的類型和位長與運算結果的類型和位長相同。但是也有兩個例外:如果運算結果是real,但是它有一個上下文決定且不是real的操作數,那么這個操作數就按照self-determined處理,然后再把它轉換為real;在比較操作中,如果兩個操作數既不全是self-determined也不全是context-determined,那么這兩個操作數就互相影響,他們就如同是context-determined操作數一樣,從而產生由它們決定的類型和位長,這時操作數的類型和位長獨立於表達式的其他部分。但是比較操作的結果總是1-bit的無符號數。
  4. 當傳播到達一個簡單的操作數時,這個操作數就轉換到傳播來的類型和位長,如果操作數必須被擴展,那么只有當傳播類型是signed時,操作數才做符號擴展。

表達式位長規則

  1. 表達式的位長(或者表達式的size)由表達式的操作數表達式所處的上下文決定。
  2. 自決定表達式(self-determined expression)就是表達式的位長完全由表達式決定,例如表示延遲的表達式。
  3. 上下文決定表達式(context-determined expression)就是表達式的位長既由表達式本身的位長決定,也有這樣的事實決定(表達式本身是另一個表達式的一部分)。例如賦值RHS的位長既依賴於其本身,也依賴與LHS的位長。
  4. 如果不想讓乘法丟失溢出的位,那么就要把結果賦值給一個位長足夠大的變量,這樣才能夠保存運算的最大結果。
  5. 在計算表達式時,中間結果就取操作數的最大位長(如果是賦值,也包含LHS)
  6. 有了{},則中間結果的位寬由里面的表達式自決定。

image

舉幾個例子

reg  [3:0] a=15;
reg  [3:0] b=2;
reg  [4:0] c;
initial
    c = a + b;

輸出結果是

image

雖然a和b都是4位,但因為在c=a+b; 中c的位長為5位,所以a和b計算的位長由上下文中c的位長決定,所以按照5位來計算,最后c為10001;

reg  [3:0] a=15;
reg  [3:0] b=2;
reg  [4:0] c;
initial
    c = {a + b};

這個例子與上一個例子不同之處在於給a+b 加上了{} ,結果為

image

從上面提到,有了{},則中間結果的位寬由里面的表達式自決定,不再考慮上下文,所以就按4位位長進行計算,因為4位計算會有數據溢出,溢出后的4位數據為0001,因為c是無符號數,將中間結果賦值給c時,位長要短於c,需要擴充位數,補0,所以c的結果為00001;

reg [8:0] a=510,b=25;
reg [7:0] c=254,d=25;
initial
    begin
        if((a+b)>=(c+d))
            $display("a+b is large than c+d");
        else
            $display("a+b is not large than c+d");
        if((a+b+0)>(c+d+0))
            $display("a+b+0 is large than c+d+0");
        else
            $display("a+b+0 is not large than c+d+0");
        if((a+b+10'b0)>(c+d+10'b0))
            $display("a+b+10'b0 is large than c+d+10'b0");
        else
            $display("a+b+10'b0 is not large than c+d+10'b0");
    end

endmodule

輸出結果

image

按照數據運算這三個都應該輸出前面大於后面

對於第一個判斷語句(a+b)>=(c+d) 來說,根據上下文,最大的位長為a和b的9位,a+b的9位運算和c+d 的8位運算都發生了溢出,如果考慮溢出后的數據,兩個的數據相等,但是因為要根據上下文的位長進行計算,所以后面c+d 的運算按照9位進行,所以后面的語句計算沒有發生溢出,所以后面的要大。

對於第二個判斷語句(a+b+0)>(c+d+0)來說,+0 ,因為沒有聲明位寬的0默認位長為32位,所以a+bc+d 的計算都按照32位長進行計算,所以沒有發生溢出,所以a+b 要大於c+d

對於第三個判斷語句(a+b+10'b0)>(c+d+10'b0) 來說,里面有一個+10'd0 ,所以運算按照10位來進行,所以沒有發生溢出,所以a+b 要大於c+d

表達式類型

表達式類型(signed或unsigned)規則如下

  1. 表達式類型只依賴於操作數,不依賴於LHS(如果是賦值表達式,就存在LHS)。
  2. 十進制數是符號數(signed)
  3. 如果沒有sign標志,那么帶base的數是無符號數(unsigned)
  4. bit-select的結果是無符號數(unsigned),不管操作數是符號數還是無符號數
  5. part-select的結果是無符號數(unsigned),不管操作數是符號數還是無符號數,即使part-select的內容是整個向量。
  6. 連接操作的結果是無符號數,不管操作數是符號數還是無符號數。
  7. 比較操作的結果是無符號數,不管操作數是符號數還是無符號數。
  8. real強制轉換integer的結果是符號數(signed)。
  9. 任何自決定(self-determined)操作數的符號和位長都由操作數自身決定,獨立於表達式的其他部分。

對於非自決定(nonself-determined)的操作數,遵從下面的規則。

  1. 如果某個操作數是real,那么結果是real。
  2. 如果某個操作數是無符號操作數,那么結果是無符號操作數,不管是什么操作。
  3. 如果所有操作數是符號整數,那么結果才是符號整數,不管是什么操作。

注意:一位有符號數只有0和-1,有符號數0就是0,有符號數1就代表着-1(符號位為負,只能表示-1)

舉個例子

reg signed [3:0] a=15;
reg  [3:0] b=2;
reg [9:0] d;
reg  signed [4:0] c;
initial
    begin
        c = a + b;
        d = a;
    end

結果

image

表達式類型只依賴於操作數,不依賴於LHS,所以我們先看RHS,右式包含着操作數a+b,因為a,b中b不是有符號變量,也就是說操作數中存在無符號變量,所以a+b 中a,b還是按照無符號變量計算。當計算時位長按照c的位長5位來計算,因為這里a和b是4位,所以要對a和b進行補位,因為a和b按照無符號變量,所以補0。下面的d=a ,d是10位長,a賦值給d要進行補位,右式的操作數a是有符號變量,所以a要用符號位來補位。

reg signed [3:0] a=15;
reg signed [3:0] b=2;
reg [9:0] d;
reg  signed [4:0] c;
initial
    begin
        c = a + b;
        d = a;
    end

結果

image

表達式類型只依賴於操作數,不依賴於LHS,所以我們先看RHS,右式包含着操作數a+b,因為a,b中a,b都是有符號變量,也就是說操作數都是有符號變量,所以a+b 中a,b還是按照有符號變量計算。當計算時位長按照c的位長5位來計算,因為這里a和b是4位,所以要對a和b進行補位,因為a和b是有符號變量,所以補符號位進行計算,計算結果發生溢出,所以結果為00001。

執行賦值的步驟

計算賦值的步驟如下:

  1. 根據賦值位長確定原則,確定RHS的位長
  2. 如果需要,就擴展RHS。不管LHS的符號是什么,擴展時都不考慮LHS的符號,只有當RHS是signed,才做符號擴展。
  3. 賦值時,如果RHS的位長大於LHS的位長,那么直接把多出的位丟棄,以匹配LHS的位長。(有可能把符號位截去)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM