开发者

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;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