Я пытаюсь написать и протестировать простой 16-разрядный чип RAM8 в Verilog с использованием Icarus Verilog.Мне трудно понять концептуально, почему симулятор iverilog показывает мне значения 'x' (неопределенные) на определенных тактах и задается вопросом, может ли кто-нибудь дать концептуальное понимание этой проблемы.
Я пыталсядве разные конструкции, одна из которых имеет смысл для вывода, но я не могу разобрать вывод второй.
Первый дизайн делает регистр out
, и назначение для выхода синхронизируется:
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
- это непрерывно назначенный провод:
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
Испытательный стенд для них обоих одинаков:
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
Мой вывод на тестовом стенде для первого проекта такой:
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
Этот вывод имеет смысл для меня.Каждый раз, когда я загружаю новое значение, вывод не определен, потому что загрузка происходит одновременно со значением, которое загружается, будучи синхронизированным в регистр вывода (следовательно, значения мусора для этого такта).
Однаковывод для тестового стенда для второго дизайна меня смущает:
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, но ничто из того, что я могу вспомнить из своего понимания регистров, не объясняет, почему это приведет к тому, что вывод будет мусором.Все регистры в моей схеме запускаются по положительному фронту тактового сигнала, так почему же отрицательный фронт меняет какое-либо значение?
Я полагаю, что в целом я могу быть смущен тем, что здесь происходит под капотом, и также был бы признателен, если бы кто-то подтвердил или опроверг мое объяснение поведения первого проекта.Заранее спасибо всем, кто нашел время, чтобы прочитать и ответить.