0
0
VhdlHow-ToBeginner · 3 min read

VHDL Code for BCD Counter: Syntax and Example

A BCD counter in VHDL counts from 0 to 9 in binary-coded decimal format and then resets. You can implement it using a process triggered by a clock and reset signal, incrementing the count and resetting after 9. The counter output is a 4-bit vector representing the decimal digit in binary.
📐

Syntax

The basic syntax for a BCD counter in VHDL includes defining an entity with clock and reset inputs and a 4-bit output. Inside the architecture, a process sensitive to the clock and reset signals increments the count on each clock rising edge and resets it when it reaches 9 or when reset is active.

  • entity: Declares inputs and outputs.
  • architecture: Contains the logic.
  • process: Runs on clock and reset changes.
  • if rising_edge(clock): Detects clock ticks.
  • count <= count + 1: Increments the counter.
  • if count = 9 then count <= 0: Resets after 9.
vhdl
entity BCD_Counter is
    Port (
        clk   : in  std_logic;
        reset : in  std_logic;
        count : out std_logic_vector(3 downto 0)
    );
end BCD_Counter;

architecture Behavioral of BCD_Counter is
    signal cnt : unsigned(3 downto 0) := (others => '0');
begin
    process(clk, reset)
    begin
        if reset = '1' then
            cnt <= (others => '0');
        elsif rising_edge(clk) then
            if cnt = "1001" then  -- 9 in binary
                cnt <= (others => '0');
            else
                cnt <= cnt + 1;
            end if;
        end if;
    end process;
    count <= std_logic_vector(cnt);
end Behavioral;
💻

Example

This example shows a complete BCD counter that counts from 0 to 9 repeatedly. It uses a clock and asynchronous reset. The output count is a 4-bit vector representing the current decimal digit in binary.

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

entity BCD_Counter is
    Port (
        clk   : in  std_logic;
        reset : in  std_logic;
        count : out std_logic_vector(3 downto 0)
    );
end BCD_Counter;

architecture Behavioral of BCD_Counter is
    signal cnt : unsigned(3 downto 0) := (others => '0');
begin
    process(clk, reset)
    begin
        if reset = '1' then
            cnt <= (others => '0');
        elsif rising_edge(clk) then
            if cnt = "1001" then
                cnt <= (others => '0');
            else
                cnt <= cnt + 1;
            end if;
        end if;
    end process;
    count <= std_logic_vector(cnt);
end Behavioral;
Output
On each rising clock edge, the output count increments from 0000 to 1001 (0 to 9 in binary) then resets to 0000.
⚠️

Common Pitfalls

Common mistakes when writing a BCD counter in VHDL include:

  • Forgetting to reset the counter to zero after reaching 9, causing it to count beyond BCD range.
  • Not using rising_edge(clk) properly, which can cause simulation or synthesis issues.
  • Mixing std_logic_vector and unsigned types without proper conversion.
  • Using synchronous reset but coding it as asynchronous, or vice versa, leading to unexpected behavior.

Always convert between unsigned and std_logic_vector when doing arithmetic.

vhdl
Wrong approach:
process(clk)
begin
    if reset = '1' then  -- Incorrect: reset checked inside clock only
        cnt <= (others => '0');
    elsif rising_edge(clk) then
        if cnt = "1001" then
            cnt <= (others => '0');
        else
            cnt <= cnt + 1;
        end if;
    end if;
end process;

Right approach:
process(clk, reset)
begin
    if reset = '1' then  -- Asynchronous reset outside clock edge
        cnt <= (others => '0');
    elsif rising_edge(clk) then
        if cnt = "1001" then
            cnt <= (others => '0');
        else
            cnt <= cnt + 1;
        end if;
    end if;
end process;
📊

Quick Reference

Tips for writing a BCD counter in VHDL:

  • Use unsigned type for arithmetic operations.
  • Check for rising_edge(clk) to detect clock ticks.
  • Reset asynchronously for immediate reset response.
  • Reset counter to zero after reaching 9 (BCD max).
  • Convert unsigned to std_logic_vector for output ports.

Key Takeaways

Use a process triggered by clock and reset to implement the BCD counter logic.
Reset the counter to zero after it reaches 9 to keep it within BCD range.
Use the unsigned type for counting and convert to std_logic_vector for output.
Check for rising_edge(clk) to increment the counter correctly.
Avoid mixing synchronous and asynchronous reset styles incorrectly.