本文使用VHDL语言设计10进制减法计数器,附带清零和置数功能。将项目分为分频器、计数器、数码管三个部分,采用元器件例化的方式,自顶向下设计。
一、代码
1.1 顶层文件
顶层文件将三个模块元器件例化和元器件映射。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity CNT10 is
port(
CLK,RST,EN: in std_logic;
data_hex : out std_logic_vector(7 downto 0);
DOUT : out std_logic_vector (3 downto 0);
COUT : OUT std_logic;
DINT : in std_logic_vector(3 downto 0);
DCON : in std_logic;
Dtest : out std_logic;
DtestMORE : out std_logic_vector(3 downto 0)
);
end CNT10;
architecture behav of CNT10 is
component digital is
port(
data : IN std_logic_vector(3 downto 0);
show : OUT std_logic_vector(7 downto 0);
com : OUT std_logic_vector(3 downto 0)
);
end component digital;
component Counter1 is
port(
clk : IN std_logic;
en : IN std_logic;
out1 : out std_logic
);
end component Counter1;
component count10 is
port(
signal clk,rst,en : in std_logic;
signal DCON : in std_logic;
signal DINT : in std_logic_vector(3 downto 0);
signal q : inout std_logic_vector(3 downto 0)
);
end component count10;
signal clk1 : std_logic;
signal data_sum : std_logic_vector(7 downto 0);
signal data_get : std_logic_vector(3 downto 0);
signal cq10 : std_logic_vector(3 downto 0) := (others => '0');
begin
part1:
Counter1 port map
(
clk => CLK,
en => EN,
out1 => clk1
);
part2:
count10 port map
(
clk => clk1,
rst => RST,
en => EN,
DCON => DCON,
DINT => DINT,
q => cq10
);
part3:
digital port map
(
data => data_get,
show => data_sum,
com => DOUT
);
Dtest <= clk1;
DtestMORE <= cq10;
data_hex <= data_sum;
data_get <= cq10;
end behav;
1.2 分频器
分频器用于将clk时钟信号放大相应倍数,否则由于时钟频率太高,计数值的减少效果看不出。out1为分频后的clk信号。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
entity Counter1 is
port
(
clk : in std_logic;
en : in std_logic;
out1 : out std_logic
);
end Counter1;
architecture Behavioral of Counter1 is
signal cp : std_logic_vector(25 downto 0) :=(others => '0');
signal clk1 : std_logic := '0';
begin
process(clk)
begin
if clk 'event and clk = '1' then
if en = '1' then
if cp = "10111110101111000010000000" then
cp <= "00000000000000000000000000";
clk1 <= not clk1;
else
cp <= cp + 1;
end if;
out1 <= clk1;
end if;
end if;
end process;
end Behavioral;
1.3 计数器
计数器实现从9倒数到0,每秒倒数一次。rst为清零端,DCON为置数端,置数的数据为DINT。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_Logic_unsigned.all;
entity count10 is
port(
signal clk,rst,en : in std_logic;
signal DCON : in std_logic;
signal DINT : in std_logic_vector(3 downto 0);
signal q : out std_logic_vector(3 downto 0)
);
end count10;
architecture Behavioral of count10 is
signal cq10 : std_logic_vector(3 downto 0) := (others => '0');
begin
process(clk,rst,en)
begin
if rst = '1' then -- 清零
cq10 <= "0000";
elsif clk'event and clk = '1' then
if en = '1' then
if DCON = '1' then --置数
cq10 <= DINT;
elsif cq10 = "0000" then
cq10 <= "1001";
else
cq10 <= cq10 - '1';
end if;
end if;
end if;
end process;
q <= cq10;
end Behavioral;
1.4 数码管
数码管将计数器输出的值转译为数码管的段码而输出。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity digital is
port(
data : IN std_logic_vector(3 downto 0);
show : OUT std_logic_vector(7 downto 0);
com : OUT std_logic_vector(3 downto 0)
);
end digital;
architecture Behavioral of digital is
begin
com <="1110"; --- 选中四个数码管中的最低位
process(data)
begin
case data is
WHEN "0000" => show <= "11000000";
WHEN "0001" => show <= "11111001";
WHEN "0010" => show <= "10100100";
WHEN "0011" => show <= "10110000";
WHEN "0100" => show <= "10011001";
WHEN "0101" => show <= "10010010";
WHEN "0110" => show <= "10000010";
WHEN "0111" => show <= "11111000";
WHEN "1000" => show <= "10000000";
WHEN "1001" => show <= "10010000";
when others => show <= "11111111";
end case;
end process;
end Behavioral;
二、仿真
创建VHDL Test Bench文件,在代码中begin后加入使能EN<=‘1’;代码。(注意仿真时需要将分频器、计数器赋初值,否则仿真将无数据。当然下载到器件上时却不需要初值,因为板子的高低电平有初值,而仿真却需要人为设定。)
ps:仿真时请修改分频器cp的值,否则无法仿真出。
从仿真波形可以看出从9开始计数到0并循环不断。仿真时分频器设置为2倍频,从dtest参数可以看出,dtest参数的值为分频器的输出(看前面1.1顶层文件)。而dtestmore和data_hex的值对应于数码管所对应的值。
最后,如果需要完整工程的可以去下载:FPGA-VHDL实现十进制减法计数器。