CDC 单脉冲信号处理
代码中的Sys_clk其实是没有用到的,项目文件:
//------------------------------------------------------
// 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
当然,光是对高速信号展宽还是不够,我们依旧没有消除亚稳态,所以这里需要再进行打两拍。也就是这样:
//------------------------------------------------------
// 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