News Uni Dev Res Blag

VHDL Counter

2010/10/05 - 01:45

-- VHDL Counter - this syntax is horrible
-- Copyright (C) 2010  ed <irc.rizon.net>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License, version 2, as
-- published by the Free Software Foundation.
--
-- You should have received a copy of the GNU General Public License along
-- with this program; if not, please refer to the following URL:
-- http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

portmap

NET "matrix[0]" LOC = C4;
NET "matrix[1]" LOC = D13;
NET "matrix[2]" LOC = B12;
NET "matrix[3]" LOC = A11;
NET "matrix[4]" LOC = D10;
NET "matrix[5]" LOC = A14;
NET "matrix[6]" LOC = D11;
NET "dsp[0]" LOC = B14;
NET "dsp[1]" LOC = A13;
NET "dsp[2]" LOC = A12;
NET "pulse" LOC = C10;
NET "btn[0]" LOC = K3;

clockdivider.vhd

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

entity clockdivider is
    port(   CLKin   :in  std_logic;  -- The 16MHz PGA clock
            CLKout  :out std_logic;  -- Divided clock output
            Flag    :in  integer range 0 to 20000000); 
end clockdivider;

architecture Behavioral of clockdivider is
    signal DivideBy :Integer := 1600000; -- 10Hz, default
begin
    process (Flag) begin
        DivideBy <= Flag;
    end process;
    
    process (CLKin)
        variable count :Natural range 0 to 20000000;
    begin
        if CLKin'event and (CLKin = '1') then
            
            -- Increment counter
            if (count >= DivideBy-1) then
                count := 0;
            else
                count := count + 1;
            end if;
            
            -- Apply clock signal
            if count >= DivideBy/2 then
                CLKout <= '0';
            else
                CLKout <= '1';
            end if;
            
        end if;
    end process;
end Behavioral;

hexcounter.vhd

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

entity hex_counter is
    port(   pulse       :in  std_logic; -- 16MHz clock #C10
            dsp         :out std_logic_vector(2 downto 0);
            matrix      :out std_logic_vector(6 downto 0);
            btn         :in  boolean);  --top right button
end hex_counter;

architecture Behavioral of hex_counter is
    component clockdivider is
    port(   CLKin   :in  std_logic; -- 100MHz clock
            CLKout  :out std_logic; -- 1,49Hz clock
            Flag    :in  integer range 0 to 20000000);
    end component;
    
    signal TS   :std_logic;
    signal CLK  :std_logic;
    signal iTS  :integer range  0 to 20000000; -- clockdivider, dspwriter
    signal iCLK :integer range  0 to 20000000; -- clockdivider, counter
    signal dspn :integer range  0 to  3 := 0;  -- next target display
    signal tmp  :integer range  0 to 15 := 0;  -- value to write to dspn
    signal cnta :integer range -1 to 16 := 0;  -- display 1 (LSB, right)
    signal cntb :integer range -1 to 16 := 0;  -- display 2 (?SB, middle)
    signal cntc :integer range -1 to 16 := 0;  -- display 3 (MSB, left)
    signal dir  :integer range -1 to  1 := 1;  -- count direction
begin

    -- Maps the counter clockdivider
    hurr: clockdivider port map (
        CLKin  => pulse,
        CLKout => CLK,
        Flag   => iCLK);
    
    -- ...as well as the displaywriter
    durr: clockdivider port map (
        CLKin  => pulse,
        CLKout => TS,
        Flag   => iTS);
    
    iTS  <= 160000;  --100Hz
    iCLK <= 1600000; -- 10Hz
    
    -- THE BUTAN
    process (btn)
    begin
        if (btn)
            then dir <= -1;
            else dir <=  1;
        end if;
    end process;
    
    -- The counter process
    process (CLK)
    begin
        if (CLK'event and CLK = '1') then
            cnta <= cnta + dir;
            
            --LSB (rightmost)
            if (cnta > 9) then
                cntb <= cntb + 1;
                cnta <= 0;
            elsif (cnta < 0) then
                cntb <= cnta - 1;
                cnta <= 9;
            end if;
                
            --Middle display
            if (cntb > 9) then
                cntc <= cntc + 1;
                cntb <= 0;
            elsif (cntb < 0) then
                cntc <= cntb - 1;
                cntb <= 9;
            end if;

            --MSB (leftmost)
            if (cntc > 9) then
                cntc <= 0;
            elsif (cntc < 0) then
                cntc <= 9;
            end if;
            
        end if;
    end process;
    
    -- The display writer process
    process (TS)
    begin
        if (TS'event and TS = '1') then
        
            if (dspn = 0) then dsp <= "110"; tmp <= cnta; end if;
            if (dspn = 1) then dsp <= "101"; tmp <= cntb; end if;
            if (dspn = 2) then dsp <= "011"; tmp <= cntc; end if;
    
            -- Rotate the display
            dspn <= dspn + 1;
            if (dspn > 2) then
                dspn <= 0;
            end if;
            
            if (tmp =  0) then matrix <= "0111111"; end if;
            if (tmp =  1) then matrix <= "0000110"; end if;
            if (tmp =  2) then matrix <= "1011011"; end if;
            if (tmp =  3) then matrix <= "1001111"; end if;
            if (tmp =  4) then matrix <= "1100110"; end if;
            if (tmp =  5) then matrix <= "1101101"; end if;
            if (tmp =  6) then matrix <= "1111101"; end if;
            if (tmp =  7) then matrix <= "0000111"; end if;
            if (tmp =  8) then matrix <= "1111111"; end if;
            if (tmp =  9) then matrix <= "1101111"; end if;
            if (tmp = 10) then matrix <= "1011111"; end if;
            if (tmp = 11) then matrix <= "1111100"; end if;
            if (tmp = 12) then matrix <= "0111001"; end if;
            if (tmp = 13) then matrix <= "1011110"; end if;
            if (tmp = 14) then matrix <= "1111001"; end if;
            if (tmp = 15) then matrix <= "1110001"; end if;
            if (tmp = 16) then matrix <= "1000000"; end if;

        end if;
    end process;
end behavioral;

testbench.vhd

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

entity testbench is
end testbench;

architecture behavior of testbench is

    -- Unit Under Test (UUT)
    component hexcounter port(
        btn    :in  boolean;
        pulse  :in  std_logic;
        matrix :out std_logic_vector(6 downto 0)
        dsp    :out std_logic_vector(2 downto 0);
    );

    -- Ports
    signal btn      :boolean   := false;
    signal pulse    :std_logic := '0';
    signal matrix   :std_logic_vector(6 downto 0);
    signal dsp      :std_logic_vector(2 downto 0);
    
    constant pulse_period :time := 10 ns;
    
begin

    -- Instantiate (UUT)
    uut :hexcounter PORT MAP (
        btn    => btn
        pulse  => pulse,
        matrix => matrix,
        dsp    => dsp,
    );

    -- Clock process definitions
    pulse_process :process
    begin
        pulse <= '0';
        wait for pulse_period/2;
        pulse <= '1';
        wait for pulse_period/2;
    end process;

    -- Stimulus process
    stim_proc: process
    begin
        wait for 100 ns;
        wait for pulse_period*10;
        wait;
    end process;

end;

Copyright © 2010 Ed Edland