【Verilog-CBB】开发与验证(2)——单比特信号CDC同步器



引言

多时钟域的设计中,CDC处理的场景还是蛮多的。单比特信号在CDC时,为保证信号采样的安全性,降低亚稳态,必须要对信号做同步处理。CDC从时钟的快慢关系来说分为两种case:快到慢、慢到快。对于脉冲型的控制信号,在以上两种case中都需要满足如下条件才能保证控制信号CDC的安全性:

源端控制信号的脉冲宽度>1.5倍目的端时钟周期 (即 "三时钟沿" 要求)。

一般建议以上条件中1.5增大为2。

在设计同步器时需要注意,源端控制信号必须为寄存器输出。否则组合逻辑的毛刺可能会影响目的端的采样。

CBB设计源码

这个功能相对来说比较简单,就不扯框图和原理了,直接上代码。

cpp 复制代码
// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================

//                 ________          ________          ________                                                               
//                |\   ____\        |\   __  \        |\   __  \                                                              
//                \ \  \___|        \ \  \|\ /_       \ \  \|\ /_                                                             
//                 \ \  \            \ \   __  \       \ \   __  \                                                            
//                  \ \  \____        \ \  \|\  \       \ \  \|\  \                                                           
//                   \ \_______\       \ \_______\       \ \_______\                                                          
//                    \|_______|        \|_______|        \|_______|  

// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================                                                                                                              
                                                                                                                                                                                                                                                                                                         
// CBB Module Name    :CBB_PULSE_SYNCHRONIZER
// CBB Created Date   :2024-08-02
// CBB Module Function:单比特脉冲信号跨时钟域处理
// Usage Limitation   :
// Author             :在路上-正出发
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------

`timescale 1ns/1ps


module  CBB_PULSE_SYNCHRONIZER #(
// ---- parameter define
parameter P_EXTEN_EN		= "ENABLE",  //"ENABLE" or "DISABLE"
parameter P_EXTEN_MULT 		= 3,	     //2 or larger
parameter P_SYNC_STAGE 		= 2,	     //2 or larger
parameter P_PULSE_WIDTH     = "CARE-1"   //"CARE-1" or "NOTCARE"
)(
// ---- port define 
input 							i_clk_src,
input 							i_rstn_src,
input 							i_pulse_src,//must be register output(source clk)

input 							i_clk_dst,
input 							i_rstn_dst,
output 							o_pulse_dst

);

reg [P_EXTEN_MULT-2:0] 			r_pluse_src_dly;
reg 				   			r_pulse_exten;
reg [P_SYNC_STAGE-1:0]			r_pulse_sync;

generate
	if(P_EXTEN_EN == "ENABLE")
	begin
		if(P_EXTEN_MULT <= 2)
		begin
			always @(posedge i_clk_src or negedge i_rstn_src) begin : proc_pulse_exten1
				if(~i_rstn_src) begin
					 r_pluse_src_dly <= {(P_EXTEN_MULT-1){1'b0}};
				end else begin
					 r_pluse_src_dly <= {i_pulse_src};
				end
			end
			always @(posedge i_clk_src or negedge i_rstn_src) begin : proc_pulse_exten2
				if(~i_rstn_src) begin
					 r_pulse_exten <= 1'b0;
				end else begin
					 r_pulse_exten <= |{r_pluse_src_dly,i_pulse_src};
				end
			end
			always @(posedge i_clk_dst or negedge i_rstn_dst) begin : proc_pulse_sync
				if(~i_rstn_dst) begin
					 r_pulse_sync <= {(P_SYNC_STAGE){1'b0}};
				end else begin
					 r_pulse_sync <= {r_pulse_sync[P_SYNC_STAGE-2:0],r_pulse_exten};
				end
			end			
	    end
	    else
	    begin
			always @(posedge i_clk_src or negedge i_rstn_src) begin : proc_pulse_exten
				if(~i_rstn_src) begin
					 r_pluse_src_dly <= {(P_EXTEN_MULT-1){1'b0}};
				end else begin
					 r_pluse_src_dly <= {r_pluse_src_dly[P_EXTEN_MULT-3:0],i_pulse_src};
				end
			end
			always @(posedge i_clk_src or negedge i_rstn_src) begin : proc_pulse_exten2
				if(~i_rstn_src) begin
					 r_pulse_exten <= 1'b0;
				end else begin
					 r_pulse_exten <= |{r_pluse_src_dly,i_pulse_src};
				end
			end
			always @(posedge i_clk_dst or negedge i_rstn_dst) begin : proc_pulse_sync
				if(~i_rstn_dst) begin
					 r_pulse_sync <= {(P_SYNC_STAGE){1'b0}};
				end else begin
					 r_pulse_sync <= {r_pulse_sync[P_SYNC_STAGE-2:0],r_pulse_exten};
				end
			end
	    end
	end
	else
	begin
		always @(posedge i_clk_dst or negedge i_rstn_dst) begin : proc_pulse_sync
			if(~i_rstn_dst) begin
				 r_pulse_sync <= {(P_SYNC_STAGE){1'b0}};
			end else begin
				 r_pulse_sync <= {r_pulse_sync[P_SYNC_STAGE-2:0],i_pulse_src};
			end
		end		
	end
endgenerate

generate
	if(P_PULSE_WIDTH == "CARE-1")
	begin
		assign o_pulse_dst = r_pulse_sync[P_SYNC_STAGE-2] & (~r_pulse_sync[P_SYNC_STAGE-1]); 
	end
	else
	begin
		assign o_pulse_dst = r_pulse_sync[P_SYNC_STAGE-1];
	end
endgenerate

endmodule

CBB使用说明

P_EXTEN_EN:需要进行脉冲展宽时,将使能开关打开;

P_EXTEN_MULT:表示脉冲在源时钟域被展宽的倍数,这个倍数需要使用者根据上述1.5或2倍关系折算。

P_SYNC_STAGE:表示目的时钟域打拍的级数。

P_PULSE_WIDTH:"CARE-1"表示,目的侧时钟域输出的脉冲宽度为1个时钟周期;"NOTCARE"则表示目的侧打拍直接输出,不取边沿。

【注意】输入信号i_pulse_src必须为寄存器输出。

CBB验证

CASE1:快--->慢(使能脉冲展宽,3倍)

CASE2:慢--->快(不使能脉冲展宽)

验证代码

cpp 复制代码
// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================

//                 ________          ________          ________                                                               
//                |\   ____\        |\   __  \        |\   __  \                                                              
//                \ \  \___|        \ \  \|\ /_       \ \  \|\ /_                                                             
//                 \ \  \            \ \   __  \       \ \   __  \                                                            
//                  \ \  \____        \ \  \|\  \       \ \  \|\  \                                                           
//                   \ \_______\       \ \_______\       \ \_______\                                                          
//                    \|_______|        \|_______|        \|_______|  

// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================                                                                                                              
                                                                                                                                                                                                                                                                                                         
// CBB Module Name    :TB_PULSE_SYNCHRONIZER
// CBB Created Date   :2024-08-03
// CBB Module Function:
// Usage Limitation   :
// Author             :在路上-正出发
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------

`timescale 1ns/1ps

