方法:
1.采用两级触发器,减少可能出现的亚稳态影响;
2.异步FIFO和DPRAM;
3.握手协议,有效使能后,确认;
方法:
1.采用两级触发器,减少可能出现的亚稳态影响;
2.异步FIFO和DPRAM;
3.握手协议,有效使能后,确认;
转载于:https://www.cnblogs.com/geekite/p/4667191.html
区别同步信号与异步信号,要弄清楚信号变为有效状态时,它是否受CLK的限制.
“异步”输入信号和时钟信号无关,输入信号变为有效状态时,器件的状态就会立即改变;而“同步”输入信号和时钟信号有关,实际上输入信号和时钟信号进行了与运算或与非运算,输入信号和时钟信号的运算结果为有效状态时,器件的状态才会改变。
同步输入信号可以过滤掉不正确状态跳变对逻辑的影响,但是需要保证有效输入信号在时钟信号跳变前完成跳变,否则输入信号就是无效的。异步信号则和同步信号的效果正好相反。使用时请根据实际情况考虑。
异步清零:只要Reset=1即可清零,不管CLK是什么;
同步清零: Reset=1,并且CLK为上升沿或下降沿时才能清零.
异步置位:只要SET=1即可置1,不管CKL是什么;
同步置位:SET=1,并且CLK为上升沿或下降沿时才置1.
同步计数:当计数器达到计数条件时,只有当时钟信号的下降沿(或上升沿)来临时,计数器才会开始处理,其他时间无论高低电平,计数器都会无视;
异步计数:当计数器达到计数条件时,它立刻就跳转,并不等待时钟信号的下降沿(或上升沿)的来临
附同步时钟和异步时钟:link
同步电路:存储电路中所有触发器的时钟输入端都接同一个时钟脉冲源,因而所有触发器的状态的变化都与所加的时钟脉冲信号同步。
异步电路:电路没有统一的时钟,有些触发器的时钟输入端与时钟脉冲源相连,这有这些触发器的状态变化与时钟脉冲同步,而其他的触发器的状态变化不与时钟脉冲同步。
用verilog描述一个异步的D触发器,即就是当有时钟clk、reset、set、信号时该处发起都会随时发出响应。然后描述一个同步的D触发器,当有时钟脉冲时才会做出响应,而reset和set发生时只会等时钟发生变化才会做出响应。
同步电路的优点:
1 可以有效的避免毛刺的影响,提高设计可靠性,同步设计是避免毛刺最简单的方法。
2 简化时序分析过程
缺点:
最大可能时钟频率是由电路中最慢的逻辑路径决定的,也就是关键路径,意思就是说每一个逻辑的运算,从简单到复杂都要在一个时钟周期内完成,同步电路往往会出现逻辑延迟过大,使得系统频率降低。
解决方式:采用流水线的设计思想,将复杂的运算分为数个简单的运算,可以帮助提高系统频率。
关于同步时钟异步时钟的讨论:link
问题:1.两个不同的晶振产生都产生100M的时钟,并且两个相位差固定,这两个时钟是同步还是异步?
2.一个参考时钟为100M的PLL分频出来一个clk1=50M,又倍频出来一个clk2=500M,请问clk1和clk2是同步时钟吗?参考时钟与倍频或者分频出来的时钟是同步还是异步?
回复: 时钟同步和异步是根据相位差是否变化确定的,如果连个时钟的相位差固定则为同步时钟,否则为异步时钟。
你举的例子里:
1.两个晶振产生的时钟。两个晶振在上电是时相位差是随机的,而且不同晶振时钟漂移抖动也不一样,所以是异步时钟。
2.时钟分频。虽然clk1和clk2是同一个时钟源分频出来的,但是一个PLL只能输出一个时钟,所以clk1和clk2只能由两个PLL产生,与两个晶振产生的时钟情况类似。故也是异步时钟
在FPGA内部PLL的参数是固定已知的工具可以分析,所以在FPGA内认为2是同步时钟
只要不是同一个晶振出来的时钟,就是异步的。晶振之间是相互独立的
问题:一个PLL一次只能产生一个时钟比如产生clk1,要想同时再产生一个clk2就得需要另一个PLL,但是这两个PLL可以共用一个晶振产生参考时钟吗?
回复:当然可以共用。
且不说这个场景是不是需要使用两个独立的PLL,即使是独立的PLL,只要是同源时钟,输出频率是整数倍关系,他们的相位关系就是确定的,不需要做异步时钟处理,只需要做好跨时钟域的约束。
并不一定要set_multipaths_cycle命令来做跨时钟与的约束,具体情况具体分析,跟你的逻辑设计有关系,有时候只需要建立generated clock关系不需要进一步添加约束,有时候需要set_multicycle,有时候可能set_max_delay合适,也可能clock group合适。约束是跟具体功能紧密相关的
异步信号同步化的目的就是在于消除可能存在的亚稳态
至于什么是异步信号同步化,请自行google…这里直接通过两级寄存器对异步信号处理实现同步化
reg rx_1,rx_2;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
rx_1 <= 1'b0;
rx_2 <= 1'b0;
end
else begin
rx_1 <= rx;//data_in
rx_2 <= rx_1;
end
如何对边沿进行检测呢,同样也是使用两级寄存器来实现,通过两级寄存器的值检测信号的变化,产生标志脉冲
reg s_0_Temp,s_1_Temp;
//reg s_2_Temp;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
s_0_Temp <= 1'b0;
s_1_Temp <= 1'b0;
//s_2_Temp <= 1'b0;
end
else begin
s_0_Temp <= signal_in;//第一拍
s_1_Temp <= s_0_Temp;//第二拍
//s_2_Temp <= s_1_Temp;//第三拍
end
//同时钟域打拍
wire pedge,nedge;
assign pedge = !s_1_Temp && s_0_Temp;
assign nedge = s_1_Temp && !s_0_Temp;
/*
//跨时钟域打拍
//wire pedge,nedge;
//assign pedge = !s_2_Temp && s_1_Temp;
//assign nedge = s_2_Temp && !s_1_Temp;
*/
相关文章:
1.异步信号的同步处理——慢时钟域到快时钟域https://blog.csdn.net/qq_39485231/article/details/105381014
2.异步信号的同步处理——快时钟域到慢时钟域(方法一)https://blog.csdn.net/qq_39485231/article/details/105378323
3.异步信号的同步处理——快时钟域到慢时钟域(方法二) https://blog.csdn.net/qq_39485231/article/details/105380869
module time_diff(
input clk_a , //输入时钟A
input rst_n , //复位信号
input pulse_a, //输入脉冲A
input clk_b , //输入时钟B
output pulse_b //输出脉冲B
);
//reg define
reg pulse_inv ; //脉冲信号转换成电平信号
reg pulse_inv_d0 ; //时钟B下打拍
reg pulse_inv_d1 ;
reg pulse_inv_d2 ;
//*****************************************************
//** main code
//*****************************************************
assign pulse_b = pulse_inv_d1 ^ pulse_inv_d2 ;
//输入脉冲转成电平信号,确保时钟B可以采到
always @(posedge clk_a or negedge rst_n) begin
if(rst_n==1'b0)
pulse_inv <= 1'b0 ;
else if(pulse_a)
pulse_inv <= ~pulse_inv;
end
//A时钟下电平信号转成时钟B下的脉冲信号
always @(posedge clk_b or negedge rst_n) begin
if(rst_n==1'b0) begin
pulse_inv_d0 <= 1'b0;
pulse_inv_d1 <= 1'b0;
pulse_inv_d2 <= 1'b0;
end
else begin
pulse_inv_d0 <= pulse_inv ;
pulse_inv_d1 <= pulse_inv_d0;
pulse_inv_d2 <= pulse_inv_d1;
end
end
endmodule
`timescale 1ns/1ns
module testbench; // 申明TestBench名称
reg clka;
reg clkb;
reg rst_n; // 申明信号
reg pulse_a;
wire pulse_b;
// 申明移位寄存器设计单元
time_diff u1(.clk_a (clka),
.clk_b (clkb),
.rst_n (rst_n),
.pulse_a (pulse_a),
.pulse_b (pulse_b));
initial begin // 建立时钟
clka = 0;
forever #10 clka = ~clka;
end
initial begin // 建立时钟
clkb = 0;
forever #100 clkb = ~clkb;
end
initial begin // 提供激励
rst_n = 0;
pulse_a = 0;
#10
rst_n = 1;
#20
pulse_a = 1;
#20
pulse_a = 0;
#250
pulse_a = 1;
#20
pulse_a = 0;
end
endmodule
需要同步的脉冲信号只能在原时钟域持续一个周期。clka是快时钟,clkb是慢时钟,程序中是让快时钟的脉冲同步的慢时钟,先是在clka下把脉冲展成电平信号,但就是这里出了问题,一旦脉冲在clka下持续时间是两个clka周期,那么就不能展成电平信号,从而导致clkb下可能采样不到信号,可以仿真看一下:
虽然当脉冲信号持续时间多于一个周期时,仍然可能会同步成功,但是不能保证100%成功,所以这种情况最好不要用这种方法。
脉冲满足在clka下只持续一个周期,那么clka相邻脉冲时间间隔至少要两个clkb周期才能保证两个相邻脉冲都能同步成功。pulse_inv是脉冲在clka下展成的电平信号,当有两个脉冲时,pulse_inv会展成一个脉冲,要想在clkb下最后能生成两个脉冲,pulse_inv的脉冲至少要持续两个clkb周期,不懂的话可以自己结合程序画波形图。
时间间隔的算法:待同步的两个脉冲的时间起点要间隔至少两个clkb周期。比如clka周期10ns,clkb周期100ns,clka脉冲持续时间是第10-20ns和210-220ns才满足条件。
这个程序对于同频但不知道相位是否有差异的信号也能进行同步,对脉冲的要求也要满足上面讲到的第一和第二点
对于慢时钟域同步到快时钟域也可以用上面的程序,对脉冲的要求也要满足上面讲到的第一和第二点。但通常慢时钟域同步到快时钟域可以用另一种简单的方法可以参考我的另一篇文章: 异步信号的同步处理——慢时钟域到快时钟域