• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

多比特跨时钟域:握手和DMUX

武飞扬头像
没有出路的年轻人
帮助1

一、握手toggle

握手又称结绳法,适用场景为数据有效信号在数据信号前一个周期或数据有效信号在数据的第一个周期,且在握手期间,数据需要保持不变,直到源时钟域收到了解绳的有效信号。

源码如下:

  1.  
    module toggle(
  2.  
    input wire clka,
  3.  
    input wire clkb,
  4.  
    input wire rst_n,
  5.  
    input wire a_en,
  6.  
    input wire [7:0] data_a_in,
  7.  
     
  8.  
    output reg [7:0] data_b_out,
  9.  
    output wire b_en,
  10.  
    output wire ack_a
  11.  
    );
  12.  
     
  13.  
    reg a_en_d1;
  14.  
    reg a_en_d2;
  15.  
    wire a_en_neg;
  16.  
     
  17.  
    reg a_req;
  18.  
     
  19.  
    reg req_d1;
  20.  
    reg req_d2;
  21.  
     
  22.  
    reg ack_d1;
  23.  
    reg ack_d2;
  24.  
     
  25.  
    wire ack_pos;
  26.  
     
  27.  
    always@(posedge clka or negedge rst_n)begin
  28.  
    if(!rst_n)begin
  29.  
    a_en_d1 <= 1'b0;
  30.  
    a_en_d2 <= 1'b0;
  31.  
    end
  32.  
    else begin
  33.  
    a_en_d1 <= a_en;
  34.  
    a_en_d2 <= a_en_d1;
  35.  
    end
  36.  
    end
  37.  
     
  38.  
    assign a_en_neg = a_en_d2 && (~a_en_d1);
  39.  
     
  40.  
    always@(posedge clka or negedge rst_n)begin
  41.  
    if(!rst_n)
  42.  
    a_req <= 1'b0;
  43.  
    else if(a_en_neg)
  44.  
    a_req <= 1'b1;
  45.  
    else if(ack_pos)
  46.  
    a_req <= 1'b0;
  47.  
    end
  48.  
     
  49.  
    always@(posedge clkb or negedge rst_n)begin
  50.  
    if(!rst_n)begin
  51.  
    req_d1 <= 1'b0;
  52.  
    req_d2 <= 1'b0;
  53.  
    end
  54.  
    else begin
  55.  
    req_d1 <= a_req;
  56.  
    req_d2 <= req_d1;
  57.  
    end
  58.  
    end
  59.  
     
  60.  
    always@(posedge clka or negedge rst_n)begin
  61.  
    if(!rst_n)begin
  62.  
    ack_d1 <= 1'b0;
  63.  
    ack_d2 <= 1'b0;
  64.  
    end
  65.  
    else begin
  66.  
    ack_d1 <= req_d2;
  67.  
    ack_d2 <= ack_d1;
  68.  
    end
  69.  
    end
  70.  
     
  71.  
    assign b_en = (~req_d2) && (req_d1);
  72.  
     
  73.  
    assign ack_pos = (~ack_d2) && ack_d1;
  74.  
     
  75.  
    assign ack_a = ack_d2;
  76.  
     
  77.  
    always@(posedge clkb or negedge rst_n)begin
  78.  
    if(!rst_n)
  79.  
    data_b_out <= 8'd0;
  80.  
    else if(b_en)
  81.  
    data_b_out <= data_a_in;
  82.  
    end
  83.  
     
  84.  
     
  85.  
    endmodule
学新通

