2013-07-18 61 views
1

我想根據實例化模塊時設置的參數設置參數。我有以下幾點。生成塊中的系統Verilog參數

module foo #(WORDS = 8); 

parameter P00 = 33; 
logic [7:0] tmp; 

generate 
    case (WORDS) 
    4: begin : A 
     assign tmp = 8'haa; 
     parameter P00 = 4; 
     end 
    8: begin : B 
     assign tmp = 8'hbb; 
     parameter P00 = 8; 
     end 
    16: begin : C 
     assign tmp = 8'hcc; 
     parameter P00 = 16; 
     end 
    default: begin : D 
       assign tmp = 8'hdd; 
       parameter P00 = 8; 
      end 
    endcase 
endgenerate 

initial begin 
    $display ("WORDS = %d", WORDS); 
    $display ("tmp = %h", tmp); 
    $display ("P00 = %d", P00); 
end 

endmodule 

我預計會重新定義P00時出現錯誤,但它會編譯並運行並顯示下列內容。

WORDS =  8 
tmp = bb 
P00 = 33 

如果我評論「參數P00 = 33」賦值,我會得到一個「標識符P00尚未聲明」。錯誤。

看起來生成塊被忽略。這裏有什麼問題?

+1

如果我正確地閱讀了語言規範,實際上當您在生成塊中使用參數類型時,實際上是在不同範圍內創建新參數。它指出,「在[生成塊]中,參數關鍵字應該是localparam關鍵字的同義詞。」此外,「本地參數與參數相同,但它們不能通過...實例參數值賦值直接修改」。如果您有語言參考的副本並希望瞭解更多信息,請參閱第6.20.4節。它看起來像你需要一種不同的方法來解決這個問題。 –

+0

@丹 - 謝謝。我沒有閱讀上面的手冊部分,但我沒有看到生成塊實際上創建了與模塊不同的範圍。我試圖顯示C.P00,但也沒有工作。如果創建新範圍,我如何訪問它? – user2382841

+0

我對此並不十分清楚。我剛開始自己​​學習這門語言,但@Morgan似乎在下面有一個很好的答案。 –

回答

0

最近在這裏有很多問題使用生成和不恰當地指定不確定是否寫了一個新的教程沒有正確地教導這些東西。

參數或Localparams不應該定義多次,它們是常量,因此不能更改值。我認爲你也缺少模塊foo中的參數關鍵字。

module foo #(
    parameter WORDS = 8 
); 

localparam P00 = WORD; 

這是常見的比例因子使用方法:

module foo #(
    parameter WIDTH = 8 
    parameter MAX_VALUE = 2**WIDTH 
); 

你所定義的樣子,你應該只使用邏輯不參數持有的價值;

我會重寫整個事情:

module foo #(WORDS = 8); 

logic [31:0] P00 = 33; 
logic [7:0] tmp; 

always @* begin 
    case (WORDS) 
    4: begin : A 
     tmp = 8'haa; 
     P00 = 4; 
     end 
    8: begin : B 
     tmp = 8'hbb; 
     P00 = 8; 
     end 
    16: begin : C 
     tmp = 8'hcc; 
     P00 = 16; 
     end 
    default: begin : D 
      tmp = 8'hdd; 
      P00 = 8; 
     end 
    endcase 
end 

使用產生的不必要的你正試圖在這裏實現什麼。

+0

謝謝。您的評論很好,但確實有效,但並不完全符合我的需求。我使用了生成塊,因爲我只希望根據單詞數來合成一個案例。該示例是模塊的簡化版本。參數的數量隨着WORDS的數量而增加。也許我誤解了你說的使用generate。另外,爲了查看是否在生成塊中設置了任何參數,添加了頂部設置P00 = 33的參數聲明。我添加它會導致錯誤,但不會導致錯誤。 – user2382841

+2

@ user2382841我會仔細檢查您的警告以及錯誤。生成對於根據參數或互連接線塊創建層次結構(多個實例)很有用。如果輸入是恆定的,則輸出是恆定的,綜合工具將很好地創建最小的硬件。如果P00是一個常數,如果邏輯(reg)或參數沒有區別。 – Morgan

0

此作品(通常說,你需要讓所有4生成塊名稱相同):

module foo #(WORDS = 8); 

parameter P00 = 33; 
logic [7:0] tmp; 

generate 
    case (WORDS) 
    4: begin : B 
     assign tmp = 8'haa; 
     parameter P00 = 4; 
     end 
    8: begin : B 
     assign tmp = 8'hbb; 
     parameter P00 = 8; 
     end 
    16: begin : B 
     assign tmp = 8'hcc; 
     parameter P00 = 16; 
     end 
    default: begin : B 
       assign tmp = 8'hdd; 
       parameter P00 = 8; 
      end 
    endcase 
endgenerate 

initial begin 
    $display ("WORDS = %d", WORDS); 
    $display ("tmp = %h", tmp); 
    $display ("P00 = %d", B.P00); 
end 

endmodule 
1

配售參數定義範圍內的生成塊生成新的本地相對於內的分層範圍的參數生成塊。 defparam通常是覆蓋參數值的方式。然而IEEE std 1800-2012明確指出一defparam不能在§ 23.10.1實現它的父範圍:

在或下一個生成塊 實例層次結構的defparam言(見第27條)或實例的數組(見28.3.5和 23.3.2)不得改變該層級以外的參數值。

對於複雜的派生參數分配,可以使用函數。例如:

parameter P01 = FUNC01(WORDS,P00); 
function byte FUNC01(input byte w,p); 
/* ... */ 
endfunction 

這也是合法的:module foo #(parameter WORDS, P00=FUNC00(WORDS));

的挑戰可能是,每個參數都需要有自己的功能。使用具有結構數據類型的參數是一種潛在的解決方法,可將分配分組爲單個函數。這種方法需要通過模擬器,合成器和其他工具進行評估。例如:

typedef struct packed { 
    int sub00; 
    byte sub01; 
    /* ... */ 
bit [13:0] subNN 
} param_t; 
paramter param_t P = FUNC_P(/* inputs */); 

function param_t FUNC_P(/* inputs */); 
    param_t rtn; 
    /* assign all rtn.sub* */ 
    return rtn; 
endfunction 

logic [P.sub01-1:0] tmpvar; 

由於Morgan指出的那樣,你可以定義大多數parameters作爲logic和使用組合塊。不過,我會強烈要求使用always_comb塊而不是always @*來保證值的計算。正如在LRM § 9.2.2.2.2表示:直到在所推斷的靈敏度 列表中的信號中出現的變化

always_comb自動在零時間執行一次,而總是 @ *等待。

+0

使用函數解決了我的問題。 – jgoeders