文章来源:FPGA入门到精通
在FPGA设计中,触发器(Flip-Flop)是常用的时序元件。
合理使用触发器对于FPGA设计的稳定性、资源利用率以及时序收敛有很大帮助。
一、触发器基础回顾
触发器是FPGA中存储一位二进制数据的单元,在时钟边沿(通常是上升沿)采样输入数据并输出。
与锁存器不同,触发器是边沿敏感的,而锁存器是电平敏感的。
FPGA中的触发器通常还带有 复位(SR) 和 时钟使能(CE) 控制端。
二、核心设计建议详解
建议1:SR优先级高于CE,避免既复位又置位
解释:在描述带复位和使能的D触发器时,复位信号(SR)的优先级必须高于时钟使能(CE)。
同时,一个触发器不能同时具备异步置位和异步复位,否则会导致综合错误。
正确示例:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
module dff_sr_priority (
input clk,
input rst_n, // 异步复位,低有效
input ce, // 时钟使能
input d,
output reg q
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) // SR优先级最高
q <= 1'b0;
else if (ce) // 仅在使能时采样
q <= d;
end
endmodule
错误示例(同时存在异步置位和复位):
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
// 错误:同一触发器既有异步置位又有异步复位
always @(posedge clk or negedge rst_n or posedge set) begin
if (!rst_n)
q <= 1'b0;
else if (set) // 某些FPGA架构不支持
q <= 1'b1;
else
q <= d;
end
建议2:避免使用锁存器,转换为带使能的D触发器
解释:锁存器由组合逻辑中的条件不完整产生,会导致时序分析困难、毛刺敏感等问题。应始终使用边沿敏感的触发器。
错误示例(产生锁存器):
ounter(lineounter(lineounter(lineounter(lineounter(line
// 缺少else分支,综合出锁存器
always @(*) begin
if (sel)
q = d;
end
正确示例(转换为触发器):
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
module avoid_latch (
input clk,
input sel,
input d,
output reg q
);
// 使用带时钟使能的触发器代替锁存器
always @(posedge clk) begin
if (sel)
q <= d;
end
endmodule
建议3:保持触发器时钟采样极性一致
解释:一个设计模块中不应混合使用上升沿和下降沿触发的触发器。
混合使用会引入额外的时钟缓冲器,增加时钟偏斜,使时序收敛困难。
错误示例(混合极性):
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
always @(posedge clk) begin // 上升沿触发
reg1 <= d1;
end
always @(negedge clk) begin // 下降沿触发——不推荐混用
reg2 <= d2;
end
正确示例(统一极性):
ounter(lineounter(lineounter(lineounter(lineounter(line
// 全部使用上升沿触发
always @(posedge clk) begin
reg1 <= d1;
reg2 <= d2;
end