【设计开发】 典型异步电路设计-脉冲同步(2)

一、前言

  上一篇文章中已经描述了简单的脉冲同步器,它可以实现简单应用场景下的同步功能,同时也存在不少应用限制或缺陷,例如:

  (1) 对src_clk域dst_clk关系较为敏感,当src_clk与dst_clk时钟频率差别很大时可能不适应;

  (2) 由于没有完整的握手机制,当多个src_pulse之间间隔较短时,可能存在脉冲同步丢失情况。

  (3) 当dst_clk时钟域出现无时钟或复位时,src_clk时钟域将丢失。

  本文将对该同步器进行改进以满足更多异步脉冲同步场景。

二、原理

  回顾上一篇文章中的同步器的基本设计原理:

  (1)源时钟域脉冲转换为源时钟域电平信号;

  (2)对单bit电平信号进行打拍的异步处理;

  (3)在目的时钟域中进行脉冲还原。

  从以上设计原理中,我们可以发现该同步器的控制传递是单向的,即仅从源时钟域到目的时钟域,目的时钟域并没有状态反馈。假设存在如下应用:

  (1) 源时钟域中的第一个脉冲和第二个脉冲间隔过短,第一个脉冲未完成同步,第二脉冲又将状态清空,导致最终脉冲同步丢失。

  

  要解决以上同步问题,需要引入异步握手机制,保证每个脉冲都同步成功,同步成功后再进行下一个脉冲同步。握手原理如下:

  sync_req: 源时钟域同步请求信号,高电平表示当前脉冲需要同步;

  sync_ack: 目的时钟域应答信号,高电平表示当前已收到同步请求;

  

  完整同步过程分为以下4个步骤:

  (1) 同步请求产生;当同步器处于空闲(即上一次已同步完成)时,源同步脉冲到达时产生同步请求信号sync_req;

  (2) 同步请求信号sync_req同步到目的时钟域,目的时钟域产生脉冲信号并将产生应答信号sync_ack;

  (3) 同步应答信号sync_ack同步到源时钟域,源时钟域检测到同步应答信号sync_ack后,清除同步请求信号;

  (4) 目的时钟域检测到sync_req撤销后,清除sync_ack应答;源时钟域将到sync_ack清除后,认为一次同步完成,可以同步下一个脉冲。

三、代码

//--====================================================================================--
// THIS FILE IS PROVIDED IN SOURCE FORM FOR FREE EVALUATION, FOR EDUCATIONAL USE OR FOR
// PEACEFUL RESEARCH.  DO NOT USE IT IN A COMMERCIAL PRODUCT . IF YOU PLAN ON USING THIS
// CODE IN A COMMERCIAL PRODUCT, PLEASE CONTACT [email protected] TO PROPERLY LICENSE
// ITS USE IN YOUR PRODUCT.
//
// Project      : Verilog Common Module
// File Name    : handshake_pulse_sync.v
// Creator(s)   : [email protected]
// Date         : 2015/12/01
// Description  : A handshake pulse sync
//
// Modification :
// (1) Initial design  2015-12-01
//
//
//--====================================================================================--

module HANDSHAKE_PULSE_SYNC
    (
        src_clk         , //source clock
        src_rst_n       , //source clock reset (0: reset)
        src_pulse       , //source clock pulse in
        src_sync_fail   , //source clock sync state: 1 clock pulse if sync fail.
        dst_clk         , //destination clock
        dst_rst_n       , //destination clock reset (0:reset)
        dst_pulse       //destination pulse out
    );

//PARA   DECLARATION

//INPUT  DECLARATION
input               src_clk     ; //source clock
input               src_rst_n   ; //source clock reset (0: reset)
input               src_pulse   ; //source clock pulse in

input               dst_clk     ; //destination clock
input               dst_rst_n   ; //destination clock reset (0:reset)

//OUTPUT DECLARATION
output              src_sync_fail   ; //source clock sync state: 1 clock pulse if sync fail.
output              dst_pulse       ; //destination pulse out

//INTER  DECLARATION
wire                dst_pulse       ;
wire                src_sync_idle   ;
reg                 src_sync_fail   ;
reg                 src_sync_req    ;
reg                 src_sync_ack    ;
reg                 ack_state_dly1  ;
reg                 ack_state_dly2  ;
reg                 req_state_dly1  ;
reg                 req_state_dly2  ;
reg                 dst_req_state   ;
reg                 dst_sync_ack    ;

