我需要生成如图所示的波形。在Verilog代码中

时间:2019-01-27 05:13:35

标签: verilog

我需要生成一个波形,如图所示。但是用我的代码,我没有得到预期的波形

在设计中,零件从测试平台随机获得了最后一个有效值。 我的问题是为什么I值在有效值处递增不等于1

设计代码:

module design_d(clk,valid,last,data);

   input clk,valid,last;
   output reg [7:0] data;

     reg [7:0] i; 
     initial
       begin
       data=0;
       i=0;
      end

always @(posedge clk,valid)
    begin

   if (valid)
   begin
     data<=i;
     i=i+1;
     $display("i=%d data=%d ",i,data);
   end
   else 
     begin
       data <=8'bz; 
     end
    end
endmodule    

测试台代码:

module test;

  reg clk,valid,last;
  wire [7:0] data;

  parameter clk_period=2;

  design_d dut(clk,valid,last,data);

  initial
  begin
    clk=1;
    valid=1;
    last=0;
  end

  always #(clk_period/2) clk=~clk;

  always @(posedge clk)
  begin 
    last=0;
    #4 last=1;
    #clk_period last=0;
    #8 last=1;
    #clk_period last=0;
    #10 last=1;
    #clk_period last=0;
    #16last=1;
    #clk_period last=0;  

    #20 last=1;
    #clk_period last=0;
  end

  always @(posedge clk or last)
  begin
     valid<=1;
     wait(last==1)
     #clk_period;
     valid<=0;
     #clk_period;
     valid<=1;
  end

  initial
  begin 
     $dumpfile("dump.vcd");
     $dumpvars(1);
     #24 $finish;
  end
endmodule

enter image description here

1 个答案:

答案 0 :(得分:1)

您似乎在使用英语方面遇到困难,这不是您的错,但是因此,我可能会错误地解释您的问题。

您拥有所需实现的波形。我认为这是学校的任务,因此我将以这种方式对待。这意味着我将*不会*给您完整的答案,但会为您提供有关您要去哪里的信息。 (这都应该在评论中,但是现在有合适的方法了。)

  

...从测试平台中随机获得了最后一个有效值。

首先要意识到的是编写一个测试平台也很困难,即使不是那么困难,那么编写RTL代码本身也是如此。

在测试平台中,您正在使用always @(posedge clk),但是在该部分中,您使用的是#...语句。这本身并没有错。危险,是的,但不一定是错误的。

但是
您的时钟的时间段为2(parameter clk_period=2;),并且在posege时钟内部,您使用的延迟是等于或大于,而不是时钟周期。如您所知,这通常会导致灾难。
阅读有关Verilog的工作原理的信息,尤其是在使用敏感度列表always @...时:在处理完本节中的所有语句之前,不会触发它。在您的情况下,这意味着它将花费多个时钟沿,直到再次开始Always块。

测试平台
我不知道分配是什么,所以我将使用您提供的波形。 由于lastvalid是您模块的输入,因此我将为您提供如何制作这些模块的指针。

valid在4个时钟周期内为高电平,然后在一个时钟周期内为低电平,然后重复自身。这意味着您需要一个每5个时钟周期重复一次的模式,因此需要制作一个计数器,该计数器可以计数0、1、2、3、4、0、1、2、3、4,...

您不应使用#.....语句来做到这一点。您应该使用测试台时钟,并制作一个可以计数的计数器!
制作如上所述的计数器是您需要在HDL中学习的第一件事!您会发现,您必须一遍又一遍地重复执行此操作。.在每个RTL代码段和每个测试平台中。

Modulo 5计数器。

我希望所有模块和测试台都进行重置。 如果可以的话,它允许我从已知状态开始新的测试。

reg [2:0] counter;

always @(posedge clk or negedge reset_n)
begin
   if (reset_n)
      counter <= ...
   else // clocked section
   begin
      if (..)
        counter <= ...
      else       
        counter <= ...
   end
end

重新开始,并首先运行上面的代码。在继续之前,请注意计数器确实在运行0,1 2,3,4,0,..。

派生信号。
接下来学习从中得出信号。
基本规则:在计时部分中,如果您需要计数器值为X的信号,则必须在周期X-1生成该信号。

因此当计数器为3时要保持最后的高电平,必须在计数器2时将其设置为高电平。

always @(posedge clk...
...
   if (counter==3'h2)
      last <= 1'b1;
   else
      last <= 1'b0;

我留给您有效的证件。

一旦测试台开始运行,就开始在design_d模块上工作。

一些提示:

  • 在计时部分中始终使用非阻塞分配<=。 **

  • 请勿使用2个时钟周期,而应使用100或1000。您会在适当的时间找出为什么效果更好。

  • 除非按照我的示例,否则请勿使用always @(posedge clk or [one or more signals] )。 **

  • 请注意缩进。我不得不对您的代码进行一些市长编辑。

** 对不起,我无法详细说明为什么大多数时候都是好的做法,因为这会使答案的大小增加三倍。目前,请按照提示操作。

我本可以花所有时间编写所有代码的十分之一的时间来编写实际代码,所以我希望您不要删除该问题,因为其他人可能会从中受益。