基于Basys2的数码管动态扫描module(verilog)的模块化设计

这篇具有很好参考价值的文章主要介绍了基于Basys2的数码管动态扫描module(verilog)的模块化设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

   

目录

一、数码管工作原理

 二、Verilog模块设计

1、原理

(1)动态扫描的优点:

(2)动态扫描原理简介:

2、Verilog模块的设计

(1)分频器:

 2、译码器模块:

3、动态扫描模块:

4、顶层模块:

三、写在最后:


在大二下学期学习《Verilog与FPGA实现》的时候鲲鲲给我们布置了课程实验,有许多实验需要用到数码管作为输出。本文旨在用模块化的思想向大家介绍笔者的通用的数码管显示模块。

一、数码管工作原理

数码管事常见的显示装置,通常由7段或8段LED组成,根据公共端连接方式分为:共阳极数码管、共阴极数码管。

顾名思义,共阴极数码管的所有LED的阴极是接在一块的,当通入高电平数码管才点亮;共阳极数码管的所有LED是阳极接在一起,输入低电平点亮,段选码如下图所示

基于Basys2的数码管动态扫描module(verilog)的模块化设计基于Basys2的数码管动态扫描module(verilog)的模块化设计

我们用的Basys2的数码管为共阳极数码管,因此本次设计采用共阳极段码表。基于Basys2的数码管动态扫描module(verilog)的模块化设计

 二、Verilog模块设计

1、原理

为了节省管脚,Basys2开发板采用的是动态扫描的方式来进行数码管显示,具体如下:

(1)动态扫描的优点:

管脚对芯片来说是非常宝贵的资源,对于我们的板子来说,用到了4个8段数码管,如果用管脚直接控制LED的亮灭的话,总共需要用到4*(8+2)=40个管脚(8是abcdefg段选,2是两个共阳极),一共用到32个管脚作为控制端;而用动态扫描的方式来进行显示的话需要4个位选(选择四个数码管中的哪一个)和8个段选(abcdefg中的哪一段,当然还有两个共阳极),一共用到12个管脚作为控制端,高下立判。

(2)动态扫描原理简介:

要实现动态扫描,最常用的是数据锁存器和移位寄存器,在某一时刻输入位选选中要显示的数码管,同时送上相应的段选码,下一时刻选中下一个数码管同时送上对应的段选码,只要扫描的频率足够快,人眼就会因为视觉暂留效应而看到的4个数码管显示不同的数字。常用的刷新频率在1KHz到60Hz,太快就会亮度不够,太慢就会闪烁。

2、Verilog模块的设计

设计的模块会将输入的4个二进制码显示在4个位的数码管上,因而需要模块:分频器(将板子50MHz时钟分频为1KHz时钟)、译码模块(二进制码转为共阳极数码管段选码)、动态扫描模块(在特定时刻选中位并送上对应的段选码)、top(顶层封装),具体代码如下:

(1)分频器:

计数分频,通过计算,输入的50MHz时钟分频为1KHz时钟,需要计数50000次,为了节省资源,计数器位宽为16位刚好满足2^16<50000<2^17。