// `define TC_FAST_2_LOW
`define TC_LOW_2_FAST

module TB_PULSE_SYNCHRONIZER ();
// ---- parameter define
parameter P_EXTEN_EN		= "DISABLE"; //"ENABLE" or "DISABLE"
parameter P_EXTEN_MULT 		= 3;	    //2 or larger
parameter P_SYNC_STAGE 		= 2;	    //2 or larger
parameter P_PULSE_WIDTH     = "CARE-1"; //"CARE-1" or "NOTCARE"

// ---- port define 
reg 							i_clk_src;
reg 							i_rstn_src;
reg 							i_pulse_src;//must be register output(source clk)

reg  							i_clk_dst;
reg  							i_rstn_dst;
wire 							o_pulse_dst;

// 产生时钟
`ifdef TC_FAST_2_LOW
initial i_clk_src = 1'b0;
always #5 i_clk_src = ~i_clk_src;
initial i_clk_dst = 1'b0;
always #10 i_clk_dst = ~i_clk_dst;
`endif

`ifdef TC_LOW_2_FAST
initial i_clk_src = 1'b0;
always #10 i_clk_src = ~i_clk_src;
initial i_clk_dst = 1'b0;
always #5 i_clk_dst = ~i_clk_dst;
`endif

// 
initial
begin
	i_rstn_src = 1'b0;
	i_rstn_dst = 1'b0;
	i_pulse_src = 1'b0;
	#100;
	i_rstn_dst = 1'b1;
	i_rstn_src = 1'b1;
	#50;
	@(posedge i_clk_src)
	i_pulse_src <= 1'b1;
	@(posedge i_clk_src)
	i_pulse_src <= 1'b0;

	@(negedge o_pulse_dst);
	#200;
	$finish;
end

CBB_PULSE_SYNCHRONIZER #(
		.P_EXTEN_EN(P_EXTEN_EN),
		.P_EXTEN_MULT(P_EXTEN_MULT),
		.P_SYNC_STAGE(P_SYNC_STAGE),
		.P_PULSE_WIDTH(P_PULSE_WIDTH)
	) U_CBB_PULSE_SYNCHRONIZER (
		.i_clk_src   (i_clk_src),
		.i_rstn_src  (i_rstn_src),
		.i_pulse_src (i_pulse_src),
		.i_clk_dst   (i_clk_dst),
		.i_rstn_dst  (i_rstn_dst),
		.o_pulse_dst (o_pulse_dst)
	);



endmodule

CBB电路综合

使能脉冲展宽

源时钟域下,控制信号经多拍延迟,源信号与延迟信号经过或门输出,输出的信号在源时钟域寄存输出,目的测时钟域对展宽的信号做打拍处理,取上升沿输出。

不使能脉冲展宽

相关推荐
超级大咸鱼1 天前
CW信号的正交解调
matlab·verilog·fpga·数字信号·解调·正交解调·cw
core5122 天前
flink SQL实现mysql source sink
mysql·flink·jdbc·source·cdc·sink·mysql-cdc
core5125 天前
flink实现复杂kafka数据读取
大数据·flink·kafka·cdc
fei_sun6 天前
【计组】实验三 ORI指令设计实验
fpga开发·verilog·计组
热爱学习地派大星9 天前
FPGA在线升级 -- Multiboot
fpga开发·verilog·fpga·远程升级·升级程序
杨德杰10 天前
Verilog实现图像处理的行缓存Line Buffer
图像处理·verilog·fpga·isp·行缓存linebuffer
core51215 天前
一文说清flink从编码到部署上线
flink·部署·yarn·编码·cdc·guava30·guava18
杨德杰17 天前
异步FIFO的实现
fpga开发·verilog
fei_sun20 天前
【Verilog】实验六 移位寄存器的设计
fpga开发·verilog
鸿乃江边鸟1 个月前
Flink CDC 使用实践以及遇到的问题
flink·cdc