赞
踩
如果你写过异步FIFO,格雷码的传输就已经包括慢时钟域到快时钟域以及快时钟域到慢时钟域的处理方法了,自己之前的异步FIFO由于理解没到位,快时钟域到慢时钟域的处理也是打拍,原因是快时钟域的时钟频率不够快。所以debug没问题。
步入正题
快到慢常用异步握手。
握手包括同步握手和异步握手;
1、同步握手:
AXI协议的VALID 和 READY信号就是同步握手关系;
2、异步握手(参考除夕之夜微信公众号)
同步逻辑设计中,脉冲信号是指从快时钟域输出的有效宽度小于慢时钟周期的信号。如果慢时钟域直接去采集这种窄脉冲信号,有可能会采集不到。
◆假如这种脉冲信号脉宽都是一致的,在知道两个时钟频率比的情况下,可以采用“快时钟域脉宽扩展+慢时钟域延迟打拍”的方法进行同步。
◆如果有时窄脉冲信号又表现出电平信号的特点,即有时信号的有效宽度大于慢时钟周期而能被慢时钟采集到,那么对此类信号再进行脉冲扩展显然是不经济的。此时,可通过“握手传输”的方法进行同步。
假设脉冲信号的高电平期间为有效信号期间,其基本原理如下。
(1) 快时钟域对脉冲信号进行检测,检测为高电平时输出高电平信号 pulse_fast_r。或者快时钟域输出信号时,不要急于将信号拉低,先保持输出信号为高电平状态。
(2) 慢时钟域对快时钟域的信号 pulse_fast_r 进行延迟打拍采样。因为此时的脉冲信号被快时钟域保持拉高状态,延迟打拍肯定会采集到该信号。
(3) 慢时钟域确认采样得到高电平信号 pulse_fast2s_r 后,再反馈给快时钟域。
(4) 快时钟域对反馈信号 pulse_fast2s_r 进行延迟打拍采样。如果检测到反馈信号为高电平,证明慢时钟域已经接收到有效的高电平信号。如果此时快时钟域自身逻辑不再要求脉冲信号为高电平状态,拉低快时钟域的脉冲信号即可。
此方法实质是通过相互握手的方式对窄脉冲信号进行脉宽扩展。
上代码:
module pulse_f2s( input wire rstn, input wire clk_fast, input wire pulse_fast, input wire signal_slow2fast, output reg pulse_fast2slow ); //快时钟域检测脉冲送到慢时钟域,等待慢时钟域反馈的信号打两拍 //这个pulse_slow送到慢时钟域打两拍才能用 parameter PULSE_INIT=1'b0; wire clear_n; reg signal_slow_r1,signal_slow_r2; reg pulse_fast_ff1,pulse_fast_ff2,pulse_fast_ff3; always@(posedge clk_fast or negedge rstn) begin if (!rstn) {pulse_fast_ff3,pulse_fast_ff2,pulse_fast_ff1}<='b0; else {pulse_fast_ff3,pulse_fast_ff2,pulse_fast_ff1}<={pulse_fast_ff2,pulse_fast_ff1,pulse_fast}; end always@(posedge clk_fast or negedge rstn) begin if (!rstn) pulse_fast2slow<='b0; else if(~clear_n & ~pulse_fast2slow) pulse_fast2slow<=~pulse_fast_ff3 & pulse_fast_ff2; else if(clear_n & pulse_fast2slow) pulse_fast2slow<='b0; end always@(posedge clk_fast or negedge rstn) begin if (!rstn) {signal_slow_r2,signal_slow_r1}<='b0; else {signal_slow_r2,signal_slow_r1}<={signal_slow_r1,signal_slow2fast}; end assign clear_n=signal_slow_r2; endmodule
`timescale 1ns/1ps module tb_pulse_f2s(); reg clk_fast; reg rstn; reg pulse_fast; reg signal_slow2fast; wire pulse_fast2slow; //快时钟域20ns 慢时钟域50ns initial begin clk_fast<=1; rstn=1; #(20) rstn=0; #20; rstn<=1; end always #10 clk_fast=~clk_fast; initial begin pulse_fast='b0; signal_slow2fast=0; #(60) pulse_fast='b1; #20; pulse_fast='b0; #300 signal_slow2fast='b1; #50 signal_slow2fast=1'b0; end pulse_f2s pulse_f2s_inst( .rstn(rstn), .clk_fast(clk_fast), .pulse_fast(pulse_fast), .signal_slow2fast(signal_slow2fast), .pulse_fast2slow(pulse_fast2slow) ); endmodule
测试图:黄线之间握手
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。