詳細的原理解釋:
單位元訊號跨時鐘域問題詳解
輸入: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;
endelse
begin
signal_in_reg1 <= signal_in;
signal_in_reg2 <= signal_in_reg1;
signal_in_reg3 <= signal_in_reg2;
endendendmodule
**tb檔案:
`timescale 1ns/
1psmodule 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;
#50rst_n =1;
#100
signal_in =1;
#100
signal_in =0;
#100
$stop;
endalways #(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
輸入: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;
endelse
begin
tmp_reg1 <= tmp;
tmp_reg2 <= tmp_reg1;
tmp_reg3 <= tmp_reg2;
endendendmodule;
**tb檔案:
`timescale 1ns/
1psmodule 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;
#10signal_a =0;
#500
//兩次脈衝時間間隔應該大於2*100ns=200ns,否則不能還原
signal_a =1;
#10signal_a =0;
#1000
$stop;
endalways #(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
**波形:
跨時鐘域分析 單位元訊號同步
處理跨時鐘域的資料有單bit和多bit之分,而打兩拍的方式常見於處理單bit資料的跨時鐘域問題。打兩拍本質就是定義兩級暫存器對資料進行延拍。流程如下圖所示 兩級暫存器的原理 兩級寄存是一級寄存的平方,兩級並不能完全消除亞穩態危害,但是提高了可靠性減少其發生概率。總的來講,就是一級概率很大,改善不大。...
「單位元訊號同步」 學習筆記(跨時鐘域問題)
文章 1.概述 訊號同步的目的是防止新時鐘域中第一級觸發器 的亞穩態訊號對下一級邏輯造成影響。簡單的同步器由兩個觸發器串聯而成,中間沒有其它組合電路。這種設計可以保證後面的觸發器獲得前乙個觸發器輸出時 前乙個觸發器已退出了亞穩態,並且輸出已穩定。2.訊號同步的要求 為了使同步工作能正常進行 從某個時...
跨時鐘域訊號處理
一 場景描述 某訊號signal需要在不同的時鐘域進行處理,需要同步到的不同的時鐘域繼續使用。舉例說明 某定時器timer包含兩個時鐘域bus clk和tmr clk。狀態暫存器sts和控制暫存器ctrl定義如下。暫存器讀寫訪問採用bus clk時鐘,timer功能採用tmr clk時鐘,當發生溢位...