Friday, June 21, 2013

8-bit Binary Counter using VHDL on Elbert FPGA Development Board

This time we'll be designing a 8-bit binary counter using VHDL and then implement it physically on Elbert FPGA Board.

PART A : VHDL Code for 8-bit binary counter and simulation.


The VHDL Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter is
    Port ( CLK : in  STD_LOGIC;
           OUTPUT : out  STD_LOGIC_VECTOR (7 downto 0));
end counter;


architecture Behavioral of counter is

signal counter : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');


begin

OUTPUT <= counter;

count_process: process(CLK)
 begin
  if rising_edge(CLK) then
   counter <= counter + 1;
  end if;
 end process;


end Behavioral;

Now, we need a VHDL Testbench code to simulate the above VHDL code. The Xilinx ISE generates most-of-the code required for a testbench (Although for larger designs, we need to edit the generated template, or write a new testbench code altogether). The code given below was generated completely by the Xilinx ISE.

Testbench Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

 
ENTITY counter_tb IS
END counter_tb;
 
ARCHITECTURE behavior OF counter_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT counter
    PORT(
         CLK : IN  std_logic;
         OUTPUT : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal CLK : std_logic := '0';

  --Outputs
   signal OUTPUT : std_logic_vector(7 downto 0);

   -- Clock period definitions
   constant CLK_period : time := 10 ns;
 
BEGIN
 
 -- Instantiate the Unit Under Test (UUT)
   uut: counter PORT MAP (
          CLK => CLK,
          OUTPUT => OUTPUT
        );

   -- Clock process definitions
   CLK_process :process
   begin
  CLK <= '0';
  wait for CLK_period/2;
  CLK <= '1';
  wait for CLK_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin  
      -- hold reset state for 100 ns.
      wait for 100 ns; 

      wait for CLK_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;

Here is the simulation output of the 8-bit counter VHDL code, using the above testbench code, in Xilinx ISIM simulator.
Simulation output in Xilinx ISIM for 8-bit binary up counter


PART B: Implementation on Elbert


Writing and simulating a VHDL code is slightly different from implementing it physically on the FPGA. We have to take care of some things, such as the VHDL code may have some non-synthesizable snippets, take care of FPGA constraints etc.
In case of our 8-bit counter, we need to notice few things:
  • The Input clock to Elbert has 12MHz frequency. This is so fast that, if we were to connect the counter outputs to the 8 on-board LEDs, all the 8 LEDs would seem to be on simultaneously! We need a slow clock!
  • To slow down the input clock, we need a clock divider. We can use the Digital Clock Module (DCM) inside the Spartan-3A family devices, or we can construct our own using a large counter. For now, we will be using the second option. We'll use DCM at a later date.
I used a 27-bit counter, and connected the 8 upper bits (MSBs), ie bits 19-26,  to the 8 on-board LEDs of Elbert. This gave me the clock frequency of ~11.44Hz at the lowest(least significant bit) LED!

New VHDL Code for Elbert:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Switches_LEDs is
    Port ( LED : out  STD_LOGIC_VECTOR(7 downto 0);
    CLK : in STD_LOGIC );
end Switches_LEDs;


architecture Behavioral of Switches_LEDs is

signal counter : STD_LOGIC_VECTOR(26 downto 0) := (others => '0'); 

begin

clk_proc: process(CLK)
 begin
  if rising_edge(CLK) then
   counter <= counter + 1;
   LED(7 downto 0) <= counter(26 downto 19);
  end if;
 end process;
 
end Behavioral;


Constraints file for this project:
NET "CLK" LOC = P40;
NET "CLK" TNM_NET = CLK;
TIMESPEC TS_CLK = PERIOD "CLK" 12 MHz HIGH 50%;


NET "LED[7]" LOC = P3;
NET "LED[6]" LOC = P4;
NET "LED[5]" LOC = P5;
NET "LED[4]" LOC = P6;
NET "LED[3]" LOC = P13;
NET "LED[2]" LOC = P9;
NET "LED[1]" LOC = P10;
NET "LED[0]" LOC = P12;

Video of the above code in action through LEDs on Elbert:


Note: I'm still learning FPGA and VHDL. Any discrepancy/error is regretted. And any new knowledge/information is heartily welcomed!

5 comments:

  1. Are you using the ISE Webpack? WHich version. It around 7 Gb right?

    ReplyDelete
  2. At the time of writing it was 14.3 Webpack. Now I have latest 14.7

    ReplyDelete
  3. Could you provide a link? How big was the download?

    ReplyDelete
  4. http://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/design-tools.html
    Size should be around 6GB for standalone linux/windows and greater for combined version

    ReplyDelete
  5. i neeed decounter 8 bit binary please

    ReplyDelete