verilog设计-cdc:多比特信号跨时钟域(DMUX)

一、前言

多比特一般为数据,其在跨时钟域传输的过程中有多种处理方式,比如DMUX,异步FIFO,双口RAM,握手处理。本文介绍通过DMUX的方式传输多比特信号。

二、DMUX同步跨时钟域数据

dmux表示数据分配器,该方法适合带数据有效标志信号的多bit数据做跨时钟域传输。其典型结构如下:

慢时钟域到快时钟域

快时钟域到慢时钟域只要将红框中换成单bit快时钟域到慢时钟域处理单元即可。

DMUX遵循的原则就是,数据不同步只对控制信号同步,这点其实和异步fifo里的思路一样,只不多异步fifo中的控制信号是多比特的格雷码,而这个场景下的控制信号是data_valid。继续观察结构可以发现,DMUX是将单bit控制信号同步之后将其最为mux的选择信号。因此使用这个结构需要满足一些要求:

1.数据和使能信号在源时钟域为同步到来的信号;

2.在目的时钟域对数据完成采样前,数据信号不能跳变;

如果不满足以上的要求,那么就可能造成数据漏同步、错同步等问题。

三、DMUX Verilog代码

3.1 慢时钟域数据到快时钟域

复制代码
module mult_bit_slow_to_fast_dmux 
    #(parameter DATAWIDTH = 8)
    (
        input                       rst_n,        

        input                       clk_slow,
        input  [DATAWIDTH-1:0]      data_slow,
        input                       data_valid_slow,

        input                       clk_fast,
        output reg [DATAWIDTH-1:0]  data_fast,
        output reg                  data_valid_fast
     );


        //signal valid slow to fast cdc
        reg data_valid_slow_reg;
        always@(posedge clk_slow or negedge rst_n)begin
            if(!rst_n)
               data_valid_slow_reg <= 1'b0;
            else
               data_valid_slow_reg <= data_valid_slow;  
        end
 
        reg data_valid_slow2fast_reg0,data_valid_slow2fast_reg1;
        always@(posedge clk_fast or negedge rst_n)begin
            if(!rst_n)
               begin
                  data_valid_slow2fast_reg0 <= 1'b0;
                  data_valid_slow2fast_reg0 <= 1'b0;
               end
            else
               begin
                  data_valid_slow2fast_reg0 <= data_valid_slow_reg ;  
                  data_valid_slow2fast_reg1 <= data_valid_slow2fast_reg0 ;
               end
        end

        always@(posedge clk_fast or negedge rst_n)begin
            if(!rst_n)
                  data_valid_fast <= 1'b0;
            else
                  data_valid_fast <= data_valid_slow2fast_reg1 ;
        end

        //data slow to fast cdc
        reg  [DATAWIDTH-1:0]      data_slow_reg,
        always@(posedge clk_slow or negedge rst_n)begin
            if(!rst_n)
                  data_slow_reg <=  0;
            else
                  data_slow_reg <= data_slow ;
        end

        always@(posedge clk_fast or negedge rst_n)begin
            if(!rst_n)
                  data_fast<=  0;
            else if(data_valid_slow2fast_reg1 == 1'b1)
                  data_fast <= data_slow_reg ;
        end




endmodule

3.2 快时钟域数据到慢时钟域

复制代码
module mult_bit_fast_to_slow_dmux 
    #(parameter DATAWIDTH = 8)
    (
        input                       rst_n,        
        
        input                       clk_fast,
        input  [DATAWIDTH-1:0]      data_fast,
        input                       data_valid_fast,

        input                        clk_slow,
        output  reg [DATAWIDTH-1:0]  data_slow,
        output  reg                  data_valid_slow


     );


        //signal valid fast to slow cdc
        reg data_valid_fast_reg;
        always@(posedge clk_fast or negedge rst_n)begin
            if(!rst_n)
               data_valid_fast_reg <= 1'b0;
            else if(data_valid_fast  == 1'b1)
               data_valid_fast_reg <= ~data_valid_fast_reg ;  
        end
 
        reg data_valid_fast2slow_reg0,data_valid_fast2slow_reg1;
        always@(posedge clk_slow or negedge rst_n)begin
            if(!rst_n)
               begin
                  data_valid_fast2slow_reg0 <= 1'b0;
                  data_valid_fast2slow_reg1 <= 1'b0;
               end
            else
               begin
                  data_valid_fast2slow_reg0<= data_valid_fast_reg ;  
                  data_valid_fast2slow_reg1<= data_valid_fast2slow_reg0;
               end
        end

       reg data_valid_fast2slow_reg2
        always@(posedge clk_slow or negedge rst_n)begin
            if(!rst_n)
                  data_valid_fast2slow_reg2 <= 1'b0;
            else
                  data_valid_fast2slow_reg2 <= data_valid_fast2slow_reg1;
        end
         
   assign data_valid_slow_ready = data_valid_fast2slow_reg1 ^ data_valid_fast2slow_reg2 ;
        
        always@(posedge clk_slow or negedge rst_n)begin
            if(!rst_n)
                  data_valid_slow<=  0;
            else 
                  data_valid_slow<= data_valid_slow_ready ;
        end
 
        //data fast to slow cdc
        reg  [DATAWIDTH-1:0]      data_fast_reg,
        always@(posedge clk_fast or negedge rst_n)begin
            if(!rst_n)
                  data_fast_reg<=  0;
            else
                  data_fast_reg<= data_fast;
        end

        always@(posedge clk_slow or negedge rst_n)begin
            if(!rst_n)
                  data_slow <=  0;
            else if(data_valid_slow_ready == 1'b1)
                  data_slow <= data_fast_reg ;
        end




endmodule
相关推荐
易享电子4 小时前
基于单片机智能台灯(调光,时钟)系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
电子凉冰6 小时前
FPGA强化-串口RS485
fpga开发
ShiMetaPi6 小时前
操作【GM3568JHF】FPGA+ARM异构开发板 使用指南:音频接口
arm开发·嵌入式硬件·fpga开发·rk3568
码不停蹄Zzz8 小时前
xdma IP使用教程1-xdma ip核配置
网络协议·tcp/ip·fpga开发
易享电子16 小时前
基于单片机电器断路器保护器系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
璞致电子1 天前
fpga开发板ZYNQ 璞致 PZ7010/7020 邮票孔核心板简介-ZYNQ7000系列小系统学习板
linux·嵌入式硬件·学习·fpga开发·fpga·fpga开发板·xilinx开发板
greatofdream1 天前
HDLBit 个人记录
fpga开发
ARM+FPGA+AI工业主板定制专家1 天前
基于JETSON/RK3588机器人高动态双目视觉系统方案
人工智能·机器学习·fpga开发·机器人·自动驾驶
li星野1 天前
打工人日报#20251010
笔记·程序人生·fpga开发·学习方法
国科安芯1 天前
核辐射检测仪中的抗辐照MCU芯片应用探索与挑战应对
网络·人工智能·单片机·嵌入式硬件·安全·fpga开发