zoukankan      html  css  js  c++  java
  • 计数器(3):避免多计少计

      计数器,FPGA设计中最常用的设计,然而有些地方需要多加注意。

    一、勿要多计

      打算计10下,所以我计数器就写计到10:cnt==10,程序如下所示。

    1、设计文件

     1 module jsq
     2 //========================< 端口 >==========================================
     3 (
     4 input   wire                clk                 ,
     5 input   wire                rst_n               ,
     6 input   wire                en                  ,
     7 output  reg   [ 4:0]        cnt                 
     8 );
     9 //========================< 信号 >==========================================
    10 reg                         en_flag             ;
    11 wire                        add_cnt             ;
    12 wire                        end_cnt             ;
    13 
    14 //========================< 程序 >==========================================
    15 always @(posedge clk or negedge rst_n) begin
    16     if(!rst_n) begin
    17         en_flag <= 0;
    18     end
    19     else if(en) begin
    20         en_flag <= 1;
    21     end
    22     else if(end_cnt) begin
    23         en_flag <= 0;
    24     end
    25 end
    26 
    27 always @(posedge clk or negedge rst_n) begin
    28     if(!rst_n)
    29         cnt <= 0;
    30     else if(add_cnt) begin
    31         if(end_cnt)
    32             cnt <= 0;
    33         else
    34             cnt <= cnt + 1;
    35     end
    36 end
    37 
    38 assign add_cnt = en_flag;
    39 assign end_cnt = add_cnt && cnt== 10; //我想计10下
    40 
    41 
    42 
    43 endmodule

    2、仿真文件

     1 `timescale 1ns/1ps  //时间精度
     2 `define    Clock 20 //时钟周期
     3 
     4 module jsq_tb;
     5 
     6 //========================< 端口 >==========================================
     7 reg                         clk                 ; //时钟,50Mhz
     8 reg                         rst_n               ; //复位,低电平有效
     9 reg                         en                  ;
    10 wire  [ 4:0]                cnt                 ;
    11 
    12 //==========================================================================
    13 //==    模块例化
    14 //==========================================================================
    15 jsq u_jsq
    16 (
    17     .clk                    (clk                ),
    18     .rst_n                  (rst_n              ),
    19     .en                     (en                 ),
    20     .cnt                    (cnt                )
    21 );
    22 
    23 //==========================================================================
    24 //==    时钟信号和复位信号
    25 //==========================================================================
    26 initial begin
    27     clk = 1;
    28     forever
    29         #(`Clock/2) clk = ~clk;
    30 end
    31 
    32 initial begin
    33     rst_n = 0; #(`Clock*20+1);
    34     rst_n = 1;
    35 end
    36 
    37 //==========================================================================
    38 //==    设计输入信号
    39 //==========================================================================
    40 initial begin
    41     en = 0;
    42     #(`Clock*20+1); //初始化完成
    43     en = 1;
    44     #(`Clock*10);
    45     en = 0;
    46     #(`Clock*100);
    47     $stop;
    48 end
    49 
    50 
    51 
    52 endmodule

    3、Modelsim仿真图像

      观察图像可以看到,计数器 cnt 计到了 cnt==10 这里,可是当我仔细数数时却发现,计数是从 0 开始计的,从 0 到 10,所以实际计了 11 下!和我之前写代码时脑中所想不一致!所以,如果只想计10下,那实际写代码应该写 9 才对。

      总结:计数器想计 n 下,那写代码只能写 cnt==n-1。

    二、勿要少记

      数据 data 和数据使能 data_en 同时来,我想数一下到底来了多少个数据。

    1、代码设计

     1 module jsq
     2 (
     3 input   wire                clk                 ,
     4 input   wire                rst_n               ,
     5 input   wire  [ 3:0]        data                ,
     6 input   wire                data_en             ,
     7 output  reg   [ 3:0]        cnt                 
     8 );
     9 
    10 always @(posedge clk or negedge rst_n) begin
    11     if(!rst_n) begin
    12         cnt <= 0;
    13     end
    14     else if(data_en) begin
    15         cnt <= cnt + 1;
    16     end
    17     else begin
    18         cnt <= 0;
    19     end
    20 end
    21 
    22 
    23 endmodule

    2、仿真设计

     1 `timescale 1ns/1ps  //时间精度
     2 `define    Clock 20 //时钟周期
     3 
     4 module jsq_tb;
     5 
     6 //========================< 端口 >==========================================
     7 reg                         clk                 ; //时钟,50Mhz
     8 reg                         rst_n               ; //复位,低电平有效
     9 reg   [ 3:0]                data                ;
    10 reg                         data_en             ;
    11 wire  [ 4:0]                cnt                 ;
    12 
    13 //==========================================================================
    14 //==    模块例化
    15 //==========================================================================
    16 jsq u_jsq
    17 (
    18     .clk                    (clk                ),
    19     .rst_n                  (rst_n              ),
    20     .data                   (data               ),
    21     .data_en                (data_en            ),
    22     .cnt                    (cnt                )
    23 );
    24 
    25 //==========================================================================
    26 //==    时钟信号和复位信号
    27 //==========================================================================
    28 initial begin
    29     clk = 1;
    30     forever
    31         #(`Clock/2) clk = ~clk;
    32 end
    33 
    34 initial begin
    35     rst_n = 0; #(`Clock*20+1);
    36     rst_n = 1;
    37 end
    38 
    39 //==========================================================================
    40 //==    设计输入信号
    41 //==========================================================================
    42 initial begin
    43     data_en = 0;
    44     data = 0;
    45     #(`Clock*20+1); //初始化完成
    46     
    47     data_en = 1;
    48     data = 0;
    49     #(`Clock);
    50     data = 1;
    51     #(`Clock);
    52     data = 2;
    53     #(`Clock);
    54     data = 3;
    55     #(`Clock);
    56     data = 4;
    57     #(`Clock);
    58     data = 5;
    59     #(`Clock);
    60     data = 6;
    61     #(`Clock);
    62     data = 7;
    63     #(`Clock);
    64     data = 8;
    65     #(`Clock);
    66     data = 9;
    67     #(`Clock);
    68     data = 0;
    69     data_en = 0;
    70     
    71     #(`Clock*100);
    72     $stop;
    73 end
    74 
    75 
    76 
    77 endmodule

    3、Modelsim仿真图像

      观察图像可以看到,计数器 cnt 计到了 cnt==10 这里,而我的 data_en 确实是维持了 10 个周期的。这种情况下,cnt 计到多少就是多少,第0下是不作数的。如果按照上面的情况,以为真实计数是 10-1=9下,反而是错的了。当然如果其他信号需要用到 cnt来搞事情,那还是需要写 cnt==n-1的,这就又回到上面第一种情况了。

      此外 cnt 较 data_en 延后了一个周期,当 data_en 都拉低了,而后 cnt 才计到 cnt==10,这是时序逻辑的特点,并非出错。

      总结:计数器计算一段波形的持续时间,最终即到 cnt==n,那波形时间就是n,不需要 -1。

  • 相关阅读:
    centos 安装 redis3.2.0 集群
    CentOS7安装配置redis-3.0.0
    CentOS7/RHEL7安装Redis步骤详解
    鸟哥之安裝 CentOS7.x
    Centos 7 学习之静态IP设置
    CentOS7 下linux不能上网解决方法​,centos7 eth0 没有ip,IP突然丢失
    javamail发送邮件(转)
    Apache James使用的方法及相关心得(转)
    Velocity缓存与穿透(转)
    十分钟搞懂什么是CGI(转)
  • 原文地址:https://www.cnblogs.com/xianyufpga/p/10809456.html
Copyright © 2011-2022 走看看