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.

Latch problem in Xilinx - Spartan 3e

Status
Not open for further replies.

therealpaulie

Newbie level 6
Joined
Oct 6, 2009
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
austria
Activity points
1,411
Hi all,

I have a questions related to the XST 737 Warning: Fount ?bit latch for signal ?? .. and so on.

Ok I know that this can be generated by incomplete case or if.

Now, could generate the following code also a latch?

case currentState is
when "00"​
nextSignal1 <= currentSignal1;​
nextState <= "01";​
when "01"
nextSignal1 <= currentSignal1;​
nextState <= "10";​
when "10"​
nextSignal1 <= currentSignal1;​
nextState <= "11";​
when "11"​
nextSignal1 <= "11";​
nextState <= "10";​
end case

(It is a FSM, where currentX is update every clock with nextX)

In my opinion, it should generate a latch because there is no other way to hold the old value.

Could you please recommend a better way to handle such a situation. Where I want to update some signals only in some states of the FSM and to hold the value in some others.

Thanks,
Paul
 

Hi Paul,

A latch is generated when you either update a register/signal without a clock, otherwise a FF is generated. When you can, use an FSM with combinatorial logic to produce FF instead of latches. To make you code a little better I would do the following:

-- **FSM State declaration **
type state_type is ( ST_00, ST_01, ST_10, ST_11 );
signal state : state_type;

signal hold_signal : std_logic_vector( 1 downto 0 );

process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
state <= ST_00;
else
case state is
when ST_00 =>
state <= ST_01;
when ST_01 =>
state <= ST_10;
when ST_10 =>
state <= ST_11;
when ST_11 =>
state <= ST_10;
end if;
end if;
end process;

hold_signal <= "00" when state = ST_00 else
"01" when state = ST_01 else
"10" when state = ST_10 else
"11";


This should synthesize without a latch

Good luck

---------- Post added at 16:52 ---------- Previous post was at 16:51 ----------

Sorry about the spacing, still haven't figured out how to space well in a reply
 

if your currentState is of 2-bits then your case statement seems to be complete...but still add a "default =>" statement at the end of case. I think this might help.

---------- Post added at 01:53 ---------- Previous post was at 01:51 ----------

by the way if your design is a small one then latch won' harm you
 

when others =>
blah...

thats always good practice if are using an std_logic_vector instead of an enumerated state type. Using the state type allows you to not have to worry about that shit, the synthesize will handle it
 

Hi,

Thank you for your answers. I still didn't manage to find out where is the warning in my vhdl code. I want ot build up a vhdl module for erase, write, read from an SPI flash.

Here is the warning:

WARNING:Xst:737 - Found 1-bit latch for signal <nOut_x>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

where x = 0 to 7

And here is the code:
Code:
begin

	spiin 	<= cSPID;
	dataout 	<= cOut;

-- !! We work with 10MHz clock
	inst_clkdivider : clkdivider 
	PORT MAP
		(
			clkin => clk,
			reset => reset,
			clkout => clk10M
		);

-- !! The update process, reset, new state, and so on.
	update : process (clk10M, reset)
	begin
		if reset = '0' then
			cState 	<= ST_IDLE;
			cSPID		<= "11011";
			ciCount	<= (others => '0');
			cInstr	<= (others => '0');
			cOut		<= (others => '0');
			inCmd		<= (others => '0');
		elsif clk10M'event and clk10M = '1' then
			cState 	<= nState;
			cSPID		<= nSPID;
			ciCount	<= niCount;
			cInstr	<= nInstr;
			cOut		<= nOut;
			inCmd		<= command;
		end if;
	end process update;



