DFF в Verilog с задержкой

Я пытаюсь реализовать проект nand2tetris в Verilog, и я врезаюсь в стену, используя icarus verilog. В книге они реализуют DFF так, q(t) = d(t-1). Выход в текущий момент - это вход в предыдущем posedge clk. Вот это DFF, которое я понял.

module Dff (
    output reg q,
    input data, clk
);

    reg p;
    reg o;

    always @(posedge clk) begin
        o <= data;
        q <= p;
    end

    always @(negedge clk) begin
        p <= o;
    end

endmodule

Этот DFF, кажется, работает нормально, когда я тестирую его напрямую. Но когда я повторно использовал его для создания бита (ячейки памяти), это сошло с ума. Интересно, что безумие отличается от использования Icarus Verilog или EDAPlayground (который использует VCS).

module Mux (out, a, b, sel);
    input a, b;
    input sel;
    output reg out;

    assign out = ~sel ? a : b;
endmodule

module Bit (
    output out,
    input data, load, clk
);

    Mux m0(in, out, data, load);
    Dff d0(out, in, clk);
endmodule

Вывод Icarus Verilog

 data | load | clk | out
------+------+-----+-----
    0 |    1 |   1 |   x
    0 |    1 |   0 |   x
    1 |    1 |   1 |   x
    1 |    1 |   0 |   x
    0 |    1 |   1 |   1
    0 |    1 |   0 |   1
    0 |    0 |   1 |   0
    0 |    0 |   0 |   0
    1 |    1 |   1 |   0
    1 |    1 |   0 |   0
    0 |    0 |   1 |   0   # !?!?!
    0 |    0 |   0 |   0   # it should be 1 here.

EDAPlayground вывод

 data | load | clk | out
------+------+-----+-----
    0 |    1 |   1 |   x
    0 |    1 |   0 |   x
    1 |    1 |   1 |   x
    1 |    1 |   0 |   x
    0 |    1 |   1 |   1
    0 |    1 |   0 |   1
    0 |    0 |   1 |   0
    0 |    0 |   0 |   0
    1 |    1 |   1 |   1  # !?!?!
    1 |    1 |   0 |   1  # it should be 0 here.
    0 |    0 |   1 |   1
    0 |    0 |   0 |   1

Код можно протестировать на EDAPlayground.


person greut    schedule 17.08.2015    source источник
comment
Я бы сказал, что ваш DFF работает некорректно, так как при синтезе он использует три D-триггера.   -  person Qiu    schedule 17.08.2015
comment
Я не знаю, смогу ли я правильно объяснить, что происходит в обоих случаях, но я сведу это здесь: потому что вы не используете неблокирующее назначение для своего блока initial (т.е. load <= 0, а не load = 0, относитесь к нему как к выходу из другого где-нибудь зарегистрируйтесь), порядок симуляции различных блоков в вашем дизайне (always в DFF, assign в Mux и always блок синхронизации и initial блок стимула) имеет значение. Т.е., когда обновления из блока initial происходят, не происходят, когда вы этого хотите, из-за назначения блокировки.   -  person Unn    schedule 17.08.2015
comment
DFF обычно чувствителен к одному краю часов, будь то позу или неровность. Почему вы используете оба?   -  person Ari    schedule 17.08.2015
comment
Ваш DFF выглядит почти как защелка. q (t) = d (t-1) - это просто always @(posedge clk) begin q <= data; end. Как указал Унн, ваши data и load стимулы должны быть неблокирующими, чтобы они не вызывали состояние гонки с часами. В качестве альтернативы можно добавить небольшую задержку для одновременного воспроизведения. Точка, являющаяся новыми значениями стимулов, должна быть обновлена ​​по истечении времени.   -  person Greg    schedule 17.08.2015
comment
Подводя итог: мои тестовые примеры плохо спроектированы, поэтому код дерьмовый, а поведение трудно предсказуемо. Большой ТА!   -  person greut    schedule 17.08.2015


Ответы (1)


Спасибо Ууну и Грегу, вот как я решил проблему. Код находится на игровой площадке EDA

DFF может быть проще.

module Dff (
    output reg q,
    input data, clk
);
    always @(posedge clk) begin
        q <= data;
    end
endmodule

Тогда виноваты тесты. Блокировка заданий вызывает путаницу. Простой способ исправить это - заменить все = на <= следующим образом:

module Bit_tb;
    reg clk = 0;
    reg data = 0;
    reg load = 1;
    wire out;

    initial begin
        #2
        data <= 1;

        #2
        load <= 0;  // load = 0; /!\ would be blocking before
        data <= 0;  // data = 0; doing this line. /!\

        #2
        $finish;
    end
endmodule
person greut    schedule 20.08.2015