FPGA学习篇——Verilog学习之计数器的实现

PS: 目前手上仍然没有板子,按照野火视频的讲解,目前我们只能做到前面六步(其实第一步设计规划也是需要看板子的硬件的,但是现在没有板子就完全与野火传授的板子一致来看)

1 设计规划及波形绘制

**任务要求:**设计一个计数器,使得FPGA中的LED等在点亮0.5s再熄灭0.5s(LED低电平有效),循环往复。

**思路:**利用系统时钟周期来设计计数器(设FPGA的时钟50MHz,即时钟一个周期20ns):

即一个sys_clk图像对应的时间是20ns,那么0.5s就需要 个周期, 设置一个中间计数变量cnt,计数时钟走过的周期数,当时钟 走过了25000个周期后,使得输出取反 从而控制LED的亮灭(注意,由于通常是从0开始计数的,那么要走25000000个周期,即计数cnt为0~24999999)

计数器原理及波形图:

  • sys_clk为系统时钟用于计数

  • sys_rst_n为复位信号,本实验这里没有很大用处,但时序逻辑一般都有复位信号

  • led_out为计数器的输出,直接连接到Led处

可以看到,当复位信号无效且时钟上升沿,cnt开始计数,直到24999999个周期时,计数器cnt清零,重新开始计数,Out控制led灯,低电平点亮高电平熄灭,每0~24999999(即0.5s)可以看到Out取反一次。

2 代码编写

复制代码
module Counter
#(
    parameter cnt_max = 25'd24999999
)
(
    input          sys_clk,
    input          sys_rst_n,
    
    output  reg    Out
);

reg  [24:0]  cnt;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt <= 25'b0;
    else if(cnt == cnt_max)
        cnt <= 25'b0;        
    else
        cnt <= cnt + 25'b1;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        Out <= 1'b0;
    else  if(cnt == cnt_max)
        Out <= ~Out;
   
endmodule
//    else if(cnt == cnt_max)
//        cnt <= 25'b0;

这里使用Quarters编译时出现了报错,以下代码编写方式会报错,详细见这一篇https://blog.csdn.net/weixin_72950851/article/details/146130167?spm=1001.2014.3001.5501

复制代码
always@(posedge sys_clk or negedge sys_rst_n)  // 敏感列表:仅时钟和复位
    if(sys_rst_n == 1'b0 || cnt == cnt_max)    // 条件判断:包含了 cnt 信号

3 逻辑仿真及波形验证

到了时序电路这,不像之前编写组合逻辑电路一般,一开始编写仿真文件时脑子有点空白,现在对仿真文件有了更深的理解。


编写仿真文件其实就相当于给你编写的模块模拟全部输入。

比如计数器我们进行波形图绘制时,输入就时钟信号clk和复位信号rst,因此我们在仿真文件中就要用代码去生成这两个输入信号:

(生成时钟信号)

(生成复位信号)

而此前组合逻辑,我们都是给模拟随机输入的情况,因此使用的是随机数,本质其实仿真文件还是去模拟所有的输入情况:

复制代码
`timescale 1ns/1ns
module tb_Counter();

reg     tb_sys_clk      ;
reg     tb_sys_rst_n    ;

wire    tb_Out          ;

initial begin
    tb_sys_clk      <= 1'b1;
    tb_sys_rst_n    <= 1'b0;
    #10
    tb_sys_rst_n    <= 1'b1;
 end
 
 
 always #10 tb_sys_clk <= ~tb_sys_clk;
 
 Counter 
 #(
    .cnt_max(25'd24999999)
 )Counter_inst(
    .sys_clk    (tb_sys_clk  ),
    .sys_rst_n  (tb_sys_rst_n),
              
    .Out        (tb_Out      )  
 );
 
 endmodule

注意,这里使用了参数parameter,在模块例化时要这样写:

++要例化的模块名++

#(

例化的参数

++给例化的模块重新命名++


. ++子模块的端口名++ ++对应要连接的顶层模块的端口名字++ ),

. ++子模块的端口名++ ++对应要连接的顶层模块的端口名字++ ),

...

);

其中,"."可理解为将两个端口连接的意思。

由于我们仿真的时间比较长,只取1s来看,在modelsim中可以看到,0.5s时输出实现了翻转:

同时,计数器也能够正常的计数,仿真验证通过。


(本贴仅是个人经验,参考哔哩哔野火视频: 16-第十三讲-计数器(二)_哔哩哔哩_bilibili如有侵权请联系我~)

相关推荐
A9better3 小时前
嵌入式开发学习日志37——stm32之USART
stm32·嵌入式硬件·学习
zhangrelay3 小时前
ROS云课三分钟-使用动态参数重配置调试Teb导航案例-251008
笔记·学习
生物小卡拉4 小时前
R脚本——Deseq2差异表达分析--v1.0
windows·经验分享·笔记·学习·信息可视化·数据分析
livana.4 小时前
小学scrach入门项目学习幸运大转盘项目
经验分享·学习·其他·scratch
Hy行者勇哥5 小时前
数据中台的数据源与数据处理流程
大数据·前端·人工智能·学习·个人开发
fat house cat_5 小时前
记一次网络io学习流水账
网络·学习
初圣魔门首席弟子6 小时前
C++ STL string(字符串)学习笔记
c++·笔记·学习
LGL6030A6 小时前
数据结构学习(2)——多功能链表的实现(C语言)
数据结构·学习·链表
iconball6 小时前
个人用云计算学习笔记 --18(NFS 服务器、iSCSI 服务器)
linux·运维·笔记·学习·云计算