-- !! Main process for SPI-EEPROM communication
	main_spi : process(cState, ciCount, inCmd, cOut, cSPID, cInstr, spiout)
	begin
		case cState is
		
			-- wait for a valid command to proceed
			when ST_IDLE =>

				nSPID		<= cSPID;
				niCount	<= "000000";
				nInstr 	<= cInstr;
				nOut		<= cOut;
				isIdle 	<= '1';
				case inCmd is
					when x"0" =>
						nState <= ST_IDLE;
						--isIdle <= '1';
					when others =>
						nState <= ST_DECODE;
						--isIdle <= '0';
				end case;
				
			-- decode command in flash instruction 
			when ST_DECODE =>
				nSPID		<= cSPID;
				niCount	<= "000000";
				case inCmd is
					when x"1" =>
						nInstr <= x"06"; 	-- WREN Write Enable
					when x"2" =>
						nInstr <= x"04"; 	-- WRDI Write Disable
					when x"3" =>
						nInstr <= x"9F"; 	-- RDID Read Identification
					when x"4" =>
						nInstr <= x"05";	-- RDSR Read Status Register
					when x"5" =>
						nInstr <= x"01";	-- WRSR Write Status Register
					when x"6" =>
						nInstr <= x"03";	-- READ Read Data Bytes
					when x"7" =>
						nInstr <= x"0B";	-- FAST_READ Read Data Bytes at High Speed
					when x"8" =>
						nInstr <= x"02";	-- PP Page Program
					when x"9" =>
						nInstr <= x"D8";	-- SE Sector Erase
					when x"A" =>
						nInstr <= x"C7";	-- BE Bulk Erase
					when x"B" =>
						nInstr <= x"B9";	-- DP Deep Power-Down
					when x"C" =>
						nInstr <= x"AB";	-- RES Release from Deep Power-Down
					when others =>
						nInstr <= x"00";
				end case;
				nOut		<= cOut;
				nState 	<= ST_CSEL;
				isIdle 	<= '1';
			
			-- Chip Select Active
			when ST_CSEL =>
				nSPID 	<= "11010"; -- put /S - Chip Select on 0 - active
				niCount	<= "000000";
				nInstr	<= cInstr;
				nOut		<= cOut;
				isIdle 	<= '0';				
				nState 	<= ST_INSTR;
			
			-- Put 8bits Instruction on SPI Data Input Line
			-- !! On the rising edge of CLK
			when ST_INSTR =>
				
				if ciCount(0) = '0' then -- in one clock put data and put clock on low
					nSPID <= "11" & cInstr(7-conv_integer(ciCount(5 downto 1))) & "00";
				else -- in the other clock put clock on high to latch data
					nSPID <= cSPID(4 downto 2) & "10";
				end if;

				nOut		<= cOut;		
				isIdle 	<= '0';				
				nInstr	<= cInstr;
				
				if ciCount = 15 then
					niCount <= (others => '0'); -- put it on zero
					case cInstr is
						-- Instructions (WREN, WRDI, BE, DP) with no address nor data
						when x"06" | x"04" | x"C7" | x"B9" =>
							nState <= ST_CDES;
						-- Instruction RDSR - has to read 8bits from Q line
						when x"05" =>
							nState <= ST_READ;
						-- !! TODO: !!
						when x"9F" | x"01" =>
							nState <= ST_CDES;
						-- Instructions (READ, PP, SE, READ_FAST) that require ADDRESS
						when x"03" | x"02" | x"D8" | x"0B"=>
							nState <= ST_ADDR;
						-- When Others -> error
						when others =>
							nState <= ST_CDES;
					end case;
				else
					niCount <= ciCount + 1; -- increment
					nState <= ST_INSTR;
				end if;				

				
			-- Put 24bits Address on SPI Data Input Line
			-- ! On the rising edge of CLK
			when ST_ADDR =>
				
				if ciCount(0) = '0' then -- in one clock put data and put clock on low
					nSPID <= "11" & address(23-conv_integer(ciCount(5 downto 1))) & "00";
				else -- in the other clock put clock on high to latch data
					nSPID <= cSPID(4 downto 2) & "10";
				end if;

				nOut		<= cOut;		
				isIdle 	<= '0';				
				nInstr	<= cInstr;	
				
				if ciCount = 47 then
					niCount <= (others => '0'); -- put it on zero				
					case cInstr is
						-- Instructions (READ) that have to read data from Q line
						when x"03" => 
							nState <= ST_READ;
						-- !! TODO: Instruction with (FAST_READ) Dummy bits
						when x"0B" =>
							nState <= ST_CDES;
						-- Instructions (SE) that don't required anything else
						when x"D8" =>
							nState <= ST_CDES;
						-- Instructions (PP) that have to write additional data on D line
						when x"02" =>
							nState <= ST_WRITE;
						-- When others -> error
						when others =>
							nState <= ST_CDES;
					end case;
				else
					nState <= ST_ADDR;
					niCount <= ciCount + 1; -- increment
				end if;			
				
			-- Read Data from Q line 
			-- ?? Old and false: !! Reading is done on the falling edge of CLK	
			-- 19.10.2010: Reading on rising edge. New data available after falling edge
			when ST_READ =>
			
				if ciCount(0) = '0' then -- put clock on low latch data from Q
					nSPID <= cSPID(4 downto 3) & "000"; 
					nOut	<= cOut;
				else -- in the other clock put clock on high 
					nSPID <= cSPID(4 downto 3) & "010";
					nOut(7-conv_integer(ciCount(5 downto 1)))	<= spiout;
				end if;

				isIdle 	<= '0';				
				nInstr	<= cInstr;		
				
				-- read and store actual data 
				-- 19.10.2010: 15 instead of 14
				if ciCount = 15 then
					niCount <= (others => '0'); -- put it on zero				
					-- there is nothing else to do, go to Chip DeSelect
					nState <= ST_CDES;
				else
					nState <= ST_READ;
					niCount <= ciCount + 1; -- increment
				end if;		
		
				
			-- Program/Write data on D line
			-- !! Programming is done on the rising edge of CLK	
			when ST_WRITE =>
				
				if ciCount(0) = '0' then -- put clock on low and update D line
					nSPID <= cSPID(4 downto 3) & datain(7-conv_integer(ciCount(5 downto 1))) & "00";
				else -- in the other clock put clock on high - latch on clock high
					nSPID <= cSPID(4 downto 2) & "10";
				end if;
				
				nOut		<= cOut;
				isIdle 	<= '0';				
				nInstr	<= cInstr;		
				
				-- ?? ha?? 19.10.2010 ?? it is 13 because the first falling edge comes from the previous 
				-- state (ST_ADDR, .. etc)
				-- modified on 19.10.2010 - 15 instead of 13 ??
				if ciCount = 15 then
					niCount <= (others => '0'); -- put it on zero				
					-- there is nothing else to do, go to Chips DeSelect
					nState <= ST_CDES;
				else
					nState <= ST_WRITE;
					niCount <= ciCount + 1; -- increment
				end if;			
		
							
			-- Chip Select Inactive
			when ST_CDES =>
				nSPID 	<= "11011"; -- put /S - Chip Select on 0 - active
				niCount	<= "000000";
				nInstr	<= cInstr;
				nOut		<= cOut;
				isIdle 	<= '0';				
				nState 	<= ST_IDLE;
			
			when others =>
				nSPID		<= cSPID;
				niCount	<= "000000";
				nInstr	<= cInstr;
				nOut		<= cOut;	
				isIdle 	<= '0';				
				nState 	<= ST_IDLE;
				
		end case;
	end process main_spi;

