参考文档

https://blog.csdn.net/u011412586/article/details/10009761

前言

对于信号需要跨时钟域处理而言,最重要的就是确保数据能稳定的传送到采样时钟域。

普通的cdc处理方法需要关注时钟域速度的异同,即分慢时钟域到快时钟域、快时钟域到慢时钟域、相位关系等问题,会让人瞬间爆炸。

那么,是否有一种相对稳定,又无需关注传送时钟域和接收时钟域两者时钟速度、相位关系的数据传递方式呢?

这里仿真验证握手结绳法,自己想的,不知道跟结绳法是不是一致的。。。。。。

思考方式为:要绝对的保证数据被接收,自然是握手应答机制。

流程

首先考虑亚稳态说明:对于异步信号的采集,不可避免的会有亚稳态,但亚稳态的恢复时间一般为1个时钟或者两个时钟,同样其不会是0、1的中间值,而是一个开发者无法确定的定值,同时你的时钟频率越高,亚稳态发生的概率就越大。

网上感觉都说的不明就里,对于简单的使用多级触发器,然后使用最高的2bit进行边沿检测,目测是不行的。

可以理解为仿真中的x值,但数字电路的本质上是有值的,要么0,要么1。

所以如果是检测一个信号的上升沿,即使采到亚稳态,那就分两种情况:

(1)边沿比较陡峭,时钟只采到1次亚稳态,那么边沿寄存器的值就可能为:00、01。检测到00,下一次就会采到01。如果是检测到01,就是想要的沿。

(2)边沿一点都不陡峭,导致时钟采到两次甚至更多次的亚问题,那这就没得玩了。因为你不知道当前是00\01\10\11,这就可能导致你的后续逻辑完蛋了。

当然这里第二种情况不予考虑,FPGA内部不太可能出现这么糟糕的上升沿,除非你的时钟过快,在时钟沿到来前,亚稳态还没有恢复过来。

极端的处理方式是(本质上是滤波):用更多位的寄存器,比如8bit,当检测到为8'b0000_1111,那就是上升沿啦,虽然这阔以绝对可靠的检测到边沿,但检测出沿的所用的时间更长,同时需要保证前级信号的高低电平长度,否则就被滤波了。。。。。。

所以,信号的边沿陡峭性是很重要的,专业术语叫做:上升时间、下降时间。

言归正传,那么握手结绳法是咋样的操作呢?

如下图所示:有点复杂

如图所示,则操作流程为:上述方法应该是支持多bit数据跨时钟域的,这里的多bit说的是FPGA内部数据,pulse_clk1表示发送数据使能,clk1检测到使能则拉高pulse_delay_clk1开始结绳。在clk2中,检测到clk1中的结绳信号的上升沿则产生pulse_clk2,clk2检测到pulse_clk2则启动clk2中的结绳pulse_delay_clk2,在clk1中检测到clk2中的结绳信号为高则解掉clk1的结绳。在clk2中检测到clk1的结绳拉低,则解绳clk2中的结绳信号pulse_delay_clk2,完成传输。

待传送数据在clk2的结绳上升沿被采样。

busy信号为clk1中的信号,在clk1的发送数据使能到来则拉高,在pulse_delay_clk2的下降沿则拉低。

可以看到,这种方式只适合少量的慢速的数据传输。

源代码

