Бесконечный цикл при моделировании дизайна счетчика программ с помощью 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?

Другие вопросы по тегам