• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

SOC/IP验证工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

verilog中同步复位,同步释放,异步复位,异步释放详解

Verilog中复位设计详解:同步/异步复位与释放

1. 基本概念

复位类型

  • 复位 (Reset):将电路初始化为已知状态
  • 释放 (Release):撤销复位信号,使电路正常工作的过程

复位分类

// 四种复位方式:
// 1. 同步复位,同步释放
// 2. 同步复位,异步释放  (不推荐)
// 3. 异步复位,同步释放  (最常用)
// 4. 异步复位,异步释放

2. 同步复位 (Synchronous Reset)

特点

  • 复位信号与时钟同步
  • 复位只在时钟有效边沿生效

代码示例

module sync_reset (
    input wire clk,
    input wire rst_n,     // 低电平复位
    input wire data_in,
    output reg data_out
);

// 同步复位实现
always @(posedge clk) begin
    if (!rst_n) begin          // 只在时钟上升沿检查复位
        data_out <= 1'b0;      // 同步复位
    end else begin
        data_out <= data_in;   // 正常工作
    end
end

endmodule

时序图

时钟  : __|--|__|--|__|--|__|--|__|--|__
复位  : ______________|-----|__________
输出  : 0000000________|11111|__________
          ↑              ↑
    复位生效(同步)    复位释放(同步)

优缺点

优点:

  1. 避免亚稳态
  2. 复位信号可以综合到触发器的数据路径
  3. 时序分析简单
  4. 对毛刺不敏感

缺点:

  1. 需要时钟才能复位
  2. 复位信号长度必须大于时钟周期
  3. 可能增加组合逻辑延迟

3. 异步复位 (Asynchronous Reset)

特点

  • 复位信号与时钟无关
  • 复位立即生效

代码示例

module async_reset (
    input wire clk,
    input wire rst_n,     // 低电平异步复位
    input wire data_in,
    output reg data_out
);

// 异步复位实现
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin          // 异步复位,立即生效
        data_out <= 1'b0;
    end else begin
        data_out <= data_in;
    end
end

endmodule

时序图

时钟  : __|--|__|--|__|--|__|--|__|--|__
复位  : ______________|-----|__________
输出  : 0000000________|11111|__________
          ↑              ↑
    复位生效(异步)    复位释放(异步)

优缺点

优点:

  1. 立即生效,不需要等待时钟
  2. 实现简单
  3. 功耗较低(复位时可关闭时钟)

缺点:

  1. 释放时可能产生亚稳态
  2. 对复位毛刺敏感
  3. 时序分析复杂

4. 同步释放 (Synchronous Release)

核心思想

将异步复位的释放过程同步化,避免亚稳态

异步复位同步释放实现

module async_reset_sync_release (
    input wire clk,
    input wire async_rst_n,    // 异步复位输入
    input wire data_in,
    output reg data_out
);

// 同步释放逻辑
reg rst_meta, rst_sync_n;

always @(posedge clk or negedge async_rst_n) begin
    if (!async_rst_n) begin
        // 异步复位阶段
        rst_meta <= 1'b0;
        rst_sync_n <= 1'b0;
    end else begin
        // 同步释放阶段:两级同步器
        rst_meta <= 1'b1;          // 第一级触发器
        rst_sync_n <= rst_meta;    // 第二级触发器
    end
end

// 使用同步后的复位信号
always @(posedge clk) begin
    if (!rst_sync_n) begin
        data_out <= 1'b0;
    end else begin
        data_out <= data_in;
    end
end

endmodule

两级同步器的作用

// 两级同步器:防止亚稳态传播
// 第一级:捕捉异步信号,可能产生亚稳态
// 第二级:稳定信号,输出干净的同步信号

5. 完整对比分析

时序行为对比

复位方式 复位生效 复位释放 亚稳态风险 推荐度
同步复位同步释放 时钟边沿 时钟边沿 无 ★★★★☆
异步复位异步释放 立即生效 立即生效 高 ★☆☆☆☆
异步复位同步释放 立即生效 时钟边沿 低 ★★★★★
同步复位异步释放 时钟边沿 立即生效 高 ☆☆☆☆☆

综合后的电路结构

// 1. 同步复位 - 综合为MUX结构
//   D触发器 + 选择器
//   data_in ---|MUX|--- D触发器
//   reset  ---|

// 2. 异步复位 - 综合为异步复位触发器
//   触发器的异步复位端直接连接

// 3. 异步复位同步释放 - 两级触发器 + 同步复位

6. 工程实践推荐

最佳实践:异步复位,同步释放

// 模块化异步复位同步释放电路
module reset_sync #(
    parameter SYNC_STAGES = 2  // 同步级数,通常为2
)(
    input wire clk,
    input wire async_rst_n,
    output wire sync_rst_n
);

reg [SYNC_STAGES-1:0] sync_reg;

