异步时钟域的问题
在一个时钟域里计数产生的计数值用于另一个时钟域时必须同步么?
如下例:
always @(posedge clk_32k or negedge rstn)begin
if((!rstn)
cnt=8'b0;
else if(cnt==8'd128)
cnt=8'b0;
else
cnt=cnt+8'b1;
end
always @(posedge clk_1M or negedge rstn)
begin
if(rstn)
en1 <= 1'b0;
else if(cnt==8'd100)
en1 <= 1'b1;
else if(cnt==8'd104)
en1 <= 1'b0;
end
这样的设计会不会有风险
你用频率快的时钟采频率慢的时钟,应该能采得到吧!
快的采慢的,数据不会有遗漏,但要做异步过度,不然可能会采到亚稳态的数据。
而且你要过度的是8比特的总线信号,要做总线异步过度电路。
功能上应该不会有问题,不过最好是先同步了在使用。
做个格雷码吧,然后再打两拍 。 你这样设计有风险的。
设计成clk_en,而不是clk. 同步设计模块应该使用同一个时钟。当然系统太大的时候使用全局异步(多个时钟域),局部同步(一个时钟域),互联专门处理CDC.
RE: 异步时钟域的问题
总线异步过度电路是什么?也是寄存器打拍么
clk_32时钟域定义两个新信号
wire set_ en_32k,clr_en_32k;
set_en_32k == (cnt==8'd100);
clr_en_32k == (cnt==8'd104);
写一个结绳模块将这两个信号结绳到1M时钟域,假设新信号名为set_en_1M, clr_en_1M
用结绳过来的信号控制en1
always @(posedge clk_1M or negedge rstn)
begin
if(rstn)
en1 <= 1'b0;
else if(set_en_1M)
en1 <= 1'b1;
else if(clr_en_1M)
en_cnt <= 1'b0;
end
谢谢楼上的详细回复,所谓的结绳模块实际上也是寄存器打拍么
结绳可以把一个周期宽度的脉冲信号从一个时钟域同步到另一个时钟域(低到高或者高到低都可以)
完全异步逻辑,进行数据传递,会产生亚稳态,就看亚稳态传播对你系统的影响多大了
必须用,不然会到亚稳态。两级FF
这样肯定有风险!
multi-bit bus在跨时钟域的时候由于时延不同可能导致错误,
比如cnt 从'hFF递增到‘h100的时候在另个时钟域可能先出现
'hFF -> 'h104 -> 'h100的情况,这样你的设计就会出现误状态。
尽量使用one-bit signal跨时钟域。
快的采慢的可以,最好还是寄存2拍,3拍最佳
可以用大拍,也可以用FIFO等异步缓冲
补充一下结绳法:原始信号是set_en_32k,所属时钟域为clk_32k;新信号名为set_en_1M,所属时钟域为clk_1M
assign din=set_en_32k?(!qout):qout;
always @(posedge clk_32k or negedge reset_n) begin
if(~reset_n)
qout<=0;
else
qout<=din;
end
always @(posedge clk_1M or reset_n) begin
if(~reset_n)
{qout2,qout1}<=2'b00;
else
{qout2,qout1}<={qout1,qout};
end
assign set_en_1M=qout2^qout1;
前辈这样子做比较适合传输1bit的信号吧
像小编这样子,8位的,岂不是用8次?
之前使用过16楼的类似思想,原来还有个名字叫结绳法,蛮形象的。
正解!
想不出错···你需要把cnt信号同步在后续clk_1m数据里面!不过这样就增加了很多你寄存器的数量!
WHAT THE HELL IS THAT
跨时钟域的讲究好多啊,学学
麻烦您能具体解释一下这句话吗?每太想清楚。
我做的话 ,结绳然后再打2拍
感觉lz的设计有异步问题 en1 可能会有毛刺
格雷码
搞复杂了,而且逻辑写错了。说白了就是在32k时钟域将多bit信号转换成1bit信号,然后同步到1M时钟域。
always @(posedge clk_32k or negedge rstn)begin
if(!rstn)
cnt<=8'b0;
else if(cnt==8'd128)
cnt<=8'b0;
else
cnt<=cnt+8'b1;
end
assign set_en_32k = cnt==8'd100;
assign clr_en_32k = cnt==8'd104;
always @(posedge clk_32k or negedge rstn) begin
if(!rstn)
en1_32k <= 1'b0;
else if(set_en_32k)
en1_32k <= 1'b1;
else if(clr_en_32k)
en1_32k <= 1'b0;
end
always @(posedge clk_1M or negedge rstn) begin
if(!rstn) begin
en1 <= 1'b0;
en1_1M_d2 <= 1'b0;
en1_1M_d1 <= 1'b0;
end
else begin
en1 <= en1_1M_d2;
en1_1M_d2 <= en1_1M_d1;
en1_1M_d1 <= en1_32k;
end
end
各位大神分析的很详细啊
正解
比较完之后再同步,就两个信号