module clk_div(
    input clk,
    output reg clk_div
    );
    //输入板子50MHz时钟,输出1KHz时钟
    //计数分频:50000次
    reg [15:0]cnt = 16'd0;
    always@(posedge clk)
    begin
        if(cnt == 16'd50000)
        begin
            cnt <= 16'd0;
        end
        else
        begin
            cnt <= cnt + 16'd1;
        end
    end
    //输出时钟控制
    always@(posedge clk)
    begin
        if(cnt <= 16'd24999)
        begin
            clk_div <= 1'b1;
        end
        else
        begin
            clk_div <= 1'b0;
        end
    end
    
endmodule

 2、译码器模块:

一个很简单的case分支实现译码,输入4位二进制编码,输出对应的8位段选码。

module wei_encoder(
    input [3:0]hex_number,
    output reg [7:0]display_code
    );
    //将输入的十六进制代码转换为共阳极数码管段选编码并输出
    always@(*)
    begin
        case(hex_number)
            4'b0000:display_code = 8'hc0;//0
            4'b0001:display_code = 8'hf9;//1
            4'b0010:display_code = 8'ha4;//2
            4'b0011:display_code = 8'hb0;//3
            4'b0100:display_code = 8'h99;//4
            4'b0101:display_code = 8'h92;//5
            4'b0110:display_code = 8'h82;//6
            4'b0111:display_code = 8'hf8;//7
            4'b1000:display_code = 8'h80;//8
            4'b1001:display_code = 8'h90;//9
            4'b1010:display_code = 8'h88;//A
            4'b1011:display_code = 8'h83;//B
            4'b1100:display_code = 8'hc6;//C
            4'b1101:display_code = 8'ha1;//D
            4'b1110:display_code = 8'h86;//E
            4'b1111:display_code = 8'h8e;//F
            default:display_code = 8'hff;//无
        endcase
    end
endmodule

3、动态扫描模块:

输入分频后的1KHz时钟作为位选信号的扫描频率,通过计数器的数值case输出位选和相应的段选信号。

module Display(
    input clk_div,
    input [7:0]Out_number_1,//第一位数字对应的段选码
    input [7:0]Out_number_2,//第二位数字对应的段选码
    input [7:0]Out_number_3,//第三位数字对应的段选码
    input [7:0]Out_number_4,//第四位数字对应的段选码
    output reg [7:0]duan_code,
    output reg [3:0]wei_code
    );
    //将输入的十六进制代码转换为共阳极数码管段选码动态扫描输出
    reg [2:0]sel_cnt;//扫描计数器
    //动态扫描
    always@(posedge clk_div)
    begin
        if(sel_cnt == 3'd4)
        begin
            sel_cnt <= 3'd0;
        end
        else
        begin
            sel_cnt <= sel_cnt + 3'd1;
        end
    end
    always@(posedge clk_div)
    begin
            case(sel_cnt)
                3'd0:
                begin
                    wei_code <= 4'b0001;
                    duan_code <= Out_number_1;
                end
                3'd1:
                begin
                    wei_code <= 4'b0010;
                    duan_code <= Out_number_2;
                end
                3'd2:
                begin
                    wei_code <= 4'b0100;
                    duan_code <= Out_number_3;
                end
                3'd3:
                begin
                    wei_code <= 4'b1000;
                    duan_code <= Out_number_4;
                end
                default:
                begin
                    wei_code <= 4'b0000;
                    duan_code <= 8'hff;
                end
            endcase
    end

endmodule

4、顶层模块:

在顶层中例化上述三个模块,封装为一个模块,方便实例化调用,具体流程:分频器将输入的clk(50MHz)分频为clk_div(1KHz),送往Display用于扫描计数器的动态扫描,wei_encoder将输入的二进制数转化为共阳极数码管对应的段选码,送往Display模块扫描输出。

module SEG_display(
    input clk,
    input [7:0]number1,
    input [7:0]number2,
    output [3:0]wei_code,
    output [7:0]duan_code
    );
    //声明内部信号线
    wire [7:0]Out_number_1;//将要输出的段选码
    wire [7:0]Out_number_2;
    wire [7:0]Out_number_3;
    wire [7:0]Out_number_4;
    wire clk_div;//分频后的时钟
    
    //模块实例化
    //时钟分频,用于数码管计数扫描
    clk_div div(
        .clk(clk),
        .clk_div(clk_div)
    );
    //将将要输出的数转化为段选码
    wei_encoder encoder1(
        .hex_number(number1[3:0]),
        .display_code(Out_number_1)
    );
    wei_encoder encoder2(
        .hex_number(number1[7:4]),
        .display_code(Out_number_2)
    );
    wei_encoder encoder3(
        .hex_number(number2[3:0]),
        .display_code(Out_number_3)
    );
    wei_encoder encoder4(
        .hex_number(number2[7:4]),
        .display_code(Out_number_4)
    );
    //数码管动态扫描显示
    Display display(
        .clk_div(clk_div),
        .Out_number_1(Out_number_1),
        .Out_number_2(Out_number_2),
        .Out_number_3(Out_number_3),
        .Out_number_4(Out_number_4),
        .duan_code(duan_code),
        .wei_code(wei_code)
    );
endmodule

三、写在最后:

这个Verilog数码管动态扫描模块可以适用于Basys2几乎所有的项目,今后我将陆续更新鲲鲲的《Verilog与FPGA实现》 给我们布置的八个实验,一方面巩固自己的知识,另一方面有助于学弟学妹们学习。笔者不才,如有疏漏,欢迎各位网友批评指正。文章来源地址https://www.toymoban.com/news/detail-484144.html

到了这里,关于基于Basys2的数码管动态扫描module(verilog)的模块化设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VHDL矩阵键盘扫描数码管显示

    1.打开Quarteus,直接点击New Project izard. 2.选择存放路径和工程名后一直Next,直到出现芯片选择页面(这里需要特别注意,这个软件不支持中文,所以工程存放路径一定不能含有中文,否则会报错) 3.选择对应的芯片,我这里选择EP4CE40F23C8,然后Next,最后Finish 4.完成工程的创建

    2023年04月24日
    浏览(51)
  • 实验八 键盘扫描及数码管显示实验

    1)学习了解键盘扫描的基本原理。 2)掌握通过并行接口芯片对键盘进行扫描并在多位数码管显示数字的方法。 编写程序,实现如下功能: 初始时数码管无显示; 第一次按下键盘时,在 最右侧数码管显示对应的十六进制数字 ; 以后每次按下键盘,则将 当前显示的数字全部

    2024年02月09日
    浏览(27)
  • 数码管扫描显示-单片机通用模板

    ①人的眼睛中的画面在0.02S(50Hz)左右,光源的闪烁频率高于50-60赫兹时,人眼通常无法察觉到光的闪烁; ②通过控制LED的亮灭透过模具贴纸从而控制数字和图案的亮灭; 在主函数main的while循环里调用,等标志更新显示 在2~4kHz的定时器里面调用 FreshDisplay() 映射到IO功能函数,频

    2024年02月19日
    浏览(26)
  • 51单片机——秒表(定时器扫描独立按键和数码管)

            这次实验主要是用定时器来定时扫描独立按键和数码管,代替两个模块函数中的延时函数。用定时器定时扫描的好处就是,主函数中的延时并不会影响按键的检测和数码管的扫描,只会影响响应速度。因为定时器是溢出就会执行中断程序,是定时的扫描。 改进的

    2024年02月10日
    浏览(39)
  • 51单片机(四)静态数码管和动态数码管显示

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月09日
    浏览(34)
  • 数码管动态显示

    8个数码管 SEL 8个显示电路 a,b,c,d,e,f,g,h SEG 要使哪一个亮,则将SEL[X]置为1,X线拉低---------使用一个 3-8译码器 ,根据cnt[2:0]来选择哪一个数码管亮 所以不同的数都可以根据SEL和SEG来进行选择 根据输入的不同的数来进行显示,一共有8个数码管,一个数的范围是0-f 。 需要4位,一

    2023年04月19日
    浏览(30)
  • 单片机——数码管动态显示

    1.头文件和定义,代码还使用了 sbit 定义来声明了两个变量 duan 和 wei,它们实际上是 P2.6 和 P2.7 端口的别名,用于控制数码管的段选和位选信号。这种方法可以使代码更具可读性,并提高代码的可维护性。定义无符号整数便于后面应用。 2.使用一个 16 个元素的数组 table,该数

    2024年02月11日
    浏览(28)
  • 【51单片机】动态数码管

    0、前言 参考: 普中51单片机开发攻略–A2.pdf 上一章我们主要是介绍一位数码管的内部结构及控制原理。下面我们再来介 绍下多位数码管及动态显示原理的相关知识。 本章所要实现的功能是:控制动态数码管从左至右显示数字 0-7。 为了正规点,工程弄个正规文件夹: http

    2024年01月21日
    浏览(55)
  • 实验(四)数码管动态显示实验

    一.实验目的、内容、仪器 实验目的: 1.熟悉数码管的功能和使用 2.了解位选和段选,和动态显示的原理 了解74HC138的引脚功能。 实验内容:接共阴极数码管,要求动态显示(HELLOC51),动态扫描显示即轮流向各位数码管送出字形码和相应的位选。 实验仪器:7SEG-MPX8-CC:八位数码管共

    2024年02月08日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包