Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

what is the problem with sequential code in vhdl for FSM?

Status
Not open for further replies.

perchick

Newbie level 5
Newbie level 5
Joined
Oct 23, 2012
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Visit site
Activity points
1,382
hello
i wrote a code for Tic-Tac-Toe checker for my homework assignment and i just got my grade and it is not good.
Im having some trouble understanding what is the problem with this code for this system and i was wondering if someone could explain to me what i did wrong here. my professor has an history of giving bed grads for codes he doesn't like and i just wanted to know if my code is really that awful or is it him.
the rules for the game: d_in writes x, and 0 from left to right row by row. if we have a winner the program stops. the output (stts) is "01" for x_win, "10" for o_win and "11" for a draw.
i didn't want to use components so i used functions and did all my calculation in one process. my professor hated my solution and in hes comments he wrote " doesn't look like HDL". i don't really understand what the difference if my code works (had 2 latches which i guess is not good, i mean beside that).
hope you can help me with this
my code:
Code:
library ieee;
use ieee.std_logic_1164.all;
--==========package and functions=====================================================
package TicTacToe is
	constant n : integer := 3;					--board size
	type state is (no_win, x_win, o_win, idle)	;	--FSM states
	type memroy_reg is array (0 to n-1) of state;	-- memory for columns
	function 	check_win (win	:state) return boolean	;	
	
	function 	status (d_in 		: std_logic_vector (1 downto 0)	;	--FSM 
				PS		: state) return state							;
					 
end TicTacToe;

package body TicTacToe is 

-------------####################################------------------------	
--function that checks if we have a winner, if we do it returns a 
--bolean flag which indicates the end of the game (end_game)
-------------####################################------------------------	
function 	check_win (win	:state) return boolean is
begin
	if win = x_win or win = o_win then
		return true;
	else
		return false;
	end if;
end check_win;


-------------************************************------------------------
--FSM function. gets present state and d_in and returns next state
-------------************************************------------------------
function	status (d_in 	: std_logic_vector (1 downto 0)	;
				 PS		: state	)	return state	is	
begin
	case PS is
		when idle =>
						
			if d_in = "01" then
				return x_win;
			elsif d_in = "10" then
				return o_win;
			else 
				return  idle;
						
			end if;
						
		when x_win =>
							
			if d_in = "10" then
				return  no_win;
			else
				return  x_win ;
			end if;
			
		when o_win =>
							
			if d_in = "01" then
				return  no_win;
			else
				return o_win;
			end if;
			
		when no_win =>
			
			 return  no_win;
					
				end case;
	end status;		
end TicTacToe;
--========== end package and functions=====================================================

library ieee;
use ieee.std_logic_1164.all;
use work.TicTacToe.all;-- use package

entity full_TicTacToe is
	port (	clk, rst_n		:in std_logic				;
			d_in	:in std_logic_vector (1 downto 0)	;
			stts	:out std_logic_vector (1 downto 0)	);
end full_TicTacToe;

