【IC设计】Verilog线性序列机点灯案例(二)(小梅哥课程)

news2024/11/26 2:47:47

文章目录

  • 该系列目录:
  • 设计目标
  • 设计思路
  • RTL 及 Testbench
  • 仿真结果
  • 存在的问题?
  • 改善后的代码
    • RTL代码
    • testbench代码
  • 仿真结果

案例和代码来自小梅哥课程,本人仅对知识点做做笔记,如有学习需要请支持官方正版。

该系列目录:

Verilog线性序列机点灯案例(一)

设计目标

我们的FPGA的时钟频率为50MHz,即每个周期20ns。
因此,在该时钟下时间和周期数的对应关系为:

持续时间对应周期数
0.25s12,500,000 cycles
0.5s25,000,000 cycles
0.75s37,500,000 cycles
1s50,000,000 cycles

我们的目标是让LED以**【亮0.25秒->灭0.5秒->亮0.75秒->灭1秒】**的规律,持续循环闪烁。

设计思路

在这里插入图片描述
为了完成这样的规律性闪烁,需要一个计数器,计数满2.5秒归零,即:当上升沿采样到125,000,000-1时,计数器归零。
然后,led灯根据当前计数器的数值,设置led的亮灭,图中已经标注了led跳变时的counter数值。下面直接上代码

RTL 及 Testbench

led_ctrl1.v 是RTL代码

module led_ctrl1(
    clk,
    rst_n,
    led_out
);
    input clk;
    input rst_n;
    output reg led_out;
    
    reg [26:0] counter;
    
    //第一个always负责counter计数器的逻辑
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            counter <= 0;
        end else if(counter == 125_000_000-1) begin
            counter <= 0;
        end else begin
            counter <= counter + 1;
        end
    end
    
    //第二个always负责led_out闪烁的逻辑
    //亮0.25s->灭0.5秒->亮0.75秒->灭1秒
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            led_out <= 0;
        end else if(counter == 0) begin
            led_out <= 1;
        end else if(counter == 12_500_000) begin
            led_out <= 0;
        end else if(counter == 37_500_000) begin
            led_out <= 1;
        end else if(counter == 75_000_000) begin
            led_out <= 0;
        end 
    end
    
endmodule

tb_led_ctrl1.v是testbench代码

`timescale 1ns / 1ns

module tb_led_ctrl1();
    reg clk;
    reg rst_n;
    wire led_out;
    initial clk = 1;
    always #10 clk = ~clk;
    
    led_ctrl1 led_ctrl1_inst0(
        .clk(clk),
        .rst_n(rst_n),
        .led_out(led_out)
    );
    
    initial begin
        rst_n = 0;
        #201;
        rst_n = 1;
        #250_000_000
        $stop;
    end
endmodule

仿真结果

从图中黄色marker标注下的时间间隔可以看出,仿真结果和预期目标一致。
在这里插入图片描述

存在的问题?

如果到此就结束了,那么案例(二)和(一)并没有多大区别。
实际上,按照刚才的实现方式可以完成功能,但存在如下问题:

  1. 仿真时间过长
    为了在实际上板时观察到led闪烁的效果,我们的闪烁都是秒级的,vivado仿真一秒时间几乎需要十几秒才能完成,能否减少仿真时间,不影响功能?
  2. 可读性较差
    在我们的代码中0.25s,0.75s这些时间尺度都是用具体的计数器的周期数来表示的,数字太大,不好理解,如何解决?

针对以上问题,观察我们的需求是让LED以**【亮0.25秒->灭0.5秒->亮0.75秒->灭1秒】**循环,那么最基本的单位可以视为0.25秒,我们可以使用两个计数器,第一个计数器计数到0.25秒(12500_000 - 1个cycles)时第二个计数器加1。按照这个思路,我们在设置led时只需要关注好第二个计数器即可,1亮,2、3灭,4、5、6亮,7、8、9、10灭,显然可读性是比0亮,12_500_000灭好多了。
此外,针对仿真时间过长的问题,我们可以在RTL模块中定义一个parameter时间单元,而在testbench仿真中重新缩小该时间单元1000倍,实际上板时只会烧录RTL模块,这样既节省了仿真时间,又不影响功能。
在这里插入图片描述

改善后的代码

RTL代码

module led_ctrl1(
    clk,
    rst_n,
    led_out
);
    input clk;
    input rst_n;
    output reg led_out;
    
    parameter MCNT = 12500_000 - 1;
    reg [26:0] counter0;
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            counter0 <= 0 ;
        else if(counter0 == MCNT)
            counter0 <= 0;
        else
            counter0 <= counter0 + 1'd1;
    end
    
    reg [3:0] counter1;
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            counter1 <= 0 ;
        else if(counter0 == MCNT) begin
           if(counter1 == 9)
              counter1 <= 0;
           else
              counter1 <= counter1 + 1'd1;
        end
        else
            counter1 <= counter1;
    end
    
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        led_out <= 0;
    else begin
        case(counter1)
            0:led_out <= 1'd1;
            1:led_out <= 1'd0;
            2:led_out <= 1'd0;
            3:led_out <= 1'd1;
            4:led_out <= 1'd1;
            5:led_out <= 1'd1;
            6:led_out <= 1'd0;
            7:led_out <= 1'd0;
            8:led_out <= 1'd0;
            9:led_out <= 1'd0;
            default:led_out <= led_out;
        endcase
    end
    
endmodule

testbench代码

`timescale 1ns / 1ns

