Weirdest bug ever

  • Thread starter Jonathan Nicolas
  • Start date
J

Jonathan Nicolas

Guest
Hi,
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...

Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays. Within the CPU
module, I assign those to different values to display debugging
information.

The CPU core is basically a simple state machine, looking something
like this:

reg [1:0] state_reg, state_next;

reg[15:0] r0_reg, r0_next; // And the same for all other registers

always @(posedge clk)
begin
state_reg <= state_next;

r0_reg <= r0_next;
// ... same for all others
end

always @*
begin
// Default values
state_next = state_reg;
r0_next = r0_reg;
// ...

// FSM code
case(state_reg)
2'b00: begin [[code for state 0 ]] state_next =
2'b01; end
2'b01: begin [[code for state 1 ]] state_next =
2'b10; end
2'b10: begin [[code for state 2 ]] state_next =
2'b11; end
2'b11: begin [[code for state 3 ]] state_next =
2'b00; end
endcase
end


The CPU always go through these 4 states for each instruction. [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.

Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:

assign dbg1 = {5'b0 , state_reg};

'dbg1' is defined as "output wire [7:0] dbg1" in the module header

This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)

Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;

Now, if I do that, everything stops working. The CPU doesn't cycle
through its states anymore.

I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register). When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00". Nothing at all is happening in the state machine.

I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc.. If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.

I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine. But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.

