cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
8,134 Views
Registered: ‎07-11-2011

FSM problem--data changing on state transition

Jump to solution

I'm trying to implement a power up procedure for an ADC from my Spartan 3e FPGA (I'm using the spartan 3e starter board. The ADC is an eval-AD7760, not the ADC already on the spartan 3e board.)parallel adc.JPG

The power up procedure for AD7760 involves writing to 2 control registers via a 16 bit bus.  It's shown in the top image (which shows the post-translate simulation) To write to a register, I have to pulse CSn low while sending the address through the bus, D(15:0), then pulse CSn low again while sending the contents through the bus. The bus contents aren't supposed to change on a CSn edge.

However, after the post-map simulation, you can see the bus changes on some CSn edges (middle image). If you zoom in (bottom image), near the CSn edge the bus momentarily changes to the value it was going to assume next, before going back to its correct value (in this case from 16'b100010, briefly to 16;b10 and back to 16'b100010 .) Is there any way to fix/explain this?

 

my fsm code is here:

 

module powerup(clock, reset, enable,RESETn,CSn,SYNC,WR, DATA,DONEWR);
input clock;
input reset;
input enable;
output RESETn;
output CSn;
output SYNC;
output WR;
output DONEWR;
output [15:0] DATA;

reg RESETn,CSn,SYNC,WR;
reg DONEWR = 0;
reg [15:0] DATA;


parameter address2 	= 'h0002;
parameter data2 		= 'b0000000000100010;
parameter address1 	= 'h0001;
parameter data1 		= 'b0000000000000000;

parameter IDLE 			= 'b000000000000000000001;
parameter RST 				= 'b000000000000000000010;
parameter WT1				= 'b000000000000000000100;				
parameter WRT2address	= 'b000000000000000001000;
parameter WRT2waita		= 'b000000000000000010000;
parameter WRT2waitb		= 'b000000000000000100000;
parameter WRT2data		= 'b000000000000001000000;
parameter WT2a				= 'b000000000000010000000;
parameter WT2b				= 'b000000000000100000000;
parameter WRT1address	= 'b000000000001000000000;
parameter WRT1waita		= 'b000000000010000000000;
parameter WRT1waitb		= 'b000000000100000000000;
parameter WRT1data		= 'b000000001000000000000;
parameter WT3				= 'b000000010000000000000;
parameter WT4				= 'b000000100000000000000;
parameter SNC				= 'b000001000000000000000;
parameter IDLE2			= 'b000010000000000000000;

reg [20:0] state =IDLE;
reg [20:0] next = IDLE;


always@ (posedge clock) begin
	
	if (reset) //receiving data from adc
		state<=IDLE;
	else
		state<=next;
		
end

always@* begin
	DONEWR = 0;
	RESETn = 1;
	CSn = 1;
	SYNC = 1;
	WR = 1;
	next = IDLE;
	case (state)

		IDLE: 	begin
						next = enable ? RST : IDLE;
					end
						
		RST: 		begin
						RESETn = 0;
						next = enable ? WT1 : RST;
					end

		WT1:	 	begin
						DATA = address2;
						next = enable ? WRT2address : WT1;
					end

		//==============WRT2=============
			WRT2address:	begin
									CSn = 0;
									DATA = address2;
									next = enable ? WRT2waita : WRT2address;
								end

			WRT2waita:		begin
									DATA = address2;	
									next = enable? WRT2waitb : WRT2waita;
								end
			
			WRT2waitb:		begin
									DATA = data2; 						
									next = enable ? WRT2data : WRT2waitb;
								end

			WRT2data:		begin
									CSn = 0;
									DATA = data2;
									next = enable ? WT2a : WRT2data;
								end

		WT2a:	 	begin
						DATA = data2;	
						next = enable ? WT2b : WT2a;
					end
	
		WT2b:	 	begin
						DATA = address1;
						next = enable ? WRT1address : WT2b;
					end
		//==============WRT1=============
			WRT1address:	begin
									CSn = 0;
									DATA = address1;
									next = enable ? WRT1waita : WRT1address;
								end

			WRT1waita:		begin
									DATA = address1;
									next = enable ? WRT1waitb : WRT1waita;
								end

			WRT1waitb:		begin
									DATA = data1;
									next = enable ? WRT1data : WRT1waitb;
								end
								
			WRT1data:		begin
									CSn = 0;
									DATA = data1;
									next = enable ? WT3 : WRT1data;
								end

		WT3: 		begin
						DATA = data1;	
						next = enable ? WT4 : WT3;
					end
				
		WT4: 		begin
						next = enable ? SNC : WT4;
					end
					
		SNC:		begin
						SYNC = 0;
						next = enable ? IDLE2 : SNC;
					end
		
		IDLE2:	begin
						DONEWR = 1;
						next = IDLE2;
					end	
					
		default: begin
						DONEWR = 0;
						next = IDLE;
					end

	endcase
	


