The codes are shared below. They are commented to help you understand the logic. For a detailed understanding watch the video. Also please make sure to like the video if it was helpful and subscribe to my YouTube channel for more such videos in the future.
Digital Clock:
--Declare the libraries library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; --we need this one because we are using "unsigned" data type. entity digital_clock is --frequency of the clock passed as a generic parameter. generic( CLOCK_FREQ : integer := 50000000 ); port( Clock : in std_logic; --system clock reset : in std_logic; --resets the time inc_secs : in std_logic; --set a pulse here to increment the seconds by 1. inc_mins : in std_logic; --set a pulse here to increment the minutes by 1. inc_hrs : in std_logic; --set a pulse here to increment the hours by 1. seconds :out unsigned(5 downto 0); --seconds output minutes :out unsigned(5 downto 0); --minutes output hours :out unsigned(4 downto 0) --hours output ); end digital_clock; architecture Behavioral of digital_clock is
--temperory signals as we cant directly perform arithmetic operations on outputs
signal secs, mins, hrs : integer := 0;
--counter used for getting the 1 sec duration from the system Clock.
signal counter : integer := 0;
begin
process(Clock, reset)
begin
if(reset = '1') then --reset the time.
secs <= 0;
mins <= 0;
hrs <= 0;
counter <= 0;
elsif(rising_edge(Clock)) then
--increment the seconds. also increment mins and hours if needed.
if(inc_secs = '1') then
if(secs = 59) then
secs <= 0;
if(mins = 59) then
mins <= 0;
if(hrs = 23) then
hrs <= 0;
else
hrs <= hrs+1;
end if;
else
mins <= mins+1;
end if;
else
secs <= secs + 1;
end if;
--increment the minutes. also increment hours if needed.
elsif(inc_mins = '1') then
if(mins = 59) then
mins <= 0;
if(hrs = 23) then
hrs <= 0;
else
hrs <= hrs+1;
end if;
else
mins <= mins+1;
end if;
--increment the hours.
elsif(inc_hrs = '1') then
if(hrs = 23) then
hrs <= 0;
else
hrs <= hrs+1;
end if;
end if;
--regular operation of the clock
if(counter = CLOCK_FREQ-1) then --counting CLOCK_FREQ times takes 1 second.
counter <= 0;
--check and change values of secs, mins and hours
if(secs = 59) then
secs <= 0;
if(mins = 59) then
mins <= 0;
if(hrs = 23) then
hrs <= 0;
else
hrs <= hrs+1;
end if;
else
mins <= mins+1;
end if;
else
secs <= secs + 1;
end if;
else
counter <= counter+1;
end if;
end if;
end process;
--The internal integer signals are converted into unsigned format.
--The size of the output unsigned signal is assigned via the 2nd parameter(5 or 6 bits)
seconds <= to_unsigned(secs, 6); minutes <= to_unsigned(mins, 6); hours <= to_unsigned(hrs, 5); end Behavioral;
Testbench:
LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; --the below library is used for finishing the simulation after we are done.
--Otherwise it will run continuously. library std; use std.env.finish; ENTITY tb_digitalClock IS END tb_digitalClock; ARCHITECTURE behavior OF tb_digitalClock IS -- Component Declaration for the Unit Under Test (UUT) COMPONENT digital_clock generic( CLOCK_FREQ : integer := 50000000 ); PORT( Clock : IN std_logic; reset : IN std_logic; inc_secs : IN std_logic; inc_mins : IN std_logic; inc_hrs : IN std_logic; seconds : OUT unsigned(5 downto 0); minutes : OUT unsigned(5 downto 0); hours : OUT unsigned(4 downto 0) ); END COMPONENT; --Inputs signal Clock : std_logic := '0'; signal reset : std_logic := '0'; signal inc_secs : std_logic := '0'; signal inc_mins : std_logic := '0'; signal inc_hrs : std_logic := '0'; --Outputs signal seconds : unsigned(5 downto 0); signal minutes : unsigned(5 downto 0); signal hours : unsigned(4 downto 0); -- Clock period definitions constant Clock_period : time := 10 ns; --Clock frequency in Hz. Use a smaller value for testbench.
--When testing on board it need to be set as 50 million, 100 million etc. constant CLOCK_FREQ : integer := 10; BEGIN -- Instantiate the Unit Under Test (UUT) uut: digital_clock GENERIC MAP(CLOCK_FREQ => CLOCK_FREQ) PORT MAP ( Clock => Clock, reset => reset, inc_secs => inc_secs, inc_mins => inc_mins, inc_hrs => inc_hrs, seconds => seconds, minutes => minutes, hours => hours ); -- Clock process definitions Clock_process :process begin Clock <= '0'; wait for Clock_period/2; Clock <= '1'; wait for Clock_period/2; end process; -- Stimulus process stim_proc: process begin reset <= '1'; -- hold reset state for 100 ns. wait for 100 ns; reset <= '0'; wait for Clock_period*CLOCK_FREQ*60*60*25; --run the clock for 25 hours --increment seconds inc_secs <= '1'; wait for Clock_period; inc_secs <= '0';
wait for Clock_period*CLOCK_FREQ*5; --wait for 5 secs after incrementing seconds once. --increment seconds 60 times inc_secs <= '1'; wait for Clock_period*60; inc_secs <= '0';
wait for Clock_period*CLOCK_FREQ*5; --wait for 5 secs after incrementing seconds. --increment minutes inc_mins <= '1'; wait for Clock_period; inc_mins <= '0';
wait for Clock_period*CLOCK_FREQ*5; --wait for 5 secs after incrementing minutes once.
--increment minutes 60 times inc_mins <= '1'; wait for Clock_period*60; inc_mins <= '0';
wait for Clock_period*CLOCK_FREQ*5; --wait for 5 secs after incrementing minutes.
--increment hours inc_hrs <= '1'; wait for Clock_period; inc_hrs <= '0';
wait for Clock_period*CLOCK_FREQ*5; --wait for 5 secs after incrementing hours once.
--increment hours 25 times inc_hrs <= '1'; wait for Clock_period*25; inc_hrs <= '0';
wait for Clock_period*CLOCK_FREQ*5; --wait for 5 secs after incrementing hours.
--apply reset reset <= '1'; --wait for 100 Clock cycles and then finish the simulation. --with the current settings it will run around 9 ms of simualtion time. wait for Clock_period*100; finish; end process; END;
So what next?
As an extension of this project I want to show you how you can convert the time into BCD format and then connect a BCD to 7 segment converter to it. This will be useful for those who want to try this clock on a real FPGA board. Look forward to it in the next post.
So until next time...
No comments:
Post a Comment