当前位置:   article > 正文

使用多路选择器(MUX)完成跨时钟域传输(含代码)_mux多路选择器

mux多路选择器

1. MUX完成多bit信号跨时钟域传输的原理

这里简单的说明一下,因为网上这方面资料比较多。简单来说,对于多bit信号,不能直接使用打两拍的方式来进行跨时钟域传输,因为各个信号的延时可能不同,打两拍可能会因为延时不同造成错误。
在这里插入图片描述
而使用MUX来进行跨时钟域传输,实际是通过一个使能信号去选通数据传输的通路,然后该选通信号是通过跨时钟域单bit信号处理方式进行处理的,首先对使能信号data enable和数据信号data bus在原时钟域打一拍,这是为了保持数据和使能信号的时序尽量一致。再在新时钟域对选通信号打两拍,这一方面是为了完成选通信号的同步,另一方面个人认为是完成使能信号的两拍延迟,从而保证使能信号完成同步后,数据信号已处于稳定,因而能保证数据传输的正确。

个人认为,MUX同步方式更适用于慢时钟域到快时钟域的传输,且数据信号最好持续几个时钟。因为使能信号需在新时钟域打两拍,如果新的时钟域更慢的话,这个两拍的时间对数据的影响可能太大了,甚至使能信号同步完成时数据已经结束了。

2.Verilog实现

时钟:1MHz和10MHz(系统时钟sys_clk为50MHz)。为了更好的仿真,将clk_cnt_1初始值设定为20,来实现时钟相位的不同。

module clk_gen(
    input sys_clk, 
    input sys_rst_n,
    
    output reg clk_1, //1MHz
    output reg clk_2 //10MHz
    );

reg [5:0] clk_cnt_1;
reg [5:0] clk_cnt_2;

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(sys_rst_n==1'b0)begin
        clk_cnt_1<=5'd20;
        clk_cnt_2<=5'd0;
        clk_1<=1'b1;
        clk_2<=1'b0;
    end    
    else begin
        clk_cnt_1<=(clk_cnt_1==6'd50)?6'd0:clk_cnt_1+1'b1;
        clk_cnt_2<=(clk_cnt_2==6'd5)?6'd0:clk_cnt_2+1'b1;
        clk_1<=(clk_cnt_1==6'd50)?~clk_1:clk_1;
        clk_2<=(clk_cnt_2==6'd5)?~clk_2:clk_2;
    end
end
 
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

数据和使能信号的产生,数据每次加111(随便定的数字),使能信号在数据的第一个时钟产生:

module data_gen(
    input clk_1,
    input rst_n,
    output reg [15:0] data,
    output valid
    );
    reg [3:0] cnt;
    assign valid=(cnt==4'd0)?1'b1:1'b0;
    always@(posedge clk_1 or negedge rst_n)begin
        if(!rst_n)begin
            data<=16'd0;
            cnt<=4'd0;
        end
        else begin
            cnt<=(cnt==4'd10)?4'd0:cnt+1'b1;
            data<=(cnt==4'd10)?data+16'd111:data;
        end
    end
    
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

跨时钟域实现代码:

module cdc(
    input clk_2,
    input clk_1,
    input [15:0] data,
    input valid,
    input rst_n,
    output reg [15:0] data_out
    );
    reg valid_reg0,valid_reg1,valid_reg;
    reg [15:0] data_reg;
    always@(posedge clk_1 or negedge rst_n)begin
        if(!rst_n)begin
            data_reg<=16'd0;
            valid_reg<=1'b0;
        end
        else begin
            data_reg<=data;
            valid_reg<=valid;
        end  
    end
    always@(posedge clk_2 or negedge  rst_n)begin
        if(!rst_n)
            {valid_reg1,valid_reg0}<=2'd0;
        else
            {valid_reg1,valid_reg0}<={valid_reg0,valid_reg};
    end
    
    always@(posedge clk_2 or negedge rst_n)begin
        if(!rst_n)
            data_out<=16'd0;
        else
            data_out<=valid_reg1?data_reg:data_out;
    end
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

顶层例化:

module top(
    input sys_clk,
    input rst_n
    );
    wire clk_1,clk_2;
    wire [15:0] data;
    wire valid;
    wire [15:0] cdc_data;
cdc u1(
    .clk_2(clk_2),
    .clk_1(clk_1),
    .data(data),
    .valid(valid),
    .rst_n(rst_n),
    .data_out(cdc_data)
    );
data_gen u2(
    .clk_1(clk_1),
    .rst_n(rst_n),
    .data(data),
    .valid(valid)
    );
clk_gen u3(
    .sys_clk(sys_clk),
    .sys_rst_n(rst_n),
    
    .clk_1(clk_1),
    .clk_2(clk_2)
    );
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

3.仿真

testbench:
module tb(

    );
    reg rst_n;
    reg sys_clk;
    initial begin
        rst_n=1'b0;
        sys_clk=1'b0;
        #100
        rst_n=1'b1;
    end
    always #10 sys_clk=~sys_clk;
top u(
    .sys_clk(sys_clk),
    .rst_n(rst_n)
    );
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

仿真结果,数据被同步到clk_2时钟域:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/263461
推荐阅读
相关标签
  

闽ICP备14008679号