fpga系列 HDL:跨时钟域同步 脉冲展宽同步 Pulse Synchronization

Pulse Synchronization

  • 脉冲同步(Pulse Synchronization)是 FPGA 设计中处理跨时钟域信号传输的常见问题和关键细节。
  • 由于不同步的时钟域之间可能存在相位差或频率差异,可能会导致亚稳态问题或数据丢失。
  • 脉冲同步的主要目标是确保一个时钟域中的脉冲信号能够在另一个时钟域安全接收。

脉冲同步代码实现

复制代码
module nocdc (
    input wire clk_src,      // 源时钟域时钟(快时钟)
    input wire clk_dst,      // 目标时钟域时钟(慢时钟)
    input wire rst_n,        // 异步复位信号(低电平有效)
    input wire pulse_in,     // 源时钟域输入脉冲
    output reg pulse_out     // 目标时钟域输出脉冲
);

    // 在源时钟域中对脉冲进行展宽
    reg pulse_in_sync;
    always @(posedge clk_src or negedge rst_n) begin
        if (!rst_n)
            pulse_in_sync <= 0;
        else
            pulse_in_sync <= pulse_in ^ pulse_in_sync; // 展宽脉冲
    end

	 // 双触发同步
    
    reg sync_ff1;
	 reg sync_ff2;
    always @(posedge clk_dst or negedge rst_n) begin
        if (!rst_n)begin
            sync_ff1 <= 0;
				sync_ff2 <= 0;
        end
		  else begin
            sync_ff1 <= pulse_in_sync;// 第一级同步触发器
				sync_ff2 <= sync_ff1;     // 第二级同步触发器
		  end
    end
    
    // 边沿检测
	 reg sync_ff3;
    always @(posedge clk_dst or negedge rst_n) begin
        if (!rst_n)
            sync_ff3 <= 0;
        else
            sync_ff3 <= sync_ff2;
    end

    // 输出脉冲
    always @(posedge clk_dst or negedge rst_n) begin
        if (!rst_n)
            pulse_out <= 0;
        else
            pulse_out <= sync_ff3 ^ sync_ff2;
    end
	 
endmodule

.vt 激励文件

复制代码
`timescale 1 ps/ 1 ps

module nocdc_vlg_tst;

    // 输入信号
    reg clk_src;          // 源时钟域时钟
    reg clk_dst;          // 目标时钟域时钟
    reg rst_n;            // 异步复位信号(低电平有效)
    reg pulse_in;         // 源时钟域输入脉冲

    // 输出信号
    wire pulse_out;       // 目标时钟域输出脉冲

    // 实例化被测模块
    nocdc uut (
        .clk_src(clk_src),
        .clk_dst(clk_dst),
        .rst_n(rst_n),
        .pulse_in(pulse_in),
        .pulse_out(pulse_out)
    );

    // 时钟生成:源时钟域时钟
    initial begin
        clk_src = 0;
        forever #5 clk_src = ~clk_src; // 100MHz (周期为 10ns)
    end

    // 时钟生成:目标时钟域时钟
    initial begin
        clk_dst = 0;
        forever #8 clk_dst = ~clk_dst; // 62.5MHz (周期为 16ns)
    end

    // 测试过程
    initial begin
        // 初始化信号
        rst_n = 0;          // 复位信号初始为低电平
        pulse_in = 0;       // 输入脉冲初始为低电平
        #20;
        rst_n = 1;          // 释放复位信号

		  
        // 等待一段时间观察输出
        #50;

        // 测试用例 2:连续多个脉冲
        #30;
        pulse_in = 1;       // 第一个脉冲
        #10;
        pulse_in = 0;
		  
        #50;
		  
        pulse_in = 1;       // 第二个脉冲
        #10;
        pulse_in = 0;

        // 等待一段时间观察输出
        #100;

        // 结束仿真
        $stop;
    end

endmodule

CG

  • 如果输入脉冲过于窄(小于源时钟周期),可能会导致展宽失败。

  • 单个脉冲也能进行展宽

  • 还可以根据需求选择上升沿或下降沿

    module nocdc (
    input wire clk_src, // 源时钟域时钟(快时钟)
    input wire clk_dst, // 目标时钟域时钟(慢时钟)
    input wire rst_n, // 异步复位信号(低电平有效)
    input wire pulse_in, // 源时钟域输入脉冲
    output reg pulse_out // 目标时钟域输出脉冲
    );

    复制代码
      // 在源时钟域中对脉冲进行展宽
      reg pulse_in_sync;
      always @(posedge clk_src or negedge rst_n) begin
          if (!rst_n)
              pulse_in_sync <= 0;
          else
              pulse_in_sync <= pulse_in ^ pulse_in_sync; // 展宽脉冲
      end
    
       // 双触发同步
      
      reg sync_ff1;
       reg sync_ff2;
      always @(posedge clk_dst or negedge rst_n) begin
          if (!rst_n)begin
              sync_ff1 <= 0;
      			sync_ff2 <= 0;
          end
      	  else begin
              sync_ff1 <= pulse_in_sync;// 第一级同步触发器
      			sync_ff2 <= sync_ff1;     // 第二级同步触发器
      	  end
      end
      
      // 边沿检测
       reg sync_ff3;
      always @(posedge clk_dst or negedge rst_n) begin
          if (!rst_n)
              sync_ff3 <= 0;
          else
              sync_ff3 <= sync_ff2;
      end
    
      
      wire sync_rise_edge = ~sync_ff2 & sync_ff3; // 上升沿检测
      wire sync_fall_edge = sync_ff2 & ~sync_ff3; // 下降沿检测
    
      // 输出脉冲
      always @(posedge clk_dst or negedge rst_n) begin
          if (!rst_n)
              pulse_out <= 0;
          else
              pulse_out <= sync_rise_edge; // 还可以根据需求选择上升沿或下降沿
      end

    endmodule

相关推荐
搬砖的小码农_Sky3 小时前
FPGA:Xilinx Kintex 7实现DDR3 SDRAM读写
fpga开发·硬件架构·硬件工程
小眼睛FPGA7 小时前
why FPGA喜欢FMC子卡?
fpga开发
tiantianuser9 小时前
NVMe简介1
fpga开发·nvme·可编程逻辑·verilogy
FPGA_ADDA10 小时前
基于RFSOC ZU28DR+DSP 6U VPX处理板
fpga开发·dsp·rfsoc28dr·zu28dr·射频采集
搬砖的小码农_Sky13 小时前
FPGA: Xilinx Kintex 7实现PCIe接口
fpga开发·硬件架构·硬件工程
9527华安13 小时前
紫光同创FPGA实现AD9280数据采集转UDP网络传输,分享PDS工程源码和技术支持和QT上位机
网络·fpga开发·udp·紫光同创·qt上位机·ad9280
9527华安1 天前
紫光同创FPGA实现AD7606数据采集转UDP网络传输,提供PDS工程源码和技术支持和QT上位机
网络·qt·fpga开发·udp·紫光同创·ad7606
szxinmai主板定制专家1 天前
基于TI AM6442+FPGA解决方案,支持6网口,4路CAN,8个串口
arm开发·人工智能·fpga开发
7yewh1 天前
FPGA前瞻篇-计数器设计与实现实例
arm开发·驱动开发·嵌入式硬件·fpga开发·硬件架构·硬件工程·精益工程
爱学习的张哥1 天前
UDP--DDR--SFP,FPGA实现之指令监测模块实现
fpga开发·udp·指令