【 FPGA 】四位16进制的数码管动态显示设计
【摘要】 数码管的动态显示是对每个数码管采用分时复用的方式轮流点亮每个数码管,在同一时间只会点亮一个数码管。
分时复用的扫描显示利用了人眼的视觉暂留特性,如果公共端的控制信号刷新速度足够快,人眼就不会区分出LED的闪烁,认为4个数码管是同时点亮。
如下图:
D1、D2、D3、D4就是公共控制端口,也就是片选端,控制哪一个数码管被选中。
而abcdefg是段选,用来控制数码管...
数码管的动态显示是对每个数码管采用分时复用的方式轮流点亮每个数码管,在同一时间只会点亮一个数码管。
分时复用的扫描显示利用了人眼的视觉暂留特性,如果公共端的控制信号刷新速度足够快,人眼就不会区分出LED的闪烁,认为4个数码管是同时点亮。
如下图:
D1、D2、D3、D4就是公共控制端口,也就是片选端,控制哪一个数码管被选中。
而abcdefg是段选,用来控制数码管的显示内容。
下面代码中的an就是片选端,以及控制信号一致的输出段码信号sseg。片选控制信号的刷新速度必须足够快才能避免闪烁感,但也不能太快,以免影响数码管的开关切换,最佳的工作频率为1000Hz左右。如果FPGA的时钟为50MHz,那么至少跑5*10^4个周期,也即50000个周期刷新一次才行,我们知道2^16=65536,2^15=32768。
所以,用16位2进制数来控制技术吧,技术满了刷新一次。
代码中采用的是18位2进制数,高2位控制片选,低16位计数满一次,进位一次,高两位的变化时00——01——10——11——00——...,分别选中数码管的其中之一,使用case语句即可完成这个功能。
下面代码中的hex0、hex1、hex2、hex3是输入信号,用来控制数码管显示的数字,dp_in用来控制小数点的亮灭。
Verilog HDL描述如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 21:03:02 01/05/2019
// Design Name:
// Module Name: scan_led_hex_disp
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module scan_led_hex_disp(
input clk,
input reset,
input [3:0] hex0, //第一个数码管显示的数字
input [3:0] hex1,
input [3:0] hex2,
input [3:0] hex3,
input [3:0] dp_in, //小数点控制
output reg [3:0] an, //片选
output reg [7:0] sseg //段选
);
localparam N = 18; //使用低16位对50Mhz的时钟进行分频(50MHZ/2^16)
reg [N-1:0] regN; //高两位作为控制信号,低16位为计数器,对时钟进行分频
reg [3:0] hex_in; //段选控制信号
reg dp;
always@(posedge clk, posedge reset)
begin
if(reset)
regN <= 0;
else
regN <= regN + 1;
end
always@ *
begin
case(regN[N-1:N-2])
2'b00:begin
an = 4'b1110; //选中第1个数码管
hex_in = hex0; //数码管显示的数字由hex_in控制,显示hex0输入的数字;
dp = dp_in[0]; //控制该数码管的小数点的亮灭
end
2'b01:begin
an = 4'b1101; //选中第二个数码管
hex_in = hex1;
dp = dp_in[1];
end
2'b10:begin
an = 4'b1011;
hex_in = hex2;
dp = dp_in[2];
end
default:begin
an = 4'b0111;
hex_in = hex3;
dp = dp_in[3];
end
endcase
end
always@ *
begin
case(hex_in)
4'h0: sseg[6:0] = 7'b0000001; //共阳极数码管
4'h1: sseg[6:0] = 7'b1001111;
4'h2: sseg[6:0] = 7'b0010010;
4'h3: sseg[6:0] = 7'b0000110;
4'h4: sseg[6:0] = 7'b1001100;
4'h5: sseg[6:0] = 7'b0100100;
4'h6: sseg[6:0] = 7'b0100000;
4'h7: sseg[6:0] = 7'b0001111;
4'h8: sseg[6:0] = 7'b0000010;
4'h9: sseg[6:0] = 7'b0000100;
4'ha: sseg[6:0] = 7'b0001000;
4'hb: sseg[6:0] = 7'b1100000;
4'hc: sseg[6:0] = 7'b0110001;
4'hd: sseg[6:0] = 7'b1000010;
4'he: sseg[6:0] = 7'b0110000;
default: sseg[6:0] = 7'b0111000;
endcase
sseg[7] = dp;
end
endmodule
共阳极数码管码表:
4'h0: sseg[6:0] = 7'b0000001; //共阳极数码管
4'h1: sseg[6:0] = 7'b1001111;
4'h2: sseg[6:0] = 7'b0010010;
4'h3: sseg[6:0] = 7'b0000110;
4'h4: sseg[6:0] = 7'b1001100;
4'h5: sseg[6:0] = 7'b0100100;
4'h6: sseg[6:0] = 7'b0100000;
4'h7: sseg[6:0] = 7'b0001111;
4'h8: sseg[6:0] = 7'b0000010;
4'h9: sseg[6:0] = 7'b0000100;
4'ha: sseg[6:0] = 7'b0001000;
4'hb: sseg[6:0] = 7'b1100000;
4'hc: sseg[6:0] = 7'b0110001;
4'hd: sseg[6:0] = 7'b1000010;
4'he: sseg[6:0] = 7'b0110000;
为了验证上述代码的实际效果,用下列代码调用上述代码来测试:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 14:05:56 01/06/2019
// Design Name:
// Module Name: scan_led_hex_disp_test
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module scan_led_hex_disp_test(
input clk,
input [3:0] sw,
output [3:0] an,
output [7:0] sseg
);
wire [3:0] a,b;
wire [7:0] sum;
assign a = {2'b00,sw[1:0]};
assign b = {2'b00,sw[3:2]};
assign sum = {4'b0,a}+{4'b0,b};
scan_led_hex_disp uu1(
.clk(clk),.reset(1'b0),
.hex3(sum[7:4]),.hex2(sum[3:0]),
.hex1(b),.hex0(a),
.dp_in(4'b1011),.an(an),.sseg(sseg)
);
endmodule
功能是两个数码管用来显示数字a和b,而其他两个数码管显示a和b之和。
文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。
原文链接:reborn.blog.csdn.net/article/details/85881999
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)