基于VHDL的数码管动态扫描电路设计,四个数码管累加显示数字0000-9999,间隔1秒。FPGA型号:EP4CE6E22C8,开发环境:Quartus18.1
一、硬件设备是FPGA入门开发板EP4CE6E22C8,数码管的原理图如下:

段选信号abcdefh是低电平有效,其中h是数码管右下角的小数点。CC1-CC4为四个数码管的片选信号,也是低电平有效。
二、数码管段选信号abcdefgh与数字0-9的对应表如下:
| abcdefgh电平 | 数字字符 |
| 0000 0011 | 0 |
| 1001 1111 | 1 |
| 0010 0101 | 2 |
| 0000 1101 | 3 |
| 1001 1001 | 4 |
| 01001001 | 5 |
| 0100 0001 | 6 |
| 0001 1011 | 7 |
| 0000 0001 | 8 |
| 0000 1001 | 9 |
三、设计思路:
由于四个数码管的段选信号是并联在一起的,所以要做到四个数码管能分别显示不同的字符,那么就控制片选信号CC1-CC4在一个时间点,只有一个片选信号有效,即一个时间节点只有一个数码管显示字符。将片选信号CC1-CC4选择使能的时间加快,利用人眼的视觉暂留现象,就可以四个数码管同时显示了。单个数码管的刷新频率大于50Hz就可以达到效果,四个数码轮流刷新,所以整体刷新频率为200Hz。
1、计数模块 2、显示(译码)模块 3、刷新显示模块
1、计数模块:
本实验要达到间隔1s计数,那么需要一个1Hz的时钟,时钟源为50MHz。
--1s时钟模块
Module_1Hz : process(clk)beginif(clk'event and clk='1')thenif(cnt_50MHz=49999999)thencnt_50MHz<=0;elsecnt_50MHz<=cnt_50MHz+1;end if;if(cnt_50MHz<=24999999)thenclk1Hz<=1;elseclk1Hz<=0;end if;end if;
end process module_1Hz;
--1s计数模块,四个数码管累加显示数字,范围0000-9999
Module_cnt : process(clk1Hz) beginif(clk1Hz'event and clk1Hz=1)then if(cnt_One=9)thenif(cnt_Ten=9)thenif(cnt_Hundred=9)thenif(cnt_thousand=9)thencnt_thousand<=0;cnt_Hundred<=0;cnt_Ten<=0;cnt_One<=0;elsecnt_thousand<=cnt_thousand+1;cnt_Hundred<=0;cnt_Ten<=0;cnt_One<=0;end if;elsecnt_Hundred<=cnt_Hundred+1;cnt_Ten<=0;cnt_One<=0;end if;elsecnt_Ten<=cnt_Ten+1;cnt_One<=0;end if;elsecnt_One<=cnt_One+1;end if; end if;
end process Module_cnt;
2、译码模块:
四个数码管都要分别显示0-9的字符,随着计数的累加,数码管显示字符各有不同,所以刷新电路显示的字符需要经过译码,对应到每个数码的当前要显示的数字字符。
--译码电路1,数码管1动态字符查表
Module_Decoding_1 : process(cnt_One)begincase cnt_One iswhen 0 => ledag1 <= "00000011";--数字0when 1 => ledag1 <= "10011111";--数字1when 2 => ledag1 <= "00100101";--数字2when 3 => ledag1 <= "00001101";--数字3when 4 => ledag1 <= "10011001";--数字4when 5 => ledag1 <= "01001001";--数字5when 6 => ledag1 <= "01000001";--数字6when 7 => ledag1 <= "00011011";--数字7when 8 => ledag1 <= "00000001";--数字8when 9 => ledag1 <= "00001001";--数字9when others => Null;end case;
end process Module_Decoding_1;
3、刷新显示模块
--200Hz扫描模块
Module_200Hz : process(clk)begin if (clk'event and clk='1') thenif (cnt_200Hz=249999) thencnt_200Hz<=0;elsecnt_200Hz<=cnt_200Hz+1;end if;if(cnt_200Hz<=124999) thenclk200Hz<=1;elseclk200Hz<=0;end if;end if;if(clk200Hz'event and clk200Hz=1)thenif(scan=3)thenscan<=0;elsescan<=scan+1;end if;end if;
end process Module_200Hz;
--刷新显示模块 Module_SG : process(scan)begin case scan iswhen 0 => SG <= ledag1;BT <= "1110";--数码管1when 1 => SG <= ledag2;BT <= "1101";--数码管2when 2 => SG <= ledag3;BT <= "1011";--数码管3when 3 => SG <= ledag4;BT <= "0111";--数码管4when others => Null;end case;end process Module_SG;
完整的代码将在最后贴出。
四、引脚锁定 pin planner

注意: 此时使用了Pin101,建立工程后,pin101默认功能是nCEO而不是I/O功能。设定完引脚进行引脚定义分析时会报错。processing->start I/O Assignment Analysis.
处理方法:project>Generate Tcl File for Project

点击ok。(作用:使用Tcl功能,用代码修改引脚功能) 插入如下图红框中的代码。
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"

保存后,选择Tool> Tcl script

选择上方生成的.tcl文件,然后点击run即可。此时Pin101就被修改为I/O功能了。
五、完整代码(初学,代码逻辑不一定完美)
library ieee;
use ieee.std_logic_1164.all;entity scan_led isport(clk : in std_logic;--50MHzSG : out std_logic_vector(7 downto 0);--段控制信号输出,abcdefgh低电平有效(小数点h不显示,时钟保持高电平),单个数码管字符显示BT : out std_logic_vector(3 downto 0) --位控制信号输出,低电平有效,四个数码管的片选);
end scan_led;architecture behave of scan_led issignal scan : integer range 0 to 3;--扫描数码管个数signal cnt_50MHz : integer range 0 to 49999999;--输入时钟计数signal cnt_200Hz : integer range 0 to 249999;--200Hz时钟计数signal clk200Hz : integer range 0 to 1;--数码管扫描时钟signal clk1Hz : integer range 0 to 1;--1s计数时钟signal ledag1,ledag2,ledag3,ledag4 : std_logic_vector(7 downto 0);--四个数码管的动态字符显示signal cnt_One,cnt_Ten,cnt_Hundred,cnt_thousand:integer range 0 to 9 :=0;--数码管计数的个位、十位、百位、千位begin
--1s时钟模块
Module_1Hz : process(clk)beginif(clk'event and clk='1')thenif(cnt_50MHz=49999999)thencnt_50MHz<=0;elsecnt_50MHz<=cnt_50MHz+1;end if;if(cnt_50MHz<=24999999)thenclk1Hz<=1;elseclk1Hz<=0;end if;end if;
end process module_1Hz;--200Hz扫描模块
Module_200Hz : process(clk)begin if (clk'event and clk='1') thenif (cnt_200Hz=249999) thencnt_200Hz<=0;elsecnt_200Hz<=cnt_200Hz+1;end if;if(cnt_200Hz<=124999) thenclk200Hz<=1;elseclk200Hz<=0;end if;end if;if(clk200Hz'event and clk200Hz=1)thenif(scan=3)thenscan<=0;elsescan<=scan+1;end if;end if;
end process Module_200Hz;--1s计数模块,四个数码管累加显示数字,范围0000-9999
Module_cnt : process(clk1Hz) beginif(clk1Hz'event and clk1Hz=1)then if(cnt_One=9)thenif(cnt_Ten=9)thenif(cnt_Hundred=9)thenif(cnt_thousand=9)thencnt_thousand<=0;cnt_Hundred<=0;cnt_Ten<=0;cnt_One<=0;elsecnt_thousand<=cnt_thousand+1;cnt_Hundred<=0;cnt_Ten<=0;cnt_One<=0;end if;elsecnt_Hundred<=cnt_Hundred+1;cnt_Ten<=0;cnt_One<=0;end if;elsecnt_Ten<=cnt_Ten+1;cnt_One<=0;end if;elsecnt_One<=cnt_One+1;end if; end if;
end process Module_cnt;
--译码电路1,数码管1动态字符查表
Module_Decoding_1 : process(cnt_One)begincase cnt_One iswhen 0 => ledag1 <= "00000011";--数字0when 1 => ledag1 <= "10011111";--数字1when 2 => ledag1 <= "00100101";--数字2when 3 => ledag1 <= "00001101";--数字3when 4 => ledag1 <= "10011001";--数字4when 5 => ledag1 <= "01001001";--数字5when 6 => ledag1 <= "01000001";--数字6when 7 => ledag1 <= "00011011";--数字7when 8 => ledag1 <= "00000001";--数字8when 9 => ledag1 <= "00001001";--数字9when others => Null;end case;
end process Module_Decoding_1;--译码电路2,数码管2动态字符查表
Module_Decoding_2 : process(cnt_Ten)begincase cnt_Ten iswhen 0 => ledag2 <= "00000011";--数字0when 1 => ledag2 <= "10011111";--数字1when 2 => ledag2 <= "00100101";--数字2when 3 => ledag2 <= "00001101";--数字3when 4 => ledag2 <= "10011001";--数字4when 5 => ledag2 <= "01001001";--数字5when 6 => ledag2 <= "01000001";--数字6when 7 => ledag2 <= "00011011";--数字7when 8 => ledag2 <= "00000001";--数字8when 9 => ledag2 <= "00001001";--数字9when others => Null;end case;
end process Module_Decoding_2;--译码电路3,数码管3动态字符查表
Module_Decoding_3 : process(cnt_Hundred)begincase cnt_Hundred iswhen 0 => ledag3 <= "00000011";--数字0when 1 => ledag3 <= "10011111";--数字1when 2 => ledag3 <= "00100101";--数字2when 3 => ledag3 <= "00001101";--数字3when 4 => ledag3 <= "10011001";--数字4when 5 => ledag3 <= "01001001";--数字5when 6 => ledag3 <= "01000001";--数字6when 7 => ledag3 <= "00011011";--数字7when 8 => ledag3 <= "00000001";--数字8when 9 => ledag3 <= "00001001";--数字9when others => Null;end case;
end process Module_Decoding_3;--译码电路4,数码管4动态字符查表
Module_Decoding_4 : process(cnt_thousand)begincase cnt_thousand iswhen 0 => ledag4 <= "00000011";--数字0when 1 => ledag4 <= "10011111";--数字1when 2 => ledag4 <= "00100101";--数字2when 3 => ledag4 <= "00001101";--数字3when 4 => ledag4 <= "10011001";--数字4when 5 => ledag4 <= "01001001";--数字5when 6 => ledag4 <= "01000001";--数字6when 7 => ledag4 <= "00011011";--数字7when 8 => ledag4 <= "00000001";--数字8when 9 => ledag4 <= "00001001";--数字9when others => Null;end case;
end process Module_Decoding_4;
--刷新显示模块 Module_SG : process(scan)begin case scan iswhen 0 => SG <= ledag1;BT <= "1110";--数码管1when 1 => SG <= ledag2;BT <= "1101";--数码管2when 2 => SG <= ledag3;BT <= "1011";--数码管3when 3 => SG <= ledag4;BT <= "0111";--数码管4when others => Null;end case;end process Module_SG; end behave;
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
