单bit 跨时钟域,从慢时钟域到快时钟域
- 1,首先,了解一些问题
- 2,RTL代码设计
- 3,testbench测试代码
- 4,RTL代码和testbench综合的电路原理图
- 5,前仿真,验证
 
参考文献1,我的专栏,多bitMUX同步器
 参考文献2,本文主要参考
1,首先,了解一些问题
(1)怎么进行跨时钟域的处理? 打两拍进行同步。
(2)同步前后时钟域的快慢延伸出了两种情况:
1,先快后慢;确保在快时钟域内能采样到值,本题解决这个问题。
2,先慢后快;
怎么将信号从快时钟域同步到慢时钟域呢?
 答:将一个脉冲信号展宽为电平信号,让一个很短的脉冲信号变成一个很长的电平信号,就可以实现被快时钟域采样到。为了实现这个目的,我们在慢时钟域重新通过组合逻辑设计寄存器外围电路,这里我们使用异或门来进行展宽。
区分电平同步、脉冲同步、边沿同步。
电平同步,就是正常的打两拍;
边沿同步,是在正常的打两拍的基础上,clkb时钟域用边沿检测电路处理一下output信号,让这个信号保证为一个周期。
脉冲同步,是指在clka时钟域将脉冲信号处理成电平信号,再进行打两拍,再重复边沿同步的边沿检测电路的操作。
2,RTL代码设计
// 单bit 跨时钟域,从慢时钟域到快时钟域
module one_bit_cdc(
data, clka, clkb, rst_n, data_out
);
input  data;
input  clka;
input  clkb;
input  rst_n;
output data_out;
reg data_r;
reg [1:0] data_b_r;
always@(posedge clka or negedge rst_n)
   if(!rst_n)
       data_r <= 0;
   else 
       data_r <= data;
// 打两拍,解决亚稳态
always@(posedge clkb or negedge rst_n)
   if(!rst_n)
       data_b_r <= 0;
   else 
       begin
       	    data_b_r[0] <= data_r;
       	    data_b_r[1] <= data_b_r[0];
       end
assign data_out = data_b_r[1];
endmodule
3,testbench测试代码
// 单bit 测试信号
module one_bit_cdc_tb;
reg  data;
reg  clka;
reg  clkb;
reg  rst_n;
wire data_out;
always #20  data = $random;
always #10   clka = ~clka;   // 时钟  周期20
always #4    clkb = ~clkb;   // 时钟  周期8   
initial begin
	  rst_n = 0;  clka = 1; clkb = 1;
#15;  rst_n = 1;
end
one_bit_cdc uu(
.data(data),
.clka(clka),
.clkb(clkb),
.rst_n(rst_n),
.data_out(data_out)
);
endmodule
4,RTL代码和testbench综合的电路原理图





















