Implementing A Digital Clock in VHDL
I am trying to make a digital clock using VHDL and I want to display the result on the VGA screen. But I am stuck with the idea that how can I convert the integer type into BCD? Because right now I am getting the hour, minute and second data as a integer and I would to implement it such that I can use it in my VGA compo开发者_StackOverflow社区nent in a most sufficient way. What would be your suggestion for that?
Thanks in advance!
If you want timers separately, you could use the division and modulo operators to convert the integers to BCD. However, that is most likely going to synthesize rather poorly. You might just implement six counters instead, something like this:
library ieee;
use ieee.std_logic_1164.all;
entity clock is
port (
resetAX : in std_logic; -- Asynchronous reset, active low
clk : in std_logic; -- Clock signal, runs faster than 1/second
second_enable : in std_logic; -- Signal active (high) only when seconds to be incremented
h_ms : out std_logic_vector(1 downto 0); -- MS digit of hour (0, 1, 2)
h_ls : out std_logic_vector(3 downto 0); -- LS digit of hour (0-9)
m_ms : out std_logic_vector(2 downto 0); -- MS digit of minute (0-5)
m_ls : out std_logic_vector(3 downto 0); -- LS digit of minute (0-9)
s_ms : out std_logic_vector(2 downto 0); -- MS digit of second (0-5)
s_ls : out std_logic_vector(3 downto 0) -- LS digit of second (0-9)
);
end clock;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture rtl of clock is
signal h_ms_int : integer range 0 to 2;
signal h_ls_int : integer range 0 to 9;
signal m_ms_int : integer range 0 to 5;
signal m_ls_int : integer range 0 to 9;
signal s_ms_int : integer range 0 to 5;
signal s_ls_int : integer range 0 to 9;
begin
COUNT: process(resetAX, clk)
begin
if resetAX = '0' then
h_ms_int <= 0;
h_ls_int <= 0;
m_ms_int <= 0;
m_ls_int <= 0;
s_ms_int <= 0;
s_ls_int <= 0;
elsif clk'event and clk='1' then
if second_enable = '1' then
if s_ls_int = 9 then
if s_ms_int = 5 then
if m_ls_int = 9 then
if m_ms_int = 5 then
if (h_ls_int = 9 or (h_ls_int=3 and h_ms_int=2)) then
if (h_ls_int=3 and h_ms_int=2) then
h_ms_int <= 0;
else
h_ms_int <= h_ms_int + 1;
end if;
h_ls_int <= 0;
else
h_ls_int <= h_ls_int + 1;
end if;
m_ms_int <= 0;
else
m_ms_int <= m_ms_int + 1;
end if;
m_ls_int <= 0;
else
m_ls_int <= m_ls_int + 1;
end if;
s_ms_int <= 0;
else
s_ms_int <= s_ms_int + 1;
end if;
s_ls_int <= 0;
else
s_ls_int <= s_ls_int + 1;
end if;
end if;
end if;
end process COUNT;
h_ms <= std_logic_vector(to_unsigned(h_ms_int, h_ms'length));
h_ls <= std_logic_vector(to_unsigned(h_ls_int, h_ls'length));
m_ms <= std_logic_vector(to_unsigned(m_ms_int, m_ms'length));
m_ls <= std_logic_vector(to_unsigned(m_ls_int, m_ls'length));
s_ms <= std_logic_vector(to_unsigned(s_ms_int, s_ms'length));
s_ls <= std_logic_vector(to_unsigned(s_ls_int, s_ls'length));
end rtl;
These are pretty small counters, so it shouldn't be too huge even with the slightly complex wrapping logic. I can't check the size of that at home since I don't have any synthesis tools available here, but I expect it should be smaller than divide-by-ten and modulo-ten logic.
What do you mean by "implement in a most sufficient (efficient?) way"? Do you mean not using 32 bits X 3 to store the time?
Does it have to be in BCD? You can just limit the size of your integers: 5 bits for the hour, 6 bits for the minute, and 6 bits for the second:
SIGNAL hour: INTEGER RANGE 0 TO 23;
SIGNAL minute: INTEGER RANGE 0 TO 59;
SIGNAL second: INTEGER RANGE 0 TO 59;
If they all need to be in one variable you could put them all into a bit vector of 17 bits.
SIGNAL time: BIT_VECTOR( 16 DOWNTO 0 );
time( 16 DOWNTO 12) <= hour;
time( 11 DOWNTO 6) <= minute;
time( 5 DOWNTO 0) <= second;
精彩评论