Finite State Machine in vhdl - vhdl

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.

Related

VHDL Sending Data from FPGA to TTL

I'm newbie in FPGAs and VHDL. This time, I m trying to send Data from FPGA to TTL. I' m using GPIO pins for TX and GND and Data can be changed with switch on FPGA. My issue is whenever i press the button on FPGA, I always see FF on terminal. I couldn't find where the problem is.
Here is TX code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector(7 downto 0);
Out_Tx : out std_logic
);
end entity;
Architecture Behavioral of UART_Tx is
constant Baudrate : integer := 9600;
constant CLK_Hiz : integer := 50000000;
constant CLK_Bit : integer := (CLK_Hiz / Baudrate) + 1;
signal tx_Data_ind : integer range 0 to 7;
signal counter_baud : integer range 0 to (CLK_Bit - 1) := 0;
signal shift_button : std_logic_vector (3 downto 0) := (others => '0');
signal button_out : std_ulogic := '1';
signal baud_pulse : std_ulogic := '0';
signal tx_enable : std_ulogic := '0';
signal tx_Data : std_logic_vector (7 downto 0) := (others => '0');
signal tx_cikis : std_ulogic;
signal tx_tamam : std_ulogic := '0';
signal counter_sil : std_ulogic := '0';
begin
process(CLK, Reset)
begin
if (Reset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif (rising_edge(CLK)) then
if (counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if (counter_sil = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, Reset)
begin
if (Reset = '0') then
tx_Data <= (others => '0');
tx_data_ind <= 0;
tx_enable <= '0';
elsif (rising_edge(CLK)) then
tx_cikis <= '1';
out_tx <= tx_cikis;
shift_button(3) <= button;
shift_button(2 downto 0) <= shift_button(3 downto 1);
if shift_button(3 downto 0) = "001" then
button_out <= '0';
end if;
if (button_out = '0') then
counter_sil <= '1';
tx_cikis <= '0';
if (tx_cikis = '0') then
tx_enable <= '1';
end if;
if (tx_enable = '1') then
counter_sil <= '0';
tx_Data <= Data;
if (baud_pulse = '1') then
tx_cikis <= tx_Data(tx_Data_ind);
if (tx_data_ind < 7) then
tx_Data_ind <= tx_Data_ind + 1;
else
tx_tamam <= '1';
end if;
if (tx_tamam = '1') then
tx_Data <= (others => '0');
tx_Data_ind <= 0;
tx_enable <= '0';
button_out <= '1';
tx_cikis <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
end Architecture;
Here is Testbench code:
library ieee;
use ieee.std_logic_1164.all;
entity tb_UART_Tx is
end tb_UART_Tx;
architecture tb of tb_UART_Tx is
component UART_Tx
port (CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector (7 downto 0);
Out_Tx : out std_logic);
end component;
signal CLK : std_logic:='0';
signal Reset : std_logic:='1';
signal Button : std_logic:='1';
signal Data : std_logic_vector (7 downto 0);
signal Out_Tx : std_logic;
constant TbPeriod : time := 20 ns;
signal TbSimEnded : std_logic := '0';
begin
dut : UART_Tx
port map (CLK => CLK,
Reset => Reset,
Button => Button,
Data => Data,
Out_Tx => Out_Tx);
clk_process: process
begin
CLK <= '0';
wait for TbPeriod/2;
CLK <= '1';
wait for TbPeriod/2;
end process;
stimuli : process
begin
Reset <= '0';
wait for 20 ns;
Button <= '1';
Data <= "00110000";
wait for 30 ns;
Button <= '0';
wait for 50 ns;
Button <= '1';
wait for 1000 ns;
-- Button <= '0';
-- wait for 30 ns;
-- Button <= '1';
TbSimEnded <= '1';
wait;
end process;
end tb;
configuration cfg_tb_UART_Tx of tb_UART_Tx is
for tb
end for;
end cfg_tb_UART_Tx;
Added Testbench results
EDIT: HERE is the working code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK: in std_logic;
nReset: in std_logic;
nButton: in std_logic;
Data: in std_logic_vector (7 downto 0);
Data_Tx: out std_logic
);
end UART_Tx;
architecture Behavioral of UART_Tx is
constant Baudrate: integer:= 9600;
constant CLK_Hiz: integer:= 50000000;
constant CLK_Bit: integer:= (CLK_Hiz / Baudrate) + 1;
signal tx_counter: integer range 1 to 9:= 1;
signal counter_baud: integer range 0 to (CLK_Bit - 1):= 0;
signal shift_nButton:std_logic_vector (3 downto 0):= (others => '1');
signal tx_reg: std_logic_vector (7 downto 0):= (others => '0');
signal nButton_out: std_ulogic:= '1';
signal baud_pulse: std_ulogic;
signal tx_out: std_ulogic:= '1';
signal counter_del: std_ulogic;
signal start_bit: std_ulogic:='0';
signal data_bit: std_ulogic:='0';
signal stop_bit: std_ulogic:='0';
begin
process(CLK,nReset)
begin
if(nReset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif(rising_edge(CLK)) then
if(counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if(counter_del = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, nReset)
begin
Data_Tx <= tx_out;
if(nReset = '0') then
tx_reg <= (others => '0');
tx_counter <= 1;
elsif(rising_edge(CLK)) then
shift_nButton(3) <= nButton;
shift_nButton(2 downto 0) <= shift_nButton(3 downto 1);
if shift_nButton(2 downto 0) = "001" then
nButton_out <= '0';
counter_del <= '1';
start_bit <= '1';
end if;
if(nButton_out = '1') then
tx_out <= '1';
elsif(nButton_out = '0') then
counter_del <= '0';
if(start_bit = '1') then
tx_out <= '0';
tx_reg <= Data;
if(baud_pulse = '1') then
start_bit <= '0';
data_bit <= '1';
end if;
end if;
if(data_bit = '1')then
if(tx_counter > 0 and tx_counter < 10) then
tx_out <= tx_reg((tx_counter)-1);
if(baud_pulse = '1') then
tx_counter <= tx_counter + 1;
if(tx_counter = 9)then
data_bit <= '0';
stop_bit <= '1';
end if;
end if;
end if;
end if;
if(stop_bit = '1') then
tx_out <= '1';
tx_counter <= 1;
if(baud_pulse = '1') then
stop_bit <= '0';
nButton_out <= '1';
tx_reg <= (others => '0');
end if;
end if;
end if;
end if;
end process;
end Behavioral;

Tic-tac-toe in VHDL

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).

When an output should go to 1, it goes to unknown

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.

VHDL code for Tic tac toe game?

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;

VHDL filtering data

I am new to VHDL. I need to write a module to do filtering of data. My module structure is:
a_rst - async reset
clk - clock
s_rst - sync reset
valid_in - 0 - no data, 1 - where is data
data_in - [7 downto 0]
Out signals:
valid_out - 0 - no data, 1 - where is data
data_out - [7 downto 0]
I write testbeanch which puts to data_in of my module: 00,01,02,03,0A,02,00,01,02,0F.
But my module returns: 00,01,AA,03,0A,02,00,01,AA,0F
insted of: 00,01,AA,03,0A,02,00,01,02,0F.
I tried to do this:
--libraries
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--entity
entity ex6_v03 is
port
(
a_rst : in std_logic;
clk : in std_logic; -- 200 MHz
s_rst : in std_logic;
valid_in : in std_logic;
data_in : in std_logic_vector (7 downto 0);
valid_out : out std_logic;
data_out : out std_logic_vector (7 downto 0)
);
end entity ex6_v03;
architecture behavior of ex6_v03 is
signal st : integer := 0;
begin
process(a_rst, clk)
begin
-- asynchronous reset
if (a_rst = '1') then
data_out <= x"00";
valid_out <= '0';
-- synchronous reset
elsif rising_edge(clk) then -- clk
if (s_rst = '1') then
valid_out <= '0';
data_out <= x"00";
else
-- normal activity
if(valid_in = '1') then
-- main logic
if(data_in = x"00") then
st <= 1;
valid_out <= '1';
data_out <= data_in;
elsif(st = 1 and data_in = x"01") then
st <= 2;
valid_out <= '1';
data_out <= data_in;
elsif(st = 2 and data_in = x"02") then
st <= 3;
valid_out <= '1';
data_out <= x"AA";
elsif(st = 3 and data_in = x"03") then
valid_out <= '1';
data_out <= data_in;
st <= 0;
else
st <= 0;
valid_out <= '1';
data_out <= data_in;
end if;
-- end main logic
else
valid_out <= '0';
data_out <= x"00";
end if;
end if;
end if;
end process;
end architecture behavior;
But my module do not wait for 0x03 and instantly sends 0xAA. How to fix this?
You need to add a 1 clock cycle buffer so you know if the next input is 03 before you choose whether to send 02 or AA. Of course, this means the output wont appear until 2 cycles after the input instead of only one. See revised code:
--libraries
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--entity
entity ex6_v03 is
port
(
a_rst : in std_logic;
clk : in std_logic; -- 200 MHz
s_rst : in std_logic;
valid_in : in std_logic;
data_in : in std_logic_vector (7 downto 0);
valid_out : out std_logic;
data_out : out std_logic_vector (7 downto 0)
);
end entity ex6_v03;
architecture behavior of ex6_v03 is
signal st : integer := 0;
signal bvalid : std_logic := '0'; --is buffer valid?
signal data_buffer : std_logic_vector (7 downto 0); --data from previous cycle
begin
process(a_rst, clk)
begin
if (a_rst = '1') then -- asynchronous reset
data_out <= x"00";
valid_out <= '0';
bvalid <= '0';
elsif rising_edge(clk) then -- clk
if (s_rst = '1') then --sync reset
valid_out <= '0';
bvalid <= '0';
data_out <= x"00";
else -- normal activity
if(valid_in = '1') then --fill buffer
if(data_in = x"00") then
st <= 1;
data_out <= data_in;
elsif(st = 1 and data_in = x"01") then
st <= 2;
data_out <= data_in;
elsif(st = 2 and data_in = x"02") then
st <= 3;
else
st <= 0;
end if;
data_buffer <= data_in;
bvalid <= '1';
else
bvalid <= '0';
end if;
if(bvalid = '1') then --use buffer to populate output
valid_out <= '1'
if(st = 3 and data_in = x"03" and valid_in = '1') then --EDIT: make sure the x"03" sitting on the input is actually valid
data_out <= x"AA"; --output for the previous cycle (buffer contains x"02")
else
data_out <= data_buffer;
end if
else
valid_out <= '0';
data_out <= x"00";
end if;
end if;
end if;
end process;
end architecture behavior;

Resources