1. 组合逻辑与时序逻辑的本质区别
在FPGA设计中,组合逻辑和时序逻辑是两种最基本的电路构建方式。很多初学者在Verilog代码中看到always块就默认它是时序逻辑,这种误解往往会导致敏感列表的错误使用。
组合逻辑的特点是输出仅取决于当前的输入信号,不依赖于过去的输入状态。典型的组合逻辑电路包括多路选择器、译码器、加法器等。在Verilog中,组合逻辑的always块应该使用电平敏感的敏感列表(如always @(*)或always @(a or b)),并且块内所有被赋值的信号都必须出现在if-else或case语句的所有分支中,否则会产生锁存器。
时序逻辑则具有记忆功能,输出不仅取决于当前输入,还取决于电路的历史状态。触发器(Flip-Flop)是最基本的时序逻辑单元。时序逻辑的always块应该使用边沿敏感的敏感列表(如always @(posedge clk)),这种结构会被综合器识别为需要寄存器来实现。
关键区别:组合逻辑无记忆功能,输出随输入立即变化;时序逻辑有记忆功能,输出只在时钟边沿变化。
2. always块敏感列表的语法陷阱
Verilog中的always块是描述硬件行为的重要结构,但其敏感列表的写法直接影响综合结果。常见的错误写法包括:
- 混合使用边沿触发和电平敏感信号:
verilog复制always @(posedge clk or a or b) // 错误!不能混用
begin
// 代码
end
- 不完整的敏感列表:
verilog复制always @(a) // 如果逻辑中还用到b,就是错误
begin
c = a + b;
end
- 时序逻辑中遗漏复位信号:
verilog复制always @(posedge clk) // 缺少复位信号
begin
if(rst)
q <= 0;
else
q <= d;
end
现代Verilog推荐使用always @(*)或always_comb(SystemVerilog)来自动推断组合逻辑的敏感列表,这可以避免手动列出敏感信号时的遗漏。对于时序逻辑,必须严格使用always @(posedge clk)或
