忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 视频 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
1234下一页
最近访问板块 发新帖
查看: 19018 | 回复: 32

[数字设计]抓外部信号的沿 [复制链接]

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-19 23:18 |显示全部楼层
以下用verilog描述,且只考虑信号上升沿,而下沿同理。
假设外部信号为sig,我们首先想到的会是
always@(posedge sig)
   ...
似乎没什么错,但这有很多的问题:
第一点,外部信号可能会有很多的毛刺,并非真正的上沿;
第二点,如此设计导致触发器所用时钟彼此不一致,特别对于像fpga之类的东西,综合虽然可以,但并不好。
其中,第一点是致命的。

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-19 23:18 |显示全部楼层
于是怎么办呢?我们还是要用到系统时钟,缓存一道试下,在上沿处生成单脉宽的一个信号。
module catch_posedge(rst,clk,sig_posedge,sig);
input rst,clk,sig;
output  sig_posedge;
reg sig_reg;
always@(posedge rst or posedge clk)
if(rst)
       sig_reg<=1'b1;
else
       sig_reg<=sig;
assign sig_posedge = !sig_reg & sig;
endmodule

似乎看起来很好了,但其实也只是五十笑百,利用一个外部可能有毛刺的信号来作为组合输出,很危险,出现真正意思上的上沿(并非毛刺)的时候,其附近如果有毛刺,那么就有抓不到的危险。

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-19 23:22 |显示全部楼层
全部用内部寄存器来组合输出应该是比较好的选择。
module catch_posedge(rst,clk,sig_posedge,sig);
input rst,clk,sig;
output  sig_posedge;
reg sig_reg,sig_reg2;
always@(posedge rst or posedge clk)
if(rst)
       {sig_reg,sig_reg2}<=2'b11;
else
       {sig_reg,sig_reg2}<={sig,sig_reg};
/*以上写法我多少有点偷工减料,不推荐这么写,还是分开写比较好,好的代码习惯是需要的*/
assign sig_posedge = !sig_reg2 & sig_reg;
endmodule

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-19 23:25 |显示全部楼层
本帖最后由 cjaizss 于 2010-10-21 13:16 编辑

然后,再滤去一次低电平下的毛刺:
module catch_posedge(rst,clk,sig_posedge,sig);
input rst,clk,sig;
output  sig_posedge;
reg [2:0]sig_reg;
always@(posedge rst or posedge clk)
if(rst)
       sig_reg[2:0]<=3'b111;
else
       sig_reg[2:0]<={sig_reg[1:0],sig};
assign sig_posedge = sig_reg==3'b011;
endmodule
基本成了

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-19 23:33 |显示全部楼层
至于“用一个外部可能有毛刺的信号来作为组合输出,很危险”这一点,请相信我,我有过惨痛的教训。