testbench如下:

  1.  
    `timescale 1ns/1ns
  2.  
    module toggle_tb();
  3.  
    reg clka;
  4.  
    reg clkb;
  5.  
    reg rst_n;
  6.  
    reg a_en;
  7.  
    reg [7:0] data_a_in;
  8.  
     
  9.  
    wire [7:0] data_b_out;
  10.  
    wire b_en;
  11.  
    wire ack_a;
  12.  
     
  13.  
    always #5 clka = ~clka;
  14.  
    always #10 clkb = ~clkb;
  15.  
     
  16.  
    initial begin
  17.  
    rst_n = 1'b0;
  18.  
    clka = 1'b0;
  19.  
    clkb = 1'b0;
  20.  
    #11;
  21.  
    rst_n = 1'b1;
  22.  
    #10000;
  23.  
    $finish;
  24.  
    end
  25.  
     
  26.  
    reg ack_a_d1;
  27.  
     
  28.  
    always@(posedge clka or negedge rst_n)begin
  29.  
    if(!rst_n)begin
  30.  
    a_en <= 1'b1;
  31.  
    ack_a_d1 <= 1'b0;
  32.  
    end
  33.  
    else begin
  34.  
    ack_a_d1 <= ack_a;
  35.  
    a_en <= (~ack_a_d1) && ack_a;
  36.  
    end
  37.  
    end
  38.  
     
  39.  
    always@(posedge clka or negedge rst_n)begin
  40.  
    if(!rst_n)
  41.  
    data_a_in <= 8'd0;
  42.  
    else if(a_en)
  43.  
    data_a_in <= {$random}%6;
  44.  
    end
  45.  
     
  46.  
    toggle toggle_inst(
  47.  
    .clka (clka),
  48.  
    .clkb (clkb),
  49.  
    .rst_n (rst_n),
  50.  
    .a_en (a_en),
  51.  
    .data_a_in (data_a_in),
  52.  
    .data_b_out (data_b_out),
  53.  
    .b_en (b_en),
  54.  
    .ack_a (ack_a)
  55.  
    );
  56.  
     
  57.  
    initial begin
  58.  
    $fsdbDumpfile("tb.fsdb");
  59.  
    $fsdbDumpvars;
  60.  
    end
  61.  
     
  62.  
     
  63.  
    endmodule
学新通

仿真结果如下:

其中G1中为源时钟域信号,G2为目的时钟域信号

学新通二,DMUX

 原理图如下:

学新通

DMUX适用于慢时钟域向快时钟域传递(因为两级同步器),且数据有效信号在数据信号的前一个周期或者数据有效信号在数据信号的第一个周期。数据信号要保证在有效信号同步期间保持不变。

源代码如下:

  1.  
    module dmux(
  2.  
    input wire clka,
  3.  
    input wire clkb,
  4.  
    input wire a_en,
  5.  
    input wire rst_n,
  6.  
    input wire [7:0] data_in,
  7.  
     
  8.  
    output reg [7:0] data_out
  9.  
    );
  10.  
     
  11.  
    reg a_en_d1;
  12.  
    reg a_en_d2;
  13.  
     
  14.  
    always@(posedge clkb or negedge rst_n)begin
  15.  
    if(!rst_n)begin
  16.  
    a_en_d1 <= 1'b0;
  17.  
    a_en_d2 <= 1'b0;
  18.  
    end
  19.  
    else begin
  20.  
    a_en_d1 <= a_en;
  21.  
    a_en_d2 <= a_en_d1;
  22.  
    end
  23.  
    end
  24.  
     
  25.  
    always@(posedge clkb or negedge rst_n)begin
  26.  
    if(!rst_n)
  27.  
    data_out <= 8'd0;
  28.  
    else if(a_en_d2)
  29.  
    data_out <= data_in;
  30.  
    end
  31.  
     
  32.  
    endmodule
学新通

testbench如下:

  1.  
    `timescale 1ns/1ns;
  2.  
    module dmux_tb();
  3.  
    reg clka;
  4.  
    reg clkb;
  5.  
    reg rst_n;
  6.  
    reg a_en;
  7.  
    reg [7:0] data_in;
  8.  
     
  9.  
    wire [7:0] data_out;
  10.  
     
  11.  
    always #10 clka = ~clka;
  12.  
    always #5 clkb = ~clkb;
  13.  
     
  14.  
    initial begin
  15.  
    clka = 1'b0;
  16.  
    clkb = 1'b0;
  17.  
    rst_n = 1'b0;
  18.  
    a_en = 1'b0;
  19.  
    data_in = 8'd0;
  20.  
    #11;
  21.  
    rst_n = 1'b1;
  22.  
    @(posedge clka)
  23.  
    a_en = 1'b1;
  24.  
    data_in = {$random} %6;
  25.  
    @(posedge clka)
  26.  
    a_en = 1'b0;
  27.  
    #33;
  28.  
    @(posedge clka)
  29.  
    a_en = 1'b1;
  30.  
    @(posedge clka)
  31.  
    a_en = 1'b0;
  32.  
    data_in = ($random)%256;
  33.  
    #100;
  34.  
    $finish;
  35.  
    end
  36.  
     
  37.  
    dmux dmux_inst(
  38.  
    .clka (clka),
  39.  
    .clkb (clkb),
  40.  
    .rst_n (rst_n),
  41.  
    .a_en (a_en),
  42.  
    .data_in (data_in),
  43.  
    .data_out (data_out)
  44.  
    );
  45.  
     
  46.  
    initial begin
  47.  
    $fsdbDumpfile("tb.fsdb");
  48.  
    $fsdbDumpvars;
  49.  
    end
  50.  
     
  51.  
    endmodule
学新通

仿真结果如下:

可以清晰看到两种情况。

学新通 

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfagig
系列文章
更多 icon
同类精品
更多 icon
继续加载