module tb_led_ctrl1();
    reg clk;
    reg rst_n;
    wire led_out;
    initial clk = 1;
    always #10 clk = ~clk;
    
    led_ctrl1 led_ctrl1_inst0(
        .clk(clk),
        .rst_n(rst_n),
        .led_out(led_out)
    );
    defparam led_ctrl1.MCNT = 12500 - 1; 
    
    initial begin
        rst_n = 0;
        #201;
        rst_n = 1;
        #20_000_000;
        $stop;
    end
endmodule

仿真结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1522780.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javaEE——线程的等待和结束

文章目录 Thread 类及常见方法启动一个线程中断一个线程变量型中断调用 interrupt() 方法来通知观察标志位是否被清除 等待一个线程获取当前线程引用休眠当前线程 线程的状态观察线程的所有状态观察 1: 关注 NEW 、 RUNNABLE 、 TERMINATED 状态的切换 多线程带来的风险为什么会…

Ubuntu 14.04:安装 PaddleOCR 2.3

目录 一、说明 1.1 如何选择版本 1.2 查看 github 中的 PaddleOCR 版本 二、安装 2.1 安装前环境准备 2.2 下载包 2.3 解压 2.4 安装依赖库 异常处理&#xff1a;Read timed out. 2.5 下载推理模型&#xff1a;inference 2.5.1 模型存放位置 2.5.2 模型下载链接 2.5.…

【5G NB-IoT NTN】3GPP R17 NB-IoT NTN介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

​​SQLiteC/C++接口详细介绍之sqlite3类(十)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;九&#xff09; 下一篇&#xff1a;​​SQLiteC/C接口详细介绍之sqlite3类&#xff08;十一&#xff09; 30.sqlite3_enable_load_extension&#x…

Docker 学习笔记一

一、什么是docker Docker 是一个基于轻量级虚拟化技术的容器&#xff0c;整个项目基于Go语言开发&#xff1b;Docker是一个C/S架构&#xff0c;后端众多模块各司其职&#xff0c;docker的daemon是运行在主机上通过client可以进行通信。 docker 由三部分组成&#xff1a;镜像(…

读算法的陷阱:超级平台、算法垄断与场景欺骗笔记12_移动平台(上)

1. 广告 1.1. 广告收入的来源 1.1.1. 向客户推荐广告投放网址 1.1.2. 提供有效提高产品广告点击率的咨询服务 1.1.3. 从合作伙伴的广告收入中捞上一笔 1.2. 对于广告主来讲&#xff0c;他们无意于与各家网站逐一谈判 1.2.1. 这种方式一是成本过高&#xff0c;二是费时费力…

C#控制台贪吃蛇

Console.Write("");// 第一次生成食物位置 // 随机生成一个食物的位置 // 食物生成完成后判断食物生成的位置与现在的蛇的身体或者障碍物有冲突 // 食物的位置与蛇的身体或者障碍物冲突了&#xff0c;那么一直重新生成食物&#xff0c;直到生成不冲突…

算法——前缀和之除自身以外数组的乘积、和为K的子数组、和可被K整除的子数组、连续数组、矩阵区域和

这几道题对于我们前面讲过的一维、二维前缀和进行了运用,包含了面对特殊情况的反操作 目录 4.除自身以外数组的乘积 4.1解析 4.2题解 5.和为K的子数组 5.1解析 5.2题解 6.和可被K整除的子数组 6.1解析 6.2题解 7.连续数组 7.1题解 7.2题解 8.矩阵区域和 8.1解析 …

在pharmit里匹配药效团

我把400个无活性的小分子&#xff08;decoys&#xff09;提交到pharmit里。 命名为decoyset00~decoyset08&#xff0c;查找时&#xff0c;按这个找。 1、导入药效团配体&#xff1a; 进入药效团筛选界面&#xff1a; 导入代表药效团模型的活性肽构象&#xff1a; 2、选择预先…

