FPGA极易入门教程----数码管篇(1)静态显示

这篇具有很好参考价值的文章主要介绍了FPGA极易入门教程----数码管篇(1)静态显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、数码管简介

        数码管是一种半导体发光器件,其基本单元是发光二极管。数码管按段数一般分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管(多一个小数点显 示)。当然也还有一些其他类型的数码管如“N”形管、“米”字管以及工业科研领域用 的 16 段管、24 段管等,在此就不详细介绍。本文仅介绍8段式的数码管。

图1:8段式的数码管结构

FPGA极易入门教程----数码管篇(1)静态显示

         在上图中,我们可以看到数码管是由7根长条形发光二极管(a~g),1个点型发光二极管dp(表示小数点)组成。这8个发光二极管的连接方式有两种:共阴极和共阳极:

  • 共阴极:8个二极管的参考地GND都接到一起,二极管的另一端单独接出(a-g、dp),通过对不同二极管的电源控制,即可实现对应二极管的亮灭,此类数码管被称为共阴极数码管。将a-g或dp的端口给与高电平,即可点亮对应的二极管;反之、给与低电平,即可熄灭对应的二极管;
  • 共阳极:8个二极管的电源都接到一起,二极管的另一端单独接出(a-g、dp),通过对不同二极管的电源控制,即可实现对应二极管的亮灭,此类数码管被称为共阳极数码管;将a-g或dp的端口给与低电平,即可点亮对应的二极管;反之、给与高电平,即可熄灭对应的二极管;​​​​​​。

        根据上述我们可以总结:共阴极数码管使用高电平控制点亮;而共阳极数码管使用低电平控制点亮。

2、数码管的显示方式

        对于共阳极数码管来说:

        假设我们使用一个7位(先不管小数点)的二进制数num来分别表示二极管a~g,即num的最高位num[6]=“a的值”,num[5]=“b的值”······num[0]=“g的值”。那么只要控制num的值,我们就可以实现点亮数码管的对应二极管。比如,num=7’b000_0110,那么就是对应的b(从右数第2位)、c(从右数第3位)被点亮,具体到数码管就是显示了一个类似“1”的效果,如下:

图2:共阴极数码管显示数字“1”

FPGA极易入门教程----数码管篇(1)静态显示

        其他数字的演示就不做了,根据这个原理可以整理出0~9这10个数字的编码方式(适用共阳极,共阴极只要将编码取反即可):

图3:共阳极数码管编码表

FPGA极易入门教程----数码管篇(1)静态显示

        这里涉及到两个概念:

  • 段选:单个数码管的二极管控制信号(a~g),控制段选可以实现数码管显示不同的数字
  • 位选:单个数码管的“电源开关”信号,只有在位选有效的情况下(有电情况下),控制数码管的段选才有意义

        也就是说通过控制位选可以控制数码管是否上电工作,通过控制段选可以控制数码管显示具体的内容

        在通常的设计中,只用一个数码管显然是不太方便的,一般都需要4个、6个或者多个(这个看自身,我们这里用6个举例)。假设我们需要用6个数码管来显示数字,那么岂不是需要控制8个*6=48个信号,也就是需要48个IO口来进行控制?虽然我们知道FPGA的IO资源比较丰富,但是也架不住这么造不是?

        所以一般在FPGA开发板中,基本都是将6个数码管的8个二极管的控制信号(段选)连接到了一起来统一控制,而将数码管的位选信号分开控制。

3、静态显示

        我们可以通过位选信号去控制数码管点亮,而在同一时刻,位选选通的数码管上显示的字形是一样的,因为我们将 6 个数码管相对应的段选连在了一起,数码管的显示自然就相同了,数码管的这种显示方式即为静态显示。

        接下来我以某Cyclone IVE的开发板为例,编写静态显示的驱动代码进行验证。该开发板有6个共阳极数码管(低电平控制亮),数码管位选控制信号(低电平有效)。

