在Verilog中,parameter
和 localparam
都用于定義常量,但是它們之間有一些重要的區
-
作用范圍:
-
parameter:可以在模塊外部被修改或重定義。它可以被作為模塊的參數傳遞給其他模塊,因此具有較廣泛的作用范圍,適用于設計中需要在多個地方使用的常量。
-
localparam:只能在定義它的模塊內使用,不能被外部修改。
localparam
常用于定義模塊內部的常量,這些常量不希望被外部更改。
-
-
可修改性:
-
parameter:是可以在實例化模塊時修改的常量。換句話說,當模塊被實例化時,可以通過提供不同的參數值來改變其行為。
-
localparam:不能在模塊實例化時被修改,它的值只能在模塊內部定義,并且始終保持固定。
-
-
默認值:
-
parameter:在模塊定義時可以為其指定默認值,但該值可以在模塊實例化時被修改。
-
localparam:它的值只能在模塊定義時設置,無法在模塊實例化時修改。
-
-
典型使用場景:
-
parameter:用于那些可能會根據不同模塊實例化的需求而變化的常量,例如控制信號寬度、數據位數等。
-
localparam:用于模塊內部需要使用的常量,這些常量不需要暴露給模塊的外部使用。比如在實現復雜功能時,常用來定義一些中間計算值。
-
?????????語法示例:
module example (input wire clk,input wire rst
);// parameter可以在實例化時修改parameter WIDTH = 8;// localparam不可以在外部修改localparam DELAY = 5;reg [WIDTH-1:0] data;reg [DELAY-1:0] delay_reg;always @(posedge clk or posedge rst) beginif (rst) begindata <= 0;delay_reg <= 0;end else begindata <= data + 1;delay_reg <= delay_reg + 1;endend
endmodule
????????在上面的例子中,WIDTH
是一個 parameter
,可以在實例化模塊時被修改,而 DELAY
是一個 localparam
,它只能在模塊內部使用,無法在實例化時被改變。?
例化時修改parameter的值
????????在Verilog中,如果你想在實例化時修改 parameter
的值,你可以在實例化模塊時指定一個新的值。localparam
是不能在實例化時修改的,所以只能修改 parameter
。
module adder #(parameter WIDTH = 8) (input wire [WIDTH-1:0] a, // 輸入信號a,位寬由WIDTH決定input wire [WIDTH-1:0] b, // 輸入信號b,位寬由WIDTH決定output wire [WIDTH-1:0] sum // 輸出結果,位寬由WIDTH決定
);assign sum = a + b; // 進行加法操作
endmodule
例化后
module top;reg [15:0] a, b; // 定義兩個16位輸入信號wire [15:0] sum; // 定義16位輸出信號// 實例化adder模塊,修改WIDTH為16adder #(16) u_adder (.a(a),.b(b),.sum(sum));initial begin// 給輸入信號賦值a = 16'hAAAA;b = 16'h5555;// 輸出結果#10; // 延時,模擬一段時間后輸出$display("a = %h, b = %h, sum = %h", a, b, sum);end
endmodule
在上面的代碼中:
????????我們實例化了 adder
模塊,并在實例化時通過 #(16)
修改了 WIDTH
為 16。這意味著 a
、b
和 sum
信號的位寬都會是 16 位,而不是默認的 8 位。在 initial
塊中,給 a
和 b
信號賦值,進行加法操作,最后輸出結果。
修改多個parameter
底層代碼:
module multiplier_adder #(parameter WIDTH_A = 8, // 輸入A的位寬parameter WIDTH_B = 8, // 輸入B的位寬parameter OP_MODE = 0 // 操作模式:0 表示加法,1 表示乘法) (input wire [WIDTH_A-1:0] a, input wire [WIDTH_B-1:0] b, output wire [WIDTH_A-1:0] sum, // 輸出加法結果output wire [WIDTH_A-1:0] product // 輸出乘法結果
);// 加法操作assign sum = a + b;// 乘法操作assign product = (OP_MODE == 1) ? (a * b) : 0; // 只有在OP_MODE為1時進行乘法計算endmodule
實例化模塊并修改多個 parameter
的值
????????接下來,我們將修改 WIDTH_A
、WIDTH_B
和 OP_MODE
的值來定制模塊的行為(按順序的方式進行修改)。
module top;reg [15:0] a, b; wire [15:0] sum, product; // 實例化multiplier_adder模塊,修改WIDTH_A為16,WIDTH_B為8,OP_MODE為1(乘法模式)multiplier_adder #(16, 8, 1) u_multiplier_adder (.a(a),.b(b),.sum(sum),.product(product));initial begina = 16'hAAAA; // a的值為16位的十六進制數b = 8'h55; // b的值為8位的十六進制數#10;$display("a = %h, b = %h, sum = %h, product = %h", a, b, sum, product);end
endmodule
命名參數實例化
module top;reg [15:0] a, b; // 定義16位輸入信號wire [15:0] sum, product;multiplier_adder #(.WIDTH_A(16), // 指定WIDTH_A為16.OP_MODE(1), // 指定OP_MODE為1(乘法).WIDTH_B(8) // 指定WIDTH_B為8) u_multiplier_adder (.a(a),.b(b),.sum(sum),.product(product));initial begina = 16'hAAAA;b = 8'h55;#10;$display("a = %h, b = %h, sum = %h, product = %h", a, b, sum, product);end
endmodule
?總結:
順序修改:通常情況下,parameter
的值是按順序修改的,傳遞的順序必須和模塊定義中的 parameter
順序一致。
命名參數:為了不按照順序修改參數,可以使用命名參數(parameter_name(value)
)的方式指定每個 parameter
的值,這樣可以確保修改的準確性,并且使代碼更具可讀性。