`timescale 1ns/1ps
module cdc_test (
input i_clk1 ,
input i_clk2 ,
// input i_rst_n ,
input i_en_clk1 ,
input [:] i_data_clk1 ,
output o_busy_clk1 ,
output o_valid_clk2 ,
output [:] o_data_clk2
);
////clk1
////clk1的发送使能边沿检测
reg [:] r_en_clk1_edge = 'b00;
always @(posedge i_clk1)
begin
r_en_clk1_edge <= {r_en_clk1_edge[],i_en_clk1};
end
reg r_en_clk2 = 'b0;////clk2的使能边沿检测
reg [:] r_en_clk2_edge = 'b00;
always @(posedge i_clk1)
begin
r_en_clk2_edge <= {r_en_clk2_edge[],r_en_clk2};
end
reg r_en_expand = 'b0; ////clk1的使能延长
always @(posedge i_clk1)
begin
if (r_en_clk1_edge == 'b01)
r_en_expand <= 'b1;
else if (r_en_clk2_edge == 'b01)
r_en_expand <= 'b0;
end
reg r_busy_clk1 = 'b0; ////传输忙碌指示,忙碌的时候clk1的数据不可发生改变
always @(posedge i_clk1)
begin
if (r_en_clk1_edge == 'b01)
r_busy_clk1 <= 'b1;
else if (r_en_clk2_edge == 'b10)
r_busy_clk1 <= 'b0;
end ////clk2
reg [:] r_en_expand_edge = 'b00; ////clk1的扩展后的使能边沿检测
always @(posedge i_clk2)
begin
r_en_expand_edge <= {r_en_expand_edge[],r_en_expand};
end always @(posedge i_clk2) ////clk2中的使能
begin
if (r_en_expand_edge == 'b01)
r_en_clk2 <= 'b1;
else if (r_en_expand_edge == 'b10)
r_en_clk2 <= 'b0;
end reg r_valid_clk2 = 'b0;
always @(posedge i_clk2)
begin
if (r_en_expand_edge == 'b01) ////上升沿表示数据有效
r_valid_clk2 <= 'b1;
else
r_valid_clk2 <= 'b0;
end
reg [:] r_data_clk2 = 'd0;
always @(posedge i_clk2)
begin
if (r_en_expand_edge == 'b01) ////上升沿刷新数据
r_data_clk2 <= i_data_clk1;
end ////信号输出 assign o_busy_clk1 = r_busy_clk1;
assign o_valid_clk2 = r_valid_clk2;
assign o_data_clk2 = r_data_clk2; endmodule // end the cdc_test model

仿真看看。

可以看到数据正确传输,不管是快到慢还是慢到快。

以后再板级测试啦。

以上。

cdc跨时钟域处理-结绳握手法的更多相关文章

  1. 跨时钟域设计【一】——Slow to fast clock domain

    跨时钟域设计是FPGA设计中经常遇到的问题,特别是对Trigger信号进行同步设计,往往需要把慢时钟域的Trigger信号同步到快时钟域下,下面是我工作中用到的慢时钟域到快时钟域的Verilog HD ...

  2. 跨时钟域设计【二】——Fast to slow clock domain

    跨时钟域设计中,对快时钟域的Trigger信号同步到慢时钟域,可以采用上面的电路实现,Verilog HDL设计如下:   // Trigger signal sync, Fast clock dom ...

  3. FPGA跨时钟域处理方法

    文章主要是基于学习后的总结. 1. 时钟域 假如设计中所有的触发器都使用一个全局网络,比如FPGA的主时钟输入,那么我们说这个设计只有一个时钟域.假如设计有两个输入时钟,如图1所示,一个时钟给接口1使 ...

  4. FPGA中亚稳态相关问题及跨时钟域处理

    前言 触发器输入端口的数据在时间窗口内发生变化,会导致时序违例.触发器的输出在一段时间内徘徊在一个中间电平,既不是0也不是1.这段时间称为决断时间(resolution time).经过resolut ...

  5. 异步FIFO跨时钟域亚稳态如何解决?

    跨时钟域的问题:前一篇已经提到要通过比较读写指针来判断产生读空和写满信号,但是读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO的读写时钟域不同,是异步的,要是将读时钟域的读指针与写时钟域 ...

  6. FPGA基础学习(3) -- 跨时钟域处理方法

    文章主要是基于学习后的总结. 1. 时钟域 假如设计中所有的触发器都使用一个全局网络,比如FPGA的主时钟输入,那么我们说这个设计只有一个时钟域.假如设计有两个输入时钟,如图1所示,一个时钟给接口1使 ...

  7. 基于FPGA的跨时钟域信号处理——专用握手信号

    在逻辑设计领域,只涉及单个时钟域的设计并不多.尤其对于一些复杂的应用,FPGA往往需要和多个时钟域的信号进行通信.异步时钟域所涉及的两个时钟之间可能存在相位差,也可能没有任何频率关系,即通常所说的不同 ...

  8. FPGA跨时钟域握手信号的结构

    FPGA跨时钟数据传输,是我们经常遇到的问题的,下面给出一种跨时钟握手操作的电路结构.先上图 先对与其他人的结构,这个结构最大的特点是使用 req 从低到高或者高到低的变化 来表示DIN数据有效并开始 ...

  9. CDC(跨时钟域)和亚稳态

随机推荐

  1. shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计

    shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计 shell中的数组的用法: shell数组中的下标是从0开始的 array=("Allen" & ...

  2. 【Redis】CacheCloud介绍及快速开始

    CacheCloud是做什么的 CacheCloud提供一个Redis云管理平台:实现多种类型(Redis Standalone.Redis Sentinel.Redis Cluster)自动部署.解 ...

  3. QML按键

    1.普通用法 import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.2 ApplicationWindow { ...

  4. 【JS新手教程】JS获取当前星期几的几种方法

    该文通过获取星期几的几种方法,介绍JS里的数组,判断,和字符串截取,可以当作新手教程看,小白也看的懂.获取星期几,可通过Date()对象的getDay()获取,获取的是一个数字,对应的是0,1,2,3 ...

  5. sonar:查询全部项目的bug和漏洞总数(只查询阻断/严重/主要级别)

    1.统计所有项目主要以上的漏洞和bug -- 统计所有项目主要以上的漏洞和bug ,) AND severity IN('BLOCKER','CRITICAL','MAJOR') 2.统计所有某个项目 ...

  6. Kafka运维大全来了!优化、监控、故障处理

    Kafka运维大全来了!优化.监控.故障处理……   Kafka概念 Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一个分布式的 ...

  7. 【GStreamer开发】GStreamer基础教程06——媒体格式和pad的Capabilities

    目标       Pad的Capabilities是一个GStreamer element的基础,因为framework大部分时间是自动处理的,所以我们几乎感觉不到它的存在.本教程比较偏向原理,介绍了 ...

  8. axios.js 在测试机ios7.1的iphone4中不能发送http请求解决方案

    原因:axios使用promise语法,浏览器不支持该语法 解决思路:使浏览器支持promise语法 具体代码: 安装es6-promise,npm i es6-promise -D. 在引入axio ...

  9. 【Luogu P3258】[JLOI2014]松鼠的新家

    Luogu P3258 题意就是对于一棵树,要求按照给出的顺序对每一个节点进行访问,记录每一个节点被经过的次数:特别地,我们认为只有从一个节点往外走才能被认为是经过一次.(最后一句话非常重要,仔细理解 ...

  10. python基础篇(三)

    PYTHON基础篇(三) 装饰器 A:初识装饰器 B:装饰器的原则 C:装饰器语法糖 D:装饰带参数函数的装饰器 E:装饰器的固定模式 装饰器的进阶 A:装饰器的wraps方法 B:带参数的装饰器 C ...