跨时钟域同步2---单bit信号同步实战(快到慢+慢到快)


IC面试中常被问到:跨时钟域信号处理——握手协议(handshake)

① 程序设计

module handshake_sync ( 
    input clk1 , //快时钟信号
    input sys_rst_n , //复位信号,低电平有效
    input read , //信号,快时钟阈的
    input clk2 , //慢时钟信号

    output read_sync_pulse //输出信号
);

 //in1表示该信号在clk1时钟域
 reg req_in1 ;
 reg ack_in1 ;
 reg ack_in1_dly1 ;
 //in2表示该信号在clk2时钟域
 reg req_in2 ;
 reg req_in2_dly1 ;
 
 //*****************************************************
 //**                   main code
 //*****************************************************
 
 //1、clk1时钟域下req信号的生成
 always @(posedge clk1 or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) 
        req_in1 <= 1'b0;
    else if(read == 1'b1)
        req_in1 <= 1'b1;
    else if(ack_in1_dly1 == 1'b1)
        req_in1 <= 1'b0;
    else
        req_in1 <= 1'b0;
 end


 //2、clk2时钟域下req信号的采样
 always @(posedge clk2 or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        req_in2 <= 1'b0;
        req_in2_dly1 <= 1'b0;
    end
    else begin
        req_in2 <= req_in1;
        req_in2_dly1 <= req_in2;
    end
 end
 
 //3、clk1时钟域下ack信号的采样 直接采样req_in2_dly1作为ack信号即可
 //这是因为有了req_in2和req_in2_dly1之后我们就可以生成dout,所以此时就可以返回ack信号了
 always @(posedge clk1 or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        ack_in1 <= 1'b0;
        ack_in1_dly1 <= 1'b0;
    end
        
    else begin
        ack_in1 <= req_in2_dly1 ;
        ack_in1_dly1 <= ack_in1;
    end
        
 end
 
 //4、dout信号的产生
 
 assign read_sync_pulse = req_in2 & ~req_in2_dly1;
 
 endmodule

② 测试代码

`timescale 1ns / 1ps

module TB();

reg sys_clk1; 
reg sys_clk2; 
reg sys_rst_n; 
reg read ;
initial begin
    sys_clk1 = 1'b0;
    sys_clk2 = 1'b0;
    sys_rst_n = 1'b0;
    
    read = 1'b0;
    
    #200
    sys_rst_n = 1'b1;
    
    #100
    read = 1'b1;
    
    #20
    read = 1'b0;
    #100
    read = 1'b1;
    #20
    read = 1'b0;
 
end
 
 always #10 sys_clk1 = ~sys_clk1;
 always #30 sys_clk2 = ~sys_clk2;
 
 handshake_sync u_handshake_sync(
    .clk1 (sys_clk1 ),
    .clk2 (sys_clk2 ),
    .sys_rst_n (sys_rst_n),
    .read (read ),
    .read_sync_pulse(read_sync_pulse )
 );
 
endmodule

③ 仿真结果在这里插入图片描述

二、慢时钟域>>>快时钟域

慢时钟域到快时钟域的同步很简单,直接打拍就可以。如果信号有效时间太短,为了更好的采样该信号,也可以适当展宽一下,步骤和上面代码里写的差不多。

相关