views:

126

answers:

2

I did a behavioral simulation of my code, and it works perfectly. The results are as predicted. When I synthesize my code and upload it to a spartan 3e FPGA and try to analyze using chipscope, the results are not even close to what I would have expected. What have I done incorrectly? http://pastebin.com/XWMekL7r

+2  A: 

Your problem is with lines 13-16, where you set initial values for state registers:

 reg    [OUTPUT_WIDTH-1:0] previousstate = 0;              
 reg    [OUTPUT_WIDTH-1:0] presentstate = 1;
 reg    [6:0] fib_number_cnt = 1;  
 reg    [OUTPUT_WIDTH-1:0] nextstate = 1; 

This is an equivalent to writing an "initial" statement assigning these values, which isn't synthesizable -- there is no such thing as a default value in hardware. When you put your design inside an FPGA, all of these registers will take on random values.

Instead, you need to initialize these counters/states inside your always block, when reset is high.

always @(posedge clk or posedge reset)
  if (reset) begin
     previousstate <= 0;
     presentstate <= 1;
     ... etc ...
  end

Answer to the follow-up questions:

When you initialize code like that, nothing at all happens in hardware -- it gets completely ignored, just as if you've put in a $display statement. The synthesis tool skips over all simulation-only constructs, while usually giving you some kind of a warning about it (that really depends on the tool).

Now, blocking and non-blocking question requires a very long answer :). I will direct you to this paper from SNUG-2000 which is probably the best paper ever written on the subject. It answers your question, as well as many others on the topic. Afterward, you will understand why using blocking statements in sequential logic is considered bad practice, and why your code works fine with blocking statements anyway.

http://cs.haifa.ac.il/courses/verilog/cummings-nonblocking-snug99.pdf


More answers:

The usual "pattern" to creating logic like yours is to have two always blocks, one defining the logic, and one defining the flops. In the former, you use blocking statements to implement logic, and in the latter you latch in (or reset) the generated value. So, something like this:

wire some_input;

// Main logic (use blocking statements)
reg state, next_state;
always @*
  if (reset) next_state = 1'b0;
  else begin
    // your state logic
    if (state) next_state = some_input;
    else next_state = 1'b0;
  end

// Flops (use non-blocking)
always @(posedge clock)
  if (reset) state <= 1'b0;
  else state <= next_state;

Note that I'm using a synchronous reset, but you can use async if needed.

Stan
Interesting point! When I initialized my registers as shown in the code, the synthesizer didnt complain. What exactly happens in hardware when something like this is done?
chester.boo
Also, when I do simulation with non-blocking statements in the always block, the numbers I get are not the same as with blocking statements. Why? (The blocking statements provide the correct results)
chester.boo
Hi, thanks for the additional input.Reading section 11, I see that I have to add extra elements to my sensitivity list for the nonblocking assignments to work correctly. But I can't mix edge triggered and level triggered elements together in the sensitivity list. I also cant make another always block with level triggered elements because that would be doing multiple assignments to the same elements in more than one always block (remember as per your suggestion I am using the edge triggered block to initialize elements when in reset state). What would you advise? Stick with blocking?
chester.boo
I've added more to the answer, since it's hard to write code in comments.
Stan
Hi Stan, Thanks for taking the time to explain. But I'm afraid that I didn't follow your last attempt. Please elaborate.
chester.boo
Let me refer you to another page that goes into more details on the basics of FSM writing in Verilog. It shows you the most commonly used FSM structures, including the one I was trying to describe. It does a much better job of explaining the topic than I could in here.http://www.asic-world.com/tidbits/verilog_fsm.html
Stan
So if I follow you correctly, I should do the math as combinational logic (blocking), but as the results are churned out, use a second always block to capture the results (nonblocking)?
chester.boo
Yes, that's generally the idea. It's not a requirement, but it makes life easier.
Stan
A: 

Lines 13-16 are correct. "reg [6:0] fib_number_cnt = 1;" is not the same as using "initial" statement. Read Xilinx synthesis guide for more detailed description of how to initialize the registers.

OutputLogic