VHDL coding tips and tricks: VHDL: Simple Digital Clock with Testbench

Monday, March 15, 2010

VHDL: Simple Digital Clock with Testbench



    Digital clock is a popular assignment topic for students of FPGA courses in universities. What I have shared here is a basic version of a digital clock. The clock will start ticking as soon as the FPGA is programmed with the bit file. There is no option to set the time or pause the clock etc.. But I believe, it is still a great code to learn many important VHDL topics. If you are looking for an advanced digital clock, then check out this digital clock with time setting feature.
   
What can you learn from this code?

If you are a beginner in VHDL, try to understand the following concepts used in this code.
  • How to generate a low frequency clock from a high a frequency clock? For example how can you generate a 1 second clock from a 100 Mhz clock.
  • How does nested if else's work in VHDL?
  • When does signals get updated with their newly assigned values?
  • How to write a testbench for your design?
  • How to instantiate a VHDL component with entity instantiation and name association.
  • How to use wait for statement in testbenches?
Without further ado, let me share the code for the simple digital clock.

digital_clock.vhd:


-- library declarations
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- entity declaration
entity digital_clock is
generic (CLOCK_FREQ : integer := 100_000_000);  --system clock frequency is customizable via this generic
port (Clk : in std_logic;
      seconds : out unsigned(5 downto 0);  --6 bit seconds output
      minutes : out unsigned(5 downto 0);  --6 bit minutes output
      hours : out unsigned(4 downto 0)  --5 bit hours output
     );
end digital_clock;

architecture Behavioral of digital_clock is

-- declaring internal signals
signal sec,min,hour : integer range 0 to 60 :=0;
signal count : integer :=1;
signal clk_1sec : std_logic :='0';

begin

--the internal signals are type casted from integer to unsigned type.
seconds <= to_unsigned(sec,6);
minutes <= to_unsigned(min,6);
hours <= to_unsigned(hour,5);

 --generates a clock of period 1 second and duty cycle 50%.
process(Clk)
begin
    if(rising_edge(Clk)) then
        count <= count+1;
        if(count = CLOCK_FREQ/2) then
            --half way across the count, the clock is toggled.
            clk_1sec <= not clk_1sec;
            count <=1;  
        end if;
    end if;
end process;

--increment and reset seconds, minutes and hours of the digital clock.
process(clk_1sec)   --period of clk_1sec is 1 second.
begin
    if(rising_edge(clk_1sec)) then
        sec <= sec+ 1;
        if(sec = 59) then
            sec<=0;  --seconds is reset to zero after it counts 60 times.
            min <= min + 1;  --min is incremented when seconds count 60 times.
            if(min = 59) then
                hour <= hour + 1;  --hours is incremented when minutes count 60 times.
                min <= 0;   --minutes is reset to zero after it counts 60 times.
                if(hour = 23) then  
                    hour <= 0;  --hours is reset to zero after it counts 24 times.
                end if;
            end if;
        end if;
    end if;
end process;

end Behavioral;
 
I believe that the code is well commented and needs no further explanation. If you dont understand something, feel free to leave a comment.

Remember the following points when using this design.
  • Set the generic parameter, CLOCK_FREQ, with the frequency of the clock available in your FPGA.
  • There are three unsigned output signals, one each for seconds, minutes and hours. They can be mapped to LED's on the board. If you want to display the values on seven segment displays on board, you would need to do few more steps. Check out this post for the same.
Below is the testbench I have created for testing the digital clock. If you have never heard of testbenches, then I recommend you to go through this beginner's post on testbenches or this youtube video on testbenches.

Testbench : tb_digital_clock.vhd


-- library declarations
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

--entity for testbench is always empty
entity tb_digital_clock is
end tb_digital_clock;

architecture Behav of tb_digital_clock is

