• 跨时钟域握手信号的实现(Verilog)


    方法

    使用握手信号是在两个不同域之间传输数据的有效方式,如下图所示:
    在这里插入图片描述
    使用握手信号xack和yreq,系统X发给系统Y,下面是使用握手信号传输数据的例子:
    1)发送器系统X将数据放到数据总线上并发出xreq请求信号,表示有效数据已经发送到接收器系统Y的数据总线上
    2)把xreq信号同步到接收器的时钟域yclk上。
    3)接收器在识别xreq同步信号yreq2后,锁存数据总线上的信号
    4)接收器发出确认信号yack,表示其已经接受了数据
    5)接收器发出的yack信号同步到发送时钟xclk上
    6)发送器在识别同步的ack信号后,将下一个数据放到数据总线上
    握手信号的时序图如下所示:
    在这里插入图片描述

    握手信号的要求

    数据应该在发送时钟域内稳定至少两个时钟上升沿,请求信号xreq的宽度应该超过两个上升沿时钟,否则从高速时钟的低速时钟域传递可能无法捕捉到该信号。缺点是是延迟太大(相比于FIFO)。

    硬件实现

    数据发送系统

    模块框图如下
    在这里插入图片描述

    module tx_data(
        input   wire            tx_clk      ,
        input   wire            xack2       ,
        input   wire            rst_n       ,
        input   wire            en          ,
    
        output  reg             xreq        ,
        output  wire    [7:0]   t_data  
    );
    
        reg     [3:0]       data1   ;
        reg     [3:0]       data2   ;
    
        //在yack2有效时data1和data2更新
        always @(posedge tx_clk or negedge rst_n) begin
            if(!rst_n) begin
                data1 <= 4'd1;
                data2 <= 4'd1;
            end
            else if(xack2) begin
                data1 <= data1 + 4'd1;
                data2 <= data2 + 4'd2;
            end
            else begin
                data1 <= data1;
                data2 <= data2;
            end
        end       
    
        //xreq信号
        always @(posedge tx_clk or negedge rst_n) begin
            if(!rst_n) begin
                xreq <= 1'b0;
            end
            else if(en) begin
                xreq <= 1'b1;
            end
            else if(xack2) begin
                xreq <= 1'b1;
            end
            else begin
                xreq <= 1'b0;
            end
        end
    
        assign t_data = {data1, data2};
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    数据接收系统

    模块框图如下:
    在这里插入图片描述

    module rv_data(
        input   wire        rv_clk      ,
        input   wire        rst_n       ,
        input   wire        yreq2       ,
        input   wire [7:0]  r_data      ,
    
        output  reg         yack        ,
        output  wire [5:0]  result           
    );
        /*
            接收到数据的第一周期进行数据计算
            第二周期返回ack信号
        */
        reg             dly1        ;
        reg     [5:0]   result_reg  ;
    
        always @(posedge rv_clk or negedge rst_n) begin
            if(!rst_n) begin
                yack <= 1'b0;
            end
            else if(dly1) begin
                yack <= 1'b1;
            end
            else begin
                yack <= 1'b0;
            end
        end
    
        always @(posedge rv_clk or negedge rst_n) begin
            if(!rst_n) begin
                dly1 <= 1'b0;
            end
            else if(yreq2) begin
                dly1 <= 1'b1;
            end
            else begin
                dly1 <= 1'b0;
            end
        end
    
        always @(posedge rv_clk or negedge rst_n) begin
            if(!rst_n) begin
                result_reg <= 'd0;
            end
            else if(yreq2) begin
                result_reg <= r_data[3:0] + r_data[7:4];
            end
            else begin
                result_reg <= result_reg;
            end
        end
    
        assign result = dly1 ? result_reg : 6'd0;
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    异步握手实现

    模块框图如下:
    在这里插入图片描述

    module shake_hand_asy(
        input   wire            tx_clk      ,
        input   wire            rv_clk      ,
        input   wire            rst_n       ,
        input   wire            en          ,
    
        output  wire    [5:0]   result 
    );
    
        wire                xreq    ;
        wire                yack    ;
        wire    [7:0]       data    ;
    
        reg                 yreq1   ;
        reg                 yreq2   ;
        reg                 xack1   ;
        reg                 xack2   ;
    
        //xreg的两级同步
        always @(posedge rv_clk or negedge rst_n) begin
            if(!rst_n) begin
                yreq1 <= 1'b0;
                yreq2 <= 1'b0;
            end
            else begin
                yreq1 <= xreq;
                yreq2 <= yreq1;
            end
        end
    
        //yack的两级同步
        always @(posedge tx_clk or rst_n) begin
            if(!rst_n) begin
                xack1 <= 1'b0;
                xack2 <= 1'b0;
            end
            else begin
                xack1 <= yack;
                xack2 <= xack1;
            end
        end
    
        tx_data u_tx_data(
        . tx_clk    (tx_clk)    ,
        . xack2     (xack2)     ,
        . rst_n     (rst_n)     ,
        . en        (en)        ,
    
        . xreq      (xreq)      ,
        . t_data    (data)
    );
    
        rv_data u_rv_data(
         .rv_clk     (rv_clk)    ,
         .rst_n      (rst_n)     ,
         .yreq2      (yreq2)     ,
         .r_data     (data)      ,
    
         .yack       (yack)      ,
         .result     (result)      
    );
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    波形仿真

    testbench代码如下:

    
    `timescale  1ns/1ns
    
    module tb_shake_hand_asy();
    
        reg         tx_clk      ;
        reg         rv_clk      ;
        reg         rst_n       ;
        reg         en          ;
    
        wire [5:0]  result      ;
    
        initial begin
            tx_clk = 1'b0;
            rv_clk = 1'b0;
            rst_n = 1'b0;
            en = 1'b0;
            #30
            rst_n = 1'b1;
            @(posedge tx_clk);
            en = 1'b1;          //启动
            @(posedge tx_clk);
            en = 1'b0;
        end
    
        always #15 tx_clk = ~tx_clk;
        always #10 rv_clk = ~rv_clk;
    
        shake_hand_asy u_shake_hand_asy(
        . tx_clk    (tx_clk)  ,
        . rv_clk    (rv_clk)  ,
        . rst_n     (rst_n)  ,
        . en        (en)  ,
    
        . result    (result)
    );
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    波形如下所示:
    在这里插入图片描述
    可知仿真正确。

    总结

    自己基础还很薄弱,继续加油!!!!

  • 相关阅读:
    获得京东商品详情 API
    Spring测试数据准备_java培训
    3分钟学会ubuntu中安装docker
    AppWeb 身份验证绕过漏洞 (CVE-2018-8715)漏洞复现
    a标签设置下划线动画
    flask中上传用户头像实现代码
    什么是人力资源管理系统?hr系统功能介绍
    NLP实战9:Transformer实战-单词预测
    kafka 通过 jdbc 从oracle抓取数据
    管理上游数据源配置
  • 原文地址:https://blog.csdn.net/weixin_45614076/article/details/127673883