Oliver 发表于 2009-1-1 22:52:02

请教MCU怎么和CPLD可靠交换数据(CPLD接收时很容易出现标志位刚好在时钟沿上,造成数

现在是MCU通过模拟总线发送数据(16位数据+RD+WR+CS)给CPLD,CPLD通过WR上升沿触发保存总线数据.同时产生一个标志给别的程序(主时钟),别的程序检测到标志后处理这个数据.



但标志变化(WR变化后的一定延迟时间)经常发生在主时钟的沿上(或附近,应该是th,ts不够),导致主时钟侧检测标志变化失败.



另外:功能仿真的时候是没问题的,通信正常,后来挂系统后发现不对,通过时序仿真也是偶尔通信失败.



程序如下:

    always @(posedge mpu_wr or negedge rst)begin

        if(!rst)begin

            mpu_wr_data                <= 'd0;

         mpu_wr_di                        <= 1'b0;

         mpu_wr_ok_flag                <= 1'b0;

        end

        else begin

            if(!mpu_cs)begin

                   mpu_wr_data        <= mpu_db_in;

                mpu_wr_di                <= mpu_di;

                mpu_wr_ok_flag        <= !mpu_wr_ok_flag;

         end

         else begin

                mpu_wr_data        <= mpu_wr_data;

                mpu_wr_di                <= mpu_wr_di;

                mpu_wr_ok_flag        <= mpu_wr_ok_flag;

         end

    end



这个方法在时序仿真时还偶尔出现标志检测成功,但16位数据里有未知X

(估计是16位数据被WR触发时在寄存器里的变化不是同时的,有前有后,有些在变化时被采样,造成出现X).



增加如下方法还是不行(用了全等:3个=号的),同时希望用主时钟打一拍形成一定的稳定时间:



这时用flag通知别的程序,设想flag和别的程序是同频同相应该没问题了.

    always @(posedge clk negedge rst)begin

        if(!rst)begin

            buf  <= 1'b0;

            flag <= 1'b0;

        end

        else begin

            if((mpu_wr_ok_flag === 1'b1) && (buf === 1'b0))begin

                buf  <= 1'b1;

                flag <= !flag;

            end 

            else if((mpu_wr_ok_flag === 1'b0) && (buf === 1'b1))begin

                buf  <= 1'b0;

                flag <= !flag;

            end

            else begin

                buf  <= buf;

                flag <= flag;

            end

        end

    end

    

    还是不行,也是主时钟对标志位和buf进行判断的时候刚好标志位变化,造成仿真波形中出现X状态.



好象按想法应该可以,我用了全等判断,如果就算本次标致变化在时钟沿上,那本次判断最多无效,下次还可以正确判断啊.结果flag直接变成X了.



请教大侠,这样的设计目的如何处理?莫非还真要用FIFO?

Oliver 发表于 2009-1-2 21:50:55

总结一下:

1.总线数据(或"命令/数据"选择)通过WR/RD边沿(异步)打入FF;



2.对WR,RD往3位宽reg里打(主时钟),1时钟左移一次.



3.在主时钟里检测到100说明出现了下降沿,可以产生相应标志;



4.在主时钟里检测到011说明出现了上升沿,可以产生相应标志;







举列用"100"检测下降沿的原理.

平时WR=1,reg肯定=3'b111了;WR变低后reg随主时钟的变化如下:



111    110    100    000            无亚稳态

111    11x    110    100    000     亚稳态后变成1

111    11x    100    000            亚稳态后变成0



可以看出通过检测"100"都能检测到WR的变低.



不过负出的代价就是检测变长了,如果WR的负脉冲太窄肯定就会丢数.



通过以上做法可以完全避免亚稳态影响(resolution time得<1周期).



大家一起探讨一下啊.

Oliver 发表于 2009-1-4 12:17:55

12楼:

为什么说用下降沿同步呢?也有可能同步的时候刚好mpu_wr_ok_flag变化.出现亚稳态.



只有对WR,RD(或者相应的flag)连打几拍来保证亚稳态不扩散(并且能保证不丢数).



我的程序是CPLD处理好每次读写后会反握手信号给处理器.



以前ARM经常等不到这个信号,现在可以等到了(通信了很多很多次都能等到).

yermin 发表于 2009-1-4 00:35:00

用时钟下降沿同步mpu_wr_ok_flag信号呢?

Oliver 发表于 2009-1-2 02:48:32

【9楼】 at90s 子非鱼:

谢谢你这么晚的回贴,我一直在折腾接口这块的地方.



我估计到实际电路应该基本能工作了.

明天整体调试看看没问题就测试一下.



我觉得也是,出现亚稳态后只要下1,2周期恢复了那系统就还可以继续工作(因为总线数据已经在上升沿被打入mpu_wr_data,并且保持到下周期).

at90s 发表于 2009-1-2 01:20:18

【7楼】 的图我认为是后仿引起的问题而已,不一定代表实际情况。



触发器因为输入数据不满足建立/保持时间而进入亚稳态后,会在一段时间内输出一个不确定的状态(可能为0,可能为1,可能为0、1电平之间的电平,也有可能在0、1之间震荡),但不管怎么样,最后都会回到一个稳态(可能为0,也可能为1),这段时间称为resolution time。只要时钟周期大于resolution time,那么后级触发器就能采到一个处于稳态的值。



下面考虑输入的异步信号由0跳变到1并且前级触发器(mpu_wr_ok_flag_buf)进入了亚稳态的情况:

假设1:若mpu_wr_ok_flag_buf退出亚稳态,并稳定在1电平,由于mpu_wr_ok_flag_buf处于0状态,那么其后的边沿检测器就能够检测到一个跳变。

假设2:若mpu_wr_ok_flag_buf退出亚稳态,并稳定在0电平,那么下一个周期该触发器肯定采到1电平(输入的异步信号这时已经稳定到1电平了),其后的情形和假设1一样。

Oliver 发表于 2009-1-2 00:39:13

【4楼】 at90s 子非鱼:

你说对了,所以我在考虑是否将WR,RD的传递改成异步FIFO方式;



通过FIFO后就不会出现亚稳态情况了.总线数据都是稳定的,只要标志稍微延迟一点点就可以了;





我的主频54MHZ,希望总线交换频率到10MHZ左右.

因为我要尽快的把数据转到CPLD内部,有可能前级是一些物理总线(非模拟的,也可能是ARM),读写脉冲快了可能CPLD会丢数.



另外的通信里不允许有错误数据(现在错都在接口这里).



谢谢你的指点;



------------------------------------------

希望继续征集到其它大侠的方案技巧.

Oliver 发表于 2009-1-2 00:31:33

刚后仿真了写100,1000和10000字的测试(没管程序功能,只看flag一周期宽度是否正常).



都在刚开始不久便出现一个错误(比原来少),下图红圈部分:

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_568043.GIF

 (原文件名:wave1.GIF) 



放大后局部:

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_568044.GIF

 (原文件名:wave2.GIF) 



可以看见1周期正脉冲变成了2周期X.

at90s 发表于 2009-1-2 00:03:59

反正我是这么干的,与133MHz主频的Power PC通信非常稳定的

at90s 发表于 2009-1-2 00:01:44

不知道你的主时钟频率多高?如果有几十兆的话,就根本不需要考虑那几拍的延时了,一般MCU的读写周期都是比较长的

at90s 发表于 2009-1-1 23:58:06

凡是异步时钟域之间的数据交换都是有可能出现亚稳态的,打2拍只是把出现亚稳态的几率降到很小而已。

本贴被 at90s 编辑过,最后修改时间:2009-01-02,00:02:56.

Oliver 发表于 2009-1-1 23:48:46

谢谢"【2楼】 at90s 子非鱼"大侠的指点...



有几个疑问啊.

就是:

1.这样等于多同步了几拍(2-3拍才输出flag信号,3-4拍别的程序才能知道flag的变化),肯定会影响MCU和CPLD的通信速率;



2.如果刚好mpu_wr_ok_flag在时钟沿变化,导致mpu_wr_ok_flag_buf中被采集到X值,那flang异或比较的时候会不会也变成X?



第二点我很快就可以验证一下,有什么在请教你了,再次谢谢.

at90s 发表于 2009-1-1 23:33:14

mpu_wr_ok_flag对于主时钟来说是一个异步信号,一般做法是打两拍后再作边沿检测:



reg  mpu_wr_ok_flag_buf;  // 打2拍同步,另外一个寄存器用于边沿检测

always @(posedge clk or negedge rst)

begin

    if (!rst)

        mpu_wr_ok_flag_buf <= 3'b0;

    else 

        mpu_wr_ok_flag_buf <= {mpu_wr_ok_flag, mpu_wr_ok_flag_buf};

end



reg flag; // 通知别的程序干活,一周期宽度

always @(posedge  clk or negedge rst)

begin

    if (!rst)

        flag <= 1'b0;

    else

        flag <= mpu_wr_ok_flag_buf ^ mpu_wr_ok_flag_buf; //检测边沿

end

Oliver 发表于 2009-1-1 23:07:33

时序仿真波形图:

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_567865.GIF

 (原文件名:wave.GIF) 



从上到下依此为:

1.主时钟(上升沿触发)

2.WR

3.标志变化(主时钟程序通过检测它的变化来处理mpu_wr_data中的数据)



图上第一个时钟是正确的,后面程序可以检测到它的变化进行处理数据;

第二个始终后flag变成了X,后面仿真就全部失败了.

huayan 发表于 2009-3-3 22:40:48

学习了!!

bbandpp 发表于 2009-3-9 22:19:07

好东西,学习了

R28FA 发表于 2009-3-24 17:00:19

不错

microcreat 发表于 2009-6-4 10:18:59

请问,楼主这个东东是用在哪个上面的,数据交换误码率高吗?
怎样避免通讯错误啊?有什么措施!

Oliver 发表于 2009-6-4 11:54:40

ARM并行总线和CPLD通讯,驱动TFT显示.

通过之前的方法误码率=0(或者小到我没法发现)

microcreat 发表于 2009-6-4 21:34:19

楼主能讲下你的具体思路吗?硬件连接图和程序中要注意的事项?谢谢!

Oliver 发表于 2009-6-4 22:22:19

都在这个贴里了啊?应该是很详细了,我不懂你为什么看了还没解决?

我就是听了"at90s 子非鱼"大侠的讲解然后接解决了啊,现在很稳定.

microcreat 发表于 2009-6-22 11:16:03

请问,楼主,你的是用了几根控制总线
我准备用
CS ---片选
RE-----读
WR-----写
data---数据(8)
addr---地址(8)

RE下降沿有效
WR上升沿有效
这样可以吗?

还有你用到全局复位和全局置位没>

Oliver 发表于 2009-6-22 11:41:30

1.边沿触发不行,行的话我就不发此贴了
2.没有用全局复置位

microcreat 发表于 2009-6-22 14:05:33

哦!我的意思是先边沿触发后,对RE/WR进行多次采样啊!

microcreat 发表于 2009-6-27 20:53:53

楼主你好!我现在想知道你对RE/WE的采样时钟!
我可以用我MCU的IO口变化速度的3倍去采样,这个办法可以吗?

zhangnaizhou 发表于 2009-9-20 16:46:55

谢谢了

Nuist_Gwgj 发表于 2011-8-14 16:58:08

MARK

gloryzkl 发表于 2011-8-14 19:26:56

学习

asma 发表于 2011-8-15 15:37:04

mark

szfrg 发表于 2012-2-21 15:43:14

记号

ddny2008 发表于 2012-2-27 21:34:05

MARK

msdy 发表于 2012-2-27 21:55:30

学习了

szfrg 发表于 2012-3-8 15:49:14

谢谢了

cmdrainsy 发表于 2012-7-15 19:07:59

怎么上面的代码全变成 这乱七八糟的东西了?
    always @(posedge clk negedge rst)begin

        if(!rst)begin

            buf  <= 1'b0;

            flag <= 1'b0;

        end

        else begin

            if((mpu_wr_ok_flag === 1'b1) && (buf === 1'b0))begin

                buf  <= 1'b1;

                flag <= !flag;

            end 

mysunmax 发表于 2012-7-15 20:04:13

mark                                       

kuailexiaorenwu 发表于 2012-7-18 19:01:06

mark                                    
页: [1]
查看完整版本: 请教MCU怎么和CPLD可靠交换数据(CPLD接收时很容易出现标志位刚好在时钟沿上,造成数