//--========================MODULE SOURCE CODE==========================--

//--=========================================--
// DST Clock :
// 1. generate src_sync_fail;
// 2. generate sync req
// 3. sync dst_sync_ack
//--=========================================--
assign src_sync_idle = ~(src_sync_req | src_sync_ack );

//report an error if src_pulse when sync busy ;
always @(posedge src_clk or negedge src_rst_n)
begin
    if(src_rst_n == 1‘b0)
        src_sync_fail   <= 1‘b0 ;
    else if (src_pulse & (~src_sync_idle))
        src_sync_fail   <= 1‘b1 ;
    else
        src_sync_fail   <= 1‘b0 ;
end

//set sync req if src_pulse when sync idle ;
always @(posedge src_clk or negedge src_rst_n)
begin
    if(src_rst_n == 1‘b0)
        src_sync_req    <= 1‘b0 ;
    else if (src_pulse & src_sync_idle)
        src_sync_req    <= 1‘b1 ;
    else if (src_sync_ack)
        src_sync_req    <= 1‘b0 ;
end

always @(posedge src_clk or negedge src_rst_n)
begin
    if(src_rst_n == 1‘b0)
        begin
            ack_state_dly1  <= 1‘b0 ;
            ack_state_dly2  <= 1‘b0 ;
            src_sync_ack    <= 1‘b0 ;
        end
        else
        begin
            ack_state_dly1  <= dst_sync_ack     ;
            ack_state_dly2  <= ack_state_dly1   ;
            src_sync_ack    <= ack_state_dly2   ;
        end
end

//--=========================================--
// DST Clock :
// 1. sync src sync req
// 2. generate dst pulse
// 3. generate sync ack
//--=========================================--
always @(posedge dst_clk or negedge dst_rst_n)
begin
    if(dst_rst_n == 1‘b0)
        begin
            req_state_dly1  <= 1‘b0 ;
            req_state_dly2  <= 1‘b0 ;
            dst_req_state   <= 1‘b0 ;
        end
    else
        begin
            req_state_dly1  <= src_sync_req     ;
            req_state_dly2  <= req_state_dly1   ;
            dst_req_state   <= req_state_dly2   ;
        end
end

//Rising Edge of dst_state generate a dst_pulse;
assign dst_pulse = (~dst_req_state) & req_state_dly2 ; 

//set sync ack when src_req = 1 , clear it when src_req = 0 ;
always @(posedge dst_clk or negedge dst_rst_n)
begin
    if(dst_rst_n == 1‘b0)
        dst_sync_ack    <= 1‘b0;
    else if (req_state_dly2)
        dst_sync_ack    <= 1‘b1;
    else
        dst_sync_ack    <= 1‘b0;
end

endmodule

四、仿真

  (1) 当目的时钟域dst_rst_n复位时,脉冲不丢失;

  

(2) 正常同步情况;

  

(3) 源脉冲频率过高情况;

  

  

时间: 2024-10-06 06:00:16

【设计开发】 典型异步电路设计-脉冲同步(2)的相关文章

【设计开发】 典型异步电路设计-脉冲同步

一.前言 在数字芯片设计中常常涉及不同的工作时钟域,在异步时钟域间控制交互.数据交互又涉及异步电路设计.良好.健壮的异步电路设计可提高系统的稳定性.可靠性.健壮性.本博文介绍异步电路中的脉冲同步设计方法. 二.应用 在设计开发过程中,经常会有如下的应用: 时钟域A的脉冲信号需同步到时钟B中使用,其中时钟A与时钟B在不同场景下有不确定的关系,如下图(1).(2)所示. (1) 慢时钟域到快时钟域的脉冲同步 (2) 快时钟域到慢时钟域的脉冲同步 三.简单的脉冲同步器 基于以上应用,设计一个简单的脉冲

[Unity3D]Unity3D游戏开发之异步记载场景并实现进度条读取效果

大家好,我是秦元培.欢迎大家关注我的博客,我的博客地址是:blog.csdn.net/qinyuanpei.终于在各种无语的论文作业中解脱了,所以立即抓紧时间来这里更新博客.博主本来计划在Unity3D游戏开发之从<魂斗罗>游戏说起(上)--目标追踪这篇文章后再写一篇<Unity3D游戏开发之从<魂斗罗>游戏说起(下)>,只是眼下博主的项目进度有些缓慢,所以想等项目稳定下来以后再和大家分享. 作为大家等待博主更新博客的回报,我们今天来说一说Unity3D中的游戏场景异步