3.1、端口

        驱动模块输入输出端口如下:

图4:数码管静态显示模块框图

FPGA极易入门教程----数码管篇(1)静态显示

         各信号含义如下:

  • 输入端:
    • sys_clk:系统时钟,我的开发板是50M,周期20ns
    • sys_rst_n:低电平有效的异步复位信号
    • num[3:0]:需要显示的数字,共10个数字,所以需要4bit的位宽
  • 输出端
    • dis_seg[6:0]:数码管7位段选,从高到底分别控制二极管a~g,低电平有效
    • dis_sel[5:0]:数码管位宽,共6个数码管所以共需要6bit,低电平有效
    • dp:小数点二极管控制信号,低电平有效

3.2、Verilog代码

        驱动代码很好写,我们只需要使用两个always块和1个assign语句即可完成。

        第1个 always块来对位选信号赋值,这里复位熄灭所有数码管;复位完成后给所有数码管供电(选中所有数码管)

//控制数码管位选信号(低电平有效),选中所有的数码管
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        dis_sel <= 6'b111111;                    //复位熄灭所有数码管
    else
        dis_sel <= 6'b000000;                    //复位完成后给所有数码管供电
end      

        第2个 always块来段选信号赋值,根据输入的数据(要显示的数)来对段选信号赋取对应的码值。

//根据数码管显示的数值,控制段选信号(低电平有效)
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        dis_seg <= 7'b111_1111;                    //复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
    else begin
        case (num)
            4'h0 : dis_seg <= 7'b000_0001;        //显示数字“0”,则数码管的段选编码为7'b000_0001
            4'h1 : dis_seg <= 7'b100_1111;
            4'h2 : dis_seg <= 7'b001_0010;
            4'h3 : dis_seg <= 7'b000_0110;
            4'h4 : dis_seg <= 7'b100_1100;
            4'h5 : dis_seg <= 7'b010_0100;
            4'h6 : dis_seg <= 7'b010_0000;
            4'h7 : dis_seg <= 7'b000_1111;
            4'h8 : dis_seg <= 7'b000_0000;
            4'h9 : dis_seg <= 7'b000_0100;        //显示数字“9”,则数码管的段选编码为7'b000_0100
            default : dis_seg <= 7'b111_1111;    //其他数字(16进制的数字相对10进制无效)则熄灭数码管
        endcase
    end
end

        小数点显示我们暂时不用,直接将其赋值1,使其失效。

assign dis_dp = 1'b1;                            //小数点,我们暂时不同,使其无效即可

        完整代码如下:

//6位8段式数码管静态显示驱动

//端口定义
module dis_sta_dri (
	input 				sys_clk ,				//时钟信号
	input 				sys_rst_n ,				//复位信号(低有效)
			
	input		[3:0]	num,					//数码管显示的十进制数
	output reg 	[5:0] 	dis_sel,				//数码管位选
	output reg 	[6:0] 	dis_seg, 				//数码管段选
	output				dis_dp					//数码管小数点
);

assign dis_dp = 1'b1;							//小数点,我们暂时不同,使其无效即可

//控制数码管位选信号(低电平有效),选中所有的数码管
always @ (posedge sys_clk or negedge sys_rst_n) begin
	if (!sys_rst_n)
		dis_sel <= 6'b111111;					//复位熄灭所有数码管
	else
		dis_sel <= 6'b000000;					//复位完成后给所有数码管供电
end

