搜索
bottom↓
回复: 17

请教: 输入信号为什么必须要时钟同步?

[复制链接]

出0入0汤圆

发表于 2016-3-22 11:56:46 | 显示全部楼层 |阅读模式

  1. module test1 ( input        nRST,
  2.              input        clk,
  3.              input        Ctrl,

  4.              output          Pulse,
  5.              output[3:0]   led );
  6.                                        

  7. reg[3:0]   cnt;
  8. reg[1:0]   state;

  9. /*---------------------------------*/
  10. //reg CTRL;       
  11.                                
  12. //always @( posedge clk )
  13. //        CTRL <= Ctrl;


  14. /*---------------------------------*/
  15. always @( posedge clk )
  16. begin
  17. if(!nRST )
  18.      begin
  19.      cnt <= 4'd0;
  20.      state <= 2'd0;
  21.      end
  22. else
  23.     case(state)
  24.         0:
  25.              if(Ctrl)        state <= 2'd1;        //这里用CTRL没有问题
  26.                        
  27.         1:               
  28.              if(cnt[3]==0)
  29.                 cnt <= cnt+4'd1;
  30.              else
  31.                 begin
  32.                 cnt <= 4'd0;
  33.                 state <= 2'd2;
  34.                       end
  35.         2:
  36.              if(cnt[3]==0)
  37.                 cnt <= cnt+4'd1;
  38.              else
  39.                 begin
  40.                 cnt <= 4'd0;
  41.                 state <= 2'd0;
  42.                 end
  43.                                
  44.         default:
  45.              state <= 2'd0;

  46.         endcase
  47. end

  48. assign    Pulse = ( state==2'd2);

  49. assign    led[3] = ~Ctrl;
  50. assign    led[2] = ~Pulse;
  51. assign    led[1:0] = 2'b11;

  52. endmodule
复制代码


上面代码用Ctrl控制产生脉冲,实际下载到板子不能工作,复位后如果Ctrl为高,可以输出脉冲,但只要切换Ctrl后,就再也不输出脉冲了。如果用时钟同步的CTRL(注释部分),则工作正常,不明白为什么?



阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2016-3-22 14:20:40 | 显示全部楼层
两次编译出来消耗的资源是一样的么?有可能被优化掉了。

出0入0汤圆

发表于 2016-3-22 18:14:02 | 显示全部楼层
这个就是亚稳态问题了吧亲。
外部来的信号,必须经过两次D触发器进行时钟同步之后,才能当作内部信号来用。
第一次经过D触发器时假如外部信号被采集为亚稳态信号(外部信号的电压 被采集为处于逻辑电平0和1之间,称为亚稳态),则输出是“不定态”,但是这个不定态是可以被当作“逻辑电平0和1”使用的。
就是第一个D触发器输出结果非0即1。
第二次经过D触发器,只是为了防止经过第一次D触发器之后,电平仍是“亚稳态”的这种意外情况。说白了第二个D触发器,只是为了防止意外,保险起见。

其实你可以理解,经过第一个D触发器是在把外部信号同步到内部。
还可以理解为 为了增强外部信号的驱动能力。

最主要的,是防止亚稳态情况出现。
涉及到外部信号输入时,一定要注意亚稳态情况!!

串口、SPI、IIC等等接收的信号,都是外部信号。。。
不知道说的对不对。。。互相交流





出200入657汤圆

发表于 2016-3-22 20:54:11 | 显示全部楼层
被编译器编译成什么东东了?
我觉得这个程序比较简单,可以到RTL层直接分析硬件实现
分析到底哪里出了问题

出0入0汤圆

 楼主| 发表于 2016-3-22 21:00:44 | 显示全部楼层
ziruo2002ab 发表于 2016-3-22 20:54
被编译器编译成什么东东了?
我觉得这个程序比较简单,可以到RTL层直接分析硬件实现
分析到底哪里出了问题 ...

其实编译没什么问题,比较了下,用同步过的外部信号仅仅只是多了个D触发器。而且我用仿真2个都是没问题的,后来想了下,仿真的时候用的是同一个时钟,所以外部信号实际上是同步的,也就是不能说明问题

出0入0汤圆

发表于 2016-3-22 22:39:08 来自手机 | 显示全部楼层
状态机你也敢用异步信号来推!!一个亚稳态就不知道进到哪个状态里死掉了。

出0入0汤圆

发表于 2016-3-22 23:16:47 | 显示全部楼层
WM_CH 发表于 2016-3-22 18:14
这个就是亚稳态问题了吧亲。
外部来的信号,必须经过两次D触发器进行时钟同步之后,才能当作内部信号来用。 ...

说的很在理一般情况用两个寄存器来将输入数据存储起来,这样使用的数据亚稳态几率小很多;你说的这个可以理解成用同步寄存器链来消除亚稳态问题

出0入0汤圆

发表于 2016-3-23 11:09:58 | 显示全部楼层
本帖最后由 jm2011 于 2016-3-23 11:23 编辑

我的看法:
1: 当你将Ctrl拉低,状态机一直在case 0,结果本来就是这样的,不知道你说的不再输出脉冲是什么意思,(是不是先拉低再拉高,这个时候依然不能输出脉冲?);当然在实际的使用上应该把异步信号打上两拍是最好的;
2:要是我做的话,我会将cnt抽出来,形成一个单独的always来做;不知道我这样想的对不对,有一个单独的计数器,输出一个信号到一个状态机,这个状态机会根据这个计数器的信号来判断自己的 状态;我觉的这样更像一个硬件结构,如下图所示:

对于第二点,需要得到大家的意见,相互学习,相互提高:)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-3-23 11:22:16 | 显示全部楼层
jm2011 发表于 2016-3-23 11:09
我的看法:
1: 当你将Ctrl拉低,状态机一直在case 0,结果本来就是这样的,不知道你说的不再输出脉冲是什 ...

