首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iverilog模拟器如何解释我的RAM代码来确定'x‘值?

iverilog模拟器如何解释我的RAM代码来确定'x‘值?
EN

Stack Overflow用户
提问于 2018-12-29 07:36:20
回答 1查看 234关注 0票数 2

我正在尝试使用Icarus Verilog在Verilog中编写和测试一个简单的16位宽RAM8芯片。我发现很难从概念上理解为什么iverilog模拟器会在某些时钟节拍上显示'x‘(未定义)值,并且想知道是否有人可以为这个问题提供概念上的理解。

我尝试了两种不同的设计,其中一种输出对我来说很有意义,但我无法解析第二种设计的输出。

第一种设计使out成为一个寄存器,对输出的赋值为时钟:

代码语言:javascript
复制
module RAM8(out, address, in, load, clk);
   output[15:0] out;
   input [15:0] in;
   input [2:0]  address;
   input        load, clk;

   reg          out;            // out is a register
   reg [15:0]   ram [7:0];      // 8-element array of 16-bit wide reg

   always @(posedge clk) begin
      if (load)
        ram[address] <= in;
      out <= ram[address];      // clocked assignment
   end
endmodule // RAM8

而第二种设计,out是一个连续分配的线:

代码语言:javascript
复制
module RAM8(out, address, in, load, clk);
   output[15:0] out;
   input [15:0] in;
   input [2:0]  address;
   input        load, clk;

   reg [15:0]   ram [7:0];      // 8-element array of 16-bit wide reg

   always @(posedge clk) begin
      if (load)
        ram[address] <= in;
   end
   assign out = ram[address];      // continuous assignment
endmodule // RAM8

这两者的测试平台是相同的:

代码语言:javascript
复制
module RAM8_tb();
   wire [15:0] out;
   reg [15:0]  in;
   reg [2:0]   address;
   reg         load;
   reg         clk;

   RAM8 DUT (
         .out(out),
         .in(in),
         .address(address),
         .load(load),
         .clk(clk)
         );

   initial begin
      clk = 0;
      load = 0;
      address = 0;
      in = 0;

      #10 load = 1; address = 0; in = 0;
      #10 load = 0; address = 0;
      #10 load = 1; address = 1; in = 1;
      #10 load = 0; address = 1;
      #10 load = 1; address = 2; in = 2;
      #10 load = 0; address = 2;
      #10 load = 1; address = 3; in = 3;
      #10 load = 0; address = 3;
      #10 load = 1; address = 4; in = 4;
      #10 load = 0; address = 4;
      #10 load = 1; address = 5; in = 5;
   end // initial begin

   always #5 clk = ~clk;

   initial #150 $stop;

   initial
     $monitor("At time %t, clk = %0d, load = %0d, address = %0d, in = %0d, out = %0d",
              $time, clk, load, address, in, out);
endmodule // RAM8_tb

我为第一个设计运行测试平台的输出是这样的:

代码语言:javascript
复制
At time                    0, clk = 0, load = 0, address = 0, in = 0, out = x
At time                    5, clk = 1, load = 0, address = 0, in = 0, out = x
At time                   10, clk = 0, load = 1, address = 0, in = 0, out = x
At time                   15, clk = 1, load = 1, address = 0, in = 0, out = x
At time                   20, clk = 0, load = 0, address = 0, in = 0, out = x
At time                   25, clk = 1, load = 0, address = 0, in = 0, out = 0
At time                   30, clk = 0, load = 1, address = 1, in = 1, out = 0
At time                   35, clk = 1, load = 1, address = 1, in = 1, out = x
At time                   40, clk = 0, load = 0, address = 1, in = 1, out = x
At time                   45, clk = 1, load = 0, address = 1, in = 1, out = 1
At time                   50, clk = 0, load = 1, address = 2, in = 2, out = 1
At time                   55, clk = 1, load = 1, address = 2, in = 2, out = x
At time                   60, clk = 0, load = 0, address = 2, in = 2, out = x
At time                   65, clk = 1, load = 0, address = 2, in = 2, out = 2
At time                   70, clk = 0, load = 1, address = 3, in = 3, out = 2
At time                   75, clk = 1, load = 1, address = 3, in = 3, out = x
At time                   80, clk = 0, load = 0, address = 3, in = 3, out = x
At time                   85, clk = 1, load = 0, address = 3, in = 3, out = 3
At time                   90, clk = 0, load = 1, address = 4, in = 4, out = 3
At time                   95, clk = 1, load = 1, address = 4, in = 4, out = x
At time                  100, clk = 0, load = 0, address = 4, in = 4, out = x
At time                  105, clk = 1, load = 0, address = 4, in = 4, out = 4
At time                  110, clk = 0, load = 1, address = 5, in = 5, out = 4
At time                  115, clk = 1, load = 1, address = 5, in = 5, out = x
At time                  120, clk = 0, load = 1, address = 5, in = 5, out = x
At time                  125, clk = 1, load = 1, address = 5, in = 5, out = 5
At time                  130, clk = 0, load = 1, address = 5, in = 5, out = 5
At time                  135, clk = 1, load = 1, address = 5, in = 5, out = 5
At time                  140, clk = 0, load = 1, address = 5, in = 5, out = 5
At time                  145, clk = 1, load = 1, address = 5, in = 5, out = 5

