博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于FPGA的跨时钟域信号处理——专用握手信号
阅读量:6590 次
发布时间:2019-06-24

本文共 2208 字,大约阅读时间需要 7 分钟。

转自:http://bbs.ednchina.com/BLOG_ARTICLE_253787.HTM

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

    图1是一个跨时钟域的异步通信实例,发送域和接收域的时钟分别是clk_a和clk_b。这两个时钟频率不同,并且存在一定的相位差。对于接收时钟域而言,来自发送时钟域的信号data_a2b有可能在任何时刻变化。

图1 跨时钟域通信

    对于上述的异步时钟域通信,设计者需要做特殊的处理以确保数据可靠的传输。由于两个异步时钟域的频率关系不确定,触发器之间的建立时间和保持时间要求也无法得到保证。如果出现建立时间或者保持时间违规,接收域将会采样到处于亚稳态数据,那么后果可想而知。

    如何有效的进行跨时钟域的信号传输呢?最基本的思想是同步,在这个基础上设计者可以利用各种协议约定进行通信。单向控制信号检测方式(前面提到过的脉冲信号检测方法,这里为了和握手方式相区别,所以如此称呼)、握手协议的方式或者借助存储器的方式都是比较常用的处理手段。

    本文将重点介绍握手方式进行异步时钟域的通信。

    图2是一个基本的握手通信方式。所谓握手,意即通信双方使用了专用控制信号进行状态指示。这个控制信号既有发送域给接收域的,也有接收域给发送域的,有别于前面的单向控制信号检测方式。

握手通信原理

    使用握手协议方式处理跨时钟域数据传输,只需要对双方的握手信号(req和ack)分别使用脉冲检测方法进行同步。在具体实现中,假设req、ack、data总线在初始化时都处于无效状态,发送域先把数据放入总线,随后发送有效的req信号给接收域。接收域在检测到有效的req信号后锁存数据总线,然后回送一个有效的ack信号表示读取完成应答。发送域在检测到有效ack信号后撤销当前的req信号,接收域在检测到req撤销后也相应撤销ack信号,此时完成一次正常握手通信。此后,发送域可以继续开始下一次握手通信,如此循环。以上所述的通信流程如图3所示。该方式能够使接收到的数据稳定可靠,有效的避免了亚稳态的出现,但控制信号握手检测会消耗通信双方较多的时间。

图3 握手通信流程

    下面通过一个简单的工程代码及其仿真测试进一步加深大家对基本握手协议的认识。

module handshack(

                clk,rst_n,

                req,datain,ack,dataout

            );

 

input clk;      //50MHz系统时钟

input rst_n;    //低电平复位信号

 

input req;      //请求信号,高电平有效

input[7:0] datain;  //输入数据

output ack;     //应答信号,高电平有效

output[7:0] dataout;//输出数据,主要用于观察是否和输入一致

 

//--------------------------------------

//req上升沿检测

reg reqr1,reqr2,reqr3;

 

always @(posedge clk or negedge rst_n)

    if(!rst_n) begin

            reqr1 <= 1'b1;

            reqr2 <= 1'b1;

            reqr3 <= 1'b1;

        end

    else begin

            reqr1 <= req;

            reqr2 <= reqr1;

            reqr3 <= reqr2;

        end

       

    //pos_req2比pos_req1延后一个时钟周期,确保数据被稳定锁存

wire pos_req1 = reqr1 & ~reqr2; //req上升沿标志位,高有效一个时钟周期

wire pos_req2 = reqr2 & ~reqr3; //req上升沿标志位,高有效一个时钟周期

 

//--------------------------------------

//数据锁存

reg[7:0] dataoutr;

 

always @(posedge clk or negedge rst_n)

    if(!rst_n) dataoutr <= 8'h00;

    else if(pos_req1) dataoutr <= datain;   //检测到req有效后锁存输入数据

   

assign dataout = dataoutr; 

   

//--------------------------------------

//产生应答信号ack

reg ackr;

 

always @(posedge clk or negedge rst_n)

    if(!rst_n) ackr <= 1'b0;

    else if(pos_req2) ackr <= 1'b1;

    else if(!req) ackr <= 1'b0;

 

assign ack = ackr;

 

endmodule

 

    该实例的verilog代码模拟了握手通信的接收域,其仿真波形如图4所示。在发送域请求信号(req)有效的若干个时钟周期后,先是数据(datain)被有效锁存了(dataout),然后接收域的应答信号(ack)也处于有效状态,此后发送域撤销请求信号,接收域也跟着撤销了应答信号,由此完成一次通信。

图4 握手通信仿真波形

转载地址:http://gozio.baihongyu.com/

你可能感兴趣的文章
Three.js 学习笔记 - 给跳一跳小游戏添加光源,阴影
查看>>
@babel/polyfill按需加载
查看>>
koa compose源码阅读
查看>>
CSS进阶(4)—— 温和padding中的诡异CSS现象
查看>>
机器学习【四】决策树
查看>>
Java 自定义HashSet
查看>>
MSSQL发送邮件
查看>>
Newtonsoft 反序列化字符串
查看>>
[LeetCode] Course Schedule
查看>>
[LeetCode] Find Median from Data Stream
查看>>
selenium层级定位及鼠标键盘操作
查看>>
SpringBoot跨域问题解决方案
查看>>
(转载)hibernate3.0配置文件模板
查看>>
46、练习:输出指定目录下的所有文件名称
查看>>
IP地址与数字地址相互转换
查看>>
.net core 允许跨域
查看>>
Knockout.Js官网学习(创建自定义绑定)
查看>>
win10 x64中 windbg x64 安装配置符号库
查看>>
python 抽象类、抽象方法、接口、依赖注入、SOLIP
查看>>
echarts 报错问题 is null 或者未定义等问题
查看>>