请教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? 总结一下:
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周期).
大家一起探讨一下啊. 12楼:
为什么说用下降沿同步呢?也有可能同步的时候刚好mpu_wr_ok_flag变化.出现亚稳态.
只有对WR,RD(或者相应的flag)连打几拍来保证亚稳态不扩散(并且能保证不丢数).
我的程序是CPLD处理好每次读写后会反握手信号给处理器.
以前ARM经常等不到这个信号,现在可以等到了(通信了很多很多次都能等到). 用时钟下降沿同步mpu_wr_ok_flag信号呢? 【9楼】 at90s 子非鱼:
谢谢你这么晚的回贴,我一直在折腾接口这块的地方.
我估计到实际电路应该基本能工作了.
明天整体调试看看没问题就测试一下.
我觉得也是,出现亚稳态后只要下1,2周期恢复了那系统就还可以继续工作(因为总线数据已经在上升沿被打入mpu_wr_data,并且保持到下周期). 【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一样。 【4楼】 at90s 子非鱼:
你说对了,所以我在考虑是否将WR,RD的传递改成异步FIFO方式;
通过FIFO后就不会出现亚稳态情况了.总线数据都是稳定的,只要标志稍微延迟一点点就可以了;
我的主频54MHZ,希望总线交换频率到10MHZ左右.
因为我要尽快的把数据转到CPLD内部,有可能前级是一些物理总线(非模拟的,也可能是ARM),读写脉冲快了可能CPLD会丢数.
另外的通信里不允许有错误数据(现在错都在接口这里).
谢谢你的指点;
------------------------------------------
希望继续征集到其它大侠的方案技巧. 刚后仿真了写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. 反正我是这么干的,与133MHz主频的Power PC通信非常稳定的 不知道你的主时钟频率多高?如果有几十兆的话,就根本不需要考虑那几拍的延时了,一般MCU的读写周期都是比较长的 凡是异步时钟域之间的数据交换都是有可能出现亚稳态的,打2拍只是把出现亚稳态的几率降到很小而已。
本贴被 at90s 编辑过,最后修改时间:2009-01-02,00:02:56. 谢谢"【2楼】 at90s 子非鱼"大侠的指点...
有几个疑问啊.
就是:
1.这样等于多同步了几拍(2-3拍才输出flag信号,3-4拍别的程序才能知道flag的变化),肯定会影响MCU和CPLD的通信速率;
2.如果刚好mpu_wr_ok_flag在时钟沿变化,导致mpu_wr_ok_flag_buf中被采集到X值,那flang异或比较的时候会不会也变成X?
第二点我很快就可以验证一下,有什么在请教你了,再次谢谢. 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 时序仿真波形图:
http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_567865.GIF
(原文件名:wave.GIF)
从上到下依此为:
1.主时钟(上升沿触发)
2.WR
3.标志变化(主时钟程序通过检测它的变化来处理mpu_wr_data中的数据)
图上第一个时钟是正确的,后面程序可以检测到它的变化进行处理数据;
第二个始终后flag变成了X,后面仿真就全部失败了. 学习了!! 好东西,学习了 不错 请问,楼主这个东东是用在哪个上面的,数据交换误码率高吗?
怎样避免通讯错误啊?有什么措施! ARM并行总线和CPLD通讯,驱动TFT显示.
通过之前的方法误码率=0(或者小到我没法发现) 楼主能讲下你的具体思路吗?硬件连接图和程序中要注意的事项?谢谢! 都在这个贴里了啊?应该是很详细了,我不懂你为什么看了还没解决?
我就是听了"at90s 子非鱼"大侠的讲解然后接解决了啊,现在很稳定. 请问,楼主,你的是用了几根控制总线
我准备用
CS ---片选
RE-----读
WR-----写
data---数据(8)
addr---地址(8)
RE下降沿有效
WR上升沿有效
这样可以吗?
还有你用到全局复位和全局置位没> 1.边沿触发不行,行的话我就不发此贴了
2.没有用全局复置位 哦!我的意思是先边沿触发后,对RE/WR进行多次采样啊! 楼主你好!我现在想知道你对RE/WE的采样时钟!
我可以用我MCU的IO口变化速度的3倍去采样,这个办法可以吗? 谢谢了 MARK 学习 mark 记号 MARK 学习了 谢谢了 怎么上面的代码全变成 这乱七八糟的东西了?
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
mark mark
页:
[1]