I am writing VHDL code of Tic-tac-toe game. In my code, winning state is delayed one turn.
(P.S. I am not very familiar with clock so, I have to set p1_play and p2_play value i.e. 1 or 0 using force in waveform). Can someone please suggest me what makes my program to delay 1 turn.
Thanks you.
(clickable)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tttt1 is
Port (
in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
in3 : in STD_LOGIC;
in4 : in STD_LOGIC;
in5 : in STD_LOGIC;
in6 : in STD_LOGIC;
in7 : in STD_LOGIC;
in8 : in STD_LOGIC;
in9 : in STD_LOGIC;
p1_play : in STD_LOGIC;
p2_play : in STD_LOGIC;
p1_win : out STD_LOGIC;
p2_win : out STD_LOGIC;
out_11 : out STD_LOGIC;
out_12 : out STD_LOGIC;
out_13 : out STD_LOGIC;
out_21 : out STD_LOGIC;
out_22 : out STD_LOGIC;
out_23 : out STD_LOGIC;
out_31 : out STD_LOGIC;
out_32 : out STD_LOGIC;
out_33 : out STD_LOGIC);
end entity tttt1;
architecture Behavioral of tttt1 is
signal temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18, temp19, temp21, temp22, temp23, temp24, temp25, temp26, temp27, temp28, temp29 :std_logic :='0';
signal p1win,p2win :std_logic :='0';
signal o11,o12,o13,o21,o22,o23,o31,o32,o33:std_logic :='0';
begin
process(in1,in2,in3,in4,in5,in6,in7,in8,in9)
begin
-----------Start Player 1 Play-------------
if(p1_play ='1' and p2_play='0') then
if (in1= '1') then
temp11 <='1';
temp21 <='0';
o11<='1';
elsif(in2= '1') then
temp12 <='1';
temp22 <='0';
o12<='1';
elsif(in3= '1') then
temp13 <='1';
temp23 <='0';
o13<='1';
elsif(in4= '1') then
temp14 <='1';
temp24 <='0';
o21<='1';
elsif(in5= '1') then
temp15 <='1';
temp25 <='0';
o22<='1';
elsif(in6= '1') then
temp16 <='1';
temp26 <='0';
o23<='1';
elsif(in7= '1') then
temp17 <='1';
temp27 <='0';
o31<='1';
elsif(in8= '1') then
temp18 <='1';
temp28 <='0';
o32<='1';
elsif(in9= '1') then
temp19 <='1';
temp29 <='0';
o33<='1';
end if;
end if;
if ((temp11='1' and temp12='1' and temp13='1') or (temp14='1' and temp15='1' and temp16='1') or (temp17='1' and temp18='1' and temp19='1')
or (temp11='1' and temp14='1' and temp17='1') or (temp12='1' and temp15='1' and temp18='1') or (temp13='1' and temp16='1' and temp19='1')
or (temp11='1' and temp15='1' and temp19='1') or (temp13='1' and temp15='1' and temp17='1')) then
p1win<='1';
end if;
---------------End Player 1 Play---------------
--------------Start Player 2 Play--------------
if(p2_play ='1' and p1_play='0') then
if (in1= '1')then
temp21 <='1';
temp11 <='0';
o11<='1';
elsif(in2= '1') then
temp22 <='1';
temp12 <='0';
o12<='1';
elsif(in3= '1') then
temp23 <='1';
temp13 <='0';
o13<='1';
elsif(in4= '1') then
temp24 <='1';
temp14 <='0';
o21<='1';
elsif(in5= '1') then
temp25 <='1';
temp15 <='0';
o22<='1';
elsif(in6= '1') then
temp26 <='1';
temp16 <='0';
o23<='1';
elsif(in7= '1') then
temp27 <='1';
temp17 <='0';
o31<='1';
elsif(in8= '1') then
temp28 <='1';
temp18 <='0';
o32<='1';
elsif(in9= '1') then
temp29 <='1';
temp19 <='0';
o33<='1';
end if;
end if;
if( (temp21='1' and temp22='1' and temp23='1') or (temp24='1' and temp25='1' and temp26='1') or (temp27='1' and temp28='1' and temp29='1')
or (temp21='1' and temp24='1' and temp27='1') or (temp22='1' and temp25='1' and temp28='1') or (temp23='1' and temp26='1' and temp29='1')
or (temp21='1' and temp25='1' and temp29='1') or (temp23='1' and temp25='1' and temp27='1')) then
p2win<='1';
end if;
---------------End Player 2 Play---------------
end process;
p1_win <= p1win;
p2_win <= p2win;
out_11 <= o11;
out_12 <= o12;
out_13 <= o13;
out_21 <= o21;
out_22 <= o22;
out_23 <= o23;
out_31 <= o31;
out_32 <= o32;
out_33 <= o33;
end Behavioral;
The cause of your delay on seeing p2_win is that temp11 through temp13, temp21 through temp 23 and temp31 through temp33 are not in the process sensitivity list (nor should they be). The update of p1_win or p2_win doesn't occur until there's an event on signal in the process sensitivity list, in this case a transistion on in3 and in9.
Making the assignments to the two win outputs separate concurrent signal assigments gets the delay right:
The modified code (With formatting for readability) looks like:
library ieee;
use ieee.std_logic_1164.all;
entity tttt1 is
port (
in1: in std_logic;
in2: in std_logic;
in3: in std_logic;
in4: in std_logic;
in5: in std_logic;
in6: in std_logic;
in7: in std_logic;
in8: in std_logic;
in9: in std_logic;
p1_play: in std_logic;
p2_play: in std_logic;
p1_win: out std_logic;
p2_win: out std_logic;
out_11: out std_logic;
out_12: out std_logic;
out_13: out std_logic;
out_21: out std_logic;
out_22: out std_logic;
out_23: out std_logic;
out_31: out std_logic;
out_32: out std_logic;
out_33: out std_logic
);
end entity tttt1;
architecture behavioral of tttt1 is
signal temp11, temp12,
temp13, temp14,
temp15, temp16,
temp17, temp18,
temp19, temp21,
temp22, temp23,
temp24, temp25,
temp26, temp27,
temp28, temp29: std_logic := '0';
signal p1win,p2win: std_logic := '0';
signal o11,o12,o13,o21,
o22,o23,o31,o32,
o33: std_logic := '0';
begin
process (in1,in2,in3,in4,in5,in6,in7,in8,in9)
begin
-----------Start Player 1 Play-------------
if p1_play = '1' and p2_play = '0' then
if in1 = '1' then
temp11 <= '1';
temp21 <= '0';
o11 <= '1';
elsif in2 = '1' then
temp12 <= '1';
temp22 <= '0';
o12 <= '1';
elsif in3 = '1' then
temp13 <= '1';
temp23 <= '0';
o13 <= '1';
elsif in4 = '1' then
temp14 <= '1';
temp24 <= '0';
o21 <= '1';
elsif in5 = '1' then
temp15 <= '1';
temp25 <= '0';
o22 <= '1';
elsif in6 = '1' then
temp16 <= '1';
temp26 <= '0';
o23<= '1';
elsif in7 = '1' then
temp17 <= '1';
temp27 <= '0';
o31<= '1';
elsif in8 = '1' then
temp18 <= '1';
temp28 <= '0';
o32 <= '1';
elsif in9 = '1' then
temp19 <= '1';
temp29 <= '0';
o33 <= '1';
end if;
end if;
-- if (temp11 = '1' and temp12 = '1' and temp13 = '1') or
-- (temp14 = '1' and temp15 = '1' and temp16 = '1') or
-- (temp17 = '1' and temp18 = '1' and temp19 = '1') or
-- (temp11 = '1' and temp14 = '1' and temp17 = '1') or
-- (temp12 = '1' and temp15 = '1' and temp18 = '1') or
-- (temp13 = '1' and temp16 = '1' and temp19 = '1') or
-- (temp11 = '1' and temp15 = '1' and temp19 = '1') or
-- (temp13 = '1' and temp15 = '1' and temp17 = '1') then
--
-- p1win <= '1';
--
-- end if;
---------------End Player 1 Play---------------
--------------Start Player 2 Play--------------
if p2_play = '1' and p1_play = '0' then
if in1 = '1' then
temp21 <= '1';
temp11 <= '0';
o11 <= '1';
elsif in2 = '1' then
temp22 <= '1';
temp12 <= '0';
o12 <= '1';
elsif in3 = '1' then
temp23 <= '1';
temp13 <= '0';
o13 <= '1';
elsif in4 = '1' then
temp24 <= '1';
temp14 <= '0';
o21 <= '1';
elsif in5 = '1' then
temp25 <= '1';
temp15 <= '0';
o22 <= '1';
elsif in6 = '1' then
temp26 <= '1';
temp16 <= '0';
o23 <= '1';
elsif in7 = '1' then
temp27 <= '1';
temp17 <= '0';
o31 <= '1';
elsif in8 = '1' then
temp28 <= '1';
temp18 <= '0';
o32 <= '1';
elsif in9 = '1' then
temp29 <= '1';
temp19 <= '0';
o33 <= '1';
end if;
end if;
-- if (temp21 = '1' and temp22 = '1' and temp23 = '1') or
-- (temp24 = '1' and temp25 = '1' and temp26 = '1') or
-- (temp27 = '1' and temp28 = '1' and temp29 = '1') or
-- (temp21 = '1' and temp24 = '1' and temp27 = '1') or
-- (temp22 = '1' and temp25 = '1' and temp28 = '1') or
-- (temp23 = '1' and temp26 = '1' and temp29 = '1') or
-- (temp21 = '1' and temp25 = '1' and temp29 = '1') or
-- (temp23 = '1' and temp25 = '1' and temp27 = '1') then
--
-- p2win <= '1';
--
-- end if;
---------------End Player 2 Play---------------
end process;
p1win <= (temp11 and temp12 and temp13) or
(temp14 and temp15 and temp16) or
(temp17 and temp18 and temp19) or
(temp11 and temp14 and temp17) or
(temp12 and temp15 and temp18) or
(temp13 and temp16 and temp19) or
(temp11 and temp15 and temp19) or
(temp13 and temp15 and temp17);
p2win <= (temp21 and temp22 and temp23) or
(temp24 and temp25 and temp26) or
(temp27 and temp28 and temp29) or
(temp21 and temp24 and temp27) or
(temp22 and temp25 and temp28) or
(temp23 and temp26 and temp29) or
(temp21 and temp25 and temp29) or
(temp23 and temp25 and temp27);
p1_win <= p1win;
p2_win <= p2win;
out_11 <= o11;
out_12 <= o12;
out_13 <= o13;
out_21 <= o21;
out_22 <= o22;
out_23 <= o23;
out_31 <= o31;
out_32 <= o32;
out_33 <= o33;
end architecture behavioral;
The functional changes are limited to making the win output assignments concurrent signal assignment statements.
A test bench was used to reproduce the stimuli in your linked waveform:
library ieee;
use ieee.std_logic_1164.all;
entity tttt1_tb is
end entity;
architecture foo of tttt1_tb is
signal in1: std_logic := '0';
signal in2: std_logic := '0';
signal in3: std_logic := '0';
signal in4: std_logic := '0';
signal in5: std_logic := '0';
signal in6: std_logic := '0';
signal in7: std_logic := '0';
signal in8: std_logic := '0';
signal in9: std_logic := '0';
signal p1_play: std_logic := '0';
signal p2_play: std_logic := '0';
signal p1_win: std_logic;
signal p2_win: std_logic;
signal out_11: std_logic;
signal out_12: std_logic;
signal out_13: std_logic;
signal out_21: std_logic;
signal out_22: std_logic;
signal out_23: std_logic;
signal out_31: std_logic;
signal out_32: std_logic;
signal out_33: std_logic;
begin
DUT:
entity work.tttt1
port map (
in1 => in1,
in2 => in2,
in3 => in3,
in4 => in4,
in5 => in5,
in6 => in6,
in7 => in7,
in8 => in8,
in9 => in9,
p1_play => p1_play,
p2_play => p2_play,
p1_win => p1_win,
p2_win => p2_win,
out_11 => out_11,
out_12 => out_12,
out_13 => out_13,
out_21 => out_21,
out_22 => out_22,
out_23 => out_23,
out_31 => out_31,
out_32 => out_32,
out_33 => out_33
);
STIMULI:
process
begin
in1 <= '1';
p1_play <= '1';
wait for 100 ns;
in1 <= '0';
in2 <= '1';
p1_play <= '0';
p2_play <= '1';
wait for 100 ns;
in2 <= '0';
in9 <= '1';
p1_play <= '1';
p2_play <= '0';
wait for 100 ns;
in5 <= '1';
in9 <= '0';
p1_play <= '0';
p2_play <= '1';
wait for 100 ns;
in5 <= '0';
in7 <= '1';
p1_play <= '1';
p2_play <= '0';
wait for 100 ns;
in7 <= '0';
in8 <= '1';
p1_play <= '0';
p2_play <= '1';
wait for 100 ns;
in3 <= '1';
in8 <= '0';
p1_play <= '1';
p2_play <= '0';
wait for 100 ns;
wait;
end process;
end architecture;
There's a missing rule check to not allow a player to capture a square obliviously. That rule should be implemented as well as a method for clearing a game. The game state is held in inferred latches, that might be more widely synthesis eligible if the latches were describe in separate process driven by a single input. There would also be an expectation that the inputs are debounced.
Because there'd be a hardware expectation that an input occurs while the value of p1_play and p2_play is stable, it is possible to use a clock and pass input events (one clock in duration). It used to be common to have these sorts of games describe asynchronously in hardware implementations (think '70s and '80s).
Related
I'm looking to control an external display where the pins are connected to the ports JA and JB on the Nexys A7 100T, I've configured the state machine below according to the instructions in the datasheet but nothing is being displayed. Since this is the first time I'm controlling a display through VHDL, I suspect that either the display is not working or something is not being initialized in the correct manner.
--- Initialization and Data transfer of LCD display---
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
entity LCD is
generic(
display_lines : std_logic := '0'; --Amount of displaylines: (0 = 1-line, 1 = 2-lines)
font_type : std_logic := '0'; -- Font type: (0 = 5x8 font, 1 = 5x11 font but only available for 1 line mode)
display_on : std_logic := '1'; -- Diplay ON/OFF: (0 = OFF, 1 = ON)
display_off : std_logic := '0';
cursor : std_logic := '0'; -- Cursor ON/OFF: (0 = OFF, 1 = ON)
blink : std_logic := '0'; -- Blink ON/OFF: (0 = OFF, 1 = ON)
I_D : std_logic := '1'; -- Increment/Decrement (0 = Decrement(move left), 1 = Increment(Move right))
shift : std_logic := '1'; -- Shift of display( 0 = Shift not perfomed, 1 = shift done according to I/D)
LCD_freq : integer := (100e6/270e3) - 1 -- Operating frequency of display
);
port(
CLK100MHZ, reset: in std_logic; -- 100MHZ clock and reset signal
LCD_RW: out std_logic; -- Read/write bit for LCD
LCD_RS: out std_logic; -- Register Select for LCD
LCD_E: out std_logic; -- Enable bit for the LCD
data: out std_logic_vector(7 downto 0) -- Data being sent to LCD including setup bits.
);
end entity;
architecture arch of LCD is
Type control is (RESET_1,RESET_2,RESET_3, FUNCTION_SET, DISPLAY_OFF1, DISPLAY_CLEAR, DISPLAY_ON1, ENTRY_MODE_SET, WRITE_T, RETURN_HOME,TOGGLE_E, HOLD);
signal freq_div :std_logic_vector(9 downto 0);
signal clk270 : std_logic; -- LCD clock
signal state, next_cmd: control;
begin
-- Clock for the LCD frequency
process(CLK100MHZ, reset)
begin
if reset = '1' then
freq_div <= (others => '0');
elsif rising_edge(CLK100MHZ) then
if freq_div = LCD_freq then
clk270 <= '1';
freq_div <= (others => '0');
else
clk270 <= '0';
freq_div <= freq_div + 1;
end if; -- freq_div
end if; -- reset
end process;
-- State diagram controlling display
process(CLK100MHZ, reset)
begin
if reset = '1' then
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= RESET_1;
elsif rising_edge(CLK100MHZ) then
if clk270 = '1' then
case state is
when RESET_1 =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= RESET_2;
when RESET_2 =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= RESET_3;
when RESET_3 =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= FUNCTION_SET;
--- Initilization steps done individually ---
when FUNCTION_SET => -- sets the function for the display
LCD_RS <= '0';
LCD_RW <= '0';
data <= "0011" & display_lines & font_type & "00";
LCD_E <= '1'; -- Enables function for display
state <= TOGGLE_E;
next_cmd <= DISPLAY_OFF1;
when DISPLAY_OFF1 => -- Turns the display off
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00001" & display_off & cursor & blink;
state <= TOGGLE_E;
next_cmd <= DISPLAY_CLEAR;
when DISPLAY_CLEAR => -- Clears the display
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00000001";
state <= TOGGLE_E;
next_cmd <= DISPLAY_ON1;
when DISPLAY_ON1 => -- Turns on the display
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00001" & display_on & cursor & blink;
state <= TOGGLE_E;
next_cmd <= ENTRY_MODE_SET;
when ENTRY_MODE_SET => -- Sets the increment and shift
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "000001" & I_D & shift;
state <= TOGGLE_E;
next_cmd <= WRITE_T;
when WRITE_T =>
LCD_RS <= '1';
LCD_RW <= '0';
LCD_E <= '1';
data <= "01000101"; --Letter T
state <= TOGGLE_E;
next_cmd <= RETURN_HOME;
when RETURN_HOME =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00000010";
state <= TOGGLE_E;
next_cmd <= WRITE_T;
-- Toggles a falling edge for Enable.
when TOGGLE_E =>
LCD_E <= '1';
state <= HOLD;
when HOLD =>
state <= next_cmd;
end case;
end if; -- clk270kHz
end if; -- reset
end process;
end arch;
The display is of the archetype ST7066U. Any feedback is appreciated.
So for a school assignment we have to make a clock using different modules and I have an up-down counter and a finite state machine. I should be able to press a button so the counter goes up by one or down by one and this for the hours, minutes and seconds.
The problem is in the testbench of my fsm. When you add a number the up_down signal should go to 1 so the counter knows it has to count up, but when this happens the signal goes to unknown and when I want decrease it the signal goes back to 0 as it should.
I have looked for why it could do this but have no clue whatsoever, does anybody know why? I'll ad my code and a screenshot of the testbench.
a) The finite state machine
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tijd_FSM is
Port ( clk_1ms : in std_logic;
BTU : in std_logic;
BTD : in STD_LOGIC;
BTR : in std_logic;
mo_tijd : in std_logic;
EupH : out std_logic;
EdownH : out std_logic;
EupM : out std_logic;
EdownM : out std_logic;
EupS : out std_logic;
EdownS : out std_logic;
up_down : out std_logic;
blink_tijd: out std_logic_vector (1 downto 0)
);
end tijd_FSM;
architecture Behavioral of tijd_FSM is
type state is (s0, s1, s2, s3);
signal present_state, next_state : state;
begin
state_reg: process (clk_1ms)
begin
if rising_edge(clk_1ms) then
if(BTR = '1' and mo_tijd = '1') then
present_state <= next_state;
else
present_state <= present_state;
end if;
end if;
end process;
--state machine process.
outputs: process (present_state, BTU, BTD)
begin
case present_state is
when s0 => --Gewone weergave
blink_tijd <= "00";
up_down <= '0';
when s1 => --Instellen UU
if(BTU ='1') then
up_down <= '1';
EupH <= '1';
elsif(BTD='1') then
up_down <= '0';
EdownH <= '1';
else
EupH <= '0';
EdownH <= '0';
end if;
blink_tijd <= "10";
when s2 => --Instellen MM
if(BTU ='1') then
up_down <= '1';
EupM <= '1';
elsif(BTD='1') then
up_down <= '0';
EdownM <= '1';
else
EupM <= '0';
EdownM <= '0';
end if;
blink_tijd <= "10";
when s3 => --Instellen SS
if(BTU ='1') then
up_down <= '1';
EupS <= '1';
elsif(BTD='1') then
up_down <= '0';
EdownS <= '1';
else
EupS <= '0';
EdownS <= '0';
end if;
blink_tijd <= "01";
when others => null;
end case;
end process;
nxt_state: process (BTR, present_state)
begin
case present_state is
when s0 =>
if BTR = '1' then next_state <= s1;
else next_state <= s0;
end if;
when s1 =>
if BTR = '1' then next_state <= s2;
else next_state <= s1;
end if;
when s2 =>
if BTR = '1' then next_state <= s3;
else next_state <= s2;
end if;
when s3 =>
if BTR = '1' then next_state <= s0;
else next_state <= s3;
end if;
when others => next_state <= s0;
end case;
end process;
end Behavioral;
b) The testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY tb_tijd_FSM IS
END tb_tijd_FSM;
ARCHITECTURE behavior OF tb_tijd_FSM IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT tijd_FSM
PORT(
clk_1ms : IN std_logic;
BTU : IN std_logic;
BTD : IN std_logic;
BTR : IN std_logic;
mo_tijd : IN std_logic;
EupH : OUT std_logic;
EdownH : OUT std_logic;
EupM : OUT std_logic;
EdownM : OUT std_logic;
EupS : OUT std_logic;
EdownS : OUT std_logic;
up_down : OUT std_logic;
blink_tijd : OUT std_logic_vector(1 downto 0)
);
END COMPONENT;
--Inputs
signal clk_1ms : std_logic := '0';
signal BTU : std_logic := '0';
signal BTD : std_logic := '0';
signal BTR : std_logic := '0';
signal mo_tijd : std_logic := '0';
--Outputs
signal EupH : std_logic;
signal EdownH : std_logic;
signal EupM : std_logic;
signal EdownM : std_logic;
signal EupS : std_logic;
signal EdownS : std_logic;
signal up_down : std_logic;
signal blink_tijd : std_logic_vector(1 downto 0);
-- Clock period definitions
constant clk_1ms_period : time := 1 ms;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: tijd_FSM PORT MAP (
clk_1ms => clk_1ms,
BTU => BTU,
BTD => BTD,
BTR => BTR,
mo_tijd => mo_tijd,
EupH => EupH,
EdownH => EdownH,
EupM => EupM,
EdownM => EdownM,
EupS => EupS,
EdownS => EdownS,
up_down => up_down,
blink_tijd => blink_tijd
);
-- Clock process definitions
clk_1ms_process :process
begin
clk_1ms <= '0';
wait for clk_1ms_period/2;
clk_1ms <= '1';
wait for clk_1ms_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
up_down <= '0';
mo_tijd <= '1';
--Hij begint in state s0
wait for 1 ms;
BTR <= '1'; --s1
wait for 1 ms;
BTR <= '0';
wait for 1 ms;
BTU <= '1';
wait for 1 ms;
BTU <= '0';
wait for 1 ms;
BTD <= '1';
wait for 1 ms;
BTD <= '0';
wait for 1 ms;
BTR <= '1'; --s2
wait for 1 ms;
BTR <= '0';
wait for 1 ms;
BTU <= '1';
wait for 1 ms;
BTU <= '0';
wait for 1 ms;
BTD <= '1';
wait for 1 ms;
BTD <= '0';
wait for 1 ms;
BTR <= '1'; -- s3
wait for 1 ms;
BTR <= '0';
wait for 1 ms;
BTU <= '1';
wait for 1 ms;
BTU <= '0';
wait for 1 ms;
BTD <= '1';
wait for 1 ms;
BTD <= '0';
wait;
end process;
END;
c) The waveform image
In stim_proc you have up_down <= '0', which drives 0 on the same signal that the output of your state machine is connected.
As long as the state machine also drives 0 everything is fine as the combination resolves to 0. When the state machine drives 1 however, the resolution is X, undefined.
As far as I can see, there is no reason for stim_proc to drive this signal, so removing that line should give you what you want.
For a project I'm making a PWM multiplexer but no succes with my FSM. When I receive an interrupt of PWM_INT the counter should increment or go to 0 if max is reached. The counter depends the state of the FSM.
This is my implementation:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Mux is
Port ( CLK : in STD_LOGIC;
RST : in STD_LOGIC;
PWM : in STD_LOGIC;
PWM_INT : in STD_LOGIC;
PWM_A : out STD_LOGIC;
PWM_B : out STD_LOGIC;
PWM_C : out STD_LOGIC);
end Mux;
architecture Behavioral of Mux is
type state is (iddle,state_1,state_2,state_3,state_4,state_5,state_6,new_fsm);
signal old_state : state ;
signal new_state : state ;
signal counter : integer range 6 downto 0;
begin
process(CLK)
begin
if RST = '1' then
counter <= 0;
PWM_A <= '0';
PWM_B <= '0';
PWM_C <= '0';
elsif CLK'event and CLK = '1' then
if PWM_INT = '1' then
if counter < 6 then
counter <= counter + 1;
else
counter <= 0;
end if;
end if;
end if;
end process;
----- Clocked Process FSM -----
process(CLK)
begin
if RST = '1' then
old_state <= iddle;
elsif (CLK'event and CLK = '1') then
old_state <= new_state;
end if;
end process;
----- Transitions -----
process(old_state,counter)
begin
case old_state is
when iddle => if counter = 0 then
new_state <= state_1;
else
new_state <= iddle;
end if;
when state_1 => if counter = 1 then
new_state <= state_2;
else
new_state <= state_1;
end if;
when state_2 => if counter = 2 then
new_state <= state_3;
else
new_state <= state_2;
end if;
when state_3 => if counter = 3 then
new_state <= state_4;
else
new_state <= state_3;
end if;
when state_4 => if counter = 4 then
new_state <= state_5;
else
new_state <= state_4;
end if;
when state_5 => if counter = 5 then
new_state <= state_6;
else
new_state <= state_5;
end if;
when state_6 => if counter = 6 then
new_state <= state_1;
else
new_state <= state_6;
end if;
when others => new_state <= iddle;
end case;
end process;
----- Output FSM -----
process(old_state)
begin
case old_state is
when iddle => PWM_A <= '0';
PWM_B <= '0';
PWM_C <= '0';
when state_1 => PWM_A <= PWM;
PWM_B <= '0';
PWM_C <= '0';
when state_2 => PWM_A <= PWM;
PWM_B <= '0';
PWM_C <= '0';
when state_3 => PWM_A <= '0';
PWM_B <= PWM;
PWM_C <= '0';
when state_4 => PWM_A <= '0';
PWM_B <= PWM;
PWM_C <= '0';
when state_5 => PWM_A <= '0';
PWM_B <= '0';
PWM_C <= PWM;
when state_6 => PWM_A <= '0';
PWM_B <= '0';
PWM_C <= PWM;
when others => PWM_A <= '0';
PWM_B <= '0';
PWM_C <= '0';
end case;
end process;
end Behavioral;
The testbench to test the program:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TB_Mux is
end TB_Mux;
architecture Behavioral of TB_Mux is
component Mux
port ( CLK : in STD_LOGIC;
RST : in STD_LOGIC;
PWM : in STD_LOGIC;
PWM_INT : in STD_LOGIC;
PWM_A : out STD_LOGIC;
PWM_B : out STD_LOGIC;
PWM_C : out STD_LOGIC);
end component;
signal CLK : STD_LOGIC;
signal RST : STD_LOGIC;
signal PWM : STD_LOGIC;
signal PWM_INT : STD_LOGIC;
signal PWM_A : STD_LOGIC;
signal PWM_B : STD_LOGIC;
signal PWM_C : STD_LOGIC;
constant CLK_Period : time:= 8 ns;
begin
u0:Mux
port map( CLK => CLK,
RST => RST,
PWM => PWM,
PWM_INT => PWM_INT,
PWM_A => PWM_A,
PWM_B => PWM_B,
PWM_C => PWM_C);
process
begin
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end process;
process
begin
PWM <= '0';
RST <= '1';
PWM_INT <= '0';
wait for 5 * clk_period;
PWM <= '1';
RST <='0';
PWM_INT <='1';
wait for 1 * clk_period;
PWM_INT <= '0';
wait for 5 * clk_period;
PWM_INT <='1';
wait for 1 * clk_period;
PWM_INT <= '0';
wait for 5 * clk_period;
PWM_INT <='1';
wait for 1 * clk_period;
PWM_INT <= '0';
wait;
end process;
end Behavioral;
Thanks in advance!
Your sensitivity lists are incomplete.
i'm trying to make my own I2C communication and i have a problem with multiply drivers, it's not like i don't understand them i just don't see them (i'm still fresh at vhdl), so please just take a look at my code and tell mi why is there such mistake.
i try to operate on flags to have multiple signal drivers on bus but there's just something not right. The multiple drivers are on scl, sda, start_clk and stop_clk. Is it because those flags are for example in two different processes?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity I2C_com is
port (
reset_en: in std_logic;
clk: in std_logic;
sda: inout std_logic;
scl: out std_logic;
RD:in std_logic;
WR: in std_logic;
addr: buffer std_logic_vector(7 downto 0)
);
end I2C_com;
architecture MAIN of I2C_com is
signal data :std_logic_vector (12 downto 0):="0000000000010";
signal i2c_clk: std_logic ;
signal clk_count : unsigned(19 downto 0):="00000000000000000100";
type program_state is (start,init,error_rd_wr,slave,ack);
signal state: program_state;
signal write_data: std_logic_vector (7 downto 0):=(others => '0');
signal read_data: std_logic_vector (7 downto 0):=(others => '0');
signal clk_enable: std_logic;
signal reset: std_logic:='1';
signal start_clk: std_logic:= 'Z';
signal stop_clk: std_logic:= 'Z';
signal strech: std_logic := '0';
signal cnt_addr: integer := 0;
signal ack_error: std_logic;
signal sda_data: std_logic;
signal start_data: std_logic:= 'Z';
begin
i2c_clock: process(clk,reset_en,reset)
begin
if reset_en = '1' or reset = '1' then
elsif falling_edge(clk) then
if clk_count < unsigned(data) then
clk_count <= clk_count + 1;
clk_enable <= '1';
else
clk_count <= x"00000";
clk_enable <= '0';
end if;
i2c_clk <= clk_enable;
if start_clk = '1' then
sda <= '0';
scl <= '0';
start_clk <= '0';
end if;
if stop_clk = '1' then
sda <= '0';
scl <= '0';
stop_clk <= '0';
end if;
end if;
end process i2c_clock;
--
process(i2c_clk,reset_en,reset)
begin
if reset_en = '1' or reset = '1' then
reset <= '0';
cnt_addr <= 0;
state <= init;
elsif rising_edge(i2c_clk) then
case state is
when init =>
if RD = '1' or WR = '1' then
state <= start;
else
state <= error_rd_wr;
end if;
when start =>
start_clk <= '1';
state <= slave;
when slave =>
start_data <= '1';
if cnt_addr < 8 then
sda_data <= addr(cnt_addr);
cnt_addr <= cnt_addr + 1;
else
cnt_addr <= 0;
state <= ack;
end if;
when error_rd_wr =>
reset <= '1';
when ack =>
start_data <= '0';
ack_error <= sda;
if ack_error = '1' then
stop_clk <= '1';
reset <= '1';
else
end if;
if RD = '1' then
elsif WR = '1' then
else
stop_clk <= '1';
reset <= '1';
end if;
end case;
end if;
end process;
sda <= sda_data when start_data = '1' else 'Z';
scl <= i2c_clk when start_clk = '0' and stop_clk = '0' else 'Z';
end MAIN;
A signal for synthesis can be driven from only one process or one continuous assign; for simulation multiple drivers are possible using resolved signals like std_logic.
The scl and sda are driven both from the i2c_clock process and the continuous assign in the end of the file.
The start_clk and stop_clk are driven both from the i2c_clock process and the other unnamed process.
One possibility for scl and sda is to only drive these from the continuous assign, since synthesis tools often prefer tri-state output to be written like:
q <= value when en = '1' else 'Z';
I have 18 output and 9 push switches to work with and one led as output which changing its states each time the push button is pressed to automate the chance of two players. my code is not working, pls help
my code is...expected behavour is that when momentarily in1 switch is high then play_to_play should toggle on each event of the inputs and according to play_to_play status and in1 high either ou11 or ou21 should go high i.e one player has played his chance and automatically at the next event it takes that it is player 2 chance
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TicTac is
Port ( in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
in3 : in STD_LOGIC;
in4 : in STD_LOGIC;
in5 : in STD_LOGIC;
in6 : in STD_LOGIC;
in7 : in STD_LOGIC;
in8 : in STD_LOGIC;
in9 : in STD_LOGIC;
reset : in STD_LOGIC;
p_to_play : out STD_Logic;
p1_win : out STD_LOGIC;
p2_win : out STD_LOGIC;
ou11 : out STD_LOGIC;
ou12 : out STD_LOGIC;
ou13 : out STD_LOGIC;
ou14 : out STD_LOGIC;
ou15 : out STD_LOGIC;
ou16 : out STD_LOGIC;
ou17 : out STD_LOGIC;
ou18 : out STD_LOGIC;
ou19 : out STD_LOGIC;
ou21 : out STD_LOGIC;
ou22 : out STD_LOGIC;
ou23 : out STD_LOGIC;
ou24 : out STD_LOGIC;
ou25 : out STD_LOGIC;
ou26 : out STD_LOGIC;
ou27 : out STD_LOGIC;
ou28 : out STD_LOGIC;
ou29 : out STD_LOGIC);
end TicTac;
architecture Behavioral of TicTac is
Signal temp1, temp2, temp3, temp4, temp5, temp6,temp7, temp8, temp9,p1_play :std_logic :='0';
signal o11,o12,o13,o14,o15,o16,o17,o18,o19,o21,o22,o23,o24,o25,o26,o27,o28,o29 :std_logic :='0';
signal p1win,p2win :std_logic :='0';
begin
process(in1,in2,in3,in4,in5,in6,in7,in8,in9,reset)
begin
if ((in1'event or in2'event or in3'event or in4'event or in5'event or in6'event or in7'event or in8'event or in9'event) and
(in1='1' or in2 ='1' or in3='1' or in4='1' or in5='1' or in6='1' or in7='1' or in8='1' or in9='1')) then
p1_play <= not(p1_play);
if(reset'event and reset= '1') then
temp1 <='0';
temp2 <='0';
temp3 <='0';
temp4 <='0';
temp5 <='0';
temp6 <='0';
temp7 <='0';
temp8 <='0';
temp9 <='0';
p1_play <= '0';
p1win <='0';
p2win <='0';
o11 <='0';
o12 <='0';
o13 <='0';
o14 <='0';
o15 <='0';
o16 <='0';
o17 <='0';
o18 <='0';
o19 <='0';
o21 <='0';
o22 <='0';
o23 <='0';
o24 <='0';
o25 <='0';
o26 <='0';
o27 <='0';
o28 <='0';
o29 <='0';
end if;
if(in1= '1') then
temp1 <='1';
end if;
if(in2= '1') then
temp2 <='1';
end if;
if(in3= '1') then
temp3 <='1';
end if;
if(in4= '1') then
temp1 <='1';
end if;
if(in5= '1') then
temp5 <='1';
end if;
if(in6= '1') then
temp6 <='1';
end if;
if(in7= '1') then
temp7 <='1';
end if;
if(in8= '1') then
temp8 <='1';
end if;
if(in9= '1') then
temp9 <='1';
end if;
if(p1_play='0' and temp1='1') then
o11 <= '1';
end if;
if(p1_play='0' and temp2='1') then
o12 <= '1';
end if;
if(p1_play='0' and temp3='1') then
o13 <= '1';
end if;
if(p1_play='0' and temp4='1') then
o14 <= '1';
end if;
if(p1_play='0' and temp5='1') then
o15 <= '1';
end if;
if(p1_play='0' and temp6='1') then
o16 <= '1';
end if;
if(p1_play='0' and temp7='1') then
o17 <= '1';
end if;
if(p1_play='0' and temp8='1') then
o18 <= '1';
end if;
if(p1_play='0' and temp9='1') then
o19 <= '1';
end if;
if(p1_play='1' and temp1='1') then
o21 <= '1';
end if;
if(p1_play='1' and temp2='1') then
o22 <= '1';
end if;
if(p1_play='1' and temp3='1') then
o23 <= '1';
end if;
if(p1_play='1' and temp4='1') then
o24 <= '1';
end if;
if(p1_play='1' and temp5='1') then
o25 <= '1';
end if;
if(p1_play='1' and temp6='1') then
o26 <= '1';
end if;
if(p1_play='1' and temp7='1') then
o27 <= '1';
end if;
if(p1_play='1' and temp8='1') then
o28 <= '1';
end if;
if(p1_play='1' and temp9='1') then
o29 <= '1';
end if;
if((o11='1' and o12='1' and o13='1') or (o14='1' and o15='1' and o16='1') or (o17='1' and o18='1' and o19='1')
or (o11='1' and o14='1' and o17='1') or (o12='1' and o15='1' and o18='1') or (o13='1' and o16='1' and o19='1')
or (o11='1' and o15='1' and o19='1') or (o13='1' and o15='1' and o17='1')) then
p1win <='1';
end if;
if((o21='1' and o22='1' and o23='1') or (o24='1' and o25='1' and o26='1') or (o27='1' and o28='1' and o29='1')
or (o21='1' and o24='1' and o27='1') or (o22='1' and o25='1' and o28='1') or (o23='1' and o26='1' and o29='1')
or (o21='1' and o25='1' and o29='1') or (o23='1' and o25='1' and o27='1')) then
p2win <='1';
end if;
end if;
end process;
ou11 <= o11;
ou12 <= o12;
ou13 <= o13;
ou14 <= o14;
ou15 <= o15;
ou16 <= o16;
ou17 <= o17;
ou18 <= o18;
ou19 <= o19;
ou21 <= o21;
ou22 <= o22;
ou23 <= o23;
ou24 <= o24;
ou25 <= o25;
ou26 <= o26;
ou27 <= o27;
ou28 <= o28;
ou29 <= o29;
p_to_play <= p1_play;
p1_win <= p1win;
p2_win <= p2win;
end Behavior
al;
Processes in VHDL are not the same as processes on a regular programming language. All signal assignments within a process actually occur at the time the process completes (actually a delta time later, which is basically a 0 time difference). Since you are trying to use the value of temp that you just assigned earlier in the process, but it hasn't actually been written yet, you are not triggering your if statement until the next time the process runs.
As an aside, I didn't notice any mechanism to prevent players from playing in spaces that they or their opponent already played.
EDIT: Also, what do you plan to do with this? If you want to put it on a real FPGA with real switches it likely won't work because of an electromechanical phenomenon called switch bouncing that makes each press of a switch seem like many to the hardware.
EDIT2: To fix this (still won't fix switch bouncing) you may want to scrap temp entirely (replacing it with the "in" signals) and put the entire contents of the process, except the reset stuff, inside your if statement that detects rising edges on the in signals.
EDIT3: Here is a VHDL model for a 4x4 tic-tac-toe board with your hardware setup expanded to the 16 squares of a 4x4 board. See if you can understand what is done and why, then adapt it to a 3x3 board.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TicTac is
Port (button : in std_logic_vector(16 downto 1);
reset : in std_logic;
p_to_play : out std_logic;
p1_win : out std_logic := '0';
p2_win : out std_logic := '0';
ou1 : out std_logic_vector(16 downto 1);
ou2 : out std_logic_vector(16 downto 1));
end TicTac;
architecture Behavioral of TicTac is
signal o1 : std_logic_vector(16 downto 1) := (others => '0');
signal o2 : std_logic_vector(16 downto 1) := (others => '0');
signal o : std_logic_vector(16 downto 1) := (others => '0');
signal p : std_logic;
signal win : std_logic;
signal win1 : std_logic;
signal win2 : std_logic;
begin
ou1 <= o1;
ou2 <= o2;
p_to_play <= p;
p1_win <= win1;
p2_win <= win2;
win <= win1 or win2;
gen_spots : for i in 1 to 16 generate --3 flip flops share a clock (button) for every space on the board
process(button(i), reset)
begin
if(reset = '1') then
o(i) <= '0';
o1(i) <= '0';
o2(i) <= '0';
elsif(button(i)'event and button(i)='1' and o(i)='0' and win='0') then
o(i) <= '1';
if (p = '0') then
o1(i) <= '1';
else
o2(i) <= '1';
end if;
end if;
end process;
end generate gen_spots;
process(o) --determines current player by xoring the o values together.
variable ot : std_logic;
begin
ot := '0';
for i in 1 to 16 loop
ot := ot xor o(i);
end loop;
p <= ot;
end process;
process(o1) --checks if player 1 wins
begin
win1 <= '0'; --only happens if none of the win1 <= '1' statements occur
for i in 0 to 3 loop
if (o1(1+i*4)='1' and o1(2+i*4)='1' and o1(3+i*4)='1' and o1(4+i*4)='1') then --rows
win1 <= '1';
end if;
if (o1(1+i)='1' and o1(5+i)='1' and o1(9+i)='1' and o1(13+i)='1') then --columns
win1 <= '1';
end if;
end loop;
if (o1(1)='1' and o1(6)='1' and o1(11)='1' and o1(16)='1') or (o1(4)='1' and o1(7)='1' and o1(10)='1' and o1(13)='1') then --diagonals
win1 <= '1';
end if;
end process;
process(o2) --checks if player 2 wins
begin
win2 <= '0'; --only happens if none of the win2 <= '1' statements occur
for i in 0 to 3 loop
if (o2(1+i*4)='1' and o2(2+i*4)='1' and o2(3+i*4)='1' and o2(4+i*4)='1') then --rows
win2 <= '1';
end if;
if (o2(1+i)='1' and o2(5+i)='1' and o2(9+i)='1' and o2(13+i)='1') then --columns
win2 <= '1';
end if;
end loop;
if (o2(1)='1' and o2(6)='1' and o2(11)='1' and o2(16)='1') or (o2(4)='1' and o2(7)='1' and o2(10)='1' and o2(13)='1') then --diagonals
win2 <= '1';
end if;
end process;
end Behavioral;
I haven't done exhaustive tests, but this compiles and works for a couple test cases.
Please remember to mark this as the correct answer if it solved your problem.
----------------------------------------------------------------------------------
----------------------------- TICTAC TOE GAME ------------------------------------
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity cs_main is
Port ( in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
in3 : in STD_LOGIC;
in4 : in STD_LOGIC;
in5 : in STD_LOGIC;
in6 : in STD_LOGIC;
in7 : in STD_LOGIC;
in8 : in STD_LOGIC;
in9 : in STD_LOGIC;
output1 : out STD_LOGIC_VECTOR (8 downto 0);
output2 : out STD_LOGIC_VECTOR (8 downto 0);
chance_real : out STD_LOGIC;
wing : out STD_LOGIC;
winr : out STD_LOGIC;
reset : in STD_LOGIC);
end cs_main;
architecture Behavioral of cs_main is
signal temp1,out1,out2,out11,out22 :std_logic_vector (8 downto 0):= "000000000";
signal chance : std_logic := '0';
signal wing1,winr1 : std_logic := '0';
begin
tictac :process(in1,in2,in3,in4,in5,in6,in7,in8,in9)
begin
if rising_edge (reset) then
out1 <= "000000000";
out2 <= "000000000";
chance <= '0';
wing1 <= '0';
winr1 <= '0';
else
if (wing1 = '0' and winr1 = '0') then
if rising_edge (in1) then
if (chance = '0') then
out1 <= "000000001";
elsif(chance = '1') then
out2 <= "000000001";
end if;
chance <= not chance ;
elsif rising_edge(in2) then
if (chance = '0') then
out1 <= "000000010";
elsif(chance = '1') then
out2 <= "000000010";
end if;
chance <= not chance ;
elsif rising_edge(in3) then
if (chance = '0') then
out1 <= "000000100";
elsif(chance = '1') then
out2 <= "000000100";
end if;
chance <= not chance ;
elsif rising_edge(in4) then
if (chance = '0') then
out1 <= "000001000";
elsif(chance = '1') then
out2 <= "000001000";
end if;
chance <= not chance ;
elsif rising_edge(in5) then
if (chance = '0') then
out1 <= "000010000";
elsif(chance = '1') then
out2 <= "000010000";
end if;
chance <= not chance ;
elsif rising_edge(in6) then
if (chance = '0') then
out1 <= "000100000";
elsif(chance = '1') then
out2 <= "000100000";
end if;
chance <= not chance ;
elsif rising_edge(in7) then
if (chance = '0') then
out1 <= "001000000";
elsif(chance = '1') then
out2 <= "001000000";
end if;
chance <= not chance ;
elsif rising_edge(in8) then
if (chance = '0') then
out1 <= "010000000";
elsif(chance = '1') then
out2 <= "010000000";
end if;
chance <= not chance ;
elsif rising_edge(in9) then
if (chance = '0') then
out1 <= "100000000";
elsif(chance = '1') then
out2 <= "100000000";
end if;
chance <= not chance ;
end if;
end if;
out11 <= out11 or out1;
out22 <= out22 or out2;
if(((out11 = "000000111" or out11 = "000111000" or out11 = "111000000" or
out11 = "001001001" or out11 = "010010010" or out11 = "100100100" or
out11 = "100010001" or out11 = "001010100" ) and chance ='0') or
((out22 = "000000111" or out22 = "000111000" or out22 = "111000000" or
out22 = "001001001" or out22 = "010010010" or out22 = "100100100" or
out22 = "100010001" or out22 = "001010100" ) and chance = '1')) then
if (chance = '0')then
wing1 <= '1';
winr1 <= '0';
elsif (chance = '1') then
wing1 <= '0';
winr1 <= '1';
end if;
else
wing1 <= '0';
winr1 <= '0';
end if;
end if;
end process tictac;
output1 <= out11 ;
output2 <= out22 ;
chance_real <= chance;
wing <= wing1;
winr <= winr1;
end Behavioral;
The code compiled without an error on my QUARTUS II version 15 software. i programmed it on my ALTERA DE2 FPGA BOARD but it does not display on the monitor. can anyone tell me what to do please
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TicTac is
Port (button : in std_logic_vector(16 downto 1);
reset : in std_logic;
p_to_play : out std_logic;
p1_win : out std_logic := '0';
p2_win : out std_logic := '0';
ou1 : out std_logic_vector(16 downto 1);
ou2 : out std_logic_vector(16 downto 1));
end TicTac;
architecture Behavioral of TicTac is
signal o1 : std_logic_vector(16 downto 1) := (others => '0');
signal o2 : std_logic_vector(16 downto 1) := (others => '0');
signal o : std_logic_vector(16 downto 1) := (others => '0');
signal p : std_logic;
signal win : std_logic;
signal win1 : std_logic;
signal win2 : std_logic;
begin
ou1 <= o1;
ou2 <= o2;
p_to_play <= p;
p1_win <= win1;
p2_win <= win2;
win <= win1 or win2;
gen_spots : for i in 1 to 16 generate --3 flip flops share a clock (button) for every space on the board
process(button(i), reset)
begin
if(reset = '1') then
o(i) <= '0';
o1(i) <= '0';
o2(i) <= '0';
elsif(button(i)'event and button(i)='1' and o(i)='0' and win='0') then
o(i) <= '1';
if (p = '0') then
o1(i) <= '1';
else
o2(i) <= '1';
end if;
end if;
end process;
end generate gen_spots;
process(o) --determines current player by xoring the o values together.
variable ot : std_logic;
begin
ot := '0';
for i in 1 to 16 loop
ot := ot xor o(i);
end loop;
p <= ot;
end process;
process(o1) --checks if player 1 wins
begin
win1 <= '0'; --only happens if none of the win1 <= '1' statements occur
for i in 0 to 3 loop
if (o1(1+i*4)='1' and o1(2+i*4)='1' and o1(3+i*4)='1' and o1(4+i*4)='1') then --rows
win1 <= '1';
end if;
if (o1(1+i)='1' and o1(5+i)='1' and o1(9+i)='1' and o1(13+i)='1') then --columns
win1 <= '1';
end if;
end loop;
if (o1(1)='1' and o1(6)='1' and o1(11)='1' and o1(16)='1') or (o1(4)='1' and o1(7)='1' and o1(10)='1' and o1(13)='1') then --diagonals
win1 <= '1';
end if;
end process;
process(o2) --checks if player 2 wins
begin
win2 <= '0'; --only happens if none of the win2 <= '1' statements occur
for i in 0 to 3 loop
if (o2(1+i*4)='1' and o2(2+i*4)='1' and o2(3+i*4)='1' and o2(4+i*4)='1') then --rows
win2 <= '1';
end if;
if (o2(1+i)='1' and o2(5+i)='1' and o2(9+i)='1' and o2(13+i)='1') then --columns
win2 <= '1';
end if;
end loop;
if (o2(1)='1' and o2(6)='1' and o2(11)='1' and o2(16)='1') or (o2(4)='1' and o2(7)='1' and o2(10)='1' and o2(13)='1') then --diagonals
win2 <= '1';
end if;
end process;
end Behavioral;