这个输出对我来说很有意义。每次我加载一个新值时,输出都是未定义的,因为加载是与加载到输出寄存器的值同时发生的(因此,该时钟节拍的垃圾值)。

然而,第二个设计的测试平台的输出让我感到困惑:

代码语言:javascript
复制
At time                    0, clk = 0, load = 0, address = 0, in = 0, out = x
At time                    5, clk = 1, load = 0, address = 0, in = 0, out = x
At time                   10, clk = 0, load = 1, address = 0, in = 0, out = x
At time                   15, clk = 1, load = 1, address = 0, in = 0, out = 0
At time                   20, clk = 0, load = 0, address = 0, in = 0, out = 0
At time                   25, clk = 1, load = 0, address = 0, in = 0, out = 0
At time                   30, clk = 0, load = 1, address = 1, in = 1, out = x
At time                   35, clk = 1, load = 1, address = 1, in = 1, out = 1
At time                   40, clk = 0, load = 0, address = 1, in = 1, out = 1
At time                   45, clk = 1, load = 0, address = 1, in = 1, out = 1
At time                   50, clk = 0, load = 1, address = 2, in = 2, out = x
At time                   55, clk = 1, load = 1, address = 2, in = 2, out = 2
At time                   60, clk = 0, load = 0, address = 2, in = 2, out = 2
At time                   65, clk = 1, load = 0, address = 2, in = 2, out = 2
At time                   70, clk = 0, load = 1, address = 3, in = 3, out = x
At time                   75, clk = 1, load = 1, address = 3, in = 3, out = 3
At time                   80, clk = 0, load = 0, address = 3, in = 3, out = 3
At time                   85, clk = 1, load = 0, address = 3, in = 3, out = 3
At time                   90, clk = 0, load = 1, address = 4, in = 4, out = x
At time                   95, clk = 1, load = 1, address = 4, in = 4, out = 4
At time                  100, clk = 0, load = 0, address = 4, in = 4, out = 4
At time                  105, clk = 1, load = 0, address = 4, in = 4, out = 4
At time                  110, clk = 0, load = 1, address = 5, in = 5, out = x
At time                  115, clk = 1, load = 1, address = 5, in = 5, out = 5
At time                  120, clk = 0, load = 1, address = 5, in = 5, out = 5
At time                  125, clk = 1, load = 1, address = 5, in = 5, out = 5
At time                  130, clk = 0, load = 1, address = 5, in = 5, out = 5
At time                  135, clk = 1, load = 1, address = 5, in = 5, out = 5
At time                  140, clk = 0, load = 1, address = 5, in = 5, out = 5
At time                  145, clk = 1, load = 1, address = 5, in = 5, out = 5

我的问题是:输出端的周期性未定义值是由什么引起的?共性似乎是当clk为0,负载为1时,但我对寄存器的理解无法解释为什么这会导致输出成为垃圾。在我的设计中,所有的寄存器都是在正时钟边沿触发的,那么为什么负边沿会改变任何值?

我想我可能会对这里发生的事情感到困惑,也希望有人能证实或反驳我对第一个设计的行为的解释。提前感谢所有花时间阅读和回答的人。

EN

回答 1

Stack Overflow用户

发布于 2018-12-29 10:15:23

在这两种情况下,得到的X值都是ram的初始值(因为您没有分配任何初始值,所以X值就是X)。如果您继续测试并遍历相同的地址,那么下一次您将看到之前编写的值。

在第一个示例中,并发读写不是问题。读取操作返回时钟边沿之前的值,而ram将包含时钟边沿之后的新值。

在第二个例子中,触发X的事件是address递增,而不是clkload信号。由于out未注册且与clk没有关联,因此只要address发生更改,您就会看到该地址上的值出现在out上。然后,在写入新值的时钟沿之后,您会看到out同时更改为该值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53965441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档