//根据数码管显示的数值,控制段选信号(低电平有效)
always @ (posedge sys_clk or negedge sys_rst_n) begin
	if (!sys_rst_n)
		dis_seg <= 7'b111_1111;					//复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
	else begin
		case (num)
			4'h0 : dis_seg <= 7'b000_0001;		//显示数字“0”,则数码管的段选编码为7'b000_0001
			4'h1 : dis_seg <= 7'b100_1111;
			4'h2 : dis_seg <= 7'b001_0010;
			4'h3 : dis_seg <= 7'b000_0110;
			4'h4 : dis_seg <= 7'b100_1100;
			4'h5 : dis_seg <= 7'b010_0100;
			4'h6 : dis_seg <= 7'b010_0000;
			4'h7 : dis_seg <= 7'b000_1111;
			4'h8 : dis_seg <= 7'b000_0000;
			4'h9 : dis_seg <= 7'b000_0100;		//显示数字“9”,则数码管的段选编码为7'b000_0100
			default : dis_seg <= 7'b111_1111;	//其他数字(16进制的数字相对10进制无效)则熄灭数码管
		endcase
	end
end

endmodule

        那么现在静态显示的驱动写好了,我们还需要写个数据生成模块,也就是我们要想办法写入数据到这个驱动来进行显示。

        这个模块只有两个always块,第1个 always块做一个1s的计时器,该计时器循环计时1s。该模块可以顺序生成0-9这10个数,每隔1s,数据累加1。

//1s计时模块,该模块循环计数到1s
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        cnt_1s <= 0;                            //复位计数器为0
    else if(cnt_1s == (50_000_000 - 1))            //计数器计数到了1s,每个时钟周期20ns,则从0开始需要计数(1_000_000_000/20 - 1)
        cnt_1s <= 0;                            //计数器清零重新开始计数
    else    
        cnt_1s <= cnt_1s + 1;                    //没有计数到1s则每个周期计数1次
end

        第2个 always块每隔1s生成1个数据,数据范围0-9循环。

//数据生成模块,从0开始累加(每1s累加一次),到9结束。然后循环
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n)
        data <= 0;                                //复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
    else if(cnt_1s == (50_000_000 - 1))begin    //每次计数到1s
        if(data == 9)                            //数据生成到了9则重新开始从0生成
            data <= 0;
        else                                    //数据没有生成到9则累加1
            data <= data + 1;        
    end
end

        有了驱动模块和数据生成模块,我们再写一个顶层模块,顶层模块调用这两个模块并完成连接,实现模块化设计。顶层模块的代码如下:

//6位8段式数码管静态顶层文件
//例化静态显示驱动模块和数据生成模块,将数据生成模块生成的数字,通过静态驱动,用数码管显示出来

//端口定义
module dis_sta_top (
	input 				sys_clk ,			//时钟信号
	input 				sys_rst_n ,			//复位信号(低有效)
			
	output  	[5:0] 	dis_sel,			//数码管位选
	output  	[6:0] 	dis_seg, 			//数码管段选
	output				dis_dp				//数码管小数点
);

wire	[3:0]	data;						//需要显示的数字

//例化静态显示驱动模块
dis_sta_dri	dis_sta_dri_inst(
	.sys_clk 	(sys_clk	),				//时钟信号
	.sys_rst_n 	(sys_rst_n	),				//复位信号(低有效)
	
	.num		(data		),				//数码管显示的十进制数
	.dis_sel	(dis_sel	),				//数码管位选
	.dis_seg 	(dis_seg	),				//数码管段选
	.dis_dp		(dis_dp		)
);	
	
//例化数据生成模块	
data_generate	data_generate_inst (	
	.sys_clk 	(sys_clk	),				//时钟信号,50M
	.sys_rst_n 	(sys_rst_n	),				//复位信号(低有效)
	
	.data 		(data		)				//4位二进制数字
);	

endmodule

3.3、Testbench及仿真结果

        可能看到这里,很多朋友就已经想要直接上板验证了。这里我说个忠告:做FPGA设计,一定要做仿真测试,一定要分析波形。做FPGA的设计不能拿着做单片机的思维来做,不能上来就是看上板结果。设计完成后,先做仿真,90%的问题(有点夸张了)都可以通过仿真规避掉。当然我知道,作为初学者,看到实验现象在板卡上显示的时候是很有趣和很有成就感的,但是相信我,如果你想在这条路上走得更远,就一定要做仿真分析波形,随着时间的流逝、经验的增加,日后一定会大幅提高你的能力,并帮你节约大量时间。

        由于我们的工程中,我已经设计了激励,所以在TB文件中,我们仅仅需要提供时钟、复位即可。完整的TB文件如下:

