目录
问题:Signal_a是clka(300M)时钟域的一个单时钟脉冲信号,如何将其同步到时钟域clkb(100M)中,并产生出Signal_b同步脉冲信号。请用Verilog代码描述,并画出对应的时序波形图说明图。(大疆FPGA逻辑岗A卷)
一、单比特信号从慢时钟域到快时钟域
(1)矩形脉冲的“0”变“1”、“1”变“0”不是立刻变化的,有一个变化的过程,运放里叫压摆率(SR)。
如果时钟采样时信号正好在变化的过程,数据传输的过程就不满足建立时间和保持时间,触发器的输出会处于不确定的状态,不等于稳定的输入值,存在“亚稳态”的问题。
(2)解决办法:
“打两拍法”,数据进来后首先打一拍,通过第一级寄存器;第一级寄存器的输出再通过第二级寄存器,第二级寄存器的输出就是相对稳定的0/1。
PS:亚稳态震荡时间(Tmet)与器件工艺、温度、环境等很多因素有关。
二、单比特信号从快时钟域到慢时钟域
(1)也存在“亚稳态”的问题
(2)还可能存在采不到的问题:
(3)解决办法:
在clka的时钟域下延长第一个Signal_a到第二个Signal_a,延长第三个Signal_a到第四个Signal_a。。。即在clka时钟下检测到Signal_a为高时,令Signal_a_L取反。
加上亚稳态的处理方法——“打两拍”,在clkb时钟域上得到Signal_a_L1和Signal_a_L2。
最后使用边沿检测的方法检测Signal_a_L2(L2的数据是稳定的,L1可能不稳定)的上升沿和下降沿还原脉冲Signal_b。
三、RTL代码
module One_bit_fast2slow(
input wire clka,
input wire Rsta_N,
input wire Signal_a,
input wire clkb,
input wire Rstb_N,
output wire Signal_b
);
//在clka时钟下检测到Signal_a为高时,令Signal_a_L取反
reg Signal_a_L = 1'b0;
always@(posedge clka or negedge Rsta_N)
begin
if(!Rsta_N)
Signal_a_L <= 1'b0;
else if(Signal_a)
Signal_a_L <= ~Signal_a_L;
end
//打三拍,加上亚稳态的处理方法——“打两拍”,边沿检测打一拍
reg Signal_a_L1 = 1'b0;
reg Signal_a_L2 = 1'b0;
reg Signal_a_L2r = 1'b0;
always@(posedge clkb or negedge Rstb_N)
begin
if(!Rstb_N)
begin
Signal_a_L1 <= 1'b0;
Signal_a_L2 <= 1'b0;
Signal_a_L2r <= 1'b0;
end
else
begin
Signal_a_L1 <= Signal_a_L;
Signal_a_L2 <= Signal_a_L1;
Signal_a_L2r <= Signal_a_L2;
end
end
//边沿检测
wire Signal_b_pose,Signal_b_nege;
assign Signal_b_pose = Signal_a_L2 && (!Signal_a_L2r); //上升沿
assign Signal_b_nege = (!Signal_a_L2) && Signal_a_L2r; //下降沿
assign Signal_b = Signal_a_L2^Signal_a_L2r; //上升沿和下降沿
endmodule
四、TB代码
`timescale 1ns/1ps
`define clk_period 3.333 //300M
`define clk_period2 10 //100M
module One_bit_fast2slow_tb();
reg clka;
reg Rsta_N;
reg Signal_a;
reg clkb;
reg Rstb_N;
wire Signal_b;
One_bit_fast2slow One_bit_fast2slow_U1(
.clka(clka),
.Rsta_N(Rsta_N),
.Signal_a(Signal_a),
.clkb(clkb),
.Rstb_N(Rstb_N),
.Signal_b(Signal_b)
);
initial clka = 1;
always #(`clk_period/2)clka = ~clka;
initial clkb = 1;
always #(`clk_period2/2)clkb = ~clkb;
initial begin
Rsta_N = 0;Rstb_N = 0;Signal_a = 0;
#(`clk_period2*20 + 1);
Rsta_N = 1;Rstb_N = 1;
#(`clk_period2*20 );
Signal_a = 1;
#(`clk_period);
Signal_a = 0;
#(`clk_period*5);
Signal_a = 1;
#(`clk_period);
Signal_a = 0;
#100;
Signal_a = 1;
#(`clk_period);
Signal_a = 0;
#(`clk_period*5);
Signal_a = 1;
#(`clk_period);
Signal_a = 0;
#10_000;
end
endmodule
五、仿真结果
六、RTL图