// 同步器链
always @(posedge clk or negedge async_rst_n) begin
    if (!async_rst_n) begin
        sync_reg <= {SYNC_STAGES{1'b0}};
    end else begin
        sync_reg <= {1'b1, sync_reg[SYNC_STAGES-1:1]};
    end
end

assign sync_rst_n = sync_reg[0];

endmodule

// 在顶层中使用
module top (
    input wire clk,
    input wire ext_rst_n,
    input wire data_in,
    output reg data_out
);

wire sys_rst_n;

// 复位同步器实例
reset_sync u_reset_sync (
    .clk(clk),
    .async_rst_n(ext_rst_n),
    .sync_rst_n(sys_rst_n)
);

// 使用同步后的复位
always @(posedge clk) begin
    if (!sys_rst_n) begin
        data_out <= 1'b0;
    end else begin
        data_out <= data_in;
    end
end

endmodule

复位网络设计

// 完整的复位系统设计
module reset_system (
    input wire clk,
    input wire power_on_rst_n,    // 上电复位
    input wire debug_rst_n,       // 调试复位
    input wire watchdog_rst_n,    // 看门狗复位
    output wire system_rst_n      // 系统复位
);

// 合并所有复位源(异步)
wire async_combined_rst_n = power_on_rst_n & 
                           debug_rst_n & 
                           watchdog_rst_n;

// 同步释放
reg [1:0] rst_sync;
always @(posedge clk or negedge async_combined_rst_n) begin
    if (!async_combined_rst_n) begin
        rst_sync <= 2'b00;
    end else begin
        rst_sync <= {1'b1, rst_sync[1]};
    end
end

assign system_rst_n = rst_sync[0];

endmodule

7. 复位相关注意事项

1. 复位去抖动

// 复位信号去抖动电路
module debounce_reset (
    input wire clk,
    input wire raw_rst_n,
    output wire stable_rst_n
);

parameter DEBOUNCE_CYCLES = 10;  // 消抖周期数
reg [DEBOUNCE_CYCLES-1:0] shift_reg;

always @(posedge clk) begin
    shift_reg <= {shift_reg[DEBOUNCE_CYCLES-2:0], raw_rst_n};
end

// 当连续DEBOUNCE_CYCLES个周期都为1时,才认为复位释放
assign stable_rst_n = &shift_reg;

endmodule

2. 复位时序检查

// 复位恢复时间检查
// 复位释放必须在时钟上升沿之前满足恢复时间(Recovery Time)
// 复位生效必须在时钟上升沿之后满足移除时间(Removal Time)

// 常用约束(SDC格式)
/*
set_false_path -from [get_ports {rst_n}] -to [get_clocks {clk}]
set_input_delay -clock clk -max 2 [get_ports {rst_n}]
set_input_delay -clock clk -min -2 [get_ports {rst_n}]
*/

3. 多时钟域复位处理

// 不同时钟域的复位同步
module multi_clk_reset (
    input wire clk_a,
    input wire clk_b,
    input wire global_rst_n,
    output wire rst_n_a,
    output wire rst_n_b
);

// 每个时钟域独立的同步器
reset_sync u_sync_a (.clk(clk_a), .async_rst_n(global_rst_n), .sync_rst_n(rst_n_a));
reset_sync u_sync_b (.clk(clk_b), .async_rst_n(global_rst_n), .sync_rst_n(rst_n_b));

endmodule

8. FPGA和ASIC中的差异

FPGA实现

// FPGA通常有专用的全局复位网络
// 推荐使用异步复位同步释放

(* ASYNC_REG = "TRUE" *)  // FPGA属性:声明异步寄存器
reg [1:0] reset_sync_reg;

// FPGA复位策略:
// 1. 使用FPGA的全局复位网络(如果有时钟)
// 2. 避免复位网络上的高扇出
// 3. 考虑使用FPGA的初始化值

ASIC实现

// ASIC需要更严格的复位设计
// 需要考虑:
// 1. 复位树的平衡
// 2. 复位信号的时序收敛
// 3. 功耗优化(门控复位)

9. 测试验证代码

module test_reset;
    reg clk;
    reg rst_n;
    reg data_in;
    wire data_out_sync;
    wire data_out_async;
    wire data_out_async_sync;
    
    // 实例化三种复位方式
    sync_reset u_sync (
        .clk(clk),
        .rst_n(rst_n),
        .data_in(data_in),
        .data_out(data_out_sync)
    );
    
    async_reset u_async (
        .clk(clk),
        .rst_n(rst_n),
        .data_in(data_in),
        .data_out(data_out_async)
    );
    
    async_reset_sync_release u_async_sync (
        .clk(clk),
        .async_rst_n(rst_n),
        .data_in(data_in),
        .data_out(data_out_async_sync)
    );
    
    // 时钟生成
    always #5 clk = ~clk;
    
    initial begin
        // 初始化
        clk = 0;
        rst_n = 0;
        data_in = 0;
        
        // 测试同步复位
        #15;
        rst_n = 1;  // 释放复位
        #10;
        data_in = 1;
        #10;
        data_in = 0;
        
        // 测试异步复位
        #5;
        rst_n = 0;  // 异步复位
        #7;         // 在时钟中间复位
        rst_n = 1;  // 释放
        #20;
        
        $finish;
    end
endmodule

10. 总结建议

设计原则

  1. 推荐使用"异步复位,同步释放":兼顾响应速度和稳定性
  2. 复位同步器至少使用2级:确保亚稳态被充分消除
  3. 复位网络要平衡:避免复位偏移(skew)
  4. 复位与时钟关系要明确:在设计中统一复位策略

选择指南

  • 高速设计:异步复位同步释放
  • 低功耗设计:同步复位
  • 接口模块:异步复位同步释放
  • IP核集成:遵循IP核的复位要求

关键点

  • 复位信号必须是全局信号
  • 复位释放不能太靠近时钟沿
  • 复位树和时钟树同样重要
  • 仿真和综合要使用相同的复位策略

posted on 2025-12-03 19:55  SOC验证工程师  阅读(670)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3