首页 > 解决方案 > Why are my Verilog output registers only outputting "x"?

问题描述

I've written the following module to take in a 12-bit stream of input, and run it through the Exponential Moving Average (EMA) formula. When simulating the program, it appears as if my output is a 12-bit stream of "don't cares". Regardless of what my input is, it isn't realized by the output register.

I'm a beginner at Verilog, so I'm sure there are a slew of issues here, but I expected to at least get some kind of output. Why is this behavior occurring and how can I fix it from occurring in the future? I've linked a screenshot of my waveform results at the bottom of this post.

My verilog module:

`timescale 1ns / 1ps
module EMATesting (     input signed [11:0] signal_in,
                        output reg signed [11:0] signal_out,
                        input clock_in,
                        input reset,
                        input enable,
                        output reg [11:0] newEMA);

reg [11:0] prevEMA;
reg [11:0] y;
reg [11:0] temp;
integer count = 0;
integer t = 1;
integer one = 1;
integer alpha = 0.5;

always @(posedge clock_in) begin

    if (reset) begin
        count = 0;
        end

    else if (count < 64) begin
         count = count + 1;
        end

//set the output equal to the first value received
    if (count == 1) begin
        newEMA = signal_in;
        end

//if not the first value, run through the formula
    else begin
        temp = newEMA;
        prevEMA = temp;
        newEMA = alpha * signal_in + (one-alpha) * prevEMA;
        count = count + 1;
        end
    end
endmodule

My verilog testbench:

`timescale 10ns / 1ns
module testbench_EMA;

reg signal_in;
reg clock_in, reset, enable;
wire [11:0] signal_out;
wire [11:0] newEMA;

initial begin
    signal_in = 0; reset = 0; enable = 0;
    clock_in = 0;
end

EMATesting DUT(signal_in, signal_out, clock_in, reset, enable, newEMA);

initial
begin
//test some values with timing intervals here 
#100;
reset = 1;
#100;
reset = 0;
enable = 1;
#100;
//set signal_in to "1" repeating 12 times
signal_in = { 12 { 1'b1}};
#100;
reset = 1;
#100; //buffer to end simulation
$finish;
end


always
    #5 clock_in = !clock_in;

endmodule

Waveform results of my testbench. Note that both output registers are giving no values.

标签: outputverilog

解决方案


您的代码中有很多错误。@先生。Snrub 列出了其中的一些。您可以纠正注释中列出的错误,通过进一步编辑您的代码,您可以使其按您的意愿工作,但还有更重要的基本问题。您必须在将来进一步和难以调试错误之前解决它们,这也有助于更好地理解 HDL 概念。

  • 首先,您需要了解软件编程语言和硬件描述语言之间的区别。您应该对此进行进一步的研究,您所犯的错误通常是由假设 HDL 类似于软件编程语言的开发人员所犯的。检查链接以获取更多信息。
  • 您需要进一步了解 Verilog HDL(或任何其他 HDL)代码是如何合成的以及使用它们的原因。
  • 需要熟悉何时以及如何使用阻塞=或非阻塞<=分配以及它们是如何工作的。检查链接。

当您研究列出的主题时,您会明白在边缘敏感(同步或顺序)always块中,使用阻塞=分配是个坏主意。

当您使用阻塞分配时,分配是按顺序完成的,就像在常见的软件编程语言中一样。在边缘敏感always块的情况下,您完成always块内所有必需分配的时间非常有限。

在您的情况下,由于边缘敏感 always 块内的所有分配都是阻塞的(假设没有重置条件):

  • 首先,它检查是否count小于 64,如果是,则完成分配。所有其他作业都在等待该作业完成。
  • 当第一次分配完成时,always具有敏感性的块posedge clock_in可能已经结束执行并等待时钟的下一个边沿。因此,其他任务没有完成。
  • 由于您尚未初始化输出寄存器,因此它们最初填充了“无关”,并且永远不会再次分配新值,因此,您得到了该输出(填充了“无关”)。
  • 即使count变得大于或等于 64,在将值分配给newEMA.

推荐阅读