二、11【FPGA】时序逻辑电路——计数器

前言

学习说明此文档为本人的学习笔记,注重实践,关于理论部分会给出相应的学习链接。

学习视频:是根据野火FPGA视频教程——第十三讲
https://www.bilibili.com/video/BV1nQ4y1Z7zN?p=3

理论学习

计数器在数字系统中主要是对脉冲的个数进行技术,实现测量、计数、控制及分频功能。控制器中的指令地址,运算器做乘法、除法。

基础知识请参考本人《数字电路技术基础》计数器部分:

《数字电子技术基础》6.3 时序逻辑电路——寄存器、计数器及脉冲发生器功能介绍_追逐者-桥的博客-CSDN博客寄存器和移位寄存器、计数器功能介绍https://blog.csdn.net/ARM_qiao/article/details/124415549

实战演练

一、设计规划

1.1 实验目标

让计数器计数1s时间间隔,来实现LED灯每隔1s闪烁一次

1.2 硬件资源

二、程序设计

2.1 模块框图及波形图  

2.2 代码编写

//
// Company: 追逐者——桥的小作坊
// Create Date: 2022/05/05 20:35:58
// Module Name: counter
// Tool Versions: Vivado 2018_3
// Description: 
// Revision 0.01 - File Created
// Additional Comments:FPGA学习代码
//
module counter
#(
parameter  COUNT_MAX = 25'd24_999_999          //作为模块的一个参数,再实例化时可修改
)              
    (
    output reg led_out ,
    input  wire sys_clk, sys_rst_n
    );
//    parameter  COUNT = 25'd24_999_999;    //可用于模块名后,再实例化时可修改
//    localparam COUNT = 25'd24_999_999;    //只能用于模块内部使用
    reg [24:0] count;
    always @(posedge sys_clk or negedge sys_rst_n)
        if(sys_rst_n == 1'b0)
            count <= 25'd0;
        else if(count == COUNT_MAX)
            count <= 25'd0;
        else 
            count <= count + 25'd1;
    always @(posedge sys_clk or negedge sys_rst_n)
        if(sys_rst_n == 1'b0)
            led_out <= 1'b0;
        else if(count == COUNT_MAX)
            led_out <= ~led_out;
        else
            led_out <= led_out;
endmodule

如果计数器结束,不只触发LED灯闪烁,而且还会触发其他输出。当多的时候不如向声明一个常数变量一样,生成一个触发标志,使用标志进行功能的触发,这样在更改调试触发条件时只需要更改标志即可,不需要每个功能的触发都改。

//count_flag:计数到最大值产生标志信号,每当计数满标志信号有效时取反
reg count_flag;
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        count <= 25'd0;
    else if(count == OUNT_MAX - 25'd1) 
        count_flag <= 1'b1;
    else
        count_flag <= 1'b0;
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        led_out <= 1'b0;
    else if(count_flag == 1'b1)
        led_out <= ~led_out;
    else
        led_out <= led_out;

综合后的RTL视图,可以右键点击视图,查看对应的代码。

三、逻辑仿真

3.1 仿真文件的编写

`timescale 1ns / 1ns
//
// Company: 追逐者——桥的小作坊
// Create Date: 2022/05/05 20:35:58
// Module Name: counter
// Tool Versions: Vivado 2018_3
// Description: 
// Revision 0.01 - File Created
// Additional Comments:FPGA学习代码
//
module tb_counter();
    reg SYS_CLK, 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 
    #(
      .COUNT_MAX (25'd15)         //作为模块的一个参数,再实例化时可修改
    ) 
    count_inst
    (
    .led_out( LED_OUT ),
    .sys_clk( SYS_CLK ), 
    .sys_rst_n(SYS_RST_N)
    );   
endmodule

3.2 仿真波形图对比

 对比上面波形图,虽然源代码是0.5s变换一次电平,但是由于仿真代码中设置的最大计数是15,因此再15后,计数器下一个状态变为0,同时改变输出电平。

四、上板验证

4.1 管脚绑定

界面绑定

Ctrl+s保存成XDC文件

编写绑定程序

set_property IOSTANDARD LVCMOS33 [get_ports led_out]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_rst_n]
set_property PACKAGE_PIN M21 [get_ports led_out]
set_property PACKAGE_PIN W19 [get_ports sys_clk]
set_property PACKAGE_PIN N15 [get_ports sys_rst_n]

综上所述,目前个人感觉还是界面绑定比较方便。

管脚绑定后硬件的连线图:

五、总结 

新语法总结
重点掌握
1 paramter 的用法 (出现在模块内部的局部定义)
知识点总结
1 、能够通过自己慢慢的分析绘制出时序逻辑电路的波形;
2 、学会根据计数器的计数时钟来精确计算我们要想计数的时间和个数,熟练的控制计数
器;
3 、能够了解 flag 脉冲标志信号的意义,如何精确产生,以及应用场景;
4 、学会分析简单时序逻辑的 RTL 视图,理解设计的 RTL 代码就是硬件的思想。
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐者-桥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值