3 / 37 · 概念
模块、端口与实例:把连接当作契约
用具名连接组合模块,检查单一驱动源与层次边界。
课时内容可免费阅读,选课后可保存学习进度。
模块边界不是时钟边界
模块组织端口和内部逻辑。实例化不会自动创建寄存器或增加一拍。串联的组合模块仍是组合路径,物理延迟相加;时钟寄存器才是明确的存储边界。端口契约要写方向、位宽、符号、驱动源和有效时刻,具名连接无需记忆位置顺序。
module select_word #(parameter integer W = 8) (
input logic [W-1:0] a, b,
input logic select_b,
output logic [W-1:0] y
);
assign y = select_b ? b : a;
endmodule
module choose_and_increment (
input logic [7:0] a, b,
input logic select_b,
output logic [8:0] result
);
logic [7:0] chosen;
select_word #(.W(8)) select_u (
.a(a), .b(b), .select_b(select_b), .y(chosen)
);
assign result = {1'b0, chosen} + 9'd1;
endmoduleselect_word 是模块类型,select_u 是实例名。.a(a) 把子模块 a 端口连到父模块 a 信号。.W(8) 在展开设计时确定,不是运行时端口值。
检查连接的两端
chosen 只有子模块 y 一个驱动源,父模块读取它。不要再在父模块其他过程中赋值;logic 不允许冲突驱动。result 是 9 位,因为 255+1=256,先通过连接操作扩展 chosen 再加。a=255,b=9 时 select_b=0 得 256,select_b=1 得 10;缩到 8 位会丢掉第一种结果的进位。
层次、文件与 top
两个定义可放同一或不同文件,但编译器必须收到全部文件。top 是 choose_and_increment;选择 select_word 会测试不同的边界。遗漏子模块定义是文件列表问题,不证明端口逻辑错误。位置连接在端口列表改变时可能悄悄改变含义。未连接输入不是有意的 0;明确连接常量或注明未用输出,并检查诊断。也要追踪层次内信号,避免无存储的组合反馈环,模块边界不会自动切断环。
练习:独立验证组合
(a,b,select_b)=(0,255,0),(0,255,1),(255,0,0),(255,0,1) 的期望依次是 1,256,256,1。对两种 select 分别遍历所选输入的 256 个值,未选输入要不同,避免相同输入掩盖反选错误。
参考模型独立选择 a 或 b 的整数值,加 1 后在组合路径稳定时比较 9 位结果。不要读取 DUT 内部 chosen,否则会共享错误选择。最后尝试加输出寄存器,明确复位是否同步、结果何时有效、对应哪个输入边沿;算术不变也会改变时间契约。