How is iverilog simulator interpreting my RAM code to determine 'x' values?












1















I am attempting to write and test a simple 16-bit width RAM8 chip in Verilog using Icarus Verilog. I'm finding it difficult to understand conceptually why the iverilog simulator is showing me 'x' (undefined) values on certain clock ticks and wondering if anybody can provide a conceptual understanding for this problem.



I've tried two different designs, one of which the output makes sense to me, but I can't parse the output of the second.



The first design makes out a register, and assignment to the output is clocked:



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


Whereas the second design, out is a continuously assigned wire:



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


The test bench for both of these is the same:



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


My output running the test bench for the first design is this:



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


This output makes sense to me. Each time I'm loading a new value, the output is undefined because the loading is happening concurrently to the value that's being loaded being clocked into the output register (hence, garbage values for that clock tick).



However the output for the test bench for the second design is confusing to me:



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


My question here is: what are the periodic undefined values at the output caused by? The commonality appears to be when the clk is 0 and the load is 1, but nothing I can recall from my understanding of registers explains why that would cause the output to be garbage. All the registers in my design are triggered on the positive clock edge, so why would a negative edge be changing any value?



I figure I may be confused generally about what's going on under the hood here, and would also appreciate somebody confirming or refuting my explanation for the behavior of the first design as well. Thanks in advance to anybody who takes the time to read and answer.










share|improve this question























  • I'd suggest you don't rely on text output to understand what is happening in your design. Waveforms make more sense when debugging hardware. It will help you understand Justin's (correct) point.

    – rascob
    Dec 30 '18 at 22:16











  • @rascob I understood his point, however I'm curious if I can use any free or cheap waveform tools along with iverilog? I'm currently limited by RAM on my 2013 MacBook and can't run Vivado.

    – Isaiah Becker-Mayer
    Jan 3 at 2:53











  • If you have to use iverilog, you can try gtkwave. If not, you can try a free version of Mentor's Modelsim. Altera provides a "Web" edition for free: intel.com/content/www/us/en/programmable/downloads/…

    – rascob
    Jan 3 at 12:52
















1















I am attempting to write and test a simple 16-bit width RAM8 chip in Verilog using Icarus Verilog. I'm finding it difficult to understand conceptually why the iverilog simulator is showing me 'x' (undefined) values on certain clock ticks and wondering if anybody can provide a conceptual understanding for this problem.



I've tried two different designs, one of which the output makes sense to me, but I can't parse the output of the second.



The first design makes out a register, and assignment to the output is clocked:



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


Whereas the second design, out is a continuously assigned wire:



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


The test bench for both of these is the same:



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


My output running the test bench for the first design is this:



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


This output makes sense to me. Each time I'm loading a new value, the output is undefined because the loading is happening concurrently to the value that's being loaded being clocked into the output register (hence, garbage values for that clock tick).



However the output for the test bench for the second design is confusing to me:



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


My question here is: what are the periodic undefined values at the output caused by? The commonality appears to be when the clk is 0 and the load is 1, but nothing I can recall from my understanding of registers explains why that would cause the output to be garbage. All the registers in my design are triggered on the positive clock edge, so why would a negative edge be changing any value?



I figure I may be confused generally about what's going on under the hood here, and would also appreciate somebody confirming or refuting my explanation for the behavior of the first design as well. Thanks in advance to anybody who takes the time to read and answer.










share|improve this question























  • I'd suggest you don't rely on text output to understand what is happening in your design. Waveforms make more sense when debugging hardware. It will help you understand Justin's (correct) point.

    – rascob
    Dec 30 '18 at 22:16











  • @rascob I understood his point, however I'm curious if I can use any free or cheap waveform tools along with iverilog? I'm currently limited by RAM on my 2013 MacBook and can't run Vivado.

    – Isaiah Becker-Mayer
    Jan 3 at 2:53











  • If you have to use iverilog, you can try gtkwave. If not, you can try a free version of Mentor's Modelsim. Altera provides a "Web" edition for free: intel.com/content/www/us/en/programmable/downloads/…

    – rascob
    Jan 3 at 12:52














1












1








1








I am attempting to write and test a simple 16-bit width RAM8 chip in Verilog using Icarus Verilog. I'm finding it difficult to understand conceptually why the iverilog simulator is showing me 'x' (undefined) values on certain clock ticks and wondering if anybody can provide a conceptual understanding for this problem.



I've tried two different designs, one of which the output makes sense to me, but I can't parse the output of the second.



The first design makes out a register, and assignment to the output is clocked:



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


Whereas the second design, out is a continuously assigned wire:



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


The test bench for both of these is the same:



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


My output running the test bench for the first design is this:



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


This output makes sense to me. Each time I'm loading a new value, the output is undefined because the loading is happening concurrently to the value that's being loaded being clocked into the output register (hence, garbage values for that clock tick).



However the output for the test bench for the second design is confusing to me:



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


My question here is: what are the periodic undefined values at the output caused by? The commonality appears to be when the clk is 0 and the load is 1, but nothing I can recall from my understanding of registers explains why that would cause the output to be garbage. All the registers in my design are triggered on the positive clock edge, so why would a negative edge be changing any value?



I figure I may be confused generally about what's going on under the hood here, and would also appreciate somebody confirming or refuting my explanation for the behavior of the first design as well. Thanks in advance to anybody who takes the time to read and answer.










share|improve this question














I am attempting to write and test a simple 16-bit width RAM8 chip in Verilog using Icarus Verilog. I'm finding it difficult to understand conceptually why the iverilog simulator is showing me 'x' (undefined) values on certain clock ticks and wondering if anybody can provide a conceptual understanding for this problem.



I've tried two different designs, one of which the output makes sense to me, but I can't parse the output of the second.



The first design makes out a register, and assignment to the output is clocked:



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


Whereas the second design, out is a continuously assigned wire:



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


The test bench for both of these is the same:



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


My output running the test bench for the first design is this:



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


This output makes sense to me. Each time I'm loading a new value, the output is undefined because the loading is happening concurrently to the value that's being loaded being clocked into the output register (hence, garbage values for that clock tick).



However the output for the test bench for the second design is confusing to me:



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


My question here is: what are the periodic undefined values at the output caused by? The commonality appears to be when the clk is 0 and the load is 1, but nothing I can recall from my understanding of registers explains why that would cause the output to be garbage. All the registers in my design are triggered on the positive clock edge, so why would a negative edge be changing any value?



I figure I may be confused generally about what's going on under the hood here, and would also appreciate somebody confirming or refuting my explanation for the behavior of the first design as well. Thanks in advance to anybody who takes the time to read and answer.







verilog fpga ram iverilog






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 28 '18 at 23:36









Isaiah Becker-MayerIsaiah Becker-Mayer

161




161













  • I'd suggest you don't rely on text output to understand what is happening in your design. Waveforms make more sense when debugging hardware. It will help you understand Justin's (correct) point.

    – rascob
    Dec 30 '18 at 22:16











  • @rascob I understood his point, however I'm curious if I can use any free or cheap waveform tools along with iverilog? I'm currently limited by RAM on my 2013 MacBook and can't run Vivado.

    – Isaiah Becker-Mayer
    Jan 3 at 2:53











  • If you have to use iverilog, you can try gtkwave. If not, you can try a free version of Mentor's Modelsim. Altera provides a "Web" edition for free: intel.com/content/www/us/en/programmable/downloads/…

    – rascob
    Jan 3 at 12:52



















  • I'd suggest you don't rely on text output to understand what is happening in your design. Waveforms make more sense when debugging hardware. It will help you understand Justin's (correct) point.

    – rascob
    Dec 30 '18 at 22:16











  • @rascob I understood his point, however I'm curious if I can use any free or cheap waveform tools along with iverilog? I'm currently limited by RAM on my 2013 MacBook and can't run Vivado.

    – Isaiah Becker-Mayer
    Jan 3 at 2:53











  • If you have to use iverilog, you can try gtkwave. If not, you can try a free version of Mentor's Modelsim. Altera provides a "Web" edition for free: intel.com/content/www/us/en/programmable/downloads/…

    – rascob
    Jan 3 at 12:52

















I'd suggest you don't rely on text output to understand what is happening in your design. Waveforms make more sense when debugging hardware. It will help you understand Justin's (correct) point.

– rascob
Dec 30 '18 at 22:16





I'd suggest you don't rely on text output to understand what is happening in your design. Waveforms make more sense when debugging hardware. It will help you understand Justin's (correct) point.

– rascob
Dec 30 '18 at 22:16













@rascob I understood his point, however I'm curious if I can use any free or cheap waveform tools along with iverilog? I'm currently limited by RAM on my 2013 MacBook and can't run Vivado.

– Isaiah Becker-Mayer
Jan 3 at 2:53





@rascob I understood his point, however I'm curious if I can use any free or cheap waveform tools along with iverilog? I'm currently limited by RAM on my 2013 MacBook and can't run Vivado.

– Isaiah Becker-Mayer
Jan 3 at 2:53













If you have to use iverilog, you can try gtkwave. If not, you can try a free version of Mentor's Modelsim. Altera provides a "Web" edition for free: intel.com/content/www/us/en/programmable/downloads/…

– rascob
Jan 3 at 12:52





If you have to use iverilog, you can try gtkwave. If not, you can try a free version of Mentor's Modelsim. Altera provides a "Web" edition for free: intel.com/content/www/us/en/programmable/downloads/…

– rascob
Jan 3 at 12:52












1 Answer
1






active

oldest

votes


















2














In both cases, the X values coming out are are the initial values of ram (which are X since you didn't assign any initial values). If you continued the test and cycled through the same addresses, the next time around you'd see the values you previously wrote.



In the first example, the concurrent read and write isn't an issue. The read is returning the value from before the clock edge, and ram will contain the new value after the clock edge.



In the second example, the event triggering the X is address incrementing, not the clk and load signals. Since out isn't registered and isn't associated with clk, as soon as address changes you see the value at that address appear on out. Then after the clock edge that writes a new value, you see out change to that value at the same time.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965441%2fhow-is-iverilog-simulator-interpreting-my-ram-code-to-determine-x-values%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    In both cases, the X values coming out are are the initial values of ram (which are X since you didn't assign any initial values). If you continued the test and cycled through the same addresses, the next time around you'd see the values you previously wrote.



    In the first example, the concurrent read and write isn't an issue. The read is returning the value from before the clock edge, and ram will contain the new value after the clock edge.



    In the second example, the event triggering the X is address incrementing, not the clk and load signals. Since out isn't registered and isn't associated with clk, as soon as address changes you see the value at that address appear on out. Then after the clock edge that writes a new value, you see out change to that value at the same time.






    share|improve this answer




























      2














      In both cases, the X values coming out are are the initial values of ram (which are X since you didn't assign any initial values). If you continued the test and cycled through the same addresses, the next time around you'd see the values you previously wrote.



      In the first example, the concurrent read and write isn't an issue. The read is returning the value from before the clock edge, and ram will contain the new value after the clock edge.



      In the second example, the event triggering the X is address incrementing, not the clk and load signals. Since out isn't registered and isn't associated with clk, as soon as address changes you see the value at that address appear on out. Then after the clock edge that writes a new value, you see out change to that value at the same time.






      share|improve this answer


























        2












        2








        2







        In both cases, the X values coming out are are the initial values of ram (which are X since you didn't assign any initial values). If you continued the test and cycled through the same addresses, the next time around you'd see the values you previously wrote.



        In the first example, the concurrent read and write isn't an issue. The read is returning the value from before the clock edge, and ram will contain the new value after the clock edge.



        In the second example, the event triggering the X is address incrementing, not the clk and load signals. Since out isn't registered and isn't associated with clk, as soon as address changes you see the value at that address appear on out. Then after the clock edge that writes a new value, you see out change to that value at the same time.






        share|improve this answer













        In both cases, the X values coming out are are the initial values of ram (which are X since you didn't assign any initial values). If you continued the test and cycled through the same addresses, the next time around you'd see the values you previously wrote.



        In the first example, the concurrent read and write isn't an issue. The read is returning the value from before the clock edge, and ram will contain the new value after the clock edge.



        In the second example, the event triggering the X is address incrementing, not the clk and load signals. Since out isn't registered and isn't associated with clk, as soon as address changes you see the value at that address appear on out. Then after the clock edge that writes a new value, you see out change to that value at the same time.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 29 '18 at 2:15









        Justin NJustin N

        212




        212






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965441%2fhow-is-iverilog-simulator-interpreting-my-ram-code-to-determine-x-values%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Monofisismo

            Angular Downloading a file using contenturl with Basic Authentication

            Olmecas