Menu
CoddyTech

参数

本课属于 Coddy Verilog 学习旅程的“基础知识”单元。第 11 课,共 90 课。

你可以创建同一个模块的多个副本,并在不同位置使用它们。这称为**多个实例**。你只需编写一次代码,就能按需重复使用,而不必一遍又一遍地编写相同的代码。每个实例都是芯片上该硬件的一个独立副本。

但是,如果你需要每个副本都不同呢?例如,一个 8 位计数器、一个 16 位计数器和一个 32 位计数器。没有参数的话,你就需要编写三个独立的模块。

参数可以解决这个问题。

参数是一个常量值,你可以在创建实例时设置它。它可以让你为模块的每个副本设置不同的配置。

声明参数

module counter #(
  parameter WIDTH = 8
)(
  input clk,
  output reg [WIDTH-1:0] count
);
  always @(posedge clk) count <= count + 1;
endmodule

#(parameter WIDTH = 8) 定义了一个名为 WIDTH 的参数,默认值为 8。

声明参数时,我们会在模块名后面紧接着、端口列表前面使用 # 符号。# 表示后面是一个用于配置模块的参数列表。如果你的模块没有参数,直接省略 # 即可。

使用参数

需要常量的地方都可以使用参数:

reg [WIDTH-1:0] data;        // 向量大小
count <= count + 1;           // 适用于任意位宽
assign out = data[WIDTH-1];   // 最高有效位的位置

覆盖参数

使用模块时,你可以更改参数值:

// 默认宽度(8 位)
counter u1 (.clk(clk), .count(count1));

// 将宽度改为 16 位
counter #(.WIDTH(16)) u2 (.clk(clk), .count(count2));

多个参数

你可以有多个参数:

module fifo #(
  parameter DEPTH = 16,
  parameter WIDTH = 8
)(
  input clk, wr_en, rd_en,
  input [WIDTH-1:0] data_in,
  output [WIDTH-1:0] data_out
);
  reg [WIDTH-1:0] memory [0:DEPTH-1];
endmodule

Localparam

localparam 与它类似,但不能从外部覆盖:

module example;
  localparam STATE_IDLE = 2'b00;
  localparam STATE_RUN = 2'b01;
  localparam STATE_STOP = 2'b10;
  // These values are fixed inside this module
endmodule

对于不应更改的常量,请使用 localparam。

challenge icon

挑战

添加一个名为 WIDTH 的参数,默认值为 4。

要做什么:

  1. 添加一个名为 WIDTH 的参数
  2. 将它的默认值设为 4
  3. 参数要放在模块名后面的 #( ) 内

亲手试试

module counter #(
  // 在这里添加参数 WIDTH,默认值为 4
  
)(
  input clk,
  input reset,
  output reg [WIDTH-1:0] count
);

endmodule
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

基础知识中的所有课

自己练习: Verilog 在线编译器