Notice anything wrong with this state machine?

J

Jeepster

Guest
This has been driving me nuts! :(
I'm compiling and simulating using quartus. The state machine is
supposed to loop forever in 100->101->110->111. But based on
simulation results, it sometimes skips 100 in some loop iterations.
Any ideas? Thanks!

always @(posedge FIFO_CLK)
case(state)
3'b000: if( FIFO2_data_available) state <= 3'b001; // wait for data
packet in FIFO2
3'b001: if(~FIFO2_data_available) state <= 3'b010; // wait until end
of data packet
3'b010: begin
start <= 1'b1;
if (state_31==3'b101) state<=3'b100;
end
3'b100: begin //0 - 511
if((read_pos==511)) state<=3'b101;
else if(1) read_pos <= read_pos+1'b1;
end
3'b101: if((state_31==3'b110)) // wait
begin
state<=3'b110;
read_pos <= 512;
end
3'b110: begin // 512 - 1023
if((read_pos==1023)) state<=3'b111;
else if(1) read_pos <= read_pos+1'b1;
end
3'b111: if((state_31==3'b101)) //wait
begin
state<=3'b100;
read_pos <= 0;
end
default: state <= 3'b000;
endcase
 
On Aug 16, 7:38 pm, Jeepster <jasimp...@gmail.com> wrote:
This has been driving me nuts! :(
I'm compiling and simulating using quartus. The state machine is
supposed to loop forever in 100->101->110->111. But based on
simulation results, it sometimes skips 100 in some loop iterations.
Any ideas? Thanks!

always @(posedge FIFO_CLK)
case(state)
3'b000: if( FIFO2_data_available) state <= 3'b001; // wait for data
packet in FIFO2
3'b001: if(~FIFO2_data_available) state <= 3'b010; // wait until end
of data packet
3'b010: begin
start <= 1'b1;
if (state_31==3'b101) state<=3'b100;
end
3'b100: begin //0 - 511
if((read_pos==511)) state<=3'b101;
else if(1) read_pos <= read_pos+1'b1;
end
3'b101: if((state_31==3'b110)) // wait
begin
state<=3'b110;
read_pos <= 512;
end
3'b110: begin // 512 - 1023
if((read_pos==1023)) state<=3'b111;
else if(1) read_pos <= read_pos+1'b1;
end
3'b111: if((state_31==3'b101)) //wait
begin
state<=3'b100;
read_pos <= 0;
end
default: state <= 3'b000;
endcase
I think I found out what the problem is. "state_31" is in another
clock domain. I had to do something like this to take it to this clock
domain and it seems to work.
reg [2:0] state_chg1; always @(posedge FIFO_CLK) state_chg1 <=
state_31;
reg [2:0] state_chg2; always @(posedge FIFO_CLK) state_chg2 <=
state_chg1;

Let me know if anything else knows funky though. Thanks.
 
On Aug 16, 7:57 pm, Jeepster <jasimp...@gmail.com> wrote:
On Aug 16, 7:38 pm, Jeepster <jasimp...@gmail.com> wrote:



This has been driving me nuts! :(
I'm compiling and simulating using quartus. The state machine is
supposed to loop forever in 100->101->110->111. But based on
simulation results, it sometimes skips 100 in some loop iterations.
Any ideas? Thanks!

always @(posedge FIFO_CLK)
case(state)
3'b000: if( FIFO2_data_available) state <= 3'b001; // wait for data
packet in FIFO2
3'b001: if(~FIFO2_data_available) state <= 3'b010; // wait until end
of data packet
3'b010: begin
start <= 1'b1;
if (state_31==3'b101) state<=3'b100;
end
3'b100: begin //0 - 511
if((read_pos==511)) state<=3'b101;
else if(1) read_pos <= read_pos+1'b1;
end
3'b101: if((state_31==3'b110)) // wait
begin
state<=3'b110;
read_pos <= 512;
end
3'b110: begin // 512 - 1023
if((read_pos==1023)) state<=3'b111;
else if(1) read_pos <= read_pos+1'b1;
end
3'b111: if((state_31==3'b101)) //wait
begin
state<=3'b100;
read_pos <= 0;
end
default: state <= 3'b000;
endcase

I think I found out what the problem is. "state_31" is in another
clock domain. I had to do something like this to take it to this clock
domain and it seems to work.
reg [2:0] state_chg1; always @(posedge FIFO_CLK) state_chg1 <=
state_31;
reg [2:0] state_chg2; always @(posedge FIFO_CLK) state_chg2 <=
state_chg1;

Let me know if anything else knows funky though. Thanks.

When crossing a clock domain with multiple bits, you need to
make sure that the data remains coherent. In simulation the
above code may work, but in real life (and in post P&R timing
simulation) you can have incorrect values in "state_chg1"
if more than one bit of "state_31" change on the same clock.

The second stage of your two-stage synchonizer will reduce the
effects of metastability (which won't show up in simulation)
but it won't fix the coherency issue.

A common method of addressing coherency is to convert the
source into grey code before synchronizing to the other
clock domain. This may not be an option if "state_31"
doesn't follow a simple count sequence. Another method
that requires more latency, but will work with any bit
sequence, is to latch the value in the original clock
domain (using a clock enable) and then create a clock
enable in the output clock domain that is on for one
cycle while the data is held latched. While this method
requires some asynchronous logic on the clock enables,
it works the same for any width or sequence of the
input data.

Another possibility may be to encode "state_31", possibly
using more bits, such that any state transition flips
at most one bit.

HTH,
Gabor
 

Welcome to EDABoard.com

Sponsor

Back
Top