题解 | #使用握手信号实现跨时钟域数据传输#

使用握手信号实现跨时钟域数据传输

https://www.nowcoder.com/practice/2bf1b28a4e634d1ba447d3495134baac

`timescale 1ns/1ns
module data_driver(
	input clk_a,
	input rst_n,
	input data_ack,
	output reg [3:0]data,
	output reg data_req
	);
//=========================================================================\\
//*****************************define sinals*******************************\\
//=========================================================================\\

reg  [2:0]  cnt_wait ;

reg  data_ack_r0  ;
reg  data_ack_r1  ;


//=========================================================================\\
//*****************************main code***********************************\\
//=========================================================================\\

//data_ack  跨时钟域处理
always@(posedge clk_a or negedge rst_n)begin
    if(!rst_n)begin
        data_ack_r0 <= 1'b0    ;
        data_ack_r1 <= 1'b0    ;
    end
    else begin
        data_ack_r0 <= data_ack     ;
        data_ack_r1 <= data_ack_r0  ;
    end

end

//data_req 边沿检测实现 数据请求信号的拉低 然后 通过等待5个时钟周期的cnt实现拉高
always@(posedge clk_a or negedge rst_n)begin
    if(!rst_n)
        data_req <=  1'b0    ;
    else if(data_ack_r0 && !data_ack_r1)
        data_req <=  1'b0    ;
    else if(cnt_wait == 'd4 )
        data_req <=  1'b1    ;
    else
        data_req <= data_req ;    
end

//cnt_wait  只有在数据响应信号为低电平的时候才会进行计数,目的是计算等待的5个时间间隔
always@(posedge clk_a or negedge rst_n)begin
    if(!rst_n)
        cnt_wait <= 'd0             ;
    else if(cnt_wait == 'd4)
        cnt_wait <= 'd0             ;
    else if(data_req == 'd0)
        cnt_wait <= cnt_wait + 1'b1 ;
    else 
        cnt_wait <= cnt_wait        ;
end

//data
always@(posedge clk_a or negedge rst_n)begin
    if(!rst_n)
        data <= 'd0        ;
    else if(data_ack_r0 && !data_ack_r1)
        data <= data + 1'b1 ;
    else
        data <= data        ;
end
endmodule


`timescale 1ns/1ns
module data_receiver(
	input                clk_b        ,
	input                rst_n        , 
	input       [3:0]    data         ,
    input                data_req     ,
	output  reg          data_ack    
	);
    
//=========================================================================\\
//*****************************define sinals*******************************\\
//=========================================================================\\

reg         data_req_r0  ;
reg         data_req_r1  ;

reg  [3:0]  data_reg     ;

//=========================================================================\\
//*****************************main code***********************************\\
//=========================================================================\\

//data_req 输入信号需要打两拍进行跨时钟域处理
always@(posedge clk_b or negedge rst_n)begin
    if(!rst_n)begin
        data_req_r0 <= 1'b0   ;
        data_req_r1 <= 1'b0   ;
    end
     else begin
        data_req_r0 <= data_req     ;
        data_req_r1 <= data_req_r0  ;
    end
end


//data_reg 
always@(posedge clk_b or negedge rst_n)begin
    if(!rst_n)
        data_reg  <= 'd0        ;
    else if(data_req_r0 && !data_req_r1)
        data_reg  <= data       ;
    else
        data_reg  <=  data_reg  ;
end

//data_ack 通过上边沿检测实现响应信号ack的生成
always@(posedge clk_b or negedge rst_n)begin
    if(!rst_n)
        data_ack <= 1'b0  ;
    else if(data_req_r0 && !data_req_r1)
        data_ack <= 1'b1  ;
    else 
        data_ack <= 1'b0  ;
end




endmodule

全部评论

相关推荐

11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
拉丁是我干掉的:把上海理工大学改成北京理工大学。成功率增加200%
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务