Verilog代码模拟但不像FPGA上预测的那样运行

che*_*boo 0 verilog synthesis fpga hdl xilinx

我对我的代码进行了行为模拟,它运行得很好.结果如预测.当我合成我的代码并将其上传到spartan 3e FPGA并尝试使用chipcope进行分析时,结果甚至不如我预期的那样接近.我做错了什么? http://pastebin.com/XWMekL7r

Sta*_*tan 5

您的问题在于第13-16行,您可以在其中设置状态寄存器的初始值:

 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; 
Run Code Online (Sandbox Code Playgroud)

这相当于编写一个"初始"语句来分配这些值,这些值是不可合成的 - 硬件中没有默认值.当您将设计放入FPGA中时,所有这些寄存器都将采用随机值.

相反,当复位很高时,您需要在always块内初始化这些计数器/状态.

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

回答后续问题:

当你初始化这样的代码时,硬件中什么都没发生 - 它被完全忽略了,就像你输入了$ display语句一样.综合工具会跳过所有仅模拟构造,同时通常会给你一些关于它的警告(这实际上取决于工具).

现在,阻塞和非阻塞问题需要很长的答案:).我将引导您阅读SNUG-2000中的这篇论文,这篇论文可能是有史以来最好的论文.它回答了您的问题,以及该主题的许多其他问题.之后,您将理解为什么在顺序逻辑中使用阻塞语句被认为是不好的做法,以及为什么您的代码无论如何都能正常使用阻塞语句.

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


更多答案:

创建像你这样的逻辑的通常"模式"是有两个始终块,一个定义逻辑,一个定义触发器.在前者中,您使用阻塞语句来实现逻辑,而在后者中,您可以锁定(或重置)生成的值.所以,像这样:

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;
Run Code Online (Sandbox Code Playgroud)

请注意,我正在使用同步重置,但如果需要,您可以使用async.