fpga系列 HDL:跨时钟域同步 双触发器同步器

server/2025/1/15 16:45:25/

目录

      • **双触发器同步器(Two-Flip-Flop Synchronizer)示例代码**:
      • 双触发器同步器的优缺点
        • 优点:
        • 缺点:
        • 适用场景:
    • 应用实例:同步来自spi_slave的单个使能信号

  • 跨时钟域的设计需要特别小心,以避免亚稳态问题。双触发器同步器(2-Flip-Flop Synchronizer) 是一种简单且广泛应用的 时钟域交叉(CDC) 同步方法,用于将一个时钟域中的信号同步到另一个时钟域中。它通过使用两个触发器级联,确保信号在跨越不同时钟域时,(以指数平方级别)降低因为时钟的不匹配导致不稳定或亚稳态(metastability)发生的概率。

https://github.com/Strivekaudani/CDC-FIFO/blob/master/source/two_flip_flop_sync.v

双触发器同步器(Two-Flip-Flop Synchronizer)示例代码

module nocdc (input wire clk_dst,      // 目标时钟域时钟input wire async_signal, // 来自源时钟域的异步信号input wire rst_n,        // 异步复位信号,低电平有效output reg sync_signal,  // 同步后的信号output reg [7:0] counter // 计数器输出
);reg sync_ff1, sync_ff2;// 使用双触发器进行同步always @(posedge clk_dst or negedge rst_n) beginif (!rst_n) beginsync_ff1 <= 1'b0;sync_ff2 <= 1'b0;end else beginsync_ff1 <= async_signal; // 第一阶段采样异步信号sync_ff2 <= sync_ff1;     // 第二阶段消除亚稳态endendassign sync_signal = sync_ff2; // 输出同步后的信号// 使用同步后的信号更新计数器always @(posedge clk_dst or negedge rst_n) beginif (!rst_n) begincounter <= 8'b0;end else if (sync_signal) begincounter <= counter + 1'b1; // 增加计数器endendendmodule
  • 第一寄存器 sync_ff1 捕获来自源时钟域的信号,可能处于亚稳态。
  • 第二寄存器 sync_ff2 采样 sync_ff1,将信号稳定到目标时钟域。

双触发器同步器的优缺点

优点:
  1. 简单高效:双触发器同步器结构简单,通常只需要两个 D 型触发器,因此在资源使用上非常高效。
  2. 低延迟:与其他更复杂的同步方法(如 FIFO)相比,双触发器同步器的延迟较低。
  3. 减少亚稳态的风险:通过两个触发器级联,可以有效降低亚稳态的发生概率,因为第二个触发器会提供额外的稳定化时间。
缺点:
  1. 仅适用于低频信号:双触发器同步器适用于频率差异较小的时钟域交叉。如果时钟域的频率差异过大,可能会导致信号丢失或同步失败。
  2. 无法处理高数据率:如果跨时钟域的数据速率较高,双触发器同步器可能无法有效同步所有数据。
  3. 可能的延迟:虽然延迟较小,但依然会引入一个时钟周期的延迟。
适用场景:
  • 双触发器同步器特别适合同步 单比特控制信号低速数据,例如用于处理外部输入的控制信号、状态标志或较慢的时钟信号。
  • 在高数据率的应用中(如 SPI、I2C、UART 等接口),可能需要更复杂的同步方法,如 FIFO 缓存等。

应用实例:同步来自spi_slave的单个使能信号

  • 使能信号SPI_OPEN_LOOP为非同步信号:
    在这里插入图片描述
  • scheduler的开环配置信号输入(SPI_OPEN_LOOP)来自spi_slave,scheduler实现如下:
// https://github.com/ChFrenkel/tinyODIN/blob/main/scheduler.v 
// 一个调度器(Scheduler)模块,且相较于原始的ODIN调度器移除了旋转FIFO相关功能
// "scheduler.v" - Scheduler module, rotating FIFOs removed from the original ODIN scheduler
// 
// Project: tinyODIN - A low-cost digital spiking neuromorphic processor adapted from ODIN.
//
// Author:  C. Frenkel, Delft University of Technology
// Cite/paper: C. Frenkel, M. Lefebvre, J.-D. Legat and D. Bol, "A 0.086-mm² 12.7-pJ/SOP 64k-Synapse 256-Neuron Online-Learning
//             Digital Spiking Neuromorphic Processor in 28-nm CMOS," IEEE Transactions on Biomedical Circuits and Systems,
//             vol. 13, no. 1, pp. 145-158, 2019.module scheduler #(parameter                   N = 256,parameter                   M = 8
)( input  wire                 CLK,input  wire                 RSTN,input  wire                 CTRL_SCHED_POP_N,input  wire [3:0]           CTRL_SCHED_VIRTS,input  wire [7:0]           CTRL_SCHED_ADDR,input  wire                 CTRL_SCHED_EVENT_IN,input  wire [M - 1:0]       CTRL_NEURMEM_ADDR,input  wire                 NEUR_EVENT_OUT,// 来自SPI配置寄存器的输入信号声明,此处接收SPI的开环配置信号,用于特定调度配置input  wire                 SPI_OPEN_LOOP,output wire                 SCHED_EMPTY,output wire                 SCHED_FULL,output wire [11:0]          SCHED_DATA_OUT
);// 用于对SPI_OPEN_LOOP信号进行同步处理的寄存器声明(双同步寄存器)reg                    SPI_OPEN_LOOP_sync_int, SPI_OPEN_LOOP_sync;wire                   push_req_n;wire                   empty_main;wire                   full_main;wire [11:0]            data_out_main;//----------------------------------------------------------------------------------// SPI信号同步逻辑部分,采用同步屏障机制对SPI_OPEN_LOOP信号进行同步处理// 确保该信号在时钟域内稳定可靠,避免亚稳态等问题,在复位(低电平有效)和时钟上升沿时进行操作//----------------------------------------------------------------------------------always @(posedge CLK, negedge RSTN) beginif(~RSTN) begin// 复位时将中间同步寄存器和最终同步寄存器都置为0SPI_OPEN_LOOP_sync_int  <= 1'b0;SPI_OPEN_LOOP_sync      <= 1'b0;endelse begin// 在正常时钟上升沿时,先将SPI_OPEN_LOOP信号同步到中间寄存器SPI_OPEN_LOOP_sync_int  <= SPI_OPEN_LOOP;// 再将中间寄存器的值同步到最终同步寄存器,形成两级同步SPI_OPEN_LOOP_sync      <= SPI_OPEN_LOOP_sync_int;endendfifo #(.width(12),.depth(128),.depth_addr(7)) fifo_spike_0 (.clk(CLK),.rst_n(RSTN),.push_req_n(full_main | push_req_n),// 推送请求.pop_req_n(empty_main | CTRL_SCHED_POP_N),// 弹出请求// 根据不同条件组合数据输入到FIFO,若有事件输入则组合虚拟相关信息和地址信息作为输入数据,否则用神经元地址信息作为输入.data_in(CTRL_SCHED_EVENT_IN? {CTRL_SCHED_VIRTS,CTRL_SCHED_ADDR} : {4'b0,CTRL_NEURMEM_ADDR}),.empty(empty_main),.full(full_main),.data_out(data_out_main));// 推送请求控制逻辑,根据SPI_OPEN_LOOP_sync信号以及神经元事件输出等情况来决定是否允许推送数据// 当SPI_OPEN_LOOP_sync为低电平且有神经元事件输出,或者有控制器的事件输入时,允许推送数据(push_req_n为低电平)assign push_req_n = ~((~SPI_OPEN_LOOP_sync & NEUR_EVENT_OUT) | CTRL_SCHED_EVENT_IN);assign SCHED_DATA_OUT = data_out_main;assign SCHED_EMPTY    = empty_main;assign SCHED_FULL     = full_main;endmodule

在这里插入图片描述


http://www.ppmy.cn/server/158605.html

相关文章

快速上手Git——Windows系统下Git的安装与简单使用流程

一、Git的下载和安装 Git官网链接&#xff1a;https://git-scm.com/ 进入官网后选择Downloads 选择与系统相符合的版本下载&#xff0c;这里我使用的是windows系统 然后点击下载 根据流程安装完成后&#xff0c;使用以下命令查看git版本 git -v运行结果&#xff1a; 二、…

PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析

PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析 目录 PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析1. 引言2. PID控制器的基本概念2.1 PID控制器的定义2.2 PID控制器的核心思想2.3 PID控制器的应用领域 3. PID控…

【Rust】结构体示例与调试

目录 思维导图 1. 引言 2. 初始程序示例 3. 使用元组重构 4. 使用结构体重构 5. 调试与输出 6. 进一步的功能扩展 思维导图 1. 引言 本文通过一个计算矩形面积的程序&#xff0c;展示了如何从简单变量逐步重构到使用结构体&#xff0c;以提高代码的清晰度和可管理性。结…

微信小程序获取当前页面路径,登录成功后重定向回原页面

&#x1f935; 作者&#xff1a;coderYYY &#x1f9d1; 个人简介&#xff1a;前端程序媛&#xff0c;目前主攻web前端&#xff0c;后端辅助&#xff0c;其他技术知识也会偶尔分享&#x1f340;欢迎和我一起交流&#xff01;&#x1f680;&#xff08;评论和私信一般会回&#…

java流式处理zip+多线程

概述 流式处理一个zip&#xff0c;zip里有多个json文件。 流式处理可以避免解压一个大的zip。再加上多线程&#xff0c;处理的效率杠杠的。 代码 package 多线程.demo05多jsonCountDownLatch;import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThro…

Python爬虫-爬取汽车之家全部汽车品牌的brandid(品牌ID)

前言 本文是该专栏的第42篇,后面会持续分享python爬虫干货知识,记得关注。 本文以汽车之家平台为例子,获取所有汽车品牌的“全部品牌ID”,即brandid数据。如下所示: 具体的实现思路以及完整实现代码逻辑,笔者将在正文进行详细介绍。废话不多说,跟着笔者直接往下看正文详…

Mycat读写分离搭建及配置超详细!!!

目录 一、Mycat产生背景二、Mycat介绍三、Mycat安装四、Mycat搭建读写分离1、 搭建MySQL数据库主从复制2、 基于mysql主从复制搭建MyCat读写分离 五、Mycat启动常见错误处理1、Caused by: io.mycat.config.util.ConfigException: SelfCheck### schema TESTDB refered by user u…

消息中间件类型介绍

消息中间件是一种在分布式系统中用于实现消息传递的软件架构模式。它能够在不同的系统或应用之间异步地传输数据&#xff0c;实现系统的解耦、提高系统的可扩展性和可靠性。以下是几种常见的消息中间件类型及其介绍&#xff1a; 1.RabbitMQ 特点&#xff1a; • 基于AMQP&#…