2013-05-09 54 views
4

我在訪問Verilog中的32個最高有效位和32個最低有效位時遇到了問題。我寫了下面的代碼,但是出現錯誤「非法部分選擇表達式」這裏的要點是我沒有訪問64位寄存器的權限。能否請你幫忙。Verilog訪問特定位

`MLT: begin 
    if (multState==0) begin 
    {C,Res}<={A*B}[31:0]; 
    multState=1; 
    end 
    else 
    begin 
    {C,Res}<={A*B}[63:32]; 
    multState=2; 
    end 

回答

0

你混合阻塞這裏非阻塞賦值:

{C,Res}<={A*B}[63:32]; //< non-blocking 
multState=2;   //< blocking 

這被認爲是不好的做法。

不確定只有{A*B}的連接操作是否有效。最好它什麼都不做。

你編碼的方式看起來像你最終會得到2個硬件乘法器。是什麼讓你說你沒有64位的reg,可用? reg不一定要暗示人字拖。如果你有2個32位寄存器,那麼你可以有1個64位寄存器。我會親自做1行的乘法運算,然後將結果拆分並輸出爲2個32位段。

但是:

x <= (a*b)[31:0]不幸不允許的。如果x是32位的,將採取最低有效位,因此,所有你需要的是:

x <= (a*b) 

採取的MSB你可以嘗試:

reg [31:0] throw_away; 
{x, throw_away} <= (a*b) ; 
+0

它不混合非阻塞和阻塞任務是問題。 AIUI的問題來自於使用阻塞分配來在不同的硬件塊之間進行通信。 http://www.sigasi.com/content/verilogs-major-flaw – 2013-05-10 11:04:00

+0

@MartinThompson我曾看過,但沒有完整閱讀。我所拿走的所有東西都是'對於同步設計,這使它們無害',但我從來沒有在Verilog中遇到過這個問題,儘管VHDL用戶有時確實指出這個錯誤在VHDL中絕不會發生;) – Morgan 2013-05-10 11:58:15

+0

從我的關鍵位(坦率地說,非Verilogger)的觀點是,你必須從不*使用*阻塞*賦值*通信*。其他任何東西都很好......而且VHDL通過不允許在進程之外訪問變量(具有阻塞語義)來強制執行。 – 2013-05-10 12:12:19

3

可惜的位選和部分選擇功能Verilog是表達式操作數的一部分。它們不是Verilog運算符(參見Verilog 2005標準文檔的第5.2.1節,IEEE標準1364-2005),因此不能應用於任何表達式,而只能直接應用於寄存器或連線。

有多種方法可以做到你想要什麼,但我會建議使用一個臨時的64位變量:

wire [31:0] A, B; 
reg [63:0] tmp; 
reg [31:0] ab_lsb, ab_msb; 

always @(posedge clk) begin 
    tmp = A*B; 
    ab_lsb <= tmp[31:0]; 
    ab_msb <= tmp[63:32]; 
end 

(該分配到ab_lsb和ab_msb可能是有條件的,否則一個簡單的「{ab_msb,ab_lsb } < = A * B;「當然也會這樣做的。」)

請注意,我使用阻塞賦值來分配'tmp',因爲我需要下面兩行中的值。這也意味着從外部 訪問'tmp'是不安全的。

另請注意,這裏不需要連接hack {A * B},因爲A * B被分配給64位寄存器。這也符合IEEE標準2064至05年的5.4.1節推薦:

乘法可以不受寬足以容納它分配結果 的東西丟失任何溢出位進行。

但是,您說:「這裏的重點是我無法訪問64位寄存器」。

所以我將介紹一個不使用任何Verilog 64位寄存器的解決方案。然而,這不會對所產生的硬件產生任何影響。 Verilog代碼只會在 中看起來不同。

這個想法是通過移位A * B的結果來訪問MSB位。這樣做的以下幼稚版本將不起作用:

ab_msb <= (A*B) >> 32; // Don't do this -- it won't work! 

爲什麼這不起作用的原因是,A * B的寬度由分配,這是32個比特的左手側確定。因此A * B的結果只包含結果的低32位。使得操作自確定的比特寬度的

的一種方式是通過使用連接操作符:

ab_msb <= {A*B} >> 32; // Don't do this -- it still won't work! 

現在被使用max確定的乘法的結果的寬度。其操作數的寬度。不幸的是,兩個操作數都是32位,因此我們仍然有32位乘法。所以我們需要擴展一個操作數爲64位,例如通過追加零 (我假設無符號操作數):

ab_msb <= {{32'd0, A}*B} >> 32; 

訪問LSB位是容易的,因爲這是反正默認行爲:

ab_lsb <= A*B; 

因此,我們最終以下替換代碼:

wire [31:0] A, B; 
reg [31:0] ab_lsb, ab_msb; 

always @(posedge clk) begin 
    ab_lsb <= A*B; 
    ab_msb <= {{32'd0, A}*B} >> 32; 
end 

Xilinx XST 14.2爲兩個版本生成相同的RTL網表。我強烈推薦第一個版本,因爲它更易於閱讀和理解。如果僅使用'ab_lsb'或'ab_msb',則綜合工具將自動丟棄'tmp'的未使用位。所以沒有什麼區別。

如果這不是您尋找的信息,那麼您可能應該澄清爲什麼以及如何「無法訪問64位寄存器」。畢竟,您也嘗試訪問代碼中64位值的位[63:32]。由於您無法計算產品A * B的高32位而沒有執行低32位所需的幾乎所有計算,您可能會要求一些不可能的事情。

+1

請注意,ab_msb <= {{32'd0,A} * B} >> 32'中的外部級聯不是必需的;內部一個足以進行乘法和64位下移。 – EML 2013-05-14 11:06:47