跳转到内容
新建笔记

模块、参数与 generate

adder #(.WIDTH(16)) u_adder (
.a (a[15:0]),
.b (b[15:0]),
.sum (sum[16:0])
);

.a(a[15:0]) 左侧是子模块端口,右侧是当前层级信号。工程代码优先使用命名连接:端口顺序变化时更安全,也更容易审查位宽。

module counter #(
parameter int unsigned WIDTH = 16
) (
input logic clk,
input logic rst,
input logic enable,
output logic [WIDTH-1:0] count
);
always_ff @(posedge clk) begin
if (rst) begin
count <= '0;
end else if (enable) begin
count <= count + 1'b1;
end
end
endmodule

参数在 elaboration 前确定,适合位宽、深度和功能选项。运行时变化的配置应使用输入端口或寄存器,而不是参数。

for (genvar i = 0; i < LANES; i++) begin : g_lane
lane_rx u_lane_rx (
.clk (clk),
.din (serial_in[i]),
.data (lane_data[i])
);
end

这会生成 LANES 个并行实例。命名块 g_lane 形成稳定层次,例如 g_lane[3].u_lane_rx,方便约束、波形和调试定位。

if (USE_PIPELINE) begin : g_pipe
always_ff @(posedge clk) begin
y <= a + b;
end
end else begin : g_comb
always_comb begin
y = a + b;
end
end

条件必须在 elaboration 时可确定。两条分支不会同时生成。

  • 模块边界围绕稳定职责和时钟域,而不是每几行代码拆一个模块。
  • 端口显式携带方向、位宽、符号和时钟域含义。
  • 数据与 valid/ready/last 等控制信号一起封装和流水。
  • 不在层级中到处使用跨层引用;调试信号通过端口或 bind/ILA 处理。
  • 对参数范围做 elaboration-time 检查,避免 WIDTH=0 等非法组合。