基于Vivado的四位数码管扫描显示VHDL实现
最近在学习FPGA,记录一下自己遇到的一些问题。
一、所需平台:
1、硬件平台:basys3(XILINX);
2、开发软件:vivado2017.4;
3、使用语言:VHDL;
二、遇到的一些问题:
1、位选信号扫描频率大概在1000hz左右,显示正常。频率过高显示乱码,过低则会出现闪烁。(利用人眼暂留原理)
2、由1可知,我们要涉及到时钟分频。开发板时钟为100MHZ,所以分频数N为100000,用计数器分频时,计数个数为(m=N/2-1),一定要给计数赋初值,否则无法计数,导致没有分频。还有就是目标分频时钟clk_f也要赋初值。
3、数码管的位选及单个数码管的段选信号,一定要分清楚是共阴还是共阳,及高电平/低电平有效。(basys3是共阳,低电平有效)
4、数码管的段控制信号的顺序一定要和管脚约束相匹配,八段数码管段由低到高位为(abcdefgh)。(h为小数点,有些没有)
三、相关代码:
1、代码
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity scan_led is
Port ( clk : in STD_LOGIC;
seg : out STD_LOGIC_VECTOR (7 downto 0); --段显示控制信号
scan : out STD_LOGIC_VECTOR (3 downto 0)); --数码管地址选择控制信号
end scan_led;
architecture Behavioral of scan_led is
signal cnt4 : integer range 0 to 3;
signal data : integer range 0 to 15;
signal cnt : integer range 0 to 49999:=0;
signal clk_f: std_logic:='0';
begin
--时钟分频产生1000hz
clk_f_gen:process(clk)
begin
if(clk'event and clk='1')then
cnt<=cnt+1;
if(cnt=49999)then
cnt<=0;
end if;
end if;
end process;
process(clk)
begin
if(clk'event and clk='1')then
if(cnt=0)then
clk_f<=not clk_f;
end if;
end if;
end process;
--用于扫描数码管地址的计数器
process(clk)
begin
if(clk_f'event and clk_f='1')then
cnt4<=cnt4+1;
if(cnt4=3) then
cnt4<=0;
end if;
end if;
end process;
--数码管地址扫描
process(clk)
begin
if(clk'event and clk='1')then
case cnt4 is
when 0 =>scan<="0111";
when 1 =>scan<="1011";
when 2 =>scan<="1101";
when 3 =>scan<="1110";
when others=>null;
end case;
end if;
end process;
--四个数码管分别显示的数字
process(clk)
begin
if(clk'event and clk='1')then
case cnt4 is
when 0 =>data<=0; --显示0223
when 1 =>data<=2;
when 2 =>data<=2;
when 3 =>data<=3;
when others=>null;
end case;
end if;
end process;
--七段译码
process(clk)
begin
if(clk'event and clk='1')then
case data is
when 0 =>seg<="00000011";
when 1 =>seg<="10011111";
when 2 =>seg<="00100101";
when 3 =>seg<="00001101";
when 4 =>seg<="10011001";
when 5 =>seg<="01001001";
when 6 =>seg<="01000001";
when 7 =>seg<="00011111";
when 8 =>seg<="00000001";
when 9 =>seg<="00001001";
when 10 =>seg<="00010001";
when 11 =>seg<="11000001";
when 12 =>seg<="01100011";
when 13 =>seg<="10000101";
when 14 =>seg<="01100001";
when 15 =>seg<="01110001";
when others=>null;
end case;
end if;
end process;
end Behavioral;
2、testbench文件:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity scan_tb is
-- Port ( );
end scan_tb;
architecture Behavioral of scan_tb is
component scan_led
port(
clk : in STD_LOGIC;
seg : out STD_LOGIC_VECTOR (7 downto 0);
scan : out STD_LOGIC_VECTOR (3 downto 0)
);
end component;
--输入信号
signal clk : STD_LOGIC := '0';
--输出信号
signal seg : STD_LOGIC_VECTOR(7 downto 0);
signal scan : STD_LOGIC_VECTOR(3 downto 0);
--时钟周期的定义
constant clk_period:time:=20ns;
begin
instant: scan_led port map
(
clk=>clk,seg=>seg,scan=>scan
);
clk_gen:process
begin
clk<='1';
wait for clk_period/2;
clk<='0';
wait for clk_period/2;
end process;
end Behavioral;
3、约束文件xdc:
set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
set_property PACKAGE_PIN W7 [get_p