10-8位7段数码管驱动实验——小梅哥FPGA设计思想与验证方法视频教程配套文档
芯航线——普利斯队长精心奉献
实验目的: 1.实现FPGA驱动数码管动态显示;
2.使用In system sources and probes editor工具,输入需要显示在数码管上的的数据,数码管显示对应数值。
实验平台:芯航线FPGA核心板、数码管_VGA_PS2模块
实验原理:
电子设计系统中常用的显示设备有数码管、LCD液晶以及VGA显示器等。其中数码管又可分为段式显示(7段、米字型等)以及点阵显示(8*8、16*16等),LCD液晶的应用可以分为字符式液晶(1602、12864等)以及真彩液晶屏,VGA显示器是现在一般的电脑显示器。芯航线开发板对以上三种设备均提供了硬件接口上。
其中8段数码管的原理图如图10-1所示,
图10-1 8段数码管原理图
由上图可以看出数码管有两种结构:共阴与共阳。这两者的区别在于,公共端是连接到地还是高电平,对于共阴数码管需要给对应段以高电平才会使其点亮,对于共阳反之。芯航线数码管_VGA_PS2模块上板载的是共阳数码管。同时为了显示数字或字符,必须对数字或字符进行编码译码。这里先不考虑小数点也就是简化为7段数码管,其编码译码格式如表10-1所示:
待显示内容 Data_disp |
段码(二进制格式) |
段码(十六进制格式) |
|||||||
a |
b |
c |
d |
e |
f |
g |
h |
||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
8'hc0 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
8'hf9 |
2 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
8'ha4 |
3 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
8'hb0 |
4 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
8'h99 |
5 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
8'h92 |
6 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
8'h82 |
7 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
8'hf8 |
8 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
8'h80 |
9 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
8'h90 |
a |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
8'h88 |
b |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
8'h83 |
c |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
8'hc6 |
d |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
8'ha1 |
e |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
8'h86 |
f |
0 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
8'h8e |
表10-1 数码管编码译码表
段式数码管工作方式有两种:静态显示方式和动态显示方式。静态显示的特点是每个数码管的段选必须接一个8位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。这种方法由于每一个数码管均需要独立的数据线因此硬件电路比较复杂,成本较高,很少使用。
为了节约IO以及成本一般采用如图2所示的电路结构,这样3个数码管接在一起就比静态的少了7*2个I/O。
图10-2三位数码管等效电路图
这样就实现了另一种显示模式,动态显示。动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
现在举例假设将扫描时间定为1S,这三个数码管分成3s,第1秒时sel数据线上为100,这时数码管0被选中,这时a=0,数码管0的LED0就可以点亮;第2秒时sel数据线上为010,这时数码管1被选中,这时b=0,数码管1的LED1就可以点亮;第3秒时sel数据线上为001,这时数码管2被选中,这时c=0,数码管2的LED2就可以点亮。这时的效果就会是数码管0的LED0亮一秒后数码管1的LED1亮一秒最后是数码管2的LED2亮一秒,这样再次循环。
这样如果使用1ms刷新时间的话由于数码管的余辉效应以及人的视觉暂留这样就会出现数码管0的LED0、数码管1的LED1以及数码管2的LED2 "同时"亮,并不会有闪烁感。
实验步骤:
由上面的分析可以得出应该有图3的框图,其接口列表如表2所示:
图10-3 模块框图
信号名称 |
功能描述 |
Clk |
50M时钟 |
Rst_n |
复位信号 |
En |
数码管使能信号1使能,0关闭 |
disp_data[31:0] |
8个数码管待显示数据,每四位组成一个BCD码 |
sel[7:0] |
数码管位选,选择当前要显示的数码管 |
seg[6:0] |
数码管段选,当前要显示的内容 |
表10-2 模块接口列表
经过以上的分析,数码管驱动模块逻辑电路图可以简化成如图10-4所示的,其中每一部分的作用如表10-3所示。
图10-4 数码管驱动模块逻辑电路图
名称 |
功能描述 |
divder |
分频产生1KHz的扫描时钟 |
Shift8 |
8位循环移位寄存器 |
MUX8 |
数据输入选择 |
MUX2 |
使能选择 |
LUT |
数据译码器 |
表10-3 子功能块功能描述
建立工程子文件夹后,新建一个以名为HEX8的工程保存在prj下,并在本工程目录的rtl文件夹下新建verilog file文件并以HEX8.v保存。由图10-3可以得出如下的信号列表
input Clk; input Rst_n; input En;
input [31:0]disp_data;
output [7:0] sel; output reg [6:0] seg; |
这里先编写分频模块,从系统时钟50M分频得到1KHz的扫描时钟,计数器值即为'd25000,这样计数器的位宽定义为15位即可。
reg [14:0]divider_cnt; reg clk_1K; always@(posedge Clk or negedge Rst_n) if(!Rst_n) divider_cnt <= 15'd0; else if(!En) divider_cnt <= 15'd0; else if(divider_cnt == 24999) divider_cnt <= 15'd0; else divider_cnt <= divider_cnt + 1'b1;
always@(posedge Clk or negedge Rst_n) if(!Rst_n) clk_1K <= 1'b0; else if(divider_cnt == 24999) clk_1K <= ~clk_1K; else clk_1K <= clk_1K; |
再编写8位循环移位寄存器,这里利用循环移位寄存器实现0000_0001 ->1000_0000的变化,进而实现数码管的位选,即实现每个扫描时钟周期选择一个数码管。移位寄存器输出值与数码管选通的对应关系如表10-4所示,其中sel7为高位。
sel0 |
sel1 |
sel2 |
sel3 |
sel4 |
sel5 |
sel6 |
sel7 |
|
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
数码管0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
数码管1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
数码管2 |
…… |
||||||||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
数码管7 |
表10-4 移位寄存器与数码管对应关系
reg [7:0]sel_r; always@(posedge clk_1K or negedge Rst_n) if(!Rst_n) sel_r <= 8'b0000_0001; else if(sel_r == 8'b1000_0000) sel_r <= 8'b0000_0001; else sel_r <= sel_r << 1; |
利用8选1多路器,选择端为当前扫描到的数码管,利用多路器将待显示数据输送到对应到数码管上。
reg [3:0]data_tmp; always@(*) case(sel_r) 8'b0000_0001:data_tmp = disp_data[3:0]; 8'b0000_0010:data_tmp = disp_data[7:4]; 8'b0000_0100:data_tmp = disp_data[11:8]; 8'b0000_1000:data_tmp = disp_data[15:12]; 8'b0001_0000:data_tmp = disp_data[19:16]; 8'b0010_0000:data_tmp = disp_data[23:20]; 8'b0100_0000:data_tmp = disp_data[27:24]; 8'b1000_0000:data_tmp = disp_data[31:28]; default:data_tmp = 4'b0000; endcase |
前面所说如果要使数码管显示数字或字符,须对数字或字符进行编码译码。这里利用一个4输入查找表,来实现7位输出用做显示译码。
always@(*) case(data_tmp) 4'h0:seg = 7'b1000000; 4'h1:seg = 7'b1111001; 4'h2:seg = 7'b0100100; 4'h3:seg = 7'b0110000; 4'h4:seg = 7'b0011001; 4'h5:seg = 7'b0010010; 4'h6:seg = 7'b0000010; 4'h7:seg = 7'b1111000; 4'h8:seg = 7'b0000000; 4'h9:seg = 7'b0010000; 4'ha:seg = 7'b0001000; 4'hb:seg = 7'b0000011; 4'hc:seg = 7'b1000110; 4'hd:seg = 7'b0100001; 4'he:seg = 7'b0000110; 4'hf:seg = 7'b0001110; endcase |
模块化的设计理念是每个模块以后调用以及控制方便,基于这种理念,这里需要加入使能信号。关于使能子模块,直接利用一个二选一多路器即可实现。
assign sel = (En)?sel_r:8'b0000_0000; |
进行分析和综合直至没有错误以及警告。
为了测试仿真编写测试激励文件,新建HEX8_tb.v文件保存到testbench文件夹下,除编写正常的时钟外,输入以下内容再次进行分析和综合直至没有错误以及警告。以下生成了复位信号以及使能信号、待显示数据的初始化以及切换,分别在数码管上显示87654321以及89abcdef。
initial begin Rst_n = 1'b0; En = 1; disp_data = 32'h12345678; #(`clk_period*20); Rst_n = 1; #(`clk_period*20); #20000000; disp_data = 32'h87654321; #20000000; disp_data = 32'h89abcdef; #20000000; $stop; end |
设置好仿真脚本后进行功能仿真,可以看到如图10-5所示的局部波形文件,可以看出在复位信号置高之前数码管均显示0,在复位结束后数码管才开始正常显示,且当待显示数据为32'h89abcdef(MSB)后,数码管从1到8依次被选通且分别显示为FEDCBA98(LSB)。即仿真通过。
图10-5 数码管功能仿真波形图
为了更便捷的进行板级调试,这里介绍Qusrtus II自带的的In system sources and probes editor(ISSP)调试工具,测试数码管可以只用其提供的源,探针等到后面的RAM中再做详细介绍。这样测试整体模块框图就可以简化为如图10-6所示。
图10-6 测试激励整体框图
这里ISSP是以IP核的形式提供的,因此第一步单击Tools—Mega Wizard Plug-In Manager来启动Mega Wizard插件管理器,并新建一个定制IP核;
图10-7 启动Mega Wizard插件管理器
在弹出的图10-8 Mega Wizard插件管理器的参数设置界面中,找到JTAG-accessible Extensions下选择In-System Source and Probes,并将输出目录确定为工程文件夹下的ip文件夹,并以hex_data保存,单击Next。
在弹出的图10-9配置界面中将源位宽定义为32,探针位宽定义为0,然后单击Next即可。
图10-8 Mega Wizard插件管理器参数设置
图10-9-1 ISSP配置界面
图10-9-2 ISSP配置界面
图10-9-3 ISSP配置界面
在本工程目录的rtl文件夹下新建verilog file文件在此文件下输入以下内容并以HEX_top.v保存,并设置为顶层文件。
module HXE_top(Clk,Rst_n,sel,seg);
input Clk; //50M input Rst_n;
output [7:0] sel;//数码管位选(选择当前要显示的数码管) output [6:0] seg;//数码管段选(当前要显示的内容)
wire[31:0]disp_data;
hex_data hex_data( .probe(), .source(disp_data) );
HXE8 HXE8( .Clk(Clk), .Rst_n(Rst_n), .En(1'b1), .disp_data(disp_data), .sel(sel), .seg(seg) ); endmodule |
分配引脚后全编译无误后下载工程到开发板中。这时可以看到数码管全显示0,与设计一致。在Quartus II中点击Tools—In-System Source and Probes Editor启动ISSP,启动后的界面如图10-11所示。这里需手动选择下载器,并将数据格式改为设计中的hex格式。
图10-10 启动ISSP
图10-11 ISSP操作界面
图10-12 切换数据格式
这样ISSP界面的Data中输入相应的数据即可在数码管上看到与之对应的显示,如图10-13所示。
图10-13 数码管显示数据
至此完成了数码管的动态显示。本节主要介绍了数码管显示数字原理、数码管动态扫描显示原理以及In system sources and probes editor(ISSP)调试工具的基本使用。