Verilog 代码在 FPGA 上进行模拟但未按预期运行

发布于 2024-08-24 18:34:23 字数 205 浏览 12 评论 0原文

我对我的代码进行了行为模拟,效果非常好。结果正如预测的那样。当我综合代码并将其上传到 spartan 3e FPGA 并尝试使用 Chipscope 进行分析时,结果与我的预期相差甚远。我做错了什么? http://pastebin.com/XWMekL7r

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

赠意 2024-08-31 18:34:24

第 13-16 行是正确的。 “reg [6:0] fib_number_cnt = 1;”与使用“初始”语句不同。阅读 Xilinx 综合指南,了解有关如何初始化寄存器的更详细说明。

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.

挽袖吟 2024-08-31 18:34:23

您的问题在于第 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;

请注意,我使用的是同步重置,但如果需要,您可以使用异步。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文