微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 求助:一个简单的verilog程序,有点小问题~

求助:一个简单的verilog程序,有点小问题~

时间:10-02 整理:3721RD 点击:
clk_50M 为50MHz
问题如下:我的目标是count7计数到600031时,让clear置1,然后马上让count6为33,为什么count6把33计数了两次
见下图的仿真波形!
仿真波形最下面两路脉冲分别为count6、count7
initial begin count6=0;end
//-----------------------------SP频率1MHz   高电平100ns  低电平 900ns -------------------------------------
output reg [19:0] count7;
reg clear;
always @(negedge clk_50M or negedge rst_n)
  begin   
      if(!rst_n)
         begin
                      count7 =0 && count6 =33 && count6 =38 && count6 =83 && count6 =88 && count6 =283 && count6 =288 && count6 =33 && count6<38)          begin
              SP <= 1'b1;
              count6 <= count6 + 1'b1;
          end
还有待解决!除此之外,为何count6=38时,SP也是高电平
仿真波形如下图所示!


我给你解释下,为你第一个例子里,count6 会计2次33。
1、看你第一个count7和clear的always敏感列表,时钟采样是negedge,那么在clk_50m的下降沿,如果count7等于600031,将看到clear为1,我们看到确实如此,clear为1,持续一个时钟周期,而且从该下降沿持续到下一个下降沿。
2、看count6的always敏感列表,时钟采样是negedge,而一个异步信号clear却是posedge,那么,神奇的一幕就出现了,上面我们说当count7为600031的时候,clear从0变1了,此时clear就是一个posedge,触发了count6的always,那么进入always判断后执行第一条if语句,直接把count6变成33了(看清楚,count66第一次变33是在clear的上升沿,不是clk的下降沿哦!),随后,clk_50M的下降沿来了,此时也进入always,此时clear还是为1(根据count7的negedge变化,clear会在当前clk_50m时钟后,才变0),那么还是会进入第一条if,所以count66又是33了,这样,你就看到count6维持33的时间,是2个clk_50m周期。
其实是一个bug导致的巧合而已,不是clk_50M导致了count6维持了2个时钟周期,再说一遍,第一次count6变成33,是在clear为1的时候,异步触发always,导致第二次是clk_50M下降沿时候触发always,判断clear依然为1,所以count6依然保持33。

给你的建议,如果把always当做时序电路用,请别用自己生成的信号放入always列表,最好只放统一的clk和rst信号,免得出现这些尴尬的bug。
其它信号,比如clear,当做使能信号,比如你在第一个列子里,把count7 == 600030时,让clear =1,这样clear就会在count7 == 600031时为1,然后在count6的always里,把clear作为使能,当clear为1时,count6 = 33,这样就不会出现“两次33”了。

always (negedge clk_50m or negedge rst_n)
begin
......
else if(count7 == 600030)
       clear = 1;
else
       clear = 0;
......
end
always (negedge clk_50m or negedge rst_n)
begin
......
else if(clear == 1)
       count6 = 33;
......
end

确实count6计数器为什么计数2次33不怎么明白,自己感觉对基本的语法只是大致了解了,对一些细枝末节的感觉就是不清不楚,还需要多学习学习,认真琢磨一下;先按照你说的来调试一下看看!谢谢你的建议哈!

只是给了个大概意思。
呃,只要把你的改后的改一下,因为那样clear持续了两个周期,我们只要一个周期就够了,
就是在count7 == 60031那个周期。
而且做同步设计要每一级流水线都是对前个数据做处理,而不是一个数据变,就全部变,那是异步了。
所以SP是总会比count6慢一个时钟周期的。
你看看这样行不行!
else if(count7==20'd600030)   
   begin  
        clear <= 1'b1;
        count7 <= count7 +1;
    end
else if(count7==20'd600031)
    begin
        count7 <= 1'b0;
        clear <= 0;
    end

说一下习惯,我基本不是判断条件太复杂的话,基本都是一个reg变量一个always块,看起来比较清楚,
知道某个条件达成后下个clk有效沿才会触发!

谢谢你的答复,问题已经全部解决了~

没事,谁都是一步一步来的,FPGA其实是个被限制得比较死的硬件,你用C语言能随便写程序,但用verilog,只能写FPGA可以综合的语句,并不是大家想象中的那么自由,你做设计,按照FPGA器件本身的规则来,是最好的,如果你硬要天马行空,什么设计思路都往上放,最后设计出的东西反而不能发挥FPGA本身性能,而且容易导致bug,所以要多积累行业经验,等你看过的代码多了,自己自然知道该怎么去写。

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

网站地图

Top