微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 请教一个异步的问题

请教一个异步的问题

时间:10-02 整理:3721RD 点击:
时钟CLKA与CLKB,可否这样操作一个信号(en):
    时钟CLKA下检测到某条件(A)时,将en置为“1”;
    然后时钟CLKB检测到en为高后,输出一个时钟宽度的脉冲,并将en拉低,置为“0”?
烦请各位高手告之,这样做可不可以?不可以的话,又是因为什么原因呢?

可以,前提是CLKA与CLKB的频率足够小,能采到(A)和en的变化

可以做成锁存器或者利用寄存器的复位置位端。但要根据你的两个时钟分析一下,能不能保证时序。比如会不会出现置0和置1同时出现。
个人意见还是换一种设计结构更保险。

那换成什么结构比较保险呢?

那要根据你的实际设计要求来更改了。我的意思是换一个设计思路。不要把两个时钟域这样混杂在一起。如果实在避不开。就要好好考虑一下能不能满足时间要求了。如果时间裕量足够也可以放心使用。

看着有点像CLKA和CLKB之间的握手,en应该做成CLKA的Req,CLKB再做一个Ack替换小编所说的一个时钟脉冲(一个时钟可能不够),当CLKA收到Ack后将en置0。

哦。知道了。谢谢楼上诸位。
因为这是一道题,所以就没办法考虑“不把两个时钟域的混在一起做”和“一个时钟不够”的问题了。原题如下:
CLKA与CLKB是不同的两个时钟,它们之间的关系任意。A时钟下有一个时钟宽度的脉冲信号A_EN,如何将该信号传递到B时钟域,得到B_EN,且脉冲宽度为一个B时钟的宽度。A_EN的频率远低于CLKA与CLKB的频率。

可行,我也這樣做,FPGA verify ok!

这个就是把1bit的数据从a域传到b域吧?
大家看看这个结构行不行。A_EN信号作为一个寄存器的时钟,在上升沿将1打入寄存器R.  R的输出作为B域寄存器Rb的时钟使能,Rb输入端接高,时钟端送入CLKB,输出作为B_EN,同时接入R的复位端(R高电平清零,否则加非门)。
大家看看这个结构可行吗?

//--------------------------------------------------------------------------------------------------------------------------------
// 采用握手电路的跨时钟域信号(ClkA与ClkB异步,且ClkA周期小于ClkB周期,DataClkA只持续一个ClkA周期)
//--------------------------------------------------------------------------------------------------------------------------------
/*-------------------------------------------------------------------*/
always @(posedge ClkA)
    if(DataClkA)
        FlagClkA <= ~FlagClkA;
    else
        FlagClkA <=  FlagClkA;
/*-------------------------------------------------------------------*/
always @(posedge ClkB)
    SyncClkB <= {SyncClkB[1:0] , FlagClkA};
/*-------------------------------------------------------------------*/
assign  DataClkB = (SyncClkB[2] ^ SyncClkB[1]);

//--------------------------------------------------------------------------------------------------------------------------------
// 采用握手电路的跨时钟域信号(ClkA与ClkB异步,且ClkA周期小于ClkB周期,DataClkA只持续一个ClkA周期)
//
// (BusyClkA会在DataClkB出现的前后两个ClkB/ClkA周期内保持为“高”,避免ClkA在此时采样DataClkA,以保护DataClkB的生成)
//--------------------------------------------------------------------------------------------------------------------------------
/*-------------------------------------------------------------------*/
always @(posedge ClkA)
    if(DataClkA & ~BusyClkA)
        FlagClkA <= ~FlagClkA;
    else
        FlagClkA <=  FlagClkA;
/*-------------------------------------------------------------------*/
always @(posedge ClkB)
    SyncClkB <= {SyncClkB[1:0],FlagClkA};
/*-------------------------------------------------------------------*/
always @(posedge ClkA)
    SyncClkA <= {SyncClkA[0],SyncClkB[1]};
/*-------------------------------------------------------------------*/
assign  DataClkB = (SyncClkB[2] ^ SyncClkB[1]);
/*-------------------------------------------------------------------*/
assign  BusyClkA =  FlagClkA ^ SyncClkA[1];

谢谢楼上。

握手,,,

好像两种情况都是“ClkA与ClkB异步,且ClkA周期小于ClkB周期,DataClkA只持续一个ClkA周期”。那么,当ClkA周期大于ClkB周期的时候呢?

好像两种情况都是“ClkA与ClkB异步,且ClkA周期小于ClkB周期,DataClkA只持续一个ClkA周期”。那么,当ClkA周期大于ClkB周期的时候呢?
在速度相当的情况下可以用FIFO(相差不是很大的情况下)
相差较大的情况下可以使用B时钟采样A时钟

在CLKA域中满足一定条件时,置EN为1,用CLKB对EN信号同步两拍,在CLKB域中对同步后的信号进行上升沿检测,当检测到上升沿后,给CLKA域返回一个寄存器信号B,在CLKA域对REG_B-D进行同步,并检测其上升沿,检测到就撤销EN,当EN被撤销后,随即这个事件又被传递给CLKB,再用来撤销REG_B。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top