I even tried using this line instead :
assign dbg1 = {4'b0,
(state_reg==2'b00) ? 4'b0001 :
(state_reg==2'b01) ? 4'b0010 :
(state_reg==2'b10) ? 4'b0100 : 4'b1000 };

My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.

Please help me out !!

Jonathan
 
On Aug 7, 1:51 am, Jonathan Nicolas <juuns...@gmail.com> wrote:
Hi,
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...

Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays.  Within the CPU
module, I assign those to different values to display debugging
information.

The CPU core is basically a simple state machine, looking something
like this:

reg [1:0] state_reg, state_next;

reg[15:0] r0_reg, r0_next; // And the same for all other registers

always @(posedge clk)
   begin
      state_reg <= state_next;

      r0_reg <= r0_next;
      // ... same for all others
   end

always @*
   begin
      // Default values
      state_next = state_reg;
      r0_next = r0_reg;
      // ...

      // FSM code
      case(state_reg)
          2'b00:  begin    [[code for state 0 ]]   state_next > 2'b01;  end
          2'b01:  begin    [[code for state 1 ]]   state_next > 2'b10;  end
          2'b10:  begin    [[code for state 2 ]]   state_next > 2'b11;  end
          2'b11:  begin    [[code for state 3 ]]   state_next > 2'b00;  end
      endcase
   end

The CPU always go through these 4 states for each instruction.  [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.

Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:

assign dbg1 = {5'b0 , state_reg};

'dbg1' is defined as "output wire [7:0] dbg1" in the module header

This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)

Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;

Now, if I do that, everything stops working.  The CPU doesn't cycle
through its states anymore.

I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register).  When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00".  Nothing at all is happening in the state machine.

I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc..  If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.

I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine.  But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.

I even tried using this line instead :
assign dbg1 = {4'b0,
    (state_reg==2'b00) ? 4'b0001 :
    (state_reg==2'b01) ? 4'b0010 :
    (state_reg==2'b10) ? 4'b0100 : 4'b1000 };

My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.

Please help me out !!

Jonathan
You've posted fragments of the code so its difficult to pinpoint where
the problem may lie. I would first suggest that rather than observing
the value through the 7 segment display on the hardware, use a
waveform viewer (e.g., gtkwave) so that you can see ALL the signals
and debug your code. You should write a testbench and dump out the
signals. Once your RTL is working, then you can try downloading it
into the hardware and running things from there.

Regarding the FSM, I would separate out the case statement for each
state / r0 register and code them separately. Also I don't see the
need for the "default values" in your case statement since they get
overwritten. Furthermore, what if at start up you get XXs? There
doesn't seem to be a reset in your code?

I prefer to write the above as follows:

First, I create a module for a D flip-flop.

/*
* Dff w/ synchronous reset (active high).
*/
module dflopr #(parameter WIDTH = 32) (/*AUTOARG*/
// Outputs
q,
// Inputs
clk, reset, d
);

input clk, reset; // clk, reset
input [WIDTH-1:0] d; // in data
output reg [WIDTH-1:0] q; // out data

always @(posedge clk)
if (reset)
q <= 0;
else
q <= d;
endmodule // flopr


Then, just instantiate the d-flip flops.

wire [1:0] state;
reg [1:0] state_next;

dflopr #(2) s(.clk(clk), .reset(reset), .d(state_next), .q(state));

always @*
case (state)
2'b00: ... state_next = 2'b01; ..
2'b01: ... state_next = 2'b10; ..
...
endcase

wire [15:0] r0;
reg [15:0] r0_next;

dflopr #(16) s(.clk(clk), .reset(reset), .d(r0_next), .q(r0));

always @*
case (r0)
// add the statements for r0
endcase

You probably need a default case in the case statement for r0 since
its a 16 bit signal and clearly you are not going to enumerate all
possibilities. By separating out the various registers, its easier to
see the state machines. Reset ensures that your flip flops will be
initialized to 0s.

Now you can move on to debug your problem by observing all the signals
on a waveform viewer. Hope this helps.
 
On Aug 7, 1:51 am, Jonathan Nicolas <juuns...@gmail.com> wrote:
Hi,
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...

Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays.  Within the CPU
module, I assign those to different values to display debugging
information.

The CPU core is basically a simple state machine, looking something
like this:

reg [1:0] state_reg, state_next;

reg[15:0] r0_reg, r0_next; // And the same for all other registers

always @(posedge clk)
   begin
      state_reg <= state_next;

      r0_reg <= r0_next;
      // ... same for all others
   end

always @*
   begin
      // Default values
      state_next = state_reg;
      r0_next = r0_reg;
      // ...

      // FSM code
      case(state_reg)
          2'b00:  begin    [[code for state 0 ]]   state_next > 2'b01;  end
          2'b01:  begin    [[code for state 1 ]]   state_next > 2'b10;  end
          2'b10:  begin    [[code for state 2 ]]   state_next > 2'b11;  end
          2'b11:  begin    [[code for state 3 ]]   state_next > 2'b00;  end
      endcase
   end

The CPU always go through these 4 states for each instruction.  [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.

Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:

assign dbg1 = {5'b0 , state_reg};

'dbg1' is defined as "output wire [7:0] dbg1" in the module header

This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)

Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;

Now, if I do that, everything stops working.  The CPU doesn't cycle
through its states anymore.

I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register).  When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00".  Nothing at all is happening in the state machine.

I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc..  If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.

I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine.  But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.

I even tried using this line instead :
assign dbg1 = {4'b0,
    (state_reg==2'b00) ? 4'b0001 :
    (state_reg==2'b01) ? 4'b0010 :
    (state_reg==2'b10) ? 4'b0100 : 4'b1000 };

My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.

Please help me out !!

Jonathan
Very often "weird" bugs that show up when touching seemingly
unrelated parts of a design are caused by a combination of
timing and synchronizing problems.

The first thing to check when a state machine stops running
is if any of the inputs to the state machine are not
synchronous to the clock. XST routinely re-codes your
state logic as "one-hot", even if you assign your state
variable to output wires. In your case I suspect the
machine is one-hot encoded, and then your LED is re-
encoded into binary from the one-hot states.

What happens to a one-hot state machine when you have an
asynchronous input is that it can become "zero-hot" or
"multiple-hot". This happens when more than one state
depends on the value of the asynchronous input. For
example you can have a state with logic to go to the
next state when the async input goes high. Now suppose
the async input doesn't meet the required clock setup time.
At a particular edge, the logic that produces the current
state (remember each state has its own flip-flop in
one-hot encoding) and the logic producing the next state
can see a different value on the async input due to
differences in routing delay through logic to the D
input of the flop. This can result in both states
becoming active if the current state sees the async
input low and the next state sees the async input high.
Conversely it can result in neither state active if
the current state sees the input high and the next
state sees it low. The latter case can cause the
state machine to "stick" since generally all of the
states require that at least one state is active on
the prior cycle in order to go active on this cycle.

As you can see, the relative timing between two sets
of logic, which includes a hefty amount of routing
delay, can easily change when you re-build the design
even if you make no changes to the state machine
logic. In the case I described above, the multi-hot
case is probably benign, but the zero-hot case would
cause exactly what you see on the LED's. In fact
I suspect that if you changed the state encoding
you would still see zero for the stuck state, since
the machine is really not stuck in any state.

Regards,
Gabor
 
On Aug 6, 10:51 pm, Jonathan Nicolas <juuns...@gmail.com> wrote:
Hi,
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...

Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays.  Within the CPU
module, I assign those to different values to display debugging
information.

The CPU core is basically a simple state machine, looking something
like this:

reg [1:0] state_reg, state_next;

reg[15:0] r0_reg, r0_next; // And the same for all other registers

always @(posedge clk)
   begin
      state_reg <= state_next;

      r0_reg <= r0_next;
      // ... same for all others
   end

always @*
   begin
      // Default values
      state_next = state_reg;
      r0_next = r0_reg;
      // ...

      // FSM code
      case(state_reg)
          2'b00:  begin    [[code for state 0 ]]   state_next > 2'b01;  end
          2'b01:  begin    [[code for state 1 ]]   state_next > 2'b10;  end
          2'b10:  begin    [[code for state 2 ]]   state_next > 2'b11;  end
          2'b11:  begin    [[code for state 3 ]]   state_next > 2'b00;  end
      endcase
   end

The CPU always go through these 4 states for each instruction.  [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.

Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:

assign dbg1 = {5'b0 , state_reg};

'dbg1' is defined as "output wire [7:0] dbg1" in the module header

This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)

Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;

Now, if I do that, everything stops working.  The CPU doesn't cycle
through its states anymore.

I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register).  When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00".  Nothing at all is happening in the state machine.

I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc..  If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.

I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine.  But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.

I even tried using this line instead :
assign dbg1 = {4'b0,
    (state_reg==2'b00) ? 4'b0001 :
    (state_reg==2'b01) ? 4'b0010 :
    (state_reg==2'b10) ? 4'b0100 : 4'b1000 };

My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.

Please help me out !!

Jonathan
Have you looked at your synthesis report (.syr) file to see if logic
is getting
stripped out or if you have weird warnings? It could be that when you
disconnect
your LEDs, XST decides that it doesn't need some of your logic.

I assume you're simulating your design as well?

John Providenza
 
On Aug 7, 11:35 am, johnp <jprovide...@yahoo.com> wrote:
On Aug 6, 10:51 pm, Jonathan Nicolas <juuns...@gmail.com> wrote:





Hi,
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...

Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays.  Within the CPU
module, I assign those to different values to display debugging
information.

The CPU core is basically a simple state machine, looking something
like this:

reg [1:0] state_reg, state_next;

reg[15:0] r0_reg, r0_next; // And the same for all other registers

always @(posedge clk)
   begin
      state_reg <= state_next;

      r0_reg <= r0_next;
      // ... same for all others
   end

always @*
   begin
      // Default values
      state_next = state_reg;
      r0_next = r0_reg;
      // ...

      // FSM code
      case(state_reg)
          2'b00:  begin    [[code for state 0 ]]   state_next > > 2'b01;  end
          2'b01:  begin    [[code for state 1 ]]   state_next > > 2'b10;  end
          2'b10:  begin    [[code for state 2 ]]   state_next > > 2'b11;  end
          2'b11:  begin    [[code for state 3 ]]   state_next > > 2'b00;  end
      endcase
   end

The CPU always go through these 4 states for each instruction.  [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.

Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:

assign dbg1 = {5'b0 , state_reg};

'dbg1' is defined as "output wire [7:0] dbg1" in the module header

This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)

Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;

Now, if I do that, everything stops working.  The CPU doesn't cycle
through its states anymore.

I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register).  When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00".  Nothing at all is happening in the state machine.

I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc..  If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.

I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine.  But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.

I even tried using this line instead :
assign dbg1 = {4'b0,
    (state_reg==2'b00) ? 4'b0001 :
    (state_reg==2'b01) ? 4'b0010 :
    (state_reg==2'b10) ? 4'b0100 : 4'b1000 };

My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.

Please help me out !!

Jonathan

Have you looked at your synthesis report (.syr) file to see if logic
is getting
stripped out or if you have weird warnings?  It could be that when you
disconnect
your LEDs, XST decides that it doesn't need some of your logic.

I assume you're simulating your design as well?

John Providenza- Hide quoted text -

- Show quoted text -
I used to have a problem like that before, my whole ALU was getting
stripped out.. But ever since I added the logic to write data to RAM,
I never had this problem again. Even when I disconnect the SSD,
nothing
gets stripped out.

Thanks,
Jonathan
 
On Aug 7, 8:53 am, gabor <ga...@alacron.com> wrote:
On Aug 7, 1:51 am, Jonathan Nicolas <juuns...@gmail.com> wrote:





Hi,
I've been playing with my Xilinx Spartan-3A FPGA starter kit for a
while now, doing all kind of projects, and I recently started writing
a simple 16-bits CPU, for educational purposes.
However, today I hit a really really weird bug in my design...

Basically, the CPU core is in its own module (with ports to access RAM
and clock and other things), but also has two 8-bits output ports,
"dbg1" and "dbg2", which I hook to 7-segment displays.  Within the CPU
module, I assign those to different values to display debugging
information.

The CPU core is basically a simple state machine, looking something
like this:

reg [1:0] state_reg, state_next;

reg[15:0] r0_reg, r0_next; // And the same for all other registers

always @(posedge clk)
   begin
      state_reg <= state_next;

      r0_reg <= r0_next;
      // ... same for all others
   end

always @*
   begin
      // Default values
      state_next = state_reg;
      r0_next = r0_reg;
      // ...

      // FSM code
      case(state_reg)
          2'b00:  begin    [[code for state 0 ]]   state_next > > 2'b01;  end
          2'b01:  begin    [[code for state 1 ]]   state_next > > 2'b10;  end
          2'b10:  begin    [[code for state 2 ]]   state_next > > 2'b11;  end
          2'b11:  begin    [[code for state 3 ]]   state_next > > 2'b00;  end
      endcase
   end

The CPU always go through these 4 states for each instruction.  [[code
for state X]] contain the actual
code, which I think is irrelevent for my bug, but it does instruction
fetching, decoding, execution, and uses
an ALU.

Here's the really weird part...
Ever since I started writing this module, I always had this line to
help debugging:

assign dbg1 = {5'b0 , state_reg};

'dbg1' is defined as "output wire [7:0] dbg1" in the module header

This way, I can always see which state the CPU is in on one of my 7-
segment displays (00, 01, 02, 03)

Now, I needed to debug part of the ALU, and changed that line,
assigning 'dbg1' to a register value, like:
assign dbg1 = r0_reg;

Now, if I do that, everything stops working.  The CPU doesn't cycle
through its states anymore.

I have my second debug output (dbg2) to another 7-segment display,
which displays the current instruction
pointer (PC register).  When 'dbg1' is connected to 'state_reg' as
before, I can see the value of PC incrementing
by 1 ever 4 clock cycles (incrementation occurs at state 01). But if I
disconnect 'dbg1', my dbg2 output always
display "00".  Nothing at all is happening in the state machine.

I've messed around with this bug for hours now, and I can't figure it
out... I tried re-designing parts of my code,
commenting out some parts, etc..  If I don't drive 'state_reg' outside
of the module through 'dbg1', nothing works.

I tried keeping the "assign dbg1 = {5'b0 , state_reg}" line, and
disconnecting "dbg1" from the 7-segment display
from the top module, and everything works fine.  But as soon as I
remove the "assign dbg1 = {5'b0 , state_reg}"
line from the CPU module, nothing happens inside.

I even tried using this line instead :
assign dbg1 = {4'b0,
    (state_reg==2'b00) ? 4'b0001 :
    (state_reg==2'b01) ? 4'b0010 :
    (state_reg==2'b10) ? 4'b0100 : 4'b1000 };

My plan with this was to display "01 02 04 08" instead of "00 01 02
03", but if I use that line instead of my old
one, everything stops working again.

Please help me out !!

Jonathan

Very often "weird" bugs that show up when touching seemingly
unrelated parts of a design are caused by a combination of
timing and synchronizing problems.

The first thing to check when a state machine stops running
is if any of the inputs to the state machine are not
synchronous to the clock.  XST routinely re-codes your
state logic as "one-hot", even if you assign your state
variable to output wires.  In your case I suspect the
machine is one-hot encoded, and then your LED is re-
encoded into binary from the one-hot states.

What happens to a one-hot state machine when you have an
asynchronous input is that it can become "zero-hot" or
"multiple-hot".  This happens when more than one state
depends on the value of the asynchronous input.  For
example you can have a state with logic to go to the
next state when the async input goes high.  Now suppose
the async input doesn't meet the required clock setup time.
At a particular edge, the logic that produces the current
state (remember each state has its own flip-flop in
one-hot encoding) and the logic producing the next state
can see a different value on the async input due to
differences in routing delay through logic to the D
input of the flop.  This can result in both states
becoming active if the current state sees the async
input low and the next state sees the async input high.
Conversely it can result in neither state active if
the current state sees the input high and the next
state sees it low.  The latter case can cause the
state machine to "stick" since generally all of the
states require that at least one state is active on
the prior cycle in order to go active on this cycle.

As you can see, the relative timing between two sets
of logic, which includes a hefty amount of routing
delay, can easily change when you re-build the design
even if you make no changes to the state machine
logic.  In the case I described above, the multi-hot
case is probably benign, but the zero-hot case would
cause exactly what you see on the LED's.  In fact
I suspect that if you changed the state encoding
you would still see zero for the stuck state, since
the machine is really not stuck in any state.

Regards,
Gabor- Hide quoted text -

- Show quoted text -
Hi, thanks for your reply.

I'm rather new to verilog programming, so I don't fully
understand what you're trying to explain. I do, however,
know that I do not have any signals that are not
clock-synchronous. If there are, it's a hidden bug!

My whole code is getting messy though, from all the trial &
error I've been through writing it, so I think I'll just
start over clean, and start with making sure the FSM works
fine, then add in modules one by one.

So far I've been doing all my testing directly on hardware,
so I think I'll do like some people suggest and start doing
simulations before, that might help me out find some bugs too.

Thanks everyone for your replies,
Jonathan
 
I reccommend you have a look at the XST guide for verilog programming.
If you stick to the guidelines- it not only allows you to create clean
synthesizable RTL, but the XST tool will automatically infer
registers, RAMs, ROMs etc.

Most of the times after doing synthesis, I look at the RTL schematic
created by XST. Sometimes missing wires, wrong connections become
cleary visible. This will also be in your warnings list after
synthesis. we tend to ignore warnings as they are not errors.

Also it's best to have all inputs to any combinational logic from an
output of a flip-flop.
 

Welcome to EDABoard.com

Sponsor

Back
Top