architecture arch_full_TicTacToe of full_TicTacToe is
begin

	process (d_in, clk, rst_n)
	variable end_game : boolean := false;--indication for the end of the game
	variable i : integer := 0;			--index columns
	variable j : integer := 0;			--index rows
	variable row_state : state := idle;	--row state
	variable stts_temp : std_logic_vector (1 downto 0) := "00";	--temp stts output
	variable memory	: memroy_reg	:= (others => idle)	;	--column memory is vector of type state
	variable diag_L2R	: state	:= idle;					--north west to south east diagonal
	variable diag_R2L	: state	:= idle;					--north east to south west diagonal
	begin
	--reset all
		if rst_n ='0' then
		
				i :=0;
				j := 0;
				end_game := false;
				stts_temp := "00";
				row_state := idle;
				memory := (others => idle);
				diag_L2R	:= idle;
				diag_R2L	:= idle;
	--if end_game=true we do not enter the rest of the code			
		elsif falling_edge (clk) and end_game = false and rst_n = '1'  then

			if i /= n then--case i didnt reach the end of the row
					row_state := status (d_in, row_state);	--extracted state from status function
					memory (i) := status (d_in, memory (i));
						if j = n-1 then--last row
				
						end_game := check_win (memory (i));	--check if we have a winner through function check_win
					
							if end_game = true then--case we do have column winner, what is the output
									case memory (i) is
										when x_win => stts_temp := "01";
										when o_win => stts_temp := "10";
										when others => null;
									end case;
							end if;
					
						end if;--j=n-1
				
				if i=j then--left to right diagonal condition
				
					diag_L2R := status (d_in, diag_L2R);
					
						if j= n-1 and end_game = false then--check last diag squar if we still do not have a winner 
						
						end_game := check_win (diag_L2R);
							
							if end_game = true then--case diag left to right won what's the output
									case diag_L2R is
										when x_win => stts_temp := "01";
										when o_win => stts_temp := "10";
										when others => null;
									end case;
							end if;
							
						end if;--j=n-1
				end if;--i=j
				
				if (i+j = n-1) then-- diag right to left condition
				
					diag_R2L := status (d_in, diag_R2L);
					
						if j = n-1 and end_game = false then--case we don't have a winner yet and we at the last squar, check for winner
						
						end_game := check_win (diag_R2L);
						
							if end_game = true then--case we do have a winner, what's the output
								case diag_R2L is
									when x_win => stts_temp := "01";
									when o_win => stts_temp := "10";
									when others => null;
								end case;
							end if;
							
						end if;--j=n-1 & end_game=false
				end if;--i+j = n-1
				
				i := i+1;
				
			else --case i=n (if i= n meaning we're reach the end of the row, input is "11")
			
				i := 0;	--zero index row
				j := j+1;--advance index column
					if  end_game = false then--if we don't have a winner yet, check if row won
					end_game := check_win (row_state);
					end if;
					
					if end_game = true then--case row won wha's the output
						case row_state is
							when x_win => stts_temp := "01";
							when o_win => stts_temp := "10";
							when others => null;
						end case;
					end if;

				row_state := idle;
			
			
			end if;--i /=n

		end if;--rst_n&rising edge&end_game
		
			if  j = n  and d_in ="11" and end_game = false then-- case no one won so far and we reach the end if the board
				stts_temp := "11";
				end_game := true;
			end if;

		

		stts <= stts_temp;
		
	end process;
	
	
	
end architecture;
 

The solution must be checked against the exact problem. There might be additional requirements defined during the course.

Did you check the code yourself with a testbench? Should you?
 

yeah, i did. the code works fine, i just wanted to know if the way i did it is OK. im interesting to know what is my professor's problem with this particular way of solution and why does he think that using function vs components is such a big deal.
maybe i just can't see it but my code is awful, hoped someone could tell me, i actually like the way i did it but i don't want to get bed habits so hoped you can tell me what the problem and what the better why of approaching this.
 

yeah, i did. the code works fine, i just wanted to know if the way i did it is OK. im interesting to know what is my professor's problem with this particular way of solution and why does he think that using function vs components is such a big deal.
maybe i just can't see it but my code is awful, hoped someone could tell me, i actually like the way i did it but i don't want to get bed habits so hoped you can tell me what the problem and what the better why of approaching this.

just my first impression.
-first of all there is the question of writing "good looking" vhdl code.
so ther first thing that bothers me is the identication, so try to better ident your code.
-second you add comments in the end of each line, that actually make it harder to read the code, they are just in adjust to the code.
so i would sugest you to write your remarks if necessary and seperate from the code.

about code
-there are like a sensitivity list that has :
"process (d_in, clk, rst_n)" - why d_in ?

- not standrd writing and you use here the rst_n asynchronous reset, and why falling edge :
"elsif falling_edge (clk) and end_game = false and rst_n = '1' then"

-using variables instead of signals -> you have to check this issue - i just couldn't follow.
anyway currently this is not a syntisizable project.
 

thank you for your comments, this is very helpful.
about the process and asynchronous rst_n, my professor did mention that in hes comments. ill keep that in mind.
the falling_edge is a mistake, i tried to change my testbench clock to be falling edge and accidentally changed all my clocks.
now i know that i shouldn't put conditions with clk'event, i should write them separately.
why cant i use variables? i used them because they change immediately in the process, im not really sure whats the difference between variables and signals in terms of real system. if you can explain me this part it will be great
i did run this through quartus and i just got like 8 warnings about "combination loop" (i don't realy know what this mean,can you explain this to me?) and a letch. i thought that if its not syntisizable quartus will tell me, isn't it?

what do you mean by "try to better ident your code"? can you elaborate please?
by the way, i have to write comments like this, its about the only thing my professor didn't deduct points

what is your impression about the code been with functions instead of components or entity use? would you write a code in this form or is it not very good writing?
 

thank you for your comments, this is very helpful.
about the process and asynchronous rst_n, my professor did mention that in hes comments. ill keep that in mind.
the falling_edge is a mistake, i tried to change my testbench clock to be falling edge and accidentally changed all my clocks.
now i know that i shouldn't put conditions with clk'event, i should write them separately.
why cant i use variables? i used them because they change immediately in the process, im not really sure whats the difference between variables and signals in terms of real system. if you can explain me this part it will be great
i did run this through quartus and i just got like 8 warnings about "combination loop" (i don't realy know what this mean,can you explain this to me?) and a letch. i thought that if its not syntisizable quartus will tell me, isn't it?

what do you mean by "try to better ident your code"? can you elaborate please?
by the way, i have to write comments like this, its about the only thing my professor didn't deduct points

what is your impression about the code been with functions instead of components or entity use? would you write a code in this form or is it not very good writing?

have a look at xilinx :
www.eecs.northwestern.edu/~seda/coding_guidelines_013003.pdf‎
specially check the "Rules for Variables and Variable Use" section.
don't knoa about altera mabee they have different implementation for variables.
 

Ok, comments on the code.

1. You should only have clk and reset in the sensitivity list.
2. You should ONLY have if statements for clock and reset in the synchronous process, not anything else. If you want asynchronous code then make another process that is asynchronous.
3. It is best not to and anything with the clock. Put it in a nested if inside the clock branch.
4. Thats a lot of variables. In a clocked process all signal assignments will generate registers. Variables can create registers but it depends where they are placed in the code. If they have to remember a value between iterations a register will be formed, otherwise you get a chain of logic. More logic between registers decreases the FMax of the system.

Did you draw a curcuit diagram BEFORE you wrote your vhdl? You should always know roughly what you expect before you write the code - VHDL is a description language, so if you dont know your circuit, how do you expect to describe it?

- - - Updated - - -

Oh - and unconstrained integers will become 32 bit values - they will eat a lot of unnecessary logic.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top