kmb32123
Newbie level 4
- Joined
- Dec 6, 2012
- Messages
- 5
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,281
- Activity points
- 1,340
I am currently working on a project to replicate a game similar to the game show Deal or No Deal. I have a decent amount of experience programming circuits in a single state via entities but this is my first attempt at a state machine. I do have a lot of experience with higher languages like java and c but those have proven to be little help. The inability for me to 'step though' code is getting me pretty frustrated. When I load the following code onto the board it seems to produce random output and I'm not sure where to start debugging. I have tried making changes and again, the effects seem unpredictable. Currently when the reset switch is on I can tell it is in the 'initiate' state because the seven segment displays display 0000. However, when I turn off the reset switch it seems to move to a different state without any other input from me. I was under the understanding that by this code it should continue to be in the 'initiate' state until it receives the confirm_in signal. Then on the other hand I could be wrong, I just would like another perspective from someone who knows more about this process.
For those of you who don't know how the game is played, a contestant chooses between one of many closed briefcases, each containing a dollar value. In my application each of the 10 case will be represent by an LED. The case the contestant chose is kept closed. After the contestant chooses there case, they select another case. This newly selected case is opened and the dollar value is displayed. Then, based on the probability of a high value in the contestant's case, they are offered a dollar value from the 'banker' to sell it for. It is at this point the contestant must choose deal or no deal. If they select deal, they sell their unopened case to the banker and receive the offer amount from the banker and the game ends. Otherwise they select another case to open and see the value. They are then offered another value. This continues until there is one unopened case left. At this point the contestant must chose to take the final offer or open their case and receive that value.
mytypes.vhd
DealOrNoDeal.vhd
DealOrNoDeal.vhd - revised 12/06/12
For those of you who don't know how the game is played, a contestant chooses between one of many closed briefcases, each containing a dollar value. In my application each of the 10 case will be represent by an LED. The case the contestant chose is kept closed. After the contestant chooses there case, they select another case. This newly selected case is opened and the dollar value is displayed. Then, based on the probability of a high value in the contestant's case, they are offered a dollar value from the 'banker' to sell it for. It is at this point the contestant must choose deal or no deal. If they select deal, they sell their unopened case to the banker and receive the offer amount from the banker and the game ends. Otherwise they select another case to open and see the value. They are then offered another value. This continues until there is one unopened case left. At this point the contestant must chose to take the final offer or open their case and receive that value.
mytypes.vhd
Code:
Library ieee;
use ieee.std_logic_1164.ALL;
use ieee.std_logic_arith.ALL;
PACKAGE mytypes IS
type segArray is array (0 to 9) of bit_vector(6 downto 0);
type boxArray is array (0 to 9) of NATURAL;
type seven_seg_vector is array (natural range <>) of bit_vector(6 downto 0);
subtype number_of_seven_segs is integer range 0 to 3;
subtype number_of_red_leds is integer range 0 to 9;
END PACKAGE mytypes;
DealOrNoDeal.vhd
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.math_real.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
library work;
use work.mytypes.all;
entity DealOrNoDeal is
Port ( clk, rst : IN STD_LOGIC;
left_in, right_in, confirm_in, decline_in : IN STD_LOGIC;
SevenSegs : out seven_seg_vector( number_of_seven_segs );
LEDs : out std_logic_vector( number_of_red_leds ));
signal sevSegKey : segArray := ("1000000", "1111001", "0100100", "0110000", "0011001",
"0010010", "0000011", "1111000", "0000000", "0011000");
function random ( max : NATURAL) return NATURAL is
variable rand: real;
variable s1 : positive := 1;
variable s2 : positive := 1;
begin
UNIFORM(s1, s2, rand);
return (INTEGER(TRUNC(rand*1000.0)) MOD max);
end function random;
function toSevenSeg ( num : NATURAL ) return seven_seg_vector is
variable output: seven_seg_vector( number_of_seven_segs );
begin
for I in number_of_seven_segs loop
output(I) := sevSegKey((num / (10 ** I)) MOD 10);
end loop;
return output;
end function toSevenSeg;
function toLogic ( num : NATURAL ) return STD_LOGIC is
begin
IF(num = 0 ) THEN
RETURN '0';
END IF;
RETURN '1';
end function toLogic;
function setLEDs(key : boxArray) return std_logic_vector is
variable output:std_logic_vector( number_of_red_leds );
begin
FOR I IN number_of_red_leds LOOP
output(I) := toLogic (key(I));
END LOOP;
return output;
end function setLEDs;
function setBoxes return boxArray is
variable boxValKey : boxArray := (1, 5, 10, 25, 50, 75, 100, 500, 750, 1000);
variable result : boxArray := (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
variable rand : NATURAL := random (10);
begin
FOR I IN number_of_red_leds LOOP
while ( boxValKey( rand ) = 0 ) LOOP
rand := (rand + 3) MOD 10;
END LOOP;
result(I) := boxValKey( rand );
boxValKey(rand) := 0;
END LOOP;
return result;
end function setBoxes;
function adjustPosition ( left : BOOLEAN; right : BOOLEAN; ledIndex : INTEGER) return NATURAL is
begin
IF (NOT(left XOR right)) THEN
return ledIndex;
END IF;
IF(LEFT) THEN
return (ledIndex - 1) MOD 10;
END IF;
return (ledIndex + 1) MOD 10;
end function adjustPosition;
function getOffer(key : boxArray) return POSITIVE is
variable sum : NATURAL := 0;
variable num : NATURAL := 0;
begin
FOR I IN number_of_red_leds LOOP
IF(key(I) /= 0) THEN
sum := sum + key(I);
num := num + 1;
END IF;
END LOOP;
sum := sum / num;
return sum;
end function getOffer;
end DealOrNoDeal;
architecture fsm of DealOrNoDeal IS
TYPE state IS (initiate, start_selector, mid_selector, display_value, offer_prompt);
SIGNAL present_state, next_state: STATE;
SIGNAL boxes : boxArray;
SIGNAL selectedBoxValue : NATURAL := 0;
SIGNAL myBoxValue : NATURAL := 0;
SIGNAL blinkDelay : NATURAL := 0;
SIGNAL highlitLED : integer range 0 to 9;
SIGNAL blinkState : std_logic;
begin
PROCESS(rst, clk)
BEGIN
IF(rst='1') THEN
present_state <= initiate;
ELSIF(clk' EVENT AND clk ='1') THEN
present_state <= next_state;
END IF;
END PROCESS;
PROCESS(present_state, left_in, right_in, confirm_in, decline_in, boxes, next_state,selectedBoxValue, myBoxValue, blinkDelay, highlitLED, blinkState)
BEGIN
CASE present_state IS
--State to initiate signals
--User presses confirm_in to move to next state
WHEN initiate =>
boxes <= setBoxes;
highlitLED <= 0;
blinkState <= '0';
SevenSegs <= toSevenSeg (0);
IF ( confirm_in = '1' ) THEN
next_state <= start_selector;
ELSE
next_state <= present_state;
END IF;
--State for the user to select their personal case
--All cases will be illuminated and the highlitLED flashes
--left_in and right_in adjust highlitLED left and right
--confirm_in stores boxes(highlitLED) for latter use and disallows this elemet to be selected later
WHEN start_selector =>
LEDs <= setLEDs(boxes);
--Supposed to make LEDs(highlitLED) blink
IF(blinkDelay > 100000)THEN
blinkState <= NOT blinkState;
blinkDelay <= 0;
ELSE
blinkDelay <= blinkDelay + 1;
END IF;
LEDs(highlitLED) <= blinkState;
IF ( ( confirm_in = '1' ) AND boxes(highlitLED) /= 0 ) THEN
next_state <= mid_selector;
myBoxValue <= boxes(highlitLED);
boxes(highlitLED) <= 0;
ELSE
next_state <= present_state;
highlitLED <= adjustPosition (left_in = '1', right_in = '1', highlitLED);
END IF;
--State for the user to select a case to open
--All unselected cases will be illuminated and the highlitLED flashes
--left_in and right_in adjust highlitLED left and right
--confirm_in stores boxes(highlitLED) for latter use and disallows this elemet to be selected later
WHEN mid_selector =>
LEDs <= setLEDs(boxes);
--Supposed to make LEDs(highlitLED) blink
IF(blinkDelay > 100000)THEN
blinkState <= NOT blinkState;
blinkDelay <= 0;
ELSE
blinkDelay <= blinkDelay + 1;
END IF;
LEDs(highlitLED) <= blinkState;
IF ( (confirm_in = '1') AND boxes(highlitLED) /= 0 ) THEN
next_state <= display_value;
selectedBoxValue <= boxes(highlitLED);
SevenSegs <= toSevenSeg (boxes(highlitLED));
boxes(highlitLED) <= 0;
ELSE
next_state <= present_state;
highlitLED <= adjustPosition ((left_in = '1'), (right_in = '1'), highlitLED);
END IF;
--State to display the value of the case the user just opened
--Goes to next state when the user presses confirm_in
WHEN display_value =>
IF ( (confirm_in = '1') ) THEN
next_state <= offer_prompt;
ELSE
next_state <= present_state;
END IF;
--State to offer the user a price for their case
--confirm_in accepts the offer and restarts the game
--decline_in sends the user to select another case
WHEN offer_prompt =>
SevenSegs <= toSevenSeg (getOffer(boxes));
IF ((confirm_in = '1')) THEN
next_state <= initiate;
ELSIF ((decline_in = '1')) THEN
next_state <= mid_selector;
ELSE
next_state <= present_state;
END IF;
END CASE;
END PROCESS;
END fsm;
DealOrNoDeal.vhd - revised 12/06/12
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.math_real.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
library work;
use work.mytypes.all;
entity DealOrNoDeal is
Port ( clk, rst : IN STD_LOGIC;
left_in, right_in, confirm_in, decline_in : IN STD_LOGIC;
SevenSegs : out seven_seg_vector( number_of_seven_segs );
LEDs : out std_logic_vector( number_of_red_leds ));
end DealOrNoDeal;
architecture fsm of DealOrNoDeal IS
function random ( max : NATURAL) return NATURAL is
variable rand: real;
variable s1 : positive := 1;
variable s2 : positive := 1;
begin
UNIFORM(s1, s2, rand);
return (INTEGER(TRUNC(rand*1000.0)) MOD max);
end function random;
function toSevenSeg ( num : NATURAL ) return seven_seg_vector is
variable output: seven_seg_vector( number_of_seven_segs );
constant sevSegKey : segArray := ("1000000", "1111001", "0100100", "0110000", "0011001",
"0010010", "0000011", "1111000", "0000000", "0011000");
begin
for I in number_of_seven_segs loop
output(I) := sevSegKey((num / (10 ** I)) MOD 10);
end loop;
return output;
end function toSevenSeg;
function toLogic ( num : NATURAL ) return STD_LOGIC is
begin
IF(num = 0 ) THEN
RETURN '0';
END IF;
RETURN '1';
end function toLogic;
function setLEDs(key : boxArray) return std_logic_vector is
variable output:std_logic_vector( number_of_red_leds );
begin
FOR I IN number_of_red_leds LOOP
output(I) := toLogic (key(I));
END LOOP;
return output;
end function setLEDs;
function setBoxes return boxArray is
variable boxValKey : boxArray;
variable result : boxArray := (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
variable rand : NATURAL;
begin
boxValKey := (1, 5, 10, 25, 50, 75, 100, 500, 750, 1000);
rand := random (10);
FOR I IN number_of_red_leds LOOP
while ( boxValKey( rand ) = 0 ) LOOP
rand := (rand + 3) MOD 10;
END LOOP;
result(I) := boxValKey( rand );
boxValKey(rand) := 0;
rand := random (10);
END LOOP;
return result;
end function setBoxes;
function adjustPosition ( left : BOOLEAN; right : BOOLEAN; ledIndex : INTEGER) return NATURAL is
begin
IF (NOT(left XOR right)) THEN
return ledIndex;
END IF;
IF(LEFT) THEN
return (ledIndex - 1) MOD 10;
END IF;
return (ledIndex + 1) MOD 10;
end function adjustPosition;
function getOffer(key : boxArray) return POSITIVE is
variable sum : NATURAL := 0;
variable num : NATURAL := 0;
begin
FOR I IN number_of_red_leds LOOP
IF(key(I) /= 0) THEN
sum := sum + key(I);
num := num + 1;
END IF;
END LOOP;
sum := sum / num;
return sum;
end function getOffer;
TYPE state IS (initiate, start_selector, mid_selector, display_value, offer_prompt);
SIGNAL present_state, next_state: STATE;
SIGNAL boxes : boxArray;
SIGNAL selectedBoxValue : NATURAL := 0;
SIGNAL myBoxValue : NATURAL := 0;
SIGNAL highlitLED : integer range 0 to 9;
begin
PROCESS(rst, clk)
BEGIN
IF(rst='1') THEN
present_state <= initiate;
ELSIF(clk' EVENT AND clk ='1') THEN
present_state <= next_state;
END IF;
END PROCESS;
PROCESS(rst, clk, highlitLED)
constant max_count : natural := 48000000;
variable count : natural range 0 to max_count;
begin
if rst = '0' then
count := 0;
LEDs <= setLEDs(boxes);
LEDs(highlitLED) <= '1';
elsif rising_edge(Clk) then
LEDs <= setLEDs(boxes);
if count < max_count/2 then
LEDs(highlitLED) <='1';
count := count + 1;
elsif count < max_count then
LEDs(highlitLED) <='0';
count := count + 1;
else
count := 0;
LEDs(highlitLED) <='1';
end if;
end if;
end process;
PROCESS(present_state, left_in, right_in, confirm_in, decline_in, selectedBoxValue, myBoxValue, highlitLED, boxes)
BEGIN
CASE present_state IS
--State to initiate signals
--User presses confirm_in to move to next state
WHEN initiate =>
selectedBoxValue <= 0;
myBoxValue <= 0;
highlitLED <= 0;
boxes <= setBoxes;
SevenSegs <= toSevenSeg (0);
IF ( confirm_in = '1' ) THEN
next_state <= start_selector;
ELSE
next_state <= present_state;
END IF;
--State for the user to select their personal case
--All cases will be illuminated and the highlitLED flashes
--left_in and right_in adjust highlitLED left and right
--confirm_in stores boxes(highlitLED) for latter use and disallows this elemet to be selected later
WHEN start_selector =>
selectedBoxValue <= 0;
boxes <= boxes;
SevenSegs <= toSevenSeg (1111);
IF ( confirm_in = '1' AND boxes(highlitLED) /= 0 ) THEN
next_state <= mid_selector;
myBoxValue <= boxes(highlitLED);
boxes(highlitLED) <= 0;
highlitLED <= 0;
ELSE
myBoxValue <= 0;
next_state <= present_state;
highlitLED <= adjustPosition (left_in = '1', right_in = '1', highlitLED);
END IF;
--State for the user to select a case to open
--All unselected cases will be illuminated and the highlitLED flashes
--left_in and right_in adjust highlitLED left and right
--confirm_in stores boxes(highlitLED) for latter use and disallows this elemet to be selected later
WHEN mid_selector =>
myBoxValue <= myBoxValue;
boxes <= boxes;
SevenSegs <= toSevenSeg (2222);
IF ( confirm_in = '1' AND boxes(highlitLED) /= 0 ) THEN
next_state <= display_value;
selectedBoxValue <= boxes(highlitLED);
boxes(highlitLED) <= 0;
highlitLED <= 0;
ELSE
selectedBoxValue <= 0;
next_state <= present_state;
highlitLED <= adjustPosition ((left_in = '1'), (right_in = '1'), highlitLED);
END IF;
--State to display the value of the case the user just opened
--Goes to next state when the user presses confirm_in
WHEN display_value =>
selectedBoxValue <= 0;
myBoxValue <= myBoxValue;
highlitLED <= 0;
boxes <= boxes;
SevenSegs <= toSevenSeg (selectedBoxValue);
IF ( confirm_in = '1' ) THEN
next_state <= offer_prompt;
ELSE
next_state <= present_state;
END IF;
--State to offer the user a price for their case
--confirm_in accepts the offer and restarts the game
--decline_in sends the user to select another case
WHEN offer_prompt =>
selectedBoxValue <= 0;
myBoxValue <= myBoxValue;
highlitLED <= 0;
boxes <= boxes;
SevenSegs <= toSevenSeg (getOffer(boxes));
IF ((confirm_in = '1')) THEN
next_state <= initiate;
ELSIF ((decline_in = '1')) THEN
next_state <= mid_selector;
ELSE
next_state <= present_state;
END IF;
END CASE;
END PROCESS;
END fsm;
Last edited: