【CDC跨时钟域信号处理】快时钟域到慢时钟域-单bit
创始人
2024-03-23 11:19:36
0

快时钟域到慢时钟域分两种情况:
1、允许采样丢失:直接采用同步器即可。
2、不允许采样丢失:原理是保证快时钟域的信号宽度满足一定的条件,使得慢时钟域有足够的时间采样到。
对于情况2有两种方法解决:①信号展宽+边沿检测②握手,且①比②要优先被选择。因为握手资源消耗较大,一般不用。

方法一

脉冲信号展宽+边沿检测,脉冲信号转换成电平信号再进行边沿检测

  • 电路图:
    在这里插入图片描述
  • 代码:(verilog是描述电路的语言,所以要心中有电路,代码就好写了)
module pulse_detect(input              clk_fast    , input              clk_slow    ,   input              rst_n       ,input               data_in     ,output           dataout
);reg data_in_fast;reg [2:0] data_slow;//将脉冲信号在快时钟域展平为电平信号。即展宽脉冲信号。在两次脉冲信号之间为电平信号。always@(posedge clk_fast or negedge rst_n)beginif(!rst_n)data_in_fast<= 0;elsedata_in_fast<= data_in ? (~data_in_fast) : data_in_fast;end//将展宽的脉冲信号在慢时钟域打两拍,并检测边沿。always@(posedge clk_slow or negedge rst_n)beginif(!rst)data_slow <= 3'b0;elsedata_slow <= {data_slow[1:0],data_in_reg};end   assign dataout = data_slow[2] ^ data_slow[1]; 
endmodule
  • 波形
    在这里插入图片描述

方法二

握手+边沿

  • 电路图:
    在这里插入图片描述
  • 代码1:
module pulse_detect(input         clk_fast  , input         clk_slow  ,   input         rst_n    ,input        data_in    ,output         dataout
);//握手方式reg fast_req;//fast时钟域的请求信号reg slow_ack;//slow时钟域的应答信号reg [2:0] slow_req;//slow时钟域的请求信号reg [2:0] fast_ack;//fast时钟域的应答信号//fast时钟域//将slow时钟域的应答信号打三拍,送到fast时钟域always@(posedge clk_fast or negedge rst_n)beginif(!rst_n)fast_ack <= 3'd0;elsefast_ack <= {fast_ack[1:0],slow_ack};end//生成请求信号fast_reqalways@(posedge clk_fast or negedge rst_n)beginif(!rst_n)fast_req <= 0;else if(data_in)fast_req <= 1'b1;else//快时钟域中没有输入数据时//如果慢时钟域应答了,01x,则快时钟域此时不请求,否则,快时钟域的请求信号维持上一时钟的状态fast_req <= ((fast_ack[1]) & (~fast_ack[2])) ? 1'b0 : fast_req;        end//slow时钟域//将fast时钟域的请求信号打三拍,送到slow时钟域always@(posedge clk_slow or negedge rst_n)beginif(!rst_n)slow_req <= 0;elseslow_req <= {slow_req[1:0],fast_req};end//生成应答信号slow_ackalways@(posedge clk_slow or negedge rst_n)beginif(!rst_n)slow_ack <= 0;else if(slow_req[1] & (~slow_req[2])) //如果快时钟域的请求信号由0变为1,01x,即发出请求信号,则慢时钟域进行应答slow_ack <= 1'b1;else//如果slow请求信号10x,即慢时钟域请求信号无效时,慢时钟域不应答//否则慢时钟域应答信号不变slow_ack <= (slow_req[2]&(~slow_req[1])) ? 1'b0 : slow_ack;end//当慢时钟域01x,发出请求信号时,输出为1.assign dataout = (~slow_req[2]) & (slow_req[1]);endmodule
  • 代码2:
module Sync_Pulse (input  src_clk,input  dst_clk,input  rst_n,input  src_pulse,output  dst_pulse);reg req_state_dly1, req_state_dly2,dst_req_state,src_sync_req;reg ack_state_dly1,src_sync_ack;wire dst_sync_ack;always @ (posedge src_clk or negedge rst_n) beginif (rst_n == 1'b0)src_sync_req <= 1'b0;else if (src_pulse)           src_sync_req <= 1'b1;else if (src_sync_ack)           src_sync_req <= 1'b0;else;endalways @ (posedge dst_clk or negedge rst_n) beginif (rst_n == 1'b0)beginreq_state_dly1 <= 1'b0;req_state_dly2 <= 1'b0;dst_req_state <= 1'b0;end else beginreq_state_dly1 <= src_sync_req;req_state_dly2 <= req_state_dly1;        dst_req_state <= req_state_dly2;endendassign dst_sync_ack = req_state_dly2;always @ (posedge src_clk or negedge rst_n) beginif (rst_n == 1'b0) beginack_state_dly1 <= 1'b0;src_sync_ack <= 1'b0;endelse beginack_state_dly1 <= dst_sync_ack;src_sync_ack <= ack_state_dly1;endendassign  dst_pulse =   dst_req_state & (~req_state_dly2);endmodule

对上述代码增加同步失败的指示信号

module handshake_pulse_sync
(input src_clk , //source clockinput src_rst_n, //source clock reset (0: reset)input src_pulse , //source clock pulse inoutput src_sync_fail , //source clock sync state: 1 clock pulse if sync fail.input dst_clk , //destination clockinput dst_rst_n , //destination clock reset (0:reset)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, ack_state_dly2 ;reg req_state_dly1, req_state_dly2 ;reg dst_req_state ;reg 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) beginif(src_rst_n == 1'b0)src_sync_fail <= 1'b0 ;else if (src_pulse & (~src_sync_idle))src_sync_fail <= 1'b1 ;elsesrc_sync_fail <= 1'b0 ;end//set sync req if src_pulse when sync idle ;always @(posedge src_clk or negedge src_rst_n) beginif(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 ;endalways @(posedge src_clk or negedge src_rst_n) beginif(src_rst_n == 1'b0) beginack_state_dly1 <= 1'b0 ;ack_state_dly2 <= 1'b0 ;src_sync_ack <= 1'b0 ;endelse beginack_state_dly1 <= dst_sync_ack ;ack_state_dly2 <= ack_state_dly1 ;src_sync_ack <= ack_state_dly2 ;endendalways @(posedge dst_clk or negedge dst_rst_n) beginif(dst_rst_n == 1'b0) beginreq_state_dly1 <= 1'b0 ;req_state_dly2 <= 1'b0 ;dst_req_state <= 1'b0 ;endelse beginreq_state_dly1 <= src_sync_req ;req_state_dly2 <= req_state_dly1 ;dst_req_state <= req_state_dly2 ;endend//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) beginif(dst_rst_n == 1'b0)dst_sync_ack <= 1'b0;else if (req_state_dly2)dst_sync_ack <= 1'b1;elsedst_sync_ack <= 1'b0;end
endmodule

电路分析:
将src时钟域的脉冲信号打一拍之后,在dst时钟域内打三拍进行同步,其中第二拍的结果作为dst时钟域的应答信号,第二拍和第三拍的结果做边沿检测,以保证在dst时钟域输出接收到的脉冲信号。

其中第二拍的应答信号,在src时钟域经过两级同步作为src的应答信号,当输入脉冲信号时,src的请求信号有效。当src的应答信号有效时,请求信号无效。

缺点:上述操作无法检测到脉冲连续输入时产生的错误,即无法检测同步失败。如:在当前脉冲信号同步过程中又发出了新的脉冲信号的情况。

快时钟域至少展宽脉冲宽度到大于慢时钟域的周期长度。

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...