The vast majority of VHDL designs uses clocked logic, also known as synchronous logic or sequential logic. A clocked process is triggered only by a master clock signal, not when any of the other input signals change.

The basic building block of clocked logic is a component called the flip-flop. There are different variants of it, and in this tutorial we are going to focus on the positive-edge-triggered flip-flop with negative reset:
flip_flop

The flip-flop is a sample-and-hold circuit, meaning that it copies the value from the input to the output when the rising edge of the clock signal arrives. The output is then held stable at the sampled value until the next rising edge of the clock, or until the reset signal is pulsed.

This blog post is part of the Basic VHDL Tutorials series.

All clocked processes are triggered simultaneously and will read their inputs at once. At the same time, they will output the results from the last iteration. The clock signal effectively creates timesteps in the data flow. This makes it manageable for the designer to create complex, deep logic. He or she can break down the actions of the algorithm into events that happen on the clock cycles.

Flip-flops or arrays of flip-flops are sometimes referred to as registers, it is the same thing.

The sensitivity list for clocked processes usually contains only the clock signal. This is because a clocked process is triggered only by a flank on the clock signal, the other input signals won’t cause it to wake up at all.

This is a template for creating a clocked process with synchronous reset:
process(Clk) is
begin
    if rising_edge(Clk) then
        if nRst = '0' then
            <reset all output signals here>
        else
            <main logic here>
        end if;
    end if;
end process;

Exercise

In this video tutorial we will learn how to create a clocked process in VHDL:

The final code for flip-flop testbench:

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

entity T17_ClockedProcessTb is
end entity;

architecture sim of T17_ClockedProcessTb is

    constant ClockFrequency : integer := 100e6; -- 100 MHz
    constant ClockPeriod    : time    := 1000 ms / ClockFrequency;

    signal Clk    : std_logic := '1';
    signal nRst   : std_logic := '0';
    signal Input  : std_logic := '0';
    signal Output : std_logic;

begin

    -- The Device Under Test (DUT)
    i_FlipFlop : entity work.T17_FlipFlop(rtl)
    port map(
        Clk    => Clk,
        nRst   => nRst,
        Input  => Input,
        Output => Output);

    -- Process for generating the clock
    Clk <= not Clk after ClockPeriod / 2;

    -- Testbench sequence
    process is
    begin
        -- Take the DUT out of reset
        nRst <= '1';

        wait for 20 ns;
        Input <= '1';
        wait for 22 ns;
        Input <= '0';
        wait for 6 ns;
        Input <= '1';
        wait for 20 ns;

        -- Reset the DUT
        nRst <= '0';

        wait;
    end process;

end architecture;

The final code for the flip-flop module:

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

entity T17_FlipFlop is
port(
    Clk    : in std_logic;
    nRst   : in std_logic; -- Negative reset
    Input  : in std_logic;
    Output : out std_logic);
end entity;

architecture rtl of T17_FlipFlop is
begin

    -- Flip-flop with synchronized reset
    process(Clk) is
    begin

        if rising_edge(Clk) then
            if nRst = '0' then
                Output <= '0';
            else
                Output <= Input;
            end if;
        end if;

    end process;

end architecture;

The waveform window in ModelSim after we pressed run, and zoomed in on the timeline:flip_flop_waveform

Get exclusive access to exercises and answers!

Analysis

We can see from the waveform that the output signal is only updated on each rising edge of the clock signal. The input signal is sampled only when the clock signal changes from ‘0’ to ‘1’. The negative dip of the input signal starting at about 45 ns is completely lost. It’s not copied to the output because it’s in between two rising edges of the clock, and therefore it is ignored.

This animation illustrates how the output reacts to the changing input and clock signals:
flipflop

The vertical lines indicate how the input signal is relative to the rising edges of the clock.

Pay special attention to the one positive pulse on the input signal starting at 20 ns. It’s synchronous to the clock and exactly one clock period long. The output doesn’t react instantaneously, it’s delayed by one clock period.

When I was learning VHDL I found this particularly hard to understand. The rising edge of the clock is synchronous with the input’s rising edge, so how can the flip-flop choose one value or the other? The simulator uses timesteps to model events in a predictable way, and signals propagate in zero time. Because the flip-flop reads the input in the exact same timestep as it updates the output, it sees the old value of the input and copies it to the output.

I should add to this answer that this isn’t really how it works. In the physical world, a signal needs time to propagate, we don’t know exactly when it arrives at the flip-flop. These propagation delays are estimated automatically for us by the software process (place and route) which converts the VHDL code into a netlist.

In reality, the input must be held stable for a few nanoseconds before and after the rising clock edge:
Setup and hold time

These critical time periods are known as setup and hold time. Fortunately, this is not something you normally have to take into consideration. When working purely with clocked logic, these problems are handled by the software which turns the VHDL code into a netlist.

Takeaway

  • Clocked processes with synchronized reset only have the clock signal on the sensitivity list
  • The if rising_edge(Clk) ensures that the process only wakes up on rising edges of the clock
  • In a synchronous design, stuff only happens at active the clock edge

Take the Basic VHDL Quiz – part 3 »
or
Go to the next tutorial »

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 thoughts on “How to create a Clocked Process in VHDL

  1. Hi Jonas!

    I’ve seen all your VHDL-Videos on Youtube and currently doing your quiz to check if I actually understood everything. They really made me more confident. Especially the delta-cycles questions gave me a chance to think through everything myself and having a feedback, if it was correct.

    Having just finished your quiz (part3) I noticed that you did not cover the topic “setup and hold time” in your Video “How to create a Clocked Process in VHDL”. This seems to be an important topic to me as failing to understand this might quickly lead to hard to find bugs in the actual application. As far as I know these timings are important to write the design constraint files (i.e. *.sdc files in Altera Quartus II for example). Could you do a Video on that topic?

    Regards,
    Stefan

    PS: Thank you for all the tutorials. They were much more helpful then others I’ve seen. Having experienced all the intentinally “buggy programs” fail and how they were fixed, was much easier to learn the rules than just being told “you can’t do this!” (=forgotten minutes later). You focus on the issue, explain why stuff failes, fast-forward on routine work (as loading files into the simulator) while giving an audible summary when doing so. Keep it up!!! 🙂

    Posted on January 15, 2019 at 3:47 pm
    1. Hi Stefan,

      Thank you for the kind words.

      Setup and hold time is indeed important to fully understand. Without knowing about that, you would be clueless when faced with some of the most common place and route errors. When dealing with external interfaces, we must specify the setup and hold time constraints, because the synthesis tool has no way of knowing the limitations of the external signal.

      But when dealing only with clocked logic internally in an FPGA, we generally don’t think about setup and hold time when designing. It is handled by the synthesis tool which derives the setup and hold time constraints from the clock frequency and duty cycle. But it is important to understand for the previously mentioned reasons.

      I didn’t want to talk too much about these issues when introducing flip-flops to new developers. My fear was that by throwing everything at you at the first mention of FFs, I would overcomplicate things. Therefore, I chose focus on the purely digital, event-driven properties of the FF. Like they behave in the perfect world of the simulator.

      By doing so, I may have made the article more confusing to the more curious reader, like yourself. Note that I tried to wash my hands by including a “this isn’t really how it works” paragraph at the end of the blog post (haha).

      Anyway, thank you for your comment. Setup and hold times will be talked about in the future in this blog.

      Jonas

      Posted on January 19, 2019 at 4:32 am