Beruflich Dokumente
Kultur Dokumente
Project 1:
Simon Game Part 1
!
Monique Kirkman-Bey
November 6, 2013
Project Overview! 3!
Top Level! 4!
Data Unit! 6!
RandomColorGenerator Component! 8!
RandomColorGenerator Simulations! 8!
GameRegister Component! 9!
correct_color, and reset. When the correct_color signal is high, the simon game continues to
cycle through the random colors. When it is low, the game displays a red screen indicating an
error. The outputs are: blue, red, green, hs, vs, and led. The red, green, and blue outputs are used
to generate the colors we see on the VGA display. The vs and hs outputs correspond to the
vertical sync and horizontal sync signals and are responsible as well for writing the colors to the
pixels on the display. the led output is simply a clock status signal that causes a light to blink on
the board in sync with the control units clock signal.
!
Second Level Diagram
!
!
Here is a second level view of the game. You can see above that all three of the external inputs
go to the control unit, and that one of the inputs, the clk signal, is shared with the data unit. You
can also see that all, but one output comes from the data unit. Hence, the data unit is responsible
for what we see on the VGA display. The output, led, is from the control unit. It allows me to
monitor the clock cycles since the entire control unit runs a slower clock. The control unit and
its clock will be discussed shortly.
!
The outputs of the control unit are the enable lines to the components within the data unit, as
well as the address and load line to the register within the data unit.
!
!
Data Unit
!
!
Here is the top level view of my data unit. The data unit has the following 7 inputs:
gameAddress_line, clk, error_enable, gameRegister_Load, game_enable, random_enable, and
reset, as well as the following 5 outputs: red, green, blu, vs, and hs.
!
A closer look at the routing of these signals can be seen below in the second level diagram of the
data unit.
!
It can be seen that the random_enable input is connected to the RandomColorGenerator
component. The gameAddress_line, gameRegister_load, reset and clk, inputs are routed to the
GameRegister. component The remaining inputs, error_enable and game_enable are routed to
the VGA_SimonController along with the clk and reset signals. It can also be seen that all
outputs of the data unit are from the VGA_Simon controller. Further explanations of these
signals and the way that their values impact the behavior of the components are to follow.
!
RandomColorGenerator Component
!
Above is a block diagram of the RandomColorGenerator component. This component is
responsible for ensuring that the simon game remains fresh and fun. It generates color codes in a
pseudo-random fashion by implementing a 32-bit Linear Feedback Shift Register. When the
RandomEnable signal is high, the random color currently being generated is seen on the color
output. When RandomEnable is low, the output is simply 00, but the generator continues to
generate random number. This behavior can be seen below in the simulations of the component.
!
!
RandomColorGenerator Simulations
!
!
!
!
It can be seen that at every clock period a new number is generated by the component. When
RandomEnable is high, the last two bits of the random number is seen on the output, color. When
enable is low, the output is set to 00, but the random numbers continue to generate. For
simulation purposes and demonstration of functionality, the signal which holds the random
number is included in the simulation. It is not an input or output of the system.
!
GameRegister Component
!
!
!
!
!
The GameRegister component stores the color codes that will be used for the game. It is a
register 2-bits wide and 20 rows long. When the load signal is high, it takes in the 2-bit color
value and stores it at the address specified by the 5-bit Gaddr input. When the load signal is low,
it outputs the value stored at the address specified by the Gaddr input.
!
!
!!
GameRegister Simulations
!
In the above simulation, the write operation is being demonstrated. It can be seen that when
gload = 1, and gaddr = 000111 that the value 01, seen on the input, is stored at address
three of the register. Below, the read operation is demonstrated.
When gload = 0, the value stored at the address specified on gadder is seen on the output. In the
above simulation, when glad = 0 and gaddr = 00010, the value 10 which is stored at
address 00010 is passed to the output.
!
!
!
!
VGA_Simon_Controller Component
!
!
This component controls the VGA display, and consequently, the game board. When all enable
signals are low, the component will cause the 4 colors to display on the board, each in its
respective corner. When game_enable is high, the component will then look at the input
game_color to determine which of the four colors to flash. If game_enable is low, the component
does not care about the value on the game_color signal. Additionally, if error_enable is high, the
entire screen will turn red, indicating an error.
Control Unit
Above, you see the top level of the Control Unit: The control unit has three input: clk, reset, and
correct_color. The outputs were explained previously during the discussion of the data unit and
its component and are as follows: gameAddress, clock, DataUnit_reset, error_enable,
gameRegister_load, game_enable, random-enable, and win_enable. Please note that the
win_enable signal is not currently connected to the data unit.
!
Following is the finite state machine inside the control unit and a detailed description of the
states.
Control_Unit Finite State Machine
!
!
!
State Name: ResetGame
Transitions into this state: The Control Unit will transition into this state from any state on the diagram if
the reset signal is asserted.
!Function: This is the initial/reset state of the circuit. It resets the appropriate enable lines to ensure that all
data unit components are ready for a new game
!Outputs asserted: random_enable = 1, game_enable = 0, error_enable = 0, gameAddress_sig =
00000";
!Transitions out of State: The Control Unit transitions out of this at the next rising edge of the next clk
signal as long as rest = 0.
!!
State Name: Play6
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check5.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
00110
!
State Name: Play7
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check6.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
00111
!
State Name: Play8
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check7.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
01000
!
State Name: Play10
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check3.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
01010
!
State Name: Play12
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check11.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
01100
!
State Name: Play14
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check13.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
01110
!
State Name: Play16
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check15.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
10000
!
State Name: Play18
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check17.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
!Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
10010
!
State Name: Play20
Transitions into this state: The Control Unit will transition into this state when the previous state was
Check19.
!Function: This state is responsible for displaying the first two colors stored in the GameRegister
!Outputs asserted: game_enable = 1, gameAddress_sig = gameAddress_sig + 1
!Transitions out of State: The Control Unit transitions out of this state when the GameAddress_sig =
10100
!
State Name: Error
Transitions into this state: The Control Unit will transition into this state when a zero is received on the
correct_color signal
!Function: When in this state, the simon game will simply display a bright red screen.
!Outputs asserted: error_enable = 1, game_Enable = 0
!Transitions out of State: The Control Unit transitions out of this state when reset = 1
!
State Name: Idle
Transitions into this state: The Control Unit will transition into this state after a full game has played and
the error state has never been entered
!Function: This state simply waits for a reset signal to indicate that another game is ready to be played.
!Outputs asserted: game_enable = 0
!Transitions out of State: The Control Unit transitions out of this state when reset = 1
!
!
Pitfalls and Future Modifications
!
!
!
ClkDivider: External Component to Internal Process
!
!
I experienced difficulty when using my clock divider and Im not sure why. The clock divider
runs as a stand alone component and demonstrates functionality when loaded to the board as a
single unit. However, when it was attached to the control unit as an external component, the
system as a whole failed. This issue was resolved by simply making the clkDivider a process
inside of the control unit rather than a component in the Data Unit.
!
!
!
Slow Start-up
!
I had difficulty working on the timing in my control unit. In order to flash the colors on the
display long enough to be seen by the human eye, the FSM needed to be slowed down. However,
I did not want the entire control unit to run on the slower flash clock, because then there would
be about a 7 second delay before the game was ready for play.
!
However, my attempts at getting the game to setup in a separate FSM using a faster clock were
unsuccessful. It led to errors in the hardware behavior and in some instances, no behavior at all.
For that reason, my control unit runs entirely on the flash clock and there is about a 7 second
delay from the time the game is reset to the time it is ready for play.
!
Hopefully, this functionality is something I will have time to address in the coming month. If not,
I hope to have time to learn to display messages on the screen. Then, I can simply use the 7
second delay to display instructions on the screen for the user.
!
!
Flashing the Same Color Twice
!
It will be necessary to add a few states to my FSM to account for the fact that even random
colors can have repeats. Unfortunately, when repeat colors are encountered, it is difficult to
identify the number of repeats. It will be necessary to flash the colors, then show the board
briefly between flashes. Otherwise, repeat colors could easily be mistaken for one flash.
!
!
Addition of the wrong_color status signal
!
While testing my simon game, I noticed that it did not wait for an input in the Check states. It
either went immediately to the next Play state or immediately went to the error state based on
the status of the correct_color signal. I learned that it was because correct_color was either 0 or 1
all the time and, thus, would always cause the state to immediately make a decision. I need to
add the wrong_color signal so that instead of making a decision immediately, the Check states
will wait for a specific condition (correct_color = 1 or wrong_color = 1) to be met before
updating the current_state. This will require modifications to both the Comparator component
and the Control Unit.
!
!
Appendix A: VHDL Code
!
!
ClkDivider
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;
!!
--This entity takes the 50 MHz board clock and provides a slower clock for the flashing of the colors.
--The clock will be high for approximately 0.33 seconds and will be low for approximately 0.33 seconds
entity clkDivider is
Port ( clk, reset : in STD_LOGIC;
flash_clock : out STD_LOGIC);
end clkDivider;
!!
architecture Behavioral of clkDivider is
!
--this will be my count signal and will allow me to divide the clock
signal count: std_logic_vector(25 downto 0) := "00000000000000000000000000";
!
begin
!
process(clk)
begin
flash_clock <= count(24); --This divides the 50 MHz clock by 2^24 providing a 2.98023 Hz clock
end process;
!
end Behavioral;
!!
RandomColorGenerator
entity RandomColorGenerator is
port (clk : in std_logic;
RandomEnable: in std_logic;
color : out std_logic_vector(1 downto 0));
end RandomColorGenerator;
!
architecture Behavioral of RandomColorGenerator is
!
--these signals are used to both hold and generate the random numbers
signal rNumber : std_logic_vector(31 downto 0) := "10110010100011100101000100001101";
signal rtemp : std_logic := '0';
!
begin
Random_Color: process(clk)
begin
! if (clk'event) and (clk = '1') then
--This portion of the code is the implementation of the linear feedback shift register.
--It will continue to generate random numbers on the rising edge of the clock, even when
--it is not enabled.
rtemp <= rNumber(0) xor rNumber(1);
rNumber(30 downto 0) <= rNumber(31 downto 1);
rNumber(31) <= rtemp;
! --When the RandomEnable line goes high, the Random Number Generator ouputs the values
--of the two least significant bits of the the shift register. When it is not enabled, it
--outputs a "00", but continues to gnerate random numbers in the background
if (RandomEnable = '1') then
color <= rNumber(1) & rNumber(0);
elsif (RandomEnable ='0') then
color <= "00";
end if;
end if;
! end process;
!
end Behavioral;
!!
GameRegister
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
!
entity GameRegister is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
Gload : in STD_LOGIC;
color : in STD_LOGIC_VECTOR (1 downto 0);
Gaddr : in STD_LOGIC_VECTOR (4 downto 0);
GColor_out : out STD_LOGIC_VECTOR (1 downto 0));
end GameRegister;
!
architecture Behavioral of GameRegister is
!
type GameArray is array (0 to 19) of std_logic_vector(1 downto 0); --creates the register type
!
signal GameRegister: GameArray;
signal index: integer := 0; --this will allow us to program the correct rows of the register
!
begin
Program_Register: Process(clk)
begin
! --these case statements decode the address entered into the corresponding register index
--they were necessary to handle invalid inputs on the Gaddr input.
case Gaddr is
when "00000" => index <= 0;
when "00001" => index <= 1;
when "00010" => index <= 2;
when "00011" => index <= 3;
when "00100" => index <= 4;
when "00101" => index <= 5;
when "00110" => index <= 6;
when "00111" => index <= 7;
when "01000" => index <= 8;
when "01001" => index <= 9;
when "01010" => index <= 10;
when "01011" => index <= 11;
when "01100" => index <= 12;
when "01101" => index <= 13;
when "01110" => index <= 14;
when "01111" => index <= 15;
when "10000" => index <= 16;
when "10001" => index <= 17;
when "10010" => index <= 18;
when "10011" => index <= 19;
when others => index <= 0;
end case;
Play1, Play2, Play3, Play4, Play5, Play6, Play7, Play8, Play9, Play10,
Play11, Play12, Play13, Play14, Play15, Play16, Play17, Play18, Play19,
Play20,
!
Check1, Check2, Check3, Check4, Check5, Check6, Check7, Check8, Check9, Check10,
Check11, Check12, Check13, Check14, Check15, Check16, Check17, Check18, Check19,
Check20,
!
error, idle);
!
signal current_state, next_State: state_type;
!
signal fclk, DataUnit_reset_sig: std_logic;
signal count: std_logic_vector(25 downto 0) := "00000000000000000000000000";
!!
begin
!
clkDivider: process(clk, reset, count)
begin
fclk <= count(24); --This divides the 50 MHz clock by 2^24 providing a 2.98023 Hz clock
clock <= clk;
end if;
end if;
DataUnit_reset <= DataUnit_reset_sig;
end process NextStateLogic;
SimonGameFSM: process
begin
case current_state is
when ResetGame =>
--DataUnit_reset <= '1';
gameAddress_sig <= "00000";
--color_count <= "00000";
random_enable <= '1';
game_enable <= '0';
error_enable <= '0';
when Setup1 => --in this state the GameRegister is written with 20 random colors
gameRegister_load <= '1';
random_enable <= '1';
end if;
when Play1 => --loops through once and plays the first color in the register
game_enable <= '1';
if (gameAddress_sig = "00001") then
next_state <= Check1;
game_enable <= '0';
elsif (gameAddress_sig < "00001") then
gameAddress_Sig <= gameAddress_Sig + 1;
next_state <= Check1;
end if;
when Check1 => --checks if the correct_color signal is high and continues to
next play state or to error state
game_enable <= '0';
gameAddress_sig <= "00000"; --this modification was made to
force the "00000" address to be read
if (correct_color = '1') then
next_state <= Play2;
else
next_state <= error;
end if;
when Play2 => --loops through twice and plays the first 2 colors in the register
game_enable <= '1';
if (gameAddress_sig = "00010") then
next_state <= Check2;
game_enable <= '0';
elsif (gameAddress_sig < "00010") then
gameAddress_Sig <= gameAddress_Sig + 1;
next_state <= Play2;
end if;
when Check2 => --checks if the correct_color signal is high and continues to next play
state or to error state
game_enable <= '0';
gameAddress_sig <= "00000";
if (correct_color = '1') then
next_state <= Play3;
else
next_state <= error;
end if;
when Play3 => --loops through 3 times and plays the first 3 colors in the
register
game_enable <= '1';
if (gameAddress_sig = "00011") then
next_state <= Check3;
game_enable <= '0';
elsif (gameAddress_sig < "00011") then
gameAddress_Sig <= gameAddress_Sig + 1;
next_state <= Play3;
end if;
end case;