//静态显示仿真激励TESTBENCH

`timescale 1ns/1ns	//时间单位/精度

//------------<模块及端口声明>----------------------------------------
module tb_dis_sta_top();

reg 			sys_clk;			//时钟信号
reg 			sys_rst_n;          //复位信号(低有效)
                                    
wire	[5:0] 	dis_sel;            //数码管位选
wire	[6:0] 	dis_seg;            //数码管段选
wire			dis_dp;             //数码管小数点

//------------<例化被测试模块>----------------------------------------
dis_sta_top		dis_sta_top_inst(
	.sys_clk	(sys_clk	),
	.sys_rst_n	(sys_rst_n	),
	
	.dis_sel	(dis_sel	),
	.dis_seg	(dis_seg	),
	.dis_dp		(dis_dp		)
);

//------------<设置初始测试条件>----------------------------------------
initial begin
	sys_clk = 1'b0;					//初始时钟为0
	sys_rst_n <= 1'b0;				//初始复位
	#25								//25个时钟周期后
	sys_rst_n <= 1'b1;				//拉高复位,系统进入工作状态
	
end
//------------<设置时钟>----------------------------------------------
always #10 sys_clk = ~sys_clk;		//系统时钟周期20ns

endmodule

        仿真结果如下:

图5:仿真结果 

FPGA极易入门教程----数码管篇(1)静态显示

        在上图中:

  • 段选信号dis_seg每隔1s变化一次(下方有刻度),根据图3:共阴极数码管编码表的对应关系,可以发现其表示的数字为0-9-0(入图所示);
  • 位选信号为6’b000000,代表6个数码管选被选中点亮(供电)
  • 小数点使能信号为高,代表其不使能,即小数点灭

这个仿真结果是符合我们的预期想法的,接下来上板验证。

3.4、上板验证

        绑定对应管脚,全编译整个文件,将sof文件通过JTAG接口下载进FPGA开发板,观察其实验现象。(开发环境在最后)。

        需要注意的是由于CSDN对视频的支持不是很友好,我把实验现象的结果视频转换成了GIF,并且加速了4倍(为了满足上传图片5M的大小限制),所以看上去数据的变化远远没有1秒。

        结果如下:

FPGA极易入门教程----数码管篇(1)静态显示

4、其他

  • 创作不易,如果本文对您有帮助,还请多多点赞、评论和收藏。您的支持是我持续更新的最大动力!
  • 关于本文,您有什么想法均可在评论区留言。如果需要整个工程,请在评论留下邮箱或者私信我邮箱(注意保护隐私)。
  • 自身能力不足,如有错误还请多多指出!
  • 预告:下一篇更新数码管的动态驱动。

版本信息

        文件:V1.0

        编号:0011

        Modelsim:Modelsim SE-64 10.4

        Quartus II:Quartus II 13.1 (64-bit)文章来源地址https://www.toymoban.com/news/detail-448492.html

到了这里,关于FPGA极易入门教程----数码管篇(1)静态显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【FPGA】数码管电子时钟

    Cyclone IV开发板上的数码管一共有6个,我们每次只能选择其中一个显示, 怎么解决电子时钟时、分、秒同时显示呢 ?要实现电子时钟首先要了解什么是 余晖效应 。 余晖效应一般指视觉暂留。 视觉暂留现象即视觉暂停现象(Persistence of vision,Visual staying phenomenon,duration of

    2024年02月08日
    浏览(49)
  • FPGA学习—数码管显示

    数码管动态显示采用了人眼暂存的原理,即时分复用,在数码管实现动态显示。 整个实验设计流程框架如下图所示: 开发板采用共阳极数码管,即低电平点亮。 本实验准备设计一个定时器,6为数码管显示24小时制的时间,所以编写一个计数模块。 改变变量COUNT的数值,可实

    2024年02月09日
    浏览(45)
  • Intel FPGA:数码管显示

    个人说明: 限于时间紧迫以及作者水平有限,本文错误、疏漏之处恐不在少数,恳请读者批评指正。意见请留言或者发送邮件至:“Email:noahpanzzz@gmail.com” 。 本博客的工程文件均存放在:GitHub:https://github.com/panziping。 本博客的地址:CSDN:https://blog.csdn.net/ZipingPan 。 参考: 芯

    2024年04月15日
    浏览(40)
  • 实验三 基于FPGA的数码管动态扫描电路设计 quartus/数码管/电路模块设计

    源文件的链接放在最后啦 实验目的: (1) 熟悉7段数码管显示译码电路的设计。 (2) 掌握数码管显示原理及静态、动态扫描电路的设计。 实验任务: (1) 基本任务1:利用FPGA硬件平台上的4位数码管做静态显示,用SW0-3输入BCD码,用SW4-7控制数码管位选; (2) 基本任务

    2024年02月07日
    浏览(59)
  • FPGA实战------数码管(1)静态显示

    led的花样点灯差不多了吧,接下来学习另一个基础的东西,数码管。 数码管在FPGA开发板上占得位置不小,在工程开发中也必不可少,比如后边的温度传感器就会用数码管来显示温度。这里先不多介绍温度传感器,过一段时间就会发了。本篇文章先用数码管来做静态显示。也

    2024年02月04日
    浏览(47)
  • FPGA项目五:数码管动态扫描

    led 数码管( LED Segment Displays )是由多个发光二极管封装在一起的器件,这些二极管组成“8”字型,在内部完成引线连接,只引出它们的各个笔划和公共电极。一般来说, led 数码管常用段数为 7 段,如下图中所示的 a、b、c、d、e、f、g,有的数码管还会添加一个小数点,如图

    2024年02月06日
    浏览(58)
  • [FPGA 学习记录] 数码管动态显示

    数码管动态显示 在上一小节当中,我们对数码管的静态显示做了一个详细的讲解;但是如果单单只掌握数码管的静态显示这种显示方式是远远不够的,因为数码管的静态显示当中,被选中的数码位它们显示的内容都是相同的,这种显示方式在我们的实际应用当中显然是不合适

    2024年02月04日
    浏览(53)
  • FPGA基础设计之数码管显示

    数码管是一种半导体发光器件,其基本单元是发光二极管。一般分为七段数码管和八段数码管,多的一段是小数点。也有其他如N型、米型数码管以及16段、24段管等。本次设计的是八段数码管 公阴极数码管高电平亮,公阳极数码管低电平亮。AC620上搭载的是公阳极数码管。 数

    2023年04月26日
    浏览(49)
  • [FPGA 学习记录] 数码管静态显示

    数码管静态显示 在我们的许多项目设计当中,我们通常需要一些显示设备来显示我们需要的信息。我们可以选择的显示设备有很多,而我们的数码管就是使用最多、最简单的显示设备之一。数码管它是一种半导体发光器件,它具有响应时间短、体积小、重量轻、寿命长的优点

    2024年02月03日
    浏览(54)
  • 【FPGA】Verilog:组合逻辑电路应用 | 数码管 | 8421BCD编码 | 转换七段数码管段码

    前言: 本章内容主要是演示Vivado下利用Verilog语言进行电路设计、仿真、综合和下载 示例:数码管的使用 功能特性: 采用 Xilinx Artix-7 XC7A35T芯片  配置方式:USB-JTAG/SPI Flash 高达100MHz 的内部时钟速度  存储器:2Mbit SRAM   N25Q064A SPI Flash(样图旧款为N25Q032A) 通用IO:Switch :

    2024年02月03日
    浏览(50)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包