FPGA-计数器的实现

  • 计数器是依托时钟实现的,在时钟沿(一般在上升沿)进行检测,实现计数加1;
  • 计数是从0开始计数的,所以计数值为(M-1),其中M为计数的值。比如计数到10,我们实现时到9即可;
  • 这里为计数器的第一种实现方法,该方法非最优方法,我们只需要了解即可,后续我们会介绍另一种方法,可以将两种方案作对比学习。
  • 实验:
    • 依托板子上的LED灯为例进行讲解,RTL代码都是一样的,针对具体的开发板只需要进行引脚的配置,注意时钟晶振的差别。
    • 实验要求:LED灯亮0.5s,灭0.5s,循环操作。
  • 波形绘制
  • RTL代码
    //计数器 
    
    module counter
    #(
    parameter CNT_MAX = 25'd24_999_999//可以作为实例化中参数传递的接口
    )
    (
        input wire Sys_Clk,
        input wire Sys_Rst_n,
        
        output reg Led_out
    );
    
    //参数定义
    //parameter既可以使用在模块内部,还可以写在模块的开始
    //parameter CNT_MAX = 25'd24_999_999; //0.5秒的计时需要的时钟周期个数(时钟从0开始计数)
    //localparam CNT_MAX = 25'd24_999_999;//只能使用在模块内部
    
    reg [24:0] Cnt;
    
    always@(posedge Sys_Clk or negedge Sys_Rst_n)
        if(Sys_Rst_n == 1'b0)
                Cnt <= 25'd0;
        else if(Cnt == CNT_MAX)
                Cnt <= 25'd0;
        else
           Cnt <= Cnt +25'd1; 
        
    always@(posedge Sys_Clk or negedge Sys_Rst_n)
        if(Sys_Rst_n == 1'b0)
            Led_out <= 1'b0;
        else if(Cnt == CNT_MAX)
            Led_out <= ~Led_out;
        else
            Led_out <= Led_out;
    
    /* module Counter
    #(
        .CNT_MAX(100),//具体这里传进去的为准,原来的和默认参数类似
    )
    (
        .Sys_Clk    (Sys_Clk),
        .Sys_Rst_n  (Sys_Rst_n),
        .Led_out    (Led_out)
    ); */
    
    endmodule
  • 仿真代码
    `timescale 1ns / 1ns
    
    module counter_tb();
    
    
    reg sys_clk;
    reg sys_rst_n;
    
    wire led_out;
    
    initial
        begin
            sys_clk <= 1'b1;
            sys_rst_n <= 1'b0;
            #20
            sys_rst_n <= 1'b1;
        end
    always #10 sys_clk = ~sys_clk;
    
    counter 
    #(
        .CNT_MAX(25'd24)//可以作为实例化中参数传递的接口
    )
    counter_inst //注意这里的实例化模块名放在parameter参数后面写
    (
        .Sys_Clk    (sys_clk),
        .Sys_Rst_n  (sys_rst_n),
                    
        .Led_out    (led_out)
    );
    
    endmodule

---------------------------------------------------------------------------------------------------------------------------------

  •  第二种方法实现计数器(推荐使用)
    • 绘制波形
    • RTL代码
      //计数器 
      
      module counter
      #(
      parameter CNT_MAX = 25'd24_999_999//可以作为实例化中参数传递的接口
      )
      (
          input wire Sys_Clk,
          input wire Sys_Rst_n,
          
          output reg Led_out
      );
      
      //参数定义
      //parameter既可以使用在模块内部,还可以写在模块的开始
      //parameter CNT_MAX = 25'd24_999_999; //0.5秒的计时需要的时钟周期个数(时钟从0开始计数)
      //localparam CNT_MAX = 25'd24_999_999;//只能使用在模块内部
      
      reg [24:0] Cnt;
      reg cnt_flag;
      
      always@(posedge Sys_Clk or negedge Sys_Rst_n)
          if(Sys_Rst_n == 1'b0)
                  Cnt <= 25'd0;
          else if(Cnt == CNT_MAX)
                  Cnt <= 25'd0;
          else
             Cnt <= Cnt +25'd1; 
      	   
      always@(posedge Sys_Clk or negedge Sys_Rst_n)
      	if(!Sys_Rst_n)
      		cnt_flag <= 1'b0;
      	else if(cnt == (CNT_MAX - 25'd1))
      		cnt_flag <= 1'b1;
      	else
      		cnt_flag < 1'b0;
          
      always@(posedge Sys_Clk or negedge Sys_Rst_n)
          if(Sys_Rst_n == 1'b0)
              Led_out <= 1'b0;
          else if(cnt_flag == 1'b1)
              Led_out <= ~Led_out;
          else
              Led_out <= Led_out;
      
      /* module Counter
      #(
          .CNT_MAX(100),//具体这里传进去的为准,原来的和默认参数类似
      )
      (
          .Sys_Clk    (Sys_Clk),
          .Sys_Rst_n  (Sys_Rst_n),
          .Led_out    (Led_out)
      ); */
      
      endmodule
    • RTL仿真代码同第一种方法。
    • Modsim仿真波形
  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值