Бесконечный цикл при моделировании дизайна счетчика программ с помощью Icarus Verilog
Я реализую простой сумматор счетчика программ со следующим прототипом:
module program_counter(input enable_count,
input enable_overwrite,
input[31:0] overwrite_value,
output[31:0] out);
При моделировании с Icarus Verilog я получаю бесконечный цикл при первом тике, на котором перезапись отключена и счетчик включен, поэтому внутренний регистр запитывается с выхода сумматора ПК (ПК + 4).
Я упростил проблему до базового кода с помощью D-триггера, используемого в качестве 1-битного регистра:
module register(input in, input set, output out);
wire not_in;
wire q0;
wire not_q0;
wire not_q;
nand (q0, in, set);
not (not_in, in);
nand (not_q0, not_in, set);
nand (out, q0, not_q);
nand (not_q, not_q0, out);
endmodule
module test;
reg clock;
reg in;
wire out;
wire not_out;
xor (x_out, out, 1); // add
or (muxed_out, x_out, in); // mux
register r(muxed_out, clock, out);
initial
begin
$dumpfile("test.vcd");
$dumpvars(0, test);
$display("\tclock,\tin,\tout");
$monitor("\t%b,\t%x,\t%b",
clock, in, out);
#0 assign in = 1; // erase register
#0 assign clock = 1;
#1 assign in = 0;
#1 assign clock = 0;
#2 assign clock = 1;
#3 assign clock = 0;
#4 assign clock = 1;
end
endmodule
Выход VCD не показывает никаких изменений состояния после застревания симуляции.
Я предполагаю, что на определенном тике сумматор постоянно подает другое значение (непрерывно добавляя), поэтому, поскольку он нестабилен, симулятор ждет, пока значение не будет зафиксировано, и застревает.
Является ли этот дизайн правильным (т.е. может быть синтезирован и должен работать)?
1 ответ
Существует комбинационный цикл: выход "регистра" возвращается на вход через тестируемые xor/ или вентили. Вы по сути создали кольцевой генератор.
Если вы добавите следующий код в регистр, вы увидите, что это происходит:
always @(in) $display("@%d: in = %d", $time, in);
Вы увидите кучу таких, когда запустите интерпретатор:
@ 1: in = 1
@ 1: in = 0
@ 1: in = 1
@ 1: in = 0
Похоже, вы пытаетесь сделать активную защелку в "регистре". Это то, что вы хотели? Триггер с триггером - обычная практика в синхронном дизайне. Для этого вам понадобятся две защелки, но стандартный (и гораздо более простой) способ сделать это в Verilog такой:
reg my_flop;
always @(posedge clk)
my_flop <= input;
Если вы действительно хотите защелку, она может быть выведена следующим образом (но она, как правило, подвержена ошибкам и обычно не рекомендуется):
always @(clk, input)
begin
if (clk)
my_flop = input;
end
Есть ли причина, по которой вы пытаетесь создать их вручную с помощью gates?