end

endmodule

 and it's instantiated in a top module like this:

 

div_clk DC1 (.clk_in(clock),.CLK_OUT(MCLK)); //divide 50 MHz by 4 to get 12.5 MHz MClk

div_clk2 DC2 (.clk_in(clock),.CLK_OUT(SLOWCLK)); 

powerup powerup (.clock(clock), .reset(reset), .enable(SLOWCLK), .RESETn(RESETn), .CSn(CSn), .SYNC(SYNC), .WR(WR),.DATA(DOUT),.DONEWR(DONEWR));

 DC1 and DC2 are just clock dividers. DC2's purpose is just to reduce the number of states in the powerup module, since you need to pulse CSn for a certain number of clock cycles, etc...

 

Thanks.

 

Lee

 

 

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Professor
Professor
10,390 Views
Registered: ‎08-14-2007

Re: FSM problem--data changing on state transition

Jump to solution

It seems that what you're seeing are decoding glitches caused by the multiplexed data

being selected by "state."  If the data needs to remain constant during state changes, you

should either encode "state" using Gray coding (if it's possible given your state sequencing)

or (better approach) use a single-process FSM that sets data in the clocked process so

any logic glitches are filtered out.  Note that one-hot coding guarantees that any state

transition changes two bits of the state variable, so it's not possible to prevent decoding

glitches.  My recommendation is to use joelby's idea for a single-process FSM.  Then the

encoding style doesn't matter.

 

-- Gabor

-- Gabor

View solution in original post

15 Replies
Highlighted
Teacher
Teacher
8,127 Views
Registered: ‎09-09-2010

Re: FSM problem--data changing on state transition

Jump to solution
I am not a Verilog expert, but the problem may be related to your use of blocking assignments in the always block.

Read:
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf

------------------------------------------
"If it don't work in simulation, it won't work on the board."
0 Kudos
Highlighted
Advisor
Advisor
8,124 Views
Registered: ‎10-05-2010

Re: FSM problem--data changing on state transition

Jump to solution

Your state machine design is a bit fishy.

 

  • You've set "next = IDLE" at the top of the always block, but you also set next in every branch of the case statement and as the default.
  • You've checked that enable is asserted in every case statement. It would be much cleaner to do this in your sequential process:
always@ (posedge clock) begin

	if (reset) //receiving data from adc
		state<=IDLE;
	else if (enable)
		state<=next;
		
end

Personally I don't like the multi-process FSM much. It's far easier to read and debug a purely sequential state machine:

 

always@ (posedge clock) begin
	
	if (reset) begin //receiving data from adc
		DONEWR <= 0;
		RESETn <= 1;
		CSn <= 1;
		SYNC <= 1;
		WR <= 1;
		state<=IDLE;
	end
	else if (enable)
		case(state)
		IDLE: state <= RST;

		RST: begin
			RESETn <= 0;
			state <= WT1;
		end

		WT1: begin
			DATA <= address2;
			state <= WRT2address;	
		end
		
		etc.

end

 Also, rather than declaring the FSM as one-hot using parameters, let Xst decide what's best or use the (* fsm_encoding = "user" *) directive to control how it's synthesised.

 

I'm not actually sure what's wrong with your code, as my eyes are a bit too tired to analyse it in detail :(

Highlighted
Professor
Professor
10,391 Views
Registered: ‎08-14-2007

Re: FSM problem--data changing on state transition

Jump to solution

It seems that what you're seeing are decoding glitches caused by the multiplexed data

being selected by "state."  If the data needs to remain constant during state changes, you

should either encode "state" using Gray coding (if it's possible given your state sequencing)

or (better approach) use a single-process FSM that sets data in the clocked process so

any logic glitches are filtered out.  Note that one-hot coding guarantees that any state

transition changes two bits of the state variable, so it's not possible to prevent decoding

glitches.  My recommendation is to use joelby's idea for a single-process FSM.  Then the

encoding style doesn't matter.

 

-- Gabor

-- Gabor

View solution in original post

Highlighted
Visitor
Visitor
8,109 Views
Registered: ‎07-11-2011

Re: FSM problem--data changing on state transition

Jump to solution

Gabor & joelby: I tried changing the encoding to gray encoding and setting the xilinx fsm encoding to "user". It works now.

 

rcingham: I looked through the paper it says you are supposed to use blocking assignments in always@* blocks.

 

Thanks everyone for the responses!

0 Kudos
Highlighted
Instructor
Instructor
8,102 Views
Registered: ‎07-21-2009

Re: FSM problem--data changing on state transition

Jump to solution

Gabor & joelby: I tried changing the encoding to gray encoding and setting the xilinx fsm encoding to "user". It works now.

 

I'm not sure what you mean by 'it works now'.  If you think you the changes you list will avoid or prevent decoding/selection glitches on the DATA assignment, you are mistaken.  Gabor's comments are entirely correct and to the point.  If you seek a rock-solid design where DATA remains stable at or near the falling edge of CSn, you will need to register DATA.  This is a very simple fix.

 

Even if the operation of your interface is not dependent on maintaining a glitch-free DATA output, the point remains that clean, monotonic transitions generally require a register.  This is worth keeping in mind, both for this design as well as the ones to follow.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
0 Kudos
Highlighted
Visitor
Visitor
8,098 Views
Registered: ‎07-11-2011

Re: FSM problem--data changing on state transition

Jump to solution

Thanks Bob for your advice. But haven't I already registered DATA with the following line?

reg [15:0] DATA;

Or do I need to do something else. Sorry if I am mistaken.

0 Kudos
Highlighted
Professor
Professor
8,093 Views
Registered: ‎08-14-2007

Re: FSM problem--data changing on state transition

Jump to solution

@liulee wrote:

Thanks Bob for your advice. But haven't I already registered DATA with the following line?

reg [15:0] DATA;

Or do I need to do something else. Sorry if I am mistaken.


Ouch!

 

NO!

 

A "reg" in Verilog only implies that storage is required for simulation, it does not

@mean that there will be a flip-flop inferred.  Specifically an "always @*" block does

not infer flip-flops (what Bob meant by register).  To get the DATA registered in

@that sense it should be in an "always @ (posedge clk)" type block.

 

-- Gabor

-- Gabor
0 Kudos
Highlighted
Instructor
Instructor
8,092 Views
Registered: ‎07-21-2009

Re: FSM problem--data changing on state transition

Jump to solution

Thanks Bob for your advice. But haven't I already registered DATA with the following line?

reg [15:0] DATA;

No, this form of declaration in Verilog is called a register, but does not implicitly infer a clocked register.  It is an ambiguity in the Verilog lexicon.  Defining a clocked register requires...  a clock.

 

I've taken the liberty of distilling (filtering) your state machine code which generates the DATA 'register'.  Do you see any clock involved in this process?

 

DATA (and CSn) are both generated from a CASE statement decoding the output of the state register.  As Gabor so clearly pointed out, a multi-bit decode of a register is a combinatorial function which is inherently NOT glitch-free.  Not only is DATA susceptible to glitching, but CS_N is also susceptible to glitching.  Laws of physics apply, and they rule.  They demand to be respected.  You ignore them at your peril.

 

always@* begin
  next = IDLE;
    case (state)
      WT1:  begin
            DATA = address2;
	end

//==============WRT2=============
      WRT2address:	begin
            DATA = address2;
	end

      WRT2waita:		begin
            DATA = address2;	
	end
      WRT2waitb:		begin
            DATA = data2; 						
	end

      WRT2data:		begin
            DATA = data2;
	end
      WT2a:	 	begin
            DATA = data2;	
	end
	
      WT2b:	 	begin
            DATA = address1;
	end
//==============WRT1=============
      WRT1address:	begin
            CSn = 0;
            DATA = address1;
	end
      WRT1waita:		begin
            DATA = address1;
	end
      WRT1waitb:		begin
            DATA = data1;
	end
      WRT1data:		begin
            CSn = 0;
            DATA = data1;
            end
      WT3: 		begin
            DATA = data1;	
	end
      default: begin
            DONEWR = 0;
            next = IDLE;
	end

    endcase

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
0 Kudos
Highlighted
Instructor
Instructor
8,091 Views
Registered: ‎07-21-2009

Re: FSM problem--data changing on state transition

Jump to solution

@gszakacs wrote:

@liulee wrote:

But haven't I already registered DATA with the following line?

reg [15:0] DATA;

 


Ouch!  NO!

 

-- Gabor


Big OUCH! indeed.

 

Gabor, you've done your good deed for the day.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
0 Kudos
Highlighted
Visitor
Visitor
5,873 Views
Registered: ‎07-11-2011

Re: FSM problem--data changing on state transition

Jump to solution

Gabor & Bob:Thanks for the corrections.

0 Kudos
Highlighted
Visitor
Visitor
5,840 Views
Registered: ‎11-07-2010

Re: FSM problem--data changing on state transition

Jump to solution

Hello,

 

> My recommendation is to use joelby's idea for a single-process FSM.  Then the

> encoding style doesn't matter.

 

What about using dual-processes FSM, calculating the future outputs with the next state signal and then registering them ? There wouldn't be any functionnal difference with the case where the outputs are calculated with the present state signal but here the outputs won't have any glitches. The only disadvantages I see is that more flip-flops are used and the combinatorial path that starts at the inputs of the FSM is increased.

 

@liulee : If you are interested, I have written a model in VHDL for the AD7760. This model tests that the interface for this AD is functionnally correct (signals, timings). It can't check glitches however.

Currently it supports only the modulator output mode and it isn't possible to skip the synchronisation part of the initialisation.

 

Jonas

0 Kudos
Highlighted
Instructor
Instructor
5,834 Views
Registered: ‎07-21-2009

Re: FSM problem--data changing on state transition

Jump to solution

What about using dual-processes FSM, calculating the future outputs with the next state signal and then registering them ? There wouldn't be any functionnal difference with the case where the outputs are calculated with the present state signal but here the outputs won't have any glitches. The only disadvantages I see is that more flip-flops are used and the combinatorial path that starts at the inputs of the FSM is increased.

 

The crucial difference between single-process and multi-process state machines is -- paraphrasing joelby's comment:

It's far easier to read and debug

 

There is no requirement for the resulting logic to be any different between single-process and mutli-process coding of the same state machine.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
0 Kudos
Highlighted
Visitor
Visitor
5,817 Views
Registered: ‎11-07-2010

Re: FSM problem--data changing on state transition

Jump to solution

> The crucial difference between single-process and multi-process state machines is

> -- paraphrasing joelby's comment:
> It's far easier to read and debug

 

I think that a good naming for states and doing the state machine compact (avoid code duplication) reduce most of this problem, but that's a good argument that I will think about.

 

> There is no requirement for the resulting logic to be any different between single-process and

> mutli-process coding of the same state machine.

 

I don't agree because multi-process state machine have glitches on outputs which isn't the case for single process state machine. Then the resulting logic should be different, right ? Anyway, most of the time readability of code should be more important than a little performance gain.

Nevertheless, it seems to me that in the cases of outputs with a great size, the resulting logic could be noticeably smaller because we can avoid flip-flops on these outputs.

 

I have the impression that the reason why the multi-process state machine style is sometimes prefered is because it is closer to a state machine implemented manually on a circuit and for people that feel more confident with hardware than with software, multi-process state machine are more natural for them.

 

Sometimes it can be helpfull to have access to the future state. For example, I often need a counter that tells how much clock cycles the FSM is on the current state, typically when I need to wait a certain amount of clock cycles on some states. Here is an example of how such a counter can be done for a multi-process state machine :

 

State_Cnt : process (Reset_i, MClk_i) is
begin
   if Reset_i = '1' then
      State_Cnt_s <= (others => '0');
   elsif Rising_Edge(MClk_i) then
      State_Cnt_s <= State_Cnt_s + 1;
      if State_Next_s /= State_s then
         State_Cnt_s <= (others => '0');
      end if;
   end if;
end process State_Cnt;

And here is an example of an utilisation of this counter on the process that calculates the future state :

(...)
when Sync =>
   State_Next_s <= Sync;
-- Wait_State(Sync) : constant that tells how much
-- clock cycles are to wait on the "Sync" state
 if State_Cnt_s = Wait_State(Sync) - 1 then State_Next_s <= Reading; end if; (...)

 

I don't think it can be done as elegantly with a one-process FSM. It can also be possibly a few more cases when having access to the future state is helpfull but I don't think it happens often.

 

Jonas

0 Kudos
Highlighted
Historian
Historian
5,807 Views
Registered: ‎02-25-2008

Re: FSM problem--data changing on state transition

Jump to solution

@jonas812 wrote:

 

> There is no requirement for the resulting logic to be any different between single-process and

> mutli-process coding of the same state machine.

 

I don't agree because multi-process state machine have glitches on outputs which isn't the case for single process state machine. Then the resulting logic should be different, right ? Anyway, most of the time readability of code should be more important than a little performance gain.


 

If you synchronize the state-machine outputs, the results should be the same as with a single-process machine.

 

 


Nevertheless, it seems to me that in the cases of outputs with a great size, the resulting logic could be noticeably smaller because we can avoid flip-flops on these outputs.


 

In an FPGA, flip-flops are not a scarce resource. "Logic size" is generally thought of as the amount of combinatorial logic between registers.

 

 


I have the impression that the reason why the multi-process state machine style is sometimes prefered is because it is closer to a state machine implemented manually on a circuit and for people that feel more confident with hardware than with software, multi-process state machine are more natural for them.


No, that's silly. 

 

 


Sometimes it can be helpfull to have access to the future state. For example, I often need a counter that tells how much clock cycles the FSM is on the current state, typically when I need to wait a certain amount of clock cycles on some states. (snip code)

 

I don't think it can be done as elegantly with a one-process FSM. It can also be possibly a few more cases when having access to the future state is helpfull but I don't think it happens often.


 

It most certainly can be done elegantly in a one-process machine. Just remember that everything is pipelined, so if you need to have something happen when downcounter = 10, compare against downcounter = 11 and everything lines up. Of course, putting proper comments in the code to explain this will help.

 

Aside: when using counters in a state machine, I've learned a few things:

 

a) If the machine has to run fast and test against a large counter, it's best to have a flag that indicates that the target count value has been reached. This flag should be registered. As such, you need to set the flag when count = target + 1 (if a decrementing counter) or count = target - 1 (if incrementing). It's much easier to test, in a state machine, against one bit than, say 32 bits in a counter.

 

b) In some cases, your incrementing or decrementing counter might be implemented as an adder instead of a counter. (Read the synthesis report). This happens if the counter is embedded in the state machine and has multiple load and/or clear conditions. Implement the counter in a separate process, with the state machine asserting a load enable along with the load value. You'll get a much faster result.

----------------------------Yes, I do this for a living.
0 Kudos
Highlighted
Newbie
Newbie
5,755 Views
Registered: ‎01-26-2012

Re: FSM problem--data changing on state transition

Jump to solution

jonas812,

I am a newbie in vhdl,

and I want to connect my fpga spartan 3A with an adc7760.

Could I read  your model to see how i can make with my application?

Thank you in advance.

 

Tags (1)
0 Kudos