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|__________
↑ ↑
复位生效(同步) 复位释放(同步)
优缺点
优点:
- 避免亚稳态
- 复位信号可以综合到触发器的数据路径
- 时序分析简单
- 对毛刺不敏感
缺点:
- 需要时钟才能复位
- 复位信号长度必须大于时钟周期
- 可能增加组合逻辑延迟
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|__________
↑ ↑
复位生效(异步) 复位释放(异步)
优缺点
优点:
- 立即生效,不需要等待时钟
- 实现简单
- 功耗较低(复位时可关闭时钟)
缺点:
- 释放时可能产生亚稳态
- 对复位毛刺敏感
- 时序分析复杂
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. 总结建议
设计原则
- 推荐使用"异步复位,同步释放":兼顾响应速度和稳定性
- 复位同步器至少使用2级:确保亚稳态被充分消除
- 复位网络要平衡:避免复位偏移(skew)
- 复位与时钟关系要明确:在设计中统一复位策略
选择指南
- 高速设计:异步复位同步释放
- 低功耗设计:同步复位
- 接口模块:异步复位同步释放
- IP核集成:遵循IP核的复位要求
关键点
- 复位信号必须是全局信号
- 复位释放不能太靠近时钟沿
- 复位树和时钟树同样重要
- 仿真和综合要使用相同的复位策略
浙公网安备 33010602011771号