--temporary signals, constants etc are declared here
constant CLOCK_FREQ : integer := 100_000_000;   --Frequency of the system clock. 100 Mhz is 1 followed by 8 zeros.
--What does the below constant do?
--Inside "System_Clock_Generation" process, we are waiting for 1 ns after incrementing count.
--In one second, there are 10^9 "1 nanoseconds".
--If the CLOCK_FREQ is high we dont need to wait too long before toggling the Clock signal.
--Thats why we are dividing 10^9 by CLOCK_FREQ.
constant CLOCK_COUNTS_IN_NS : integer := 1000_000_000/CLOCK_FREQ;  --used for creating the clock with any frequency.
signal Clock : std_logic := '0';
signal secs : unsigned(5 downto 0);
signal mins : unsigned(5 downto 0);
signal hrs : unsigned(4 downto 0);
signal count : integer := 1;

begin

--This type of instantiation is known as "entity instantiation with name association"
--Instantiating digital clock entity
Digi_Clock : entity work.digital_clock 
    --generic map(CLOCK_FREQ => CLOCK_FREQ)   -- uncomment this line and comment next line for implementing on fpga.
	generic map(CLOCK_FREQ => 10)   -- comment this line and uncomment above line for implementing on fpga.
    port map(Clk => Clock,
      seconds => secs,
      minutes => mins,
      hours => hrs);

--generates a clock signal of frequency CLOCK_FREQ and duty cycle 50%.
System_Clock_Generation : process
begin
    if(count = CLOCK_COUNTS_IN_NS/2) then
    	Clock <= not Clock;  --toggle the clock signal after the count variable reaches mid point.
	count <= 1;
    else
	count <= count + 1;
    end if;
    wait for 1 ns;  --wait for 1 nano second before going through the "process" again.
end process;

end Behav;

The testbench is well commented as well, so I will spare you from further explanations. The code was simulated using modelsim software. I have shared relevant parts of the simulation waveform below:

Simulation waveform:


Simulation waveform for simple digital clock in VHDL using modelsim software


 

