我对我的代码进行了行为模拟,它运行良好。结果如预期。当我合成我的代码并将其上传到 spartan 3e FPGA 并尝试使用chipscope 进行分析时,结果甚至与我的预期不相近。我做错了什么? http://pastebin.com/XWMekL7r
2 回答
您的问题出在第 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;
这相当于编写一个“初始”语句来分配这些值,这是不可综合的——硬件中没有默认值这样的东西。当您将设计放入 FPGA 中时,所有这些寄存器都将采用随机值。
相反,当重置为高时,您需要在 always 块中初始化这些计数器/状态。
always @(posedge clk or posedge reset)
if (reset) begin
previousstate <= 0;
presentstate <= 1;
... etc ...
end
回答后续问题:
当你像这样初始化代码时,硬件中什么也没有发生——它被完全忽略,就像你放入了一个 $display 语句一样。综合工具会跳过所有仅用于模拟的结构,同时通常会给您一些警告(这实际上取决于工具)。
现在,阻塞和非阻塞问题需要很长的答案:)。我将引导您阅读 SNUG-2000 中的这篇论文,这可能是关于该主题的最佳论文。它回答了您以及该主题的许多其他问题。之后,您将了解为什么在顺序逻辑中使用阻塞语句被认为是不好的做法,以及为什么您的代码无论如何都可以正常使用阻塞语句。
http://cs.haifa.ac.il/courses/verilog/cummings-nonblocking-snug99.pdf
更多答案:
创建像您这样的逻辑的通常“模式”是有两个 always 块,一个定义逻辑,一个定义翻牌。在前者中,您使用阻塞语句来实现逻辑,而在后者中,您锁定(或重置)生成的值。所以,像这样:
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;
请注意,我使用的是同步重置,但如果需要,您可以使用异步。
第 13-16 行是正确的。“注册 [6:0] fib_number_cnt = 1;” 与使用“初始”语句不同。阅读 Xilinx 综合指南,了解如何初始化寄存器的更详细说明。