文章目录


详细的原理解释:​

1.慢速时钟域同步到快速时钟域

输入:singal_in,来自10MHz慢速时钟域的单比特信号
输出:singal_out,输出100MHz快速时钟域的单比特信号

10MHz = 100ns
100MHz = 10ns

因为慢速时钟域的最短信号长度为1个时钟时钟周期即:100ns,大于快速时钟域的时钟周期10ns,所以只需要打3拍即可:

/* 从慢速时钟域同步到快速时钟域 */

module top(
//inputs
input clk, //快速时钟,时钟100MHz
input rst_n,
input signal_in, //来自慢速时钟域,时钟10MHz

//outputs
output signal_out //同步到快速时钟域之后的信号
);

reg signal_in_reg1;
reg signal_in_reg2;
reg signal_in_reg3;

assign signal_out = signal_in_reg3;

always @ (posedge clk)
begin
if(!rst_n)
begin
signal_in_reg1 <= 0;
signal_in_reg2 <= 0;
signal_in_reg3 <= 0;
end
else
begin
signal_in_reg1 <= signal_in;
signal_in_reg2 <= signal_in_reg1;
signal_in_reg3 <= signal_in_reg2;
end
end

endmodule

仿真TB文件:

`timescale 1ns/1ps

module top_tb;

reg clk_100m; //Period=10ns;
reg rst_n;
reg signal_in;

wire signal_out;

initial
begin
clk_100m = 1;
rst_n = 0;
signal_in = 0;
#50
rst_n = 1;
#100
signal_in = 1;
#100
signal_in = 0;
#100
$stop;
end

always #(10/2) clk_100m <= !clk_100m;


top top_ut(
//inputs
.clk(clk_100m),
.rst_n(rst_n),
.signal_in(signal_in),

//outputs
.signal_out(signal_out)
);

endmodule

仿真波形:

FPGA单比特信号跨时钟域处理_FPGA

2.快速时钟域同步到慢速时钟域

输入:singal_a,来自100MHz快速时钟域的单比特信号
输出:singal_b,输出10MHz慢速时钟域的单比特信号

10MHz = 100ns
100MHz = 10ns

这里仅仅针对输入信号的脉冲宽度仅有1个快速时钟周期宽度的信号,即singal_a的信号宽度仅有10ns宽,且两个脉冲间隔时间大于两个慢速时钟周期,即2*100ns=200ns。

先在快速时钟域下把边沿信号换为电平信号,再在慢速时钟域下把电平信号打3拍,再在慢速时钟域下把电平信号转换为边沿信号:

/* 快速时钟域同步到慢速时钟域,针对脉冲宽度只有1个clk的信号 */

module fast_to_low(
//inputs
input clk_a, //快速时钟100MHz
input rst_n_a, //复位信号
input signal_a, //快速时钟信号,单比特,1个clk宽度脉冲

input clk_b, //慢速时钟20MHz
input rst_n_b,

//outputs
output signal_b //同步之后的慢速时钟域的信号
);

reg tmp;
reg tmp_reg1;
reg tmp_reg2;
reg tmp_reg3;

assign signal_b = tmp_reg2 ^ tmp_reg3; //电平信号转换为边沿

/* 在快速时钟域下,把单clk脉冲信号,转换为边沿信号,在高电平时翻转,要求两个脉冲间隔时间不能太短 */
always @ (posedge clk_a)
begin
if(!rst_n_a)
tmp <= 0;
else if(signal_a)
tmp <= ~tmp;
end

/* 在慢速时钟域下对 */
always @ (posedge clk_b)
begin
if(!rst_n_b)
begin
tmp_reg1 <= 0;
tmp_reg2 <= 0;
tmp_reg3 <= 0;
end
else
begin
tmp_reg1 <= tmp;
tmp_reg2 <= tmp_reg1;
tmp_reg3 <= tmp_reg2;
end
end

endmodule;

仿真TB文件:

`timescale 1ns/1ps

module top_tb;

reg clk_a; //100MHz = 10ns;
reg clk_b; //10MHz = 100ns;

reg rst_n_a;
reg rst_n_b;

reg signal_a; //快速时钟域信号

wire signal_b; //慢速时钟域信号

initial
begin
clk_a = 1;
clk_b = 1;
rst_n_a = 0;
rst_n_b = 0;
signal_a = 0;
#300
rst_n_a = 1;
rst_n_b = 1;
#500
signal_a = 1;
#10
signal_a = 0;
#500 //两次脉冲时间间隔应该大于2*100ns=200ns,否则不能还原
signal_a = 1;
#10
signal_a = 0;
#1000

$stop;
end

always #(10/2) clk_a <= !clk_a; //100MHz = 10ns
always #(100/2) clk_b <= !clk_b; //10MHz = 100ns

fast_to_low fast_to_low_ut(
//inputs
.clk_a(clk_a),
.rst_n_a(rst_n_a),
.signal_a(signal_a),

.clk_b(clk_b),
.rst_n_b(rst_n_b),

//outputs
.signal_b(signal_b)
);

endmodule

仿真波形:

FPGA单比特信号跨时钟域处理_跨时钟_02