QT 异步函数和同步函数交换问题

同步函数与异步函数 依据微软的MSDN上的解说: (1)   同步函数:当一个函数是同步执行时,那么当该函数被调用时不会立即返回,直到该函数所要做的事情全都做完了才返回. (2)   异步函数:如果一个异步函数被调用时,该函数会立即返回尽管该函数规定的操作任务还没有完成. (3) 在一个线程中分别调用上述两种函数会对调用线程有何影响呢? 当一个线程调用一个同步函数时(例如:该函数用于完成写文件任务),如果该函数没有立即完成规定的操作,则该操作会导致该调用线程的挂起(将CPU的使用权交给系统,让系

MySQL 5.5 主从复制异步、半同步以及注意事项详解

大纲 一.前言 二.Mysql 基础知识 三.Mysql 复制(Replication) 四.Mysql 复制(Replication)类型 五.Mysql 主从复制基本步骤 六.Mysql 主从复制(异步) 七.Mysql 主从复制(半同步) 八.Mysql 复制工具 九.Mysql 复制注意事项 十.Mysql 复制过滤 一.前言 从这一篇博客开始我们就来学习mysql的高级课程,在前面的几篇博客我们讲解了mysql基础知识.mysql日志类型.mysql配置文件.mysql备份策略,这一篇

linux 异步信号的同步处理方式

关于代码的可重入性,设计开发人员一般只考虑到线程安全,异步信号处理函数的安全却往往被忽略.本文首先介绍如何编写安全的异步信号处理函数:然后举例说明在多线程应用中如何构建模型让异步信号在指定的线程中以同步的方式处理. 应用中编写安全的信号处理函数 在开发多线程应用时,开发人员一般都会考虑线程安全,会使用 pthread_mutex 去保护全局变量.如果应用中使用了信号,而且信号的产生不是因为程序运行出错,而是程序逻辑需要,譬如 SIGUSR1.SIGRTMIN 等,信号在被处理后应用程序还将正常运

数据库设计开发规范

1 数据库命名约定  1.1 规则 (1) 命名富有意义英文词汇,多个单词组成的,中间以下划线分割. (2) 除数据库名称长度为1-8个字符,其余为1-30个字符,dblink名称也不要超过30个字符. (3)命名只能使用英文字母,数字和下划线,字母全部小写 (4)避免使用Oracle的保留字如level.关键字如type. 1. 2系统模块 编号 名称 英文 缩写 1 系统管理 system sys 2 配置管理 dictionary dic 3 设备系统 equipment equ 4 通讯

Android开发之异步详解(二)之AsyncTask

请尊重他人的劳动成果,转载请注明出处:Android开发之异步详解(二)之AsyncTask http://blog.csdn.net/fengyuzhengfan/article/details/40212745 我曾在<Android开发之异步详解(一)之Thread+Handler>一文中介绍过通过Thread+Handler实现异步操作.感兴趣的朋友可以看一下. 虽然Thread+Handler可以实现更新主线程的UI并实现异步,但Thread+Handler模式需要为每一个任务创建一

【转】C#异步编程及其同步机制

C#异步编程及其同步机制 本篇文章涵盖一下几部分内容: 1. 什么是异步编程,为什么会需要异步编程 2. .NET下的异步编程及其发展 3. .NET线程同步机制及线程间数据封送 4. 异步模式 5. 线程安全及异常处理 6. 线程取消 什么是异步编程,为什么会需要异步编程 这个世界上资源是受限的.但资源限制和懒惰一样促进了工业和科技的发展.在计算机方面举个例子,计算机非得是二进制吗?对计算机来说二进制最好吗?不是,这是由于当时工业水平限制,把电压分成两份表示0和1比分成三份更加方便且可靠:虚拟

mysql数据库设计开发规范

1.设计 1. 一般都使用INNODB存储引擎,除非读写比率<1%,才考虑使用MYISAM存储引擎:其他存储引擎请在DBA的建议下使用. 2. Stored procedure (包括存储过程,函数,触发器)对于MYSQL来说还不是很成熟,没有完善的出错记录处理,不建议使用. 3. UUID(),USER()这样的MYSQL INSIDE函数对于复制来说是很危险的,会导致主备数据.不一致.所以请不要使用.如果一定要使用UUID作为主键,让应用程序来产生. 4. 请不要使用外键约束,如果数据存在外