搞机笔记 MI8 dipper

刷回MIUI 之前刷了 lineage-19.1-20220728-nightly-dipper-signed 基于安卓12&#xff0c;实现了以下功能 TWRPmagisk & ROOTmicroG 退回MIUI的原因有&#xff1a; lineage 墓碑 管不住APP后台&#xff0c;太卡了MIUI提供了3GB的虚拟内存lineage 不支持人脸识别lineag…

【基础CSS】

本文章属于学习笔记&#xff0c;在https://www.freecodecamp.org/chinese/learn/2022/responsive-web-design/中练习 二、 CSS 样式&#xff0c;新建一个文件.css&#xff0c;该文件不含有style标签 <style>. h1&#xff0c;h2&#xff0c;p{ text-align&#xff1a;ce…

[长城杯 2021 院校组]funny_js

[长城杯 2021 院校组]funny_js 审题 根据题名提示为js&#xff0c;再在ida中查看&#xff0c;基本可以确定为quickjs题 QuickJS 是一个快速、灵活且易于嵌入的 JavaScript 引擎&#xff0c;适用于需要在资源受限环境下运行 JavaScript 代码的场景。 工具准备 来到Linux&…

Linux学习方法-框架学习法——Linux系统框架

配套视频学习链接&#xff1a;https://www.bilibili.com/video/BV1HE411w7by?p2&vd_sourced488bc722b90657aaa06a1e8647eddfc 目录 Linux系统框架(从裸机到OS) Linux可看成是一个大软件/大程序 应用和驱动 内核态和用户态 Linux的文件系统 Linux初学者首先要搞清楚三…

第二门课:改善深层神经网络<超参数调试、正则化及优化>-超参数调试、Batch正则化和程序框架

文章目录 1 调试处理2 为超参数选择合适的范围3 超参数调试的实践4 归一化网络的激活函数5 将Batch Norm拟合进神经网络6 Batch Norm为什么会奏效&#xff1f;7 测试时的Batch Norm8 SoftMax回归9 训练一个SoftMax分类器10 深度学习框架11 TensorFlow 1 调试处理 需要调试的参…

单片机第四季-第一课:RTOS

1&#xff0c;RTOS来龙去脉 操作系统是什么&#xff1f; 以人类社会类比&#xff0c;小公司三四个人都是干活的&#xff0c;大公司有几万人其中有几千人从事管理工作&#xff0c;他们的工作是让其他人的干活效率更高。 51单片机为什么没有操作系统&#xff0c;因为51的性能太…

如何将Excel两列数据转换为统计图、曲线图、折线图?如何自定义某一列作为Excel的统计图横纵坐标?

这样&#xff0c;横坐标就更换为指定选中的数据了 我们还可以修改统计图的样式 也可以修改统计图的类型

Java关于物联网消息引擎:EMQ X

1.背景 1、5G 时代&#xff0c;万物互联 随着5G的到来&#xff0c;万物互联已经成为现实&#xff0c;物联网行业得以蓬勃发展&#xff0c;催生了很多的应用&#xff0c;比如&#xff1a;物联网pass平台&#xff0c;车联网&#xff0c;面向云平台的IOT-Hub&#xff0c;NB-IoT蜂…

HCIP—BGP邻居关系建立实验

BGP的邻居称为&#xff1a;IBGP对等体 EBGP对等体 1.EBGP对等体关系&#xff1a; 位于 不同自治系统 的BGP路由器之间的BGP对等体关系 EBGP对等体一般使用 直连建立 对等体关系&#xff0c;EBGP邻居之间的报文 TTL中值设置为1 两台路由器之间建立EBGP对等体关系&#xff0…

MacBook使用——彻底卸载并删除软件:NTFS for Mac

问题 之前因MacBook读写NTFS格式移动硬盘&#xff0c;我安装并使用了 Paragon NTFS for Mac &#xff0c;试用期结束后将其从【应用程序】中卸载移除了。但之后每次开机启动时&#xff0c;系统还是会弹出【激活】通知&#xff0c;如下图 解决 Step1、在用户目录下的 Library 目…

学习shell脚本

文章目录 什么是shell脚本为什么要学习shell脚本第一个脚本编写与执行 简单的shell脚本练习简单案例脚本的执行方式差异(source、sh script、./script) 如何使用shell脚本的判断式利用test命令的测试功能利用判断符号[ ]shell脚本的默认变量($0、$1...) shell脚本的条件判断式利…