【Verilog】跨时钟域处理(一)——多bit MUX同步

跨时钟域处理的概念

简单来讲,“跨时钟域处理”即:

①输入和输出的参照时钟不同。
②中间过程的多个步骤会由不同的时钟控制。

跨时钟域处理一般涉及“打拍”,即输入和输出中间空几个时钟周期作为缓冲,其目的在于:

打拍(缓冲)可以减小亚稳态概率。

打拍的经验原则

一般的,在时钟切换的时候,依照后来的时钟打两拍
(如由clk_a切换到clk_b,那么需要clk_b先空打两拍,再进行别的操作。)

【详细了解:CDC:跨时钟域处理】


多bit MUX同步的概念和框架

【Verilog】跨时钟域处理(一)——多bit MUX同步_第1张图片

在data_en为高期间,data_in将保持不变,data_en为高至少保持3个B时钟周期。表明,当data_en为高时,可将数据进行同步。data_in端数据变化频率很低,相邻两个数据间的变化,至少间隔10个B时钟周期。

【Verilog】跨时钟域处理(一)——多bit MUX同步_第2张图片


多bit MUX同步 解析

【Verilog】跨时钟域处理(一)——多bit MUX同步_第3张图片
时钟clk_a负责:
① 数据data_in输入时,参照时钟a。(打一拍)
② 使能信号data_en输入时,参照时钟a。(打一拍)

时钟clk_b负责:
① 使能信号data_en延时打两拍,即过两个D触发器。这个过程参照时钟b。
② 数据最终输出dataout,输出时参照时钟b。


多bit MUX同步 代码实现

1. 时钟域clk_a: data_in和data_en寄存。(打一拍)

//clk_a打一拍接受数据和接受使能信号en
reg	[3:0]	data_reg;
always@(posedge clk_a or negedge arstn)
begin
	if(!arstn)	data_reg <= 0;
		else	data_reg <= data_in;
end
reg en_data_reg;	
always@(posedge clk_a or negedge arstn)
begin
	if(!brstn)	en_data_reg <= 0;
		else	en_data_reg <= data_en;   	//存入
end

2. 时钟域clk_b: en信号打两拍 + dataout输出

//clk_b负责使能信号en的打拍
reg	en_clap_one;	//1
reg en_clap_two;	//2
always@(posedge clk_b or negedge brstn)
begin
	if(!brstn)	en_clap_one <= 0;
		else	en_clap_one <= en_data_reg;	//第一拍
end
always@(posedge clk_b or negedge brstn)
begin
	if(!brstn)	en_clap_two <= 0;
		else	en_clap_two <= en_clap_one;	//第二拍
end

//clk_b负责输出
always@(posedge clk_b or negedge brstn)
begin
	if(!brstn)	dataout <= 0;
		else	dataout <= (en_clap_two) ? data_reg : dataout;
end

完整代码:

module mux(
	input 				clk_a	, 
	input 				clk_b	,   
	input 				arstn	,
	input				brstn   ,
	input		[3:0]	data_in	,
	input               data_en ,

	output reg  [3:0] 	dataout
);

/*
	跨时钟域传输:输入和输出的参照时钟不同。中间过程的多个步骤会由不同的时钟控制。
	本题:clk_a接受数据--->clk_b延时两拍,然后数据才输出。
*/

//clk_a打一拍接受数据和接受使能信号en
reg	[3:0]	data_reg;
always@(posedge clk_a or negedge arstn)
begin
	if(!arstn)	data_reg <= 0;
		else	data_reg <= data_in;
end
reg en_data_reg;	
always@(posedge clk_a or negedge arstn)
begin
	if(!brstn)	en_data_reg <= 0;
		else	en_data_reg <= data_en;   	//存入
end

//clk_b负责使能信号en的打拍
reg	en_clap_one;	//1
reg en_clap_two;	//2
always@(posedge clk_b or negedge brstn)
begin
	if(!brstn)	en_clap_one <= 0;
		else	en_clap_one <= en_data_reg;	//第一拍
end
always@(posedge clk_b or negedge brstn)
begin
	if(!brstn)	en_clap_two <= 0;
		else	en_clap_two <= en_clap_one;	//第二拍
end

//clk_b负责输出
always@(posedge clk_b or negedge brstn)
begin
	if(!brstn)	dataout <= 0;
		else	dataout <= (en_clap_two) ? data_reg : dataout;
end

endmodule

你可能感兴趣的:(Verilog杂记,fpga开发,verilog)