Digilent Spartan-3 Starter Kit Board Tutorial

Flashing Digital Clock

This project is created to test 7-segment displays on Digilent Spartan-3 Starter Kit Board. Because the 4 7-segment displays on the board is addressed using an "anode" which activates which display is to be refreshed, the lower trigger frequency causes a flashing effect. Techniques involved in this exercise include finite state machines, slow/exact clock generation, and refreshing 7-segment display.

To exercise this tutorial you will have to have the following hardware and software:

Hardware: Digilent Spartan-3 Starter Kit Board
Software: Xilinx ISE 8.1.03i

Step 1: Get the compressed project ball and uncompress it in a place you know where to get it.
Step 2: Start Xilinx ISE 8.1.03i and open the above project using project navigator.
Step 3: Double click Generate Programming File in the Processes window. (Skip this step if you don't want to re-complile the projet.)
Step 4: Start iMPACT and choose the programming file  display.bit for XC3-S200.
Step 5: Right click on XC3-S200 in IMPACT and choose program...

Have fun!

----------------------------------------------------------------------------------
-- Company: Department of Computer Science, University of Texas at San Antonio
-- Engineer: Chia-Tien Dan Lo
-- 
-- Create Date: 16:32:58 08/14/2006 
-- Design Name: Flashing Digital Clock 
-- Module Name: display - Behavioral 
-- Project Name: SevenSegTest 
-- Target Devices: Xilinx Spartan III XC3-S200 4C (Taiwan)
-- Tool versions: ISE 8.1.03i
-- Description: Test Digilent Spartan-3 Starter Kit Board in terms of a flashing digital clock
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: Basic logic design experience required
-- Pin Assignment for Digilent Spartan-3 Starter Kit Board:
-- data(7) => E14 a
-- data(6) => G13 b
-- data(5) => N15 c
-- data(4) => P15 d
-- data(3) => R16 e
-- data(2) => F13 f
-- data(1) => N16 g
-- data(0) => P16 dp
-- clk => T9 50 MHz
-- reset => M13 BTN0 
-- anode(3)=> E13
-- anode(2)=> F14
-- anode(1)=> G14
-- anode(0)=> D14
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity display is
Port ( clk: in STD_LOGIC;
reset : in STD_LOGIC;
data : out STD_LOGIC_VECTOR (7 downto 0);
anode : out STD_LOGIC_VECTOR (3 downto 0));
end display;

architecture Behavioral of display is
-- a FSM is used to update each digit in the 7-Segment displays
type state_type is (d0, d1, d2, d3);
type char is (d, A, n, L, o, s);
signal next_state, curr_state: state_type;
-- slow_clk: 1 Hz, mid_clk: 5 Hz, start is used to display dAn Lo at beginning 
signal slow_clk, mid_clk, start: std_logic;
-- one counter for one 7-segment display
signal counter0, counter1, counter2, counter3: integer range 0 to 9;

-- decode "dAn Lo" to 7-segment signals
function char_to_led(c: char) return std_logic_vector is
begin
case c is
when d => return "1000010";
when A => return "0001000";
when n => return "1101010";
when L => return "1110001";
when o => return "1100010";
when others => return "1111111";
end case;
end char_to_led;
-- decode number to 7-segment signals
function num_to_led(digit: integer) return std_logic_vector is
begin
case digit is
when 0 => return "0000001";
when 1 => return "1001111";
when 2 => return "0010010";
when 3 => return "0000110";
when 4 => return "1001100";
when 5 => return "0100100";
when 6 => return "1100000";
when 7 => return "0001111";
when 8 => return "0000000";
when 9 => return "0001100";
when others => return "1111111";
end case;
--return "1111111";
end num_to_led;
begin

-- slow clock to 1 Hz (slow_clk) and 5 Hz (mid_clk)
p1: process(clk, reset)
variable cnt, cnt1: integer;
begin
if reset = '1' then
cnt := 0;
cnt1 := 0;
slow_clk <= '0';
mid_clk <= '0';
elsif clk'event and clk='1' then
cnt := cnt +1;
cnt1 := cnt1 + 1;
if cnt = 25000000 then
cnt := 0;
slow_clk <= not slow_clk;
end if;
if cnt1 = 500000 then
cnt1 := 0;
mid_clk <= not mid_clk;
end if;
end if;
end process;

-- counter process, counter1 and counter3 only count to 5!
p2: process(slow_clk, start)
begin
if start = '1' then
counter0 <= 0;
counter1 <= 0;
counter2 <= 0;
counter3 <= 0;
elsif slow_clk'event and slow_clk='1' then
if counter0 < 9 then 
counter0 <= counter0 + 1;
else
counter0 <= 0;
-- counter1 counts to 6
if counter1 < 5 then
counter1 <=counter1 + 1;
else
counter1 <= 0;
if counter2 < 9 then
counter2 <= counter2 + 1;
else
counter2 <= 0;
if counter3 < 5 then
counter3 <= counter3 +1;
else
counter3 <= 0;
end if;
end if;
end if;
end if; 
end if;
end process;

-- output data for 7-segment displays
-- the DP for the second digit blinks in 1 Hz (slow_clk) 
p3: process(curr_state, next_state, counter0, counter1, counter2, counter3, slow_clk)
begin
case curr_state is 
when d0 =>
next_state <= d1;
if start = '1' then
if slow_clk = '1' then
data <= char_to_led(s)&"1";
else
data <= char_to_led(o)&"1";
end if;
else
data <= num_to_led(counter0)&"1";
end if;
anode <= "1110";
when d1 =>
next_state <= d2;
if start = '1' then 
if slow_clk = '1' then
data <= char_to_led(n)&"1";
else 
data <= char_to_led(L)&"1";
end if;
else
data <= num_to_led(counter1)&"1";
end if;
anode <= "1101";
when d2 =>
next_state <= d3;
if start = '1' then 
if slow_clk = '1' then
data <= char_to_led(A)&"1";
else 
data <= char_to_led(s)&"1";
end if;
else
data <= num_to_led(counter2)&slow_clk;
end if;
anode <= "1011";
when d3 =>
next_state <= d0;
if start = '1' then 
if slow_clk = '1' then
data <= char_to_led(d)&"1";
else 
data <= char_to_led(s)&"1";
end if;
else
data <= num_to_led(counter3)&"1";
end if;
anode <= "0111";
end case;
end process;

-- refresh display data in 5 Hz and cause flashing effect
p4: process(mid_clk, reset)
begin
if reset = '1' then
curr_state <= d0;
elsif mid_clk'event and mid_clk = '1' then
curr_state <= next_state;
end if;
end process;

-- count 5 slow clocks, then change start signal
-- this will display "dAn Lo"
p5: process(slow_clk, reset)
variable cnt: integer;
begin
if reset = '1' then
cnt := 0;
start <= '1';
elsif slow_clk'event and slow_clk='1' then
cnt := cnt + 1;
if cnt = 10 then
start <= '0';
end if;
end if;
end process;
end Behavioral;