一般来说,写状态机要控制流和数据流分开,就是说状态跳转时就不要给数据流赋值,数据流根据状态在另外一个always中,这样写清晰。

出0入0汤圆

发表于 2016-3-23 11:25:35 | 显示全部楼层
far_infrared 发表于 2016-3-23 11:22
一般来说,写状态机要控制流和数据流分开,就是说状态跳转时就不要给数据流赋值,数据流根据状态在另外一 ...

控制流的产生一个always,数据流的产生一个always,状态转移一个always;这个是不是就是所谓的三段式的写法?

出0入0汤圆

发表于 2016-3-23 11:36:34 | 显示全部楼层
jm2011 发表于 2016-3-23 11:25
控制流的产生一个always,数据流的产生一个always,状态转移一个always;这个是不是就是所谓的三段式的写 ...

对,我比较喜欢这样用,看着简洁,调试也方便。

出0入0汤圆

发表于 2016-3-23 11:37:34 | 显示全部楼层
far_infrared 发表于 2016-3-23 11:36
对,我比较喜欢这样用,看着简洁,调试也方便。

这次真的是学习了 ,让你这样一说,我也清晰了好多;

以前一直不知道为什么要三段式的;

出0入0汤圆

发表于 2016-3-23 11:40:06 | 显示全部楼层
跨时钟域的问题,这是很常见的

出0入0汤圆

 楼主| 发表于 2016-3-23 15:08:41 | 显示全部楼层
far_infrared 发表于 2016-3-23 11:22
一般来说,写状态机要控制流和数据流分开,就是说状态跳转时就不要给数据流赋值,数据流根据状态在另外一 ...

谢谢,受益匪浅

出0入0汤圆

 楼主| 发表于 2016-3-23 15:09:50 | 显示全部楼层
jm2011 发表于 2016-3-23 11:09
我的看法:
1: 当你将Ctrl拉低,状态机一直在case 0,结果本来就是这样的,不知道你说的不再输出脉冲是什 ...

先拉低再拉高,这个时候依然不能输出脉冲。谢谢,受益匪浅

出0入0汤圆

发表于 2016-3-23 22:50:06 | 显示全部楼层
xyzabc 发表于 2016-3-23 15:09
先拉低再拉高,这个时候依然不能输出脉冲。谢谢,受益匪浅

明天去单位跑一下板子去,抓一下波形看看 。。。。

感觉这个问题很奇怪。

出0入0汤圆

发表于 2016-3-24 09:43:08 | 显示全部楼层
本帖最后由 jm2011 于 2016-3-24 09:46 编辑

在DE0-NANO的板子上实测了一下,没有发现楼主说的问题,Crtl来回的切换都能看见LED的闪烁;

我的时钟比较高,只修改了计数器的范围,其它的和楼主的一样;个人认为这个简单的电路,对Ctrl打不打一排不会影响状态机的运行;

我现在主要不理解的是,1:如果Ctrl第一次是亚稳态的时候状态机会跑到那里去,2:如果Ctrl从亚稳态恢复到稳态,这个状态机还能不能继续跑下去?

javascript:;

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2016-3-24 11:43:31 | 显示全部楼层
jm2011 发表于 2016-3-24 09:43
在DE0-NANO的板子上实测了一下,没有发现楼主说的问题,Crtl来回的切换都能看见LED的闪烁;

我的时钟比较 ...


谢谢你的热心,我用的芯片是EPM240,之前试过很多次,刚才又试了下,确实不行。但按照你说的将cnt独立出来改成下面的代码,确实可以


  1. module   test( input  nRST,
  2.                      input  clk,
  3.                      input  Ctrl,

  4.                      output  Pulse,
  5.                      output[3:0]  led );
  6.                
  7. reg[24:0] cnt;
  8. reg[1:0] state;
  9. reg cntRst;

  10. wire cntEnd;

  11. /*------------------------------------*/
  12. always @( posedge clk )
  13. begin
  14. if( !nRST || cntRst )
  15.     cnt <= 25'd0;
  16. else
  17.     cnt <= cnt+25'd1;
  18. end
  19.        

  20. /*------------------------------------*/
  21. always @( state )
  22. begin
  23.     case(state)
  24.           0,2:
  25.                   cntRst = 1;
  26.           1,3:
  27.                   cntRst = 0;
  28.     endcase
  29. end


  30. /*------------------------------------*/
  31. always @( posedge clk )
  32. begin
  33. if(!nRST )
  34.     state <= 2'd0;
  35. else
  36.     case(state)
  37.            0:
  38.               if(Ctrl)    state <= 2'd1;
  39.           1:               
  40.              if(cntEnd)    state <= 2'd2;
  41.           2:               
  42.              state <= 2'd3;
  43.          3:
  44.             if(cntEnd)    state <= 2'd0;
  45.     endcase
  46. end

  47. assign cntEnd = cnt[24];
  48. assign Pulse = ( state[1]==1'b1);

  49. assign led[3] = ~Ctrl;
  50. assign led[2] = ~Pulse;
  51. assign led[1:0] = 2'b11;


  52. endmodule
复制代码

回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-13 10:30

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表