论坛徽章:
0
发表于 2010-10-20 09:01 |显示全部楼层
lz 牛,这样在实际工作中的体会很有实际意义,远比一些纸上谈兵有实际意义.

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-20 09:18 |显示全部楼层
对于其原因,我的电脑截图不知为什么出了问题,所以无法截图了.有兴趣的用modelsim仿真一下以下的电路,仔细对照一下波形图,再想想或许就明白了.

  1. `timescale 1ns/1ps
  2. module reset_module_test(
  3.                                 gpio,
  4.                                 clk,
  5.                                 rst,
  6.                                 io_out
  7.     );
  8. input gpio,clk,rst;
  9. output io_out;

  10. parameter REG_WILDTH=6;


  11. reg io_out;
  12. reg [REG_WILDTH-1:0]gpio_reg;
  13. wire negedge_gpio, posedge_gpio;


  14. assign negedge_gpio = (&(gpio_reg[REG_WILDTH-1:REG_WILDTH/2])) & (!(|(gpio_reg[REG_WILDTH/2-1:0])));
  15. assign posedge_gpio = (!(|(gpio_reg[REG_WILDTH-1:REG_WILDTH/2]))) &  (&(gpio_reg[REG_WILDTH/2-1:0]));


  16. always@(posedge rst or posedge clk)
  17. if(rst)
  18.   gpio_reg <= 0;
  19. else
  20.         gpio_reg <= {gpio_reg[REG_WILDTH-2:0], gpio};
  21.        
  22. always@(posedge rst or posedge clk)
  23. if(rst)
  24.   io_out <= 1'b0;
  25. else
  26.   begin
  27.         if(negedge_gpio)
  28.                 io_out <= 1'b0;
  29.         else if(posedge_gpio)
  30.                 io_out <= 1'b1;
  31.   end

  32. endmodule


  33. module testbench
  34.   ();
  35.   reg clk,gpio,rst;
  36.   wire io_out;
  37.   reset_module_test reset_module_inst(
  38.                                 gpio,
  39.                                 clk,
  40.                                 rst,
  41.                                 io_out
  42.     );
  43.     initial
  44.     forever
  45.     begin
  46.     clk=0;
  47.     #2.5;
  48.     clk=1;
  49.     #2.5;
  50.     end
  51.    
  52.     initial
  53.       begin
  54.         rst=0;
  55.         #7;
  56.         rst=1;
  57.         #20;
  58.         rst=0;
  59.       end
  60.       
  61.     initial
  62.       begin
  63.         gpio = 1;
  64.         #1000;
  65.         gpio=0;
  66.         #100;
  67.         gpio=1;
  68.         #2000;
  69.         gpio=0;
  70.         #99;
  71.         gpio=1;
  72.         #4000;
  73.         gpio=0;
  74.         #12;
  75.         gpio=1;
  76.         #4000;
  77.         gpio=0;
  78.         #5;
  79.         gpio=1;
  80.         #2;
  81.         gpio=0;
  82.         #7;
  83.         gpio=1;
  84.         #6;
  85.         gpio=0;
  86.         #197;
  87.         gpio=1;
  88.         #5000;
  89.         $display("OK!");
  90.         $stop();
  91.         end
  92. endmodule

复制代码

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-20 09:19 |显示全部楼层
lz 牛,这样在实际工作中的体会很有实际意义,远比一些纸上谈兵有实际意义.
system888net 发表于 2010-10-20 09:01



    这不是牛不牛的问题,这是常识,可是初学者却不一定有这样的常识.

论坛徽章:
0
发表于 2010-10-20 10:44 |显示全部楼层
这不是牛不牛的问题,这是常识,可是初学者却不一定有这样的常识.
cjaizss 发表于 2010-10-20 09:19



    问题解决的方法没有掌握之前就是实际问题,掌握之后就是常识了,在解决问题的过程所花的代价(时间,金钱)等就构成了解决问题的成本,能有效地解决问题的方法就是好方法,至于这个方法是高深的还是属于常识的,这属于各个人的主观评价了,但不论大家如何评价,不能否认的是解决了实际问题的这个客观结果.
   
   因此善于解决问题的人和能有效解决问题的方法就是牛!

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
发表于 2010-10-21 12:29 |显示全部楼层
对于其原因,我的电脑截图不知为什么出了问题,所以无法截图了.有兴趣的用modelsim仿真一下以下的电路,仔细对 ...
cjaizss 发表于 2010-10-20 09:18



    解决这个问题似乎就有点麻烦了,这是信号干扰很大的情况了。
  但方法还是一样存在:我们只辨别缓存为全1的时候认定为高电平,全0认定低电平。

  1.   `timescale 1ns/1ps

  2. module reset_module_test(

  3.                                 gpio,

  4.                                 clk,

  5.                                 rst,

  6.                                 io_out

  7.     );

  8. input gpio,clk,rst;

  9. output io_out;



  10. parameter REG_WILDTH=6;

  11. reg io_out;

  12. reg [REG_WILDTH-1:0]gpio_reg;

  13. wire negedge_gpio, posedge_gpio;
  14. always@(posedge rst or posedge clk)
  15.      if(rst)
  16.              io_out <= 1'b0;
  17.      else if(&gpio_reg)
  18.              io_out <= 1'b1;
  19.      else if(!(|gpio_reg))
  20.              io_out <= 1'b0;
  21. endmodule
  22.    
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP