FPGA單比特信號(hào)跨時(shí)鐘域處理
1.慢速時(shí)鐘域同步到快速時(shí)鐘域
輸入:singal_in,來(lái)自10MHz慢速時(shí)鐘域的單比特信號(hào)
輸出:singal_out,輸出100MHz快速時(shí)鐘域的單比特信號(hào)
10MHz = 100ns
100MHz = 10ns
因?yàn)槁贂r(shí)鐘域的最短信號(hào)長(zhǎng)度為1個(gè)時(shí)鐘時(shí)鐘周期即:100ns,大于快速時(shí)鐘域的時(shí)鐘周期10ns,所以只需要打3拍即可:
/* 從慢速時(shí)鐘域同步到快速時(shí)鐘域 */
module top(
//inputs
input clk, //快速時(shí)鐘,時(shí)鐘100MHz
input rst_n,
input signal_in, //來(lái)自慢速時(shí)鐘域,時(shí)鐘10MHz
//outputs
output signal_out //同步到快速時(shí)鐘域之后的信號(hào)
);
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
仿真波形:
2.快速時(shí)鐘域同步到慢速時(shí)鐘域
輸入:singal_a,來(lái)自100MHz快速時(shí)鐘域的單比特信號(hào)
輸出:singal_b,輸出10MHz慢速時(shí)鐘域的單比特信號(hào)
10MHz = 100ns
100MHz = 10ns
這里僅僅針對(duì)輸入信號(hào)的脈沖寬度僅有1個(gè)快速時(shí)鐘周期寬度的信號(hào),即singal_a的信號(hào)寬度僅有10ns寬,且兩個(gè)脈沖間隔時(shí)間大于兩個(gè)慢速時(shí)鐘周期,即2*100ns=200ns。
先在快速時(shí)鐘域下把邊沿信號(hào)轉(zhuǎn)換為電平信號(hào),再在慢速時(shí)鐘域下把電平信號(hào)打3拍,再在慢速時(shí)鐘域下把電平信號(hào)轉(zhuǎn)換為邊沿信號(hào):
/* 快速時(shí)鐘域同步到慢速時(shí)鐘域,針對(duì)脈沖寬度只有1個(gè)clk的信號(hào) */
module fast_to_low(
//inputs
input clk_a, //快速時(shí)鐘100MHz
input rst_n_a, //復(fù)位信號(hào)
input signal_a, //快速時(shí)鐘信號(hào),單比特,1個(gè)clk寬度脈沖
input clk_b, //慢速時(shí)鐘20MHz
input rst_n_b,
//outputs
output signal_b //同步之后的慢速時(shí)鐘域的信號(hào)
);
reg tmp;
reg tmp_reg1;
reg tmp_reg2;
reg tmp_reg3;
assign signal_b = tmp_reg2 ^ tmp_reg3; //電平信號(hào)轉(zhuǎn)換為邊沿
/* 在快速時(shí)鐘域下,把單clk脈沖信號(hào),轉(zhuǎn)換為邊沿信號(hào),在高電平時(shí)翻轉(zhuǎn),要求兩個(gè)脈沖間隔時(shí)間不能太短 */
always @ (posedge clk_a)
begin
if(!rst_n_a)
tmp <= 0;
else if(signal_a)
tmp <= ~tmp;
end
/* 在慢速時(shí)鐘域下對(duì) */
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; //快速時(shí)鐘域信號(hào)
wire signal_b; //慢速時(shí)鐘域信號(hào)
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 //兩次脈沖時(shí)間間隔應(yīng)該大于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
仿真波形:
詳細(xì)的原理解釋?zhuān)?a style="font-size: inherit;line-height: inherit;color: rgb(30, 107, 184);overflow-wrap: break-word;" rel="nofollow" target="_blank">單比特信號(hào)跨時(shí)鐘域問(wèn)題詳解
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!