`timescale 1ns/1ns

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
);
//MUX同步器 用于 多bit跨时钟域的处理  
//关键在于当使能信号稳定的时候进行数据的传输
//步骤:将使能信号在本域打一拍 稳定信号
//然后在异域打两拍 减少亚稳态。 
//然后再用一个二选一数据选择器 进行信号的选通。
reg data_en_a ;
always@(posedge clk_a or negedge arstn)begin
    if(!arstn)
	    data_en_a <= 1'b0   ;
	else 
	    data_en_a <= data_en ;   
	    
end

reg data_en_b   ;
reg data_en_b_r ;
always@(posedge clk_b or negedge brstn)begin
	if(!brstn)begin
	    data_en_b   <= 1'b0 ;
		data_en_b_r <= 1'b0 ;
	end
	else begin
		data_en_b   <= data_en_a ;
		data_en_b_r <= data_en_b ;
	end
end

always@(posedge clk_b or negedge brstn)begin
	if(!brstn)
	     dataout <= 'd0       ;
	else if(data_en_b_r == 1'b1)
	     dataout <=  data_in  ; 
    else 
	     dataout <= dataout   ;

end
endmodule

跨时钟域处理有多重处理方式:

1.单bit跨时钟域处理:

(1)慢时钟域转快时钟域 : 直接两级DFF打拍即可

(2)快时钟域转慢时钟域: 可能出现漏采 所以需要对快时钟域的脉冲进行拓宽。(握手机制)

处理流程: 将clk_fast 下的脉冲 在本域下进行拉高,生成data_a信号 将data_a信号进行跨时钟域处理(在clk_slow时钟域下打两拍) ,生成 data_b ,data_b_r信号 。data_b_r 信号为高代表慢时钟域已经接受到了这个脉冲。所以将data_b_r信号再跨时钟域处理(在clk_fast时钟域下再打两拍),生成data_a_r ,data_a_rr信号。使用data_a_rr ==1'b1 作为拓宽脉冲的拉低使能信号。

慢时钟域这边对data_b_r 打一拍 生成data_b_rr 信号 做上边沿检测 生成脉冲信号。

2.多bit跨时钟域处理:

(1)异步FIFO+格雷码

(2)握手协议

(3)DMUX选择器:在快时钟域转慢时钟域时 仍然需要对使能信号进行脉冲扩宽。