39 comments:

  1. Nice code... But I only want to ask one ques, say i have to set clock manually. How will that can be done..

    ReplyDelete
  2. awsome! but how will it look like if i want the results to be displayed on the LCD

    ReplyDelete
  3. i still don't understand how to generate the necessary clock frequency. For 100 MHz clock, why you wait for 'count' till 50000000 instead of 100000000?

    ReplyDelete
    Replies
    1. we are counting for half cycle and changing the value to the high state again

      Delete
  4. @timmy : look at the code snippet carefully.What we are doing here is that a signal 'clk' is toggled whenever the count reaches 50m(50 million). This means that
    clk='1' for 50m clock cycles of clk1.
    then clk='1' for 50m clock cycles of clk1.and this toggling goes on.
    In effect, one clock cycle of clk = 100m clock cycles of clk1.

    I hope now you understand.

    ReplyDelete
  5. can u postt the testbench for it?

    ReplyDelete
  6. hey....how can we adjust the time of this clock?? i mean if we press the BTN1 it should increment or decrement the minutes.....do you have a sample code for this..??

    ReplyDelete
  7. Hey...do you ppl have a code which can adjust the time of the clock using its different buttons or switches??i mean if switch/button is pressed it increment or decrements the time??kindly help out

    ReplyDelete
  8. @Uzar : This is the basic code for the clock. I dont have the code for the time setting part.

    ReplyDelete
  9. hi i wnt vhdl code for interfacing gsm and gpsm modem to fpga

    ReplyDelete
  10. can u send me another code for digital clock

    ReplyDelete
  11. hi can u send me another code for digital clock

    ReplyDelete
  12. how to set mode pin in clock using vhdl code?

    ReplyDelete
  13. can anyone help to write a vhdl program for analog to digital converter

    ReplyDelete
  14. Hi. Sorry for this newbie question. Why do you use integer type for sec,min,hour and then convert to std_logic_vector? Why aren´t sec,min,hour declared as std_logic_vector in the beginning?
    Regards,
    Maia

    ReplyDelete
  15. what value i am supposed to give as/ for "clk1"...?? i mean what is input here precisely if i want to see simulation wave-forms for tis program?? ...reply ASAP....im in so hurry....plz....

    ReplyDelete
  16. hey what as an input i am supposed to put here in "clk1"???...reply ASAP....i want to see simulation waveforms in xilinx and model sim also...plz reply ASAP........

    ReplyDelete
  17. please post code for a Stop Watch, which displays the time in three decimal digits, and counts from 00.0 to 99.9 seconds and wraps around. It contains a synchronous clear signal, clr, which
    returns the count to 00.0, and an enable signal, go, which enables and suspends the
    counting. This design is basically a BCD (binary-coded decimal) counter, which counts
    in BCD format. Our Broad has a 100-MHz clock;

    ReplyDelete
  18. Your code doesn't work. The time increments from 22:58:59 to 00:00:00 due to crappy coding.

    ReplyDelete
  19. What should be input parameters while creating testbench? What should be clock high and low time,input setup time,output valid delay,offset,initial length of testbench in nanoseconds????
    plz reply asap...coz m not getng op waveform

    ReplyDelete
  20. how will it look like if i want the results to be displayed on the LCD??

    ReplyDelete
    Replies
    1. for that u have to create UCF file for display.and need to refresh the LCD pannel at very low time like 50msec such that it has to keep on updating.

      Delete
  21. Hey...just for curiosity...I wanted to extend the concept to show date,month and year also....but actly finding some problem with month identification...can anyone help????

    ReplyDelete
  22. hi
    why in vhdl i need to write
    if sec = 59 then sec <= 0
    while in verilog, to get same result, i need to write
    if (sec == 60) begin sec = 0 end
    can you give explanation?

    ReplyDelete
    Replies
    1. hi!
      sec, min and hour were declared as signals and not variables. A signal will take a full clock cycle to change and so, the value zero will be passed to sec in the following clock circle where the value was actually supposed to be 60.

      Delete
  23. Hey anyone know how can we record time ? Does anyone have code for that ?

    ReplyDelete
  24. Hiii.....plz tell me how to burn this code on fpga

    ReplyDelete
  25. hello, i want to design a circuit in which 2 counters will count simultaneously such that first counter will count from 0 to 7, after that second counter will count 1, again first counter will count 0 to 7 and second counter will count 2.

    ReplyDelete
    Replies
    1. You can do it in a very similar way as in this digital clock code. try to understand how this code works and I am sure you can do it yourself. I also help students for a fee in their projects.

      Delete
  26. Hello, I've some troubles with this code, can U help me pls?

    Parsing architecture of entity .
    ERROR:HDLCompiler:841 - "C:\Users\Tom\Desktop\VSB\1. semestr\PHP\projekty\Clock_project\clk.vhd" Line 46: Expecting type std_logic for .
    ERROR:HDLCompiler:841 - "C:\Users\Tom\Desktop\VSB\1. semestr\PHP\projekty\Clock_project\clk.vhd" Line 47: Expecting type std_logic for .
    ERROR:HDLCompiler:841 - "C:\Users\Tom\Desktop\VSB\1. semestr\PHP\projekty\Clock_project\clk.vhd" Line 48: Expecting type std_logic for .
    ERROR:HDLCompiler:854 - "C:\Users\Tom\Desktop\VSB\1. semestr\PHP\projekty\Clock_project\clk.vhd" Line 41: Unit ignored due to previous errors.
    VHDL file C:\Users\Tom\Desktop\VSB\1. semestr\PHP\projekty\Clock_project\clk.vhd ignored due to errors

    ReplyDelete
  27. This comment has been removed by the author.

    ReplyDelete
  28. Hi, can some one send me the block diagram of digital clock. like how can we make it to display it on VGA. I have VGA code and clock code but i dont know how to combine them together.

    ReplyDelete
  29. Can you write a code to connect LED Xilinx board , please answer me as soon as you can .thank you

    ReplyDelete
  30. Hello please can you send test file ??

    ReplyDelete
  31. let me ask, how to communicate with real time block in Cylone IV

    ReplyDelete
  32. I want vhdl code for generating clock frequency of 26.6Mhz and 16Mhz from 80Mhz frequency

    ReplyDelete
    Replies
    1. see this post: https://vhdlguru.blogspot.com/2013/08/fractional-clock-division-dual-modulus.html

      Delete
  33. post test bench as well for this code

    ReplyDelete