[FPGA] FPGA基础入门教程 - 008 - 第七章 让你的FPGA设计更可靠

第七章 让你的FPGA设计更可靠

时序收敛的艺术

什么是时序收敛

  • 设计中的所有时序路径都满足时序要求
  • 包括建立时间和保持时间的要求

基本时序约束

1
2
3
4
5
6
7
8
# 定义时钟
create_clock -period 10 -name sys_clk [get_ports clk]

# 定义输入延迟
set_input_delay -clock sys_clk 2 [get_ports data_in]

# 定义输出延迟
set_output_delay -clock sys_clk 2 [get_ports data_out]

常见时序问题解决方法

  1. 减少组合逻辑层数
  2. 使用流水线技术
  3. 合理布局关键路径

跨时钟域处理技巧

为什么要关注跨时钟域

  • 防止亚稳态
  • 确保数据正确传输
  • 避免功能错误

基本的跨时钟域处理方法

  1. 双触发器同步
    1
    2
    3
    4
    5
    6
    // 双触发器同步器
    reg sync_ff1, sync_ff2;
    always @(posedge clk_dest) begin
     sync_ff1 <= data_src;
     sync_ff2 <= sync_ff1;
    end
    
  2. 异步FIFO
    1
    2
    3
    4
    5
    6
    7
    8
    // 异步FIFO的基本结构
    module async_fifo (
     input wr_clk,
     input rd_clk,
     input [7:0] data_in,
     output [7:0] data_out
     // ... 其他端口
    );
    

复位设计的注意事项

复位类型选择

  • 同步复位:时序可控,但占用资源多
  • 异步复位:资源少,但需要特别注意去除毛刺

复位使用建议

  1. 统一使用一种复位方式
  2. 关键模块考虑使用同步复位
  3. 复位信号要经过去抖动处理
1
2
3
4
5
6
7
8
// 同步复位示例
always @(posedge clk) begin
    if (rst) begin
        // 复位逻辑
    end else begin
        // 正常逻辑
    end
end

常见设计陷阱与解决方案

锁存器的避免

  • 在组合逻辑中确保所有条件都被覆盖
  • 使用默认赋值避免锁存器
1
2
3
4
5
6
7
8
9
10
11
12
13
// 错误示例
always @(*) begin
    if (sel)
        out = a;
    // 缺少else,会产生锁存器
end

// 正确示例
always @(*) begin
    out = b;    // 默认值
    if (sel)
        out = a;
end

时钟选择器的使用

  • 避免用组合逻辑生成时钟
  • 使用BUFGMUX等专用时钟切换资源

关键信号的处理

  1. 重要控制信号要考虑冗余
  2. 状态机要考虑异常状态处理
  3. 关键数据路径要加校验

小结

可靠的FPGA设计需要注意很多细节,本章介绍的这些要点都是实际工作中经常遇到的。建议初学者在开始设计时就养成良好的习惯,这样能避免很多不必要的问题。