Maybe I should ignore this warning, but the problem is the code doesn't work (both in Post Route Simulation and on Spartan 3E dev. kit). The value of cOut (last - LSB - byte from tp2 signal) changes somehow during the ST_INSTR state. It should remain constant.

See the attachement for simulation waveforms from ModelSim.

Any suggestions are welcome. Also, if you have any other observation about my code please share them to me. I'm far away of being an expert, so any advice would be useful.

Thanks,
Paul
 

Attachments

  • vhdl_cout.jpg
    vhdl_cout.jpg
    93.1 KB · Views: 95

I found the problem.

In my code I have somewhere the line:

Code:
nOut(7-conv_integer(ciCount(5 downto 1)))	<= spiout;

As far as I understood only one bit was updated, for all the others a latch was generated - on the test board everything was ok, but in the simulation: DISASTER (as one can in the previous post attachement).

After I changed it to:
Code:
for index in 0 to 7 loop
	if index = (7 - conv_integer(ciCount(5 downto 1))) then
		nOut(index)	<= spiout;
	else
		nOut(index)	<= cOut(index);
	end if;
end loop;
the warnings were gone, and the simulation looks nice (no more undefined states and values).

If someone has experience with this problem, please let me know if this is how this problems must be solved. Maybe there are some better solutions.

Paul
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top