目录
一、原理
a 在第一个时钟域中检测需要跨时钟域的脉冲信号din的上升沿;
b 检测到上升沿时,将新设置的信号p_1置1;
c 将信号p_1通过打两拍同步到第二个时钟域,得到信号p_1_to_2_d2;
d 在第二个时钟域中,检测信号p_1_to_2_d2从0到1,得到同步后的脉冲信号dout;
e 将信号p_1_to_2_d2通过打两拍同步到第一个时钟域,得到信号p_2_to_1_d2;
f 在第一个时钟域中,检测信号p_2_to_1_d2从0到1,得到信号q;
g 在第一个时钟域中,当信号q为1时,将信号p_1置0;
二、设计代码
`timescale 1ns / 1ps
module cdc_pulse
(
input clk1,
input clk2,
input rstn1,
input rstn2,
input din,
output dout
);
reg din_d;
wire in_r;
reg p_1;
reg p_1_to_2_d1, p_1_to_2_d2;
reg p_1_to_2_d3;
reg p_2_to_1_d1, p_2_to_1_d2;
reg p_2_to_1_d3;
wire q;
always @ (posedge clk1 or negedge rstn1) begin
if (~rstn1)
din_d <= 'b0;
else
din_d <= din;
end
assign in_r = din & ~din_d;
always @ (posedge clk1 or negedge rstn1) begin
if (~rstn1)
p_1 <= 'b0;
else if (in_r)
p_1 <= 'b1;
else if (q)
p_1 <= 'b0;
end
always @ (posedge clk2 or negedge rstn2) begin
if (~rstn2) begin
p_1_to_2_d1 <= 'b0;
p_1_to_2_d2 <= 'b0;
end
else begin
p_1_to_2_d1 <= p_1;
p_1_to_2_d2 <= p_1_to_2_d1;
end
end
always @ (posedge clk2 or negedge rstn2) begin
if (~rstn2)
p_1_to_2_d3 <= 'b0;
else
p_1_to_2_d3 <= p_1_to_2_d2;
end
assign dout = p_1_to_2_d2 & ~p_1_to_2_d3;
always @ (posedge clk1 or negedge rstn1) begin
if (~rstn1) begin
p_2_to_1_d1 <= 'b0;
p_2_to_1_d2 <= 'b0;
end
else begin
p_2_to_1_d1 <= p_1_to_2_d2;
p_2_to_1_d2 <= p_2_to_1_d1;
end
end
always @ (posedge clk1 or negedge rstn1) begin
if (~rstn1)
p_2_to_1_d3 <= 'b0;
else
p_2_to_1_d3 <= p_2_to_1_d2;
end
assign q = p_2_to_1_d2 & ~p_2_to_1_d3;
endmodule
三、testbench
1、慢时钟域到快时钟域
`timescale 1ns / 1ps
module cdc_tb();
reg clk1;
reg rst1_n;
reg clk2;
reg rst2_n;
reg cin;
wire cout;
cdc_pulse u(
.clk1(clk1),
.rstn1(rst1_n),
.clk2(clk2),
.rstn2(rst2_n),
.din(cin),
.dout(cout)
);
initial begin
rst1_n = 0;
rst2_n = 0;
clk1 = 0;
clk2 = 0;
#50
rst1_n = 1;
rst2_n = 1;
end
always #30 clk1 = ~clk1;
always #10 clk2 = ~clk2;
initial begin
cin <= 0;
#90
cin <= 1;
#60
cin <= 0;
end
endmodule
2、快时钟域到慢时钟域
`timescale 1ns / 1ps
module cdc_tb();
reg clk1;
reg rst1_n;
reg clk2;
reg rst2_n;
reg cin;
wire cout;
cdc_pulse u(
.clk1(clk1),
.rstn1(rst1_n),
.clk2(clk2),
.rstn2(rst2_n),
.din(cin),
.dout(cout)
);
initial begin
rst1_n = 0;
rst2_n = 0;
clk1 = 0;
clk2 = 0;
#50
rst1_n = 1;
rst2_n = 1;
end
always #10 clk1 = ~clk1;
always #30 clk2 = ~clk2;
initial begin
cin <= 0;
#70
cin <= 1;
#20
cin <= 0;
end
endmodule
PS:觉得有用就点个赞收藏吧