开发者

Verilog code simulates but does not run as predicted on FPGA

I did a behavioral simulation of my code, and it works perfectly. The results are as predicted. Whe开发者_开发技巧n 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


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