FPGA Clock with Verilog VHDL
Learn to create a clock using basic Verilog code on a FPGA development board in order to practice the use of Verilog VHDL.
The basic operating principle of this FPGA clock is to divide the crystal oscillator using a divide-by-n counter so that it gives a 1 Hz signal. Using this signal, increment a display counter. Finally, use the counter's stored value to drive a 7 segment display driver to output the time to the user.
This project was done as a school assignment on VHDL programming and using FPGAs.
Timer.vhd
LIBRARY work;
USE work.Mod10CounterPackage.Mod10Counter;
USE work.Mod6CounterPackage.Mod6Counter;
USE work.SegDriverPackage.SegDriver;
USE work.Mod500ThousandCounterPackage.Mod500ThousandCounter;
ENTITY UpDownTimer IS
PORT(
CLOCK_50 : IN BIT;
KEY : IN BIT_VECTOR(0 DOWNTO 0);
SW : IN BIT_VECTOR(2 DOWNTO 0);
HEX0 : OUT BIT_VECTOR(6 DOWNTO 0);
HEX1 : OUT BIT_VECTOR(6 DOWNTO 0);
HEX2 : OUT BIT_VECTOR(6 DOWNTO 0);
HEX3 : OUT BIT_VECTOR(6 DOWNTO 0);
HEX4 : OUT BIT_VECTOR(6 DOWNTO 0);
HEX5 : OUT BIT_VECTOR(6 DOWNTO 0);
HEX6 : OUT BIT_VECTOR(6 DOWNTO 0);
HEX7 : OUT BIT_VECTOR(6 DOWNTO 0);
RCO : OUT BIT
);
END ENTITY;
ARCHITECTURE Behavior OF UpDownTimer IS
--Instantiate the Display Drivers Signals --
SIGNAL Display0 : INTEGER RANGE 0 TO 15;
SIGNAL Display1 : INTEGER RANGE 0 TO 15;
SIGNAL Display2 : INTEGER RANGE 0 TO 15;
SIGNAL Display3 : INTEGER RANGE 0 TO 15;
SIGNAL Display4 : INTEGER RANGE 0 TO 15;
SIGNAL Display5 : INTEGER RANGE 0 TO 15;
--Instantiate all of our counters Signals --
SIGNAL RCO0to1 : BIT;
SIGNAL RCO1to2 : BIT;
SIGNAL RCO2to3 : BIT;
SIGNAL RCO3to4 : BIT;
SIGNAL RCO4to5 : BIT;
SIGNAL RCO5to6 : BIT;
BEGIN
-- Initialize the other segments to blank --
HEX0 <= "1111111";
HEX1 <= "1111111";
Divider: Mod500ThousandCounter PORT MAP(CLOCK_50, NOT(KEY(0)), SW(2), RCO0to1);
Hundreths: Mod10Counter PORT MAP(RCO0to1, NOT(KEY(0)), SW(0), RCO1to2, Display0);
Tenths: Mod10Counter PORT MAP(RCO1to2, NOT(KEY(0)), SW(0), RCO2to3, Display1);
Seconds: Mod10Counter PORT MAP(RCO2to3, NOT(KEY(0)), SW(0), RCO3to4, Display2);
Tens: Mod6Counter PORT MAP(RCO3to4, NOT(KEY(0)), SW(0), RCO4to5, Display3);
Minutes: Mod10Counter PORT MAP(RCO4to5, NOT(KEY(0)), SW(0), RCO5to6, Display4);
TensMinutes: Mod6Counter PORT MAP(RCO5to6, NOT(KEY(0)), SW(0), RCO, Display5);
Seg0: SegDriver PORT MAP(Display0, SW(1), HEX2);
Seg1: SegDriver PORT MAP(Display1, SW(1), HEX3);
Seg2: SegDriver PORT MAP(Display2, SW(1), HEX4);
Seg3: SegDriver PORT MAP(Display3, SW(1), HEX5);
Seg4: SegDriver PORT MAP(Display4, SW(1), HEX6);
Seg5: SegDriver PORT MAP(Display5, SW(1), HEX7);
END ARCHITECTURE;
Mod5MillionCounter.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY Mod500ThousandCounter IS
PORT( Clock :IN BIT;
Reset :IN BIT;
Halt :IN BIT;
RCO :OUT BIT);
END ENTITY;
ARCHITECTURE Behavior OF Mod500ThousandCounter IS
BEGIN
PROCESS(Clock)
VARIABLE I: INTEGER := 0;
BEGIN
IF(Halt='0') THEN
IF(Reset='1') THEN
RCO<='0';
i := 0;
ELSIF(Clock'EVENT and Clock='1') THEN
IF(i = 499999) THEN
RCO<='1';
i := 0;
ELSE
RCO<='0';
i := i + 1;
END IF;
END IF;
END IF;
END PROCESS;
END Behavior;
PACKAGE Mod500ThousandCounterPackage IS
COMPONENT Mod500ThousandCounter
PORT( Clock :IN BIT;
Reset :IN BIT;
Halt :IN BIT;
RCO :OUT BIT);
END COMPONENT;
END PACKAGE;
Mod10Counter.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY Mod10Counter IS
PORT( Clock :IN BIT;
Reset :IN BIT;
Dir :IN BIT;
RCO :OUT BIT;
OUT_BUS:BUFFER INTEGER RANGE 0 to 9);
END ENTITY;
ARCHITECTURE Behavior OF Mod10Counter IS
BEGIN
PROCESS(Clock)
BEGIN
IF(Reset = '1') THEN
RCO<='0';
OUT_BUS<=0;
ELSIF(Clock'EVENT AND Clock='1') THEN
IF(OUT_BUS = 9 AND Dir = '0') THEN
RCO<='1';
OUT_BUS<=0;
ELSIF(OUT_BUS = 0 AND Dir = '1') THEN
RCO<='1';
OUT_BUS<=9;
ELSE
RCO<='0';
IF(Dir='0') THEN
OUT_BUS<=OUT_BUS + 1;
ELSE
OUT_BUS<=OUT_BUS - 1;
END IF;
END IF;
END IF;
END PROCESS;
END Behavior;
PACKAGE Mod10CounterPackage IS
COMPONENT Mod10Counter
PORT( Clock :IN BIT;
Reset :IN BIT;
Dir :IN BIT;
RCO :OUT BIT;
OUT_BUS:BUFFER INTEGER RANGE 0 to 9);
END COMPONENT;
END PACKAGE;
Mod6Counter.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY Mod6Counter IS
PORT( Clock :IN BIT;
Reset :IN BIT;
Dir :IN BIT;
RCO :OUT BIT;
OUT_BUS:BUFFER INTEGER RANGE 0 to 5);
END ENTITY;
ARCHITECTURE Behavior OF Mod6Counter IS
BEGIN
PROCESS(Clock)
BEGIN
IF(Reset = '1') THEN
RCO<='0';
OUT_BUS<=0;
ELSIF(Clock'EVENT AND Clock='1') THEN
IF(OUT_BUS = 5 AND Dir = '0') THEN
RCO<='1';
OUT_BUS<=0;
ELSIF(OUT_BUS = 0 AND Dir = '1') THEN
RCO<='1';
OUT_BUS<=5;
ELSE
RCO<='0';
IF(Dir='0') THEN
OUT_BUS<=OUT_BUS + 1;
ELSE
OUT_BUS<=OUT_BUS - 1;
END IF;
END IF;
END IF;
END PROCESS;
END Behavior;
PACKAGE Mod6CounterPackage IS
COMPONENT Mod6Counter
PORT( Clock :IN BIT;
Reset :IN BIT;
Dir :IN BIT;
RCO :OUT BIT;
OUT_BUS:BUFFER INTEGER RANGE 0 to 5);
END COMPONENT;
END PACKAGE;
SegDriver.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY SegDriver IS
PORT(
Digit : IN INTEGER RANGE 0 TO 15;
Freeze : IN BIT;
Segment : BUFFER BIT_VECTOR(6 DOWNTO 0));
END ENTITY;
ARCHITECTURE Behavior OF SegDriver IS
BEGIN
PROCESS(Digit)
BEGIN
IF(Freeze = '0') THEN
CASE Digit IS
WHEN 0 => Segment <= "1000000";
WHEN 1 => Segment <= "1111001";
WHEN 2 => Segment <= "0100100";
WHEN 3 => Segment <= "0110000";
WHEN 4 => Segment <= "0011001";
WHEN 5 => Segment <= "0010010";
WHEN 6 => Segment <= "0000010";
WHEN 7 => Segment <= "1111000";
WHEN 8 => Segment <= "0000000";
WHEN 9 => Segment <= "0010000";
WHEN 10 => Segment <= "0001000";
WHEN 11 => Segment <= "0000011";
WHEN 12 => Segment <= "1000110";
WHEN 13 => Segment <= "0100001";
WHEN 14 => Segment <= "0000110";
WHEN 15 => Segment <= "0001110";
END CASE;
ELSE
Segment<=Segment;
END IF;
END PROCESS;
END Behavior;
PACKAGE SegDriverPackage IS
COMPONENT SegDriver
PORT(
Digit : IN INTEGER RANGE 0 TO 15;
Freeze : IN BIT;
Segment : BUFFER BIT_VECTOR(6 DOWNTO 0));
END COMPONENT;
END PACKAGE;
Comments
Post a Comment