FPGA数码管动态扫描技术详解:从原理到Verilog实现
创作时间:
作者:
@小白创作中心
FPGA数码管动态扫描技术详解:从原理到Verilog实现
引用
CSDN
1.
https://blog.csdn.net/m0_58544042/article/details/142529023
数码管动态扫描是FPGA应用中的一个经典案例,通过控制数码管的选通信号和段码信号,可以在有限的硬件资源下实现多位数码管的显示。本文将从数码管动态扫描的原理、逻辑建模到Verilog代码实现进行详细讲解。
数码管动态扫描原理
下图是常见的数码管样式:
我们通过控制a、b、c、d、e、f、g、dp这8个管脚来实现从0到F(15)的数码显示,其内部结构如下:
可以看到数码有共阴极和共阳极两种接法,控制各个端口的高低电平即可实现数码显示,其中SEL为选通信号;两种接法对应数码显示的对照表如下:
控制多个数码管的结构如图:
可以看到,多个数码管共用管脚,这样做节省了引脚,只需通过SEL信号进行选通控制实现不同数码管的亮灭;
逻辑建模
我们预实现8个LED灯按照预设的数据进行点亮;
逻辑建模过程如下:
- 控制实现不同LED灯点亮,需要设计点亮时间间隔,已知人眼的视觉暂留为20ms,所以要设计间隔小于20ms,这样在人眼中8个LED灯就是同时点亮的,选取间隔为1ms,因此需要设计1ms计数器。
- 共8个LED灯,即8个状态,每隔1ms为一个状态,因此需要用1ms计数器控制计数值为8的计数器计数,这样就实现了不同时刻选通不同LED灯。
- 在某一时刻确定了要点亮的LED灯后,需要明确要显示的数值,因此选通信号要控制一个8选1选择器,这个选择器的8个端口分别为8个时刻想要显示的数码值。
- 确定某一时刻数码管要显示的值后,需要将该数值用共阴极或共阳极的二进制方式进行表示,此时才能正确的显示。
原理图大致如下:
Verilog代码实现
由于代码各部分均较简单,直接附代码如下:
module Hex_8(clk,restn,led_data,sel,seg);
input clk,restn;
input [31:0]led_data;
output reg [7:0]sel;
output reg [7:0]seg;
parameter clk_freq = 50_000_000;
parameter led_freq = 1000;
parameter MCNT = clk_freq/led_freq-1;
//1ms 时钟计数器
reg [29:0]clk_1ms;
always@(posedge clk or negedge restn)
if(!restn)
clk_1ms<=0;
else if(clk_1ms==MCNT)
clk_1ms<=0;
else
clk_1ms<=clk_1ms+1;
//位计数器
reg[2:0]cnt;
always@(posedge clk or negedge restn)
if(!restn)
cnt<=0;
else if(clk_1ms==MCNT)
cnt<=cnt+1;
//3_8译码器
always@(posedge clk or negedge restn)
if(!restn)
sel<=8'b0000_0000;
else
case(cnt)
3'd0:sel<=8'b0000_0001;
3'd1:sel<=8'b0000_0010;
3'd2:sel<=8'b0000_0100;
3'd3:sel<=8'b0000_1000;
3'd4:sel<=8'b0001_0000;
3'd5:sel<=8'b0010_0000;
3'd6:sel<=8'b0100_0000;
3'd7:sel<=8'b1000_0000;
endcase
//输入数据定义
reg [3:0]data_temp;
always@(*)
case(cnt)
3'd0:data_temp<=led_data[3:0];
3'd1:data_temp<=led_data[7:4];
3'd2:data_temp<=led_data[11:8];
3'd3:data_temp<=led_data[15:12];
3'd4:data_temp<=led_data[19:16];
3'd5:data_temp<=led_data[23:20];
3'd6:data_temp<=led_data[27:24];
3'd7:data_temp<=led_data[31:28];
endcase
always@(posedge clk)
case(data_temp)
4'd0: seg<=8'b1100_0000;
4'd1: seg<=8'b1111_1001;
4'd2: seg<=8'b1010_0100;
4'd3: seg<=8'b1011_0000;
4'd4: seg<=8'b1001_1001;
4'd5: seg<=8'b1001_0010;
4'd6: seg<=8'b1000_0010;
4'd7: seg<=8'b1111_1000;
4'd8: seg<=8'b1000_0000;
4'd9: seg<=8'b1001_0000;
4'd10:seg<=8'b1000_1000;
4'd11:seg<=8'b1000_0011;
4'd12:seg<=8'b1100_0110;
4'd13:seg<=8'b1010_0001;
4'd14:seg<=8'b1000_0110;
4'd15:seg<=8'b1000_1110;
endcase
endmodule
测试代码:
`timescale 1ns / 1ns
module Hex_8_tb();
reg clk;
reg restn;
reg[31:0]led_data;
wire[7:0]sel;
wire[7:0]seg;
Hex_8 Hex_8_inst(
.clk(clk),
.restn(restn),
.led_data(led_data),
.sel(sel),
.seg(seg)
);
initial begin
restn = 0;
#201
restn = 1;
#1000
led_data = 32'h2024_0925;
#10000000
$stop;
end
initial clk = 1;
always #10 clk = ~clk;
endmodule
仿真结果:(输入数据为20240925)经过对照表格,也是没有问题的
热门推荐
商鞅变法:是革新还是灾难?探讨商鞅的历史地位!
英语未来式——Be going to 和 Will,如何选择?
神秘符号揭示PLC的秘密,解读 PLC 计数器的奥秘
CAD圆弧绘制技巧详解:从基础到实战
法律上的因果关系怎么理解
换手率越高说明什么?高换手率反映了怎样的市场现象?
观察 | 紧日子政策下,公立医院医护人员薪酬的未来走向
电磁学-高斯定理的证明和应用
新干线路线扩张,阴云笼罩,前途多舛
司美替尼Selumetinib的副作用管理与患者生活质量提升策略
幼儿园教育价值
湛江就业困局:如何破局迎接转型挑战
普洱茶知识:保健功效与饮用指南
现代控制理论:应用实例分析与故障诊断的深入教程
随风而逝的“桂陵柿叶”
研究生去日本留学贵吗?全面解析留学成本与性价比!
MBTI人格类型全解析:从领袖型到完美主义者
4K分辨率为何不如1080p清晰
对称加密算法的原理和优缺点
怎样远离紫外线辐射呢?
数字化时代的财务管理:挑战与机遇
直播间“文物”泛滥!鉴宝直播真的靠谱吗?
易经与中医:源远流长的理论纽带
近红外光谱技术煤质检测革新:在线化转型与工业智能化实践
液相色谱分析中峰拖尾的原因与解决方案
大数据医疗:5大应用、5个痛点、5种趋势
大名鼎鼎的10大阴间恐怖动漫,全看过的都是狠人
怎样在银行办理对公账户的销户?
开源路由操作系统OpenWrt详解
合肥职业技术学院:合肥市唯一市属公办综合性高职院校