22
2022
04

CDC 单脉冲信号处理

代码中的Sys_clk其实是没有用到的,项目文件:

cdc_single.zip

//------------------------------------------------------
// File Name        : cdc.v
// Author           : ChanRa1n
// Description      : a cdc test ex
// Called by        : TopModule
// Revision History : 2022-04-22
// Revision         : 1.0
// Email            : chenyu@myfpga.cn
// Copyright(c) 2018-Now, MYFPGA.CN, All right reserved.
//------------------------------------------------------

module cdc (
    input   wire   [0:0]   Sys_clk,
    input   wire   [0:0]   Sys_rst_n,

    input   wire   [0:0]   Clk_50M_in,
    input   wire   [0:0]   Clk_10M_in,

    input   wire   [0:0]   Sig_50M_in,
    input   wire   [0:0]   Sig_10M_in,

    output  wire   [0:0]   Sig_out_fast2slow,
    output  wire   [0:0]   Sig_out_slow2fast,

    output  wire   [0:0]   Sig_out_fast2slow_dff2,
    output  wire   [0:0]   Sig_out_slow2fast_dff2
);
//-----------------------------------------------------------------------------
    reg   [0:0]   Sig_out_fast2slow_reg ;
    reg   [0:0]   Sig_out_slow2fast_reg ;  
    assign   Sig_out_fast2slow = Sig_out_fast2slow_reg ;
    assign   Sig_out_slow2fast = Sig_out_slow2fast_reg ;

    always@(posedge Clk_10M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_fast2slow_reg <= 0 ;
        end
        else begin
            Sig_out_fast2slow_reg <= Sig_50M_in ;
        end
    end

    always@(posedge Clk_50M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_slow2fast_reg <= 0 ;
        end
        else begin
            Sig_out_slow2fast_reg <= Sig_10M_in ;
        end
    end
//-----------------------------------------------------------------------------
    reg   [0:0]   Sig_out_fast2slow_lvl_reg  ;
    reg   [0:0]   Sig_out_fast2slow_adj_reg0 ;
    reg   [0:0]   Sig_out_fast2slow_adj_reg1 ;

    always@(posedge Clk_50M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_fast2slow_lvl_reg <= 0 ;
        end
        else begin
            if(Sig_50M_in)
                Sig_out_fast2slow_lvl_reg <= ~Sig_out_fast2slow_lvl_reg ;
            else
                Sig_out_fast2slow_lvl_reg <= Sig_out_fast2slow_lvl_reg ;
        end
    end

    always@(posedge Clk_10M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_fast2slow_adj_reg0 <= 0 ;
            Sig_out_fast2slow_adj_reg1 <= 0 ;
        end
        else begin
            Sig_out_fast2slow_adj_reg0 <= Sig_out_fast2slow_lvl_reg ;
            Sig_out_fast2slow_adj_reg1 <= Sig_out_fast2slow_adj_reg0;
        end
    end

    assign   Sig_out_fast2slow_dff2 = Sig_out_fast2slow_adj_reg0 != Sig_out_fast2slow_adj_reg1;
//-----------------------------------------------------------------------------
    reg   [0:0]   Sig_out_slow2fast_lvl_reg  ;
    reg   [0:0]   Sig_out_slow2fast_adj_reg0 ;
    reg   [0:0]   Sig_out_slow2fast_adj_reg1 ;

    always@(posedge Clk_10M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_slow2fast_lvl_reg <= 0 ;
        end
        else begin
            if(Sig_50M_in)
                Sig_out_slow2fast_lvl_reg <= ~Sig_out_slow2fast_lvl_reg ;
            else
                Sig_out_slow2fast_lvl_reg <= Sig_out_slow2fast_lvl_reg ;
        end
    end

    always@(posedge Clk_50M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_slow2fast_adj_reg0 <= 0 ;
            Sig_out_slow2fast_adj_reg1 <= 0 ;
        end
        else begin
            Sig_out_slow2fast_adj_reg0 <= Sig_out_slow2fast_lvl_reg ;
            Sig_out_slow2fast_adj_reg1 <= Sig_out_slow2fast_adj_reg0;
        end
    end

    assign   Sig_out_slow2fast_dff2 = Sig_out_slow2fast_adj_reg0 != Sig_out_slow2fast_adj_reg1 ;

//-----------------------------------------------------------------------------
endmodule


//------------------------------------------------------
// File Name        : cdc_tb.v
// Author           : ChanRa1n
// Description      : Testbench file for cdc_tb
// Called by        : Simulation
// Revision History : 2022-04-22
// Revision         : 1.0
// Email            : chenyu@myfpga.cn
// Copyright(c) 2018-Now, MYFPGA.CN, All right reserved.
//------------------------------------------------------

`default_nettype wire
`timescale 1ns/1ns

module cdc_tb ();
    reg Sys_clk;
    reg Sys_rst_n;

    reg    [0:0]   Clk_50M_in;
    reg    [0:0]   Clk_10M_in;
    reg    [0:0]   Sig_50M_in;
    reg    [0:0]   Sig_10M_in;
    wire   [0:0]   Sig_out_fast2slow;
    wire   [0:0]   Sig_out_slow2fast;
    wire   [0:0]   Sig_out_fast2slow_dff2;
    wire   [0:0]   Sig_out_slow2fast_dff2;

    localparam CLK_PERIOD = 10;

    always #(CLK_PERIOD/2) Sys_clk=~Sys_clk;
    always #(100) Clk_10M_in=~Clk_10M_in;
    always #(20) Clk_50M_in=~Clk_50M_in;

    initial begin
        #1 Sys_rst_n<=1'b0;Sys_clk<=1'b0;Clk_10M_in<=0;
        #1 Clk_50M_in<=0;
        #(CLK_PERIOD*3) Sys_rst_n<=1;
        #(CLK_PERIOD*3000);
        $stop;
    end
   
    initial begin
        forever begin
        @(posedge Clk_10M_in);
        Sig_10M_in <= {$random} % 2;
        end
    end

    initial begin
        forever begin
        @(posedge Clk_50M_in);
        Sig_50M_in <= {$random} % 2;
        end
    end

    cdc cdc (
    .Sys_clk(Sys_clk),
    .Sys_rst_n(Sys_rst_n),
    .Clk_50M_in(Clk_50M_in),
    .Clk_10M_in(Clk_10M_in),
    .Sig_50M_in(Sig_50M_in),
    .Sig_10M_in(Sig_10M_in),
    .Sig_out_fast2slow(Sig_out_fast2slow),
    .Sig_out_slow2fast(Sig_out_slow2fast),
    .Sig_out_fast2slow_dff2(Sig_out_fast2slow_dff2),
    .Sig_out_slow2fast_dff2(Sig_out_slow2fast_dff2)
    );

endmodule

image.png

image.png

image.png


当然,光是对高速信号展宽还是不够,我们依旧没有消除亚稳态,所以这里需要再进行打两拍。也就是这样:

//------------------------------------------------------
// File Name        : cdc.v
// Author           : ChanRa1n
// Description      : a cdc test ex
// Called by        : TopModule
// Revision History : 2022-04-22
// Revision         : 1.0
// Email            : chenyu@myfpga.cn
// Copyright(c) 2018-Now, MYFPGA.CN, All right reserved.
//------------------------------------------------------

module cdc (
    input   wire   [0:0]   Sys_clk,
    input   wire   [0:0]   Sys_rst_n,

    input   wire   [0:0]   Clk_50M_in,
    input   wire   [0:0]   Clk_10M_in,

    input   wire   [0:0]   Sig_50M_in,
    input   wire   [0:0]   Sig_10M_in,

    output  wire   [0:0]   Sig_out_fast2slow,
    output  wire   [0:0]   Sig_out_slow2fast,

    output  wire   [0:0]   Sig_out_fast2slow_dff2,
    output  wire   [0:0]   Sig_out_slow2fast_dff2
);
//-----------------------------------------------------------------------------
    reg   [0:0]   Sig_out_fast2slow_reg ;
    reg   [0:0]   Sig_out_slow2fast_reg ;  
    assign   Sig_out_fast2slow = Sig_out_fast2slow_reg ;
    assign   Sig_out_slow2fast = Sig_out_slow2fast_reg ;

    always@(posedge Clk_10M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_fast2slow_reg <= 0 ;
        end
        else begin
            Sig_out_fast2slow_reg <= Sig_50M_in ;
        end
    end

    always@(posedge Clk_50M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_slow2fast_reg <= 0 ;
        end
        else begin
            Sig_out_slow2fast_reg <= Sig_10M_in ;
        end
    end
//-----------------------------------------------------------------------------
    reg   [0:0]   Sig_out_fast2slow_lvl_reg  ;
    reg   [0:0]   Sig_out_fast2slow_adj_reg0 ;
    reg   [0:0]   Sig_out_fast2slow_adj_reg1 ;
    reg   [0:0]   Sig_out_fast2slow_adj_reg2 ;
    reg   [0:0]   Sig_out_fast2slow_adj_reg3 ;

    always@(posedge Clk_50M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_fast2slow_lvl_reg <= 0 ;
        end
        else begin
            if(Sig_50M_in)
                Sig_out_fast2slow_lvl_reg <= ~Sig_out_fast2slow_lvl_reg ;
            else
                Sig_out_fast2slow_lvl_reg <= Sig_out_fast2slow_lvl_reg ;
        end
    end

    always@(posedge Clk_10M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_fast2slow_adj_reg0 <= 0 ;
            Sig_out_fast2slow_adj_reg1 <= 0 ;
        end
        else begin
            Sig_out_fast2slow_adj_reg0 <= Sig_out_fast2slow_lvl_reg ;
            Sig_out_fast2slow_adj_reg1 <= Sig_out_fast2slow_adj_reg0;
        end
    end

    always@(posedge Clk_10M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_fast2slow_adj_reg2 <= 0 ;
            Sig_out_fast2slow_adj_reg3 <= 0 ;
        end
        else begin
            Sig_out_fast2slow_adj_reg2 <= Sig_out_fast2slow_adj_reg0 != Sig_out_fast2slow_adj_reg1 ;
            Sig_out_fast2slow_adj_reg3 <= Sig_out_fast2slow_adj_reg2;
        end
    end

    assign   Sig_out_fast2slow_dff2 = Sig_out_fast2slow_adj_reg3;
//-----------------------------------------------------------------------------
    reg   [0:0]   Sig_out_slow2fast_lvl_reg  ;
    reg   [0:0]   Sig_out_slow2fast_adj_reg0 ;
    reg   [0:0]   Sig_out_slow2fast_adj_reg1 ;
    reg   [0:0]   Sig_out_slow2fast_adj_reg2 ;
    reg   [0:0]   Sig_out_slow2fast_adj_reg3 ;

    always@(posedge Clk_10M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_slow2fast_lvl_reg <= 0 ;
        end
        else begin
            if(Sig_50M_in)
                Sig_out_slow2fast_lvl_reg <= ~Sig_out_slow2fast_lvl_reg ;
            else
                Sig_out_slow2fast_lvl_reg <= Sig_out_slow2fast_lvl_reg ;
        end
    end

    always@(posedge Clk_50M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_slow2fast_adj_reg0 <= 0 ;
            Sig_out_slow2fast_adj_reg1 <= 0 ;
           
        end
        else begin
            Sig_out_slow2fast_adj_reg0 <= Sig_out_slow2fast_lvl_reg ;
            Sig_out_slow2fast_adj_reg1 <= Sig_out_slow2fast_adj_reg0;
        end
    end

    always@(posedge Clk_50M_in or negedge Sys_rst_n)begin
        if(~Sys_rst_n)begin
            Sig_out_slow2fast_adj_reg2 <= 0 ;
            Sig_out_slow2fast_adj_reg3 <= 0 ;
        end
        else begin
            Sig_out_slow2fast_adj_reg2 <= Sig_out_slow2fast_adj_reg0 != Sig_out_slow2fast_adj_reg1 ;
            Sig_out_slow2fast_adj_reg3 <= Sig_out_slow2fast_adj_reg2;
        end
    end

    assign   Sig_out_slow2fast_dff2 = Sig_out_slow2fast_adj_reg3 ;

//-----------------------------------------------------------------------------
endmodule

image.png


« 上一篇 下一篇 »

返回顶部
请先 登录 再评论,若不是会员请先 注册