前言
之前在亚稳态和异步FIFO中就有提到跨时钟域,一直没有单独写一篇跨时钟域的笔记
正文
一、什么是跨时钟域
从字面意思理解,跨了2个不同的时钟域,那势必会出现一个问题,从时钟域A过来的信号难以满足时钟域B中触发器的建立时间和保持时间,就会造成亚稳态问题,并且在跨时钟域中,还需要区分跨时钟域的信号是单比特还是多比特,是从快时钟域到慢时钟域,还是从慢时钟域到快时钟域,对于上述不同的类型,有不同的解决方法
二、跨时钟的分类
注:快时钟<=2*慢时钟,这样才能定义出快慢
2.1 单比特:慢时钟域—>快时钟域
使用同步器的方法来处理跨时钟域问题,通常同步器只需要2个触发器即可;注意是将输入信号同步到快时钟域,因此在打拍时敏感信号列表里是目标快时钟域
补充:2级触发器还可以用来检测信号上升沿或下降沿
设计文件
module cdc_m_k (
input clk_a,//10M
input clk_b,//100M
input rst_n,
input pulse_in_a,
output pulse_out_b
);
reg reg_in_1;
reg reg_in_2;
always @(posedge clk_b or negedge rst_n) begin
if(!rst_n)begin
reg_in_1 <= 1'b0;
reg_in_2 <= 1'b0;
end
else begin
reg_in_1 <= pulse_in_a;
reg_in_2 <= reg_in_1;
end
end
assign pulse_out_b = reg_in_2;
endmodule
测试文件
`timescale 1ps/1ps
module tb_cdc_m_k ();
reg clk_a;
reg clk_b;
reg rst_n;
reg pulse_in_a;
wire pulse_out_b;
initial begin
clk_a = 1'b0;
clk_b = 1'b0;
rst_n = 1'b0;
pulse_in_a = 1'b0;
#6
rst_n = 1'b1;
#29
pulse_in_a = 1'b1;
#200
pulse_in_a = 1'b0;
#90
pulse_in_a = 1'b1;
end
always #100 clk_a = ~clk_a;
always #10 clk_b = ~clk_b;
cdc_m_k cdc_m_k_inst(
.clk_a(clk_a),
.clk_b(clk_b),
.rst_n(rst_n),
.pulse_in_a(pulse_in_a),
.pulse_out_b(pulse_out_b)
);
endmodule
2.2 单比特:快时钟域—>慢时钟域
从快时钟域到慢时钟域,可能会出现下图中的信号漏采,如图,快时钟域采的紫色虚线,而慢时钟域采的绿色虚线,明显有很多信号慢时钟域下没有采到
于是先将快时钟域下的信号进行扩宽,