Как чередовать два всегда блока?

Я хотел бы разработать простой код Verilog, который содержит два блока always, выполняющихся поочередно, например, рукопожатие. Я хочу использовать два флага, do_A и do_B, чтобы управлять двумя блоками, block_A и block_B. Ожидаемый результат должен быть ABABAB... Есть ли способ исправить следующий код? Спасибо за помощь.

    module tb;
    reg clock, reset, do_A, do_B;

    initial begin clock = 0; reset = 0; #50; reset = 150; #50; reset = 0; end
    always #50 clock = ~clock;

    always @(posedge clock) begin: block_A
        if (reset) do_B <= 0;
        else if (do_A) begin
            do_B <= 0;
            $display("A");
        end 
    end

    always @(posedge clock) begin:block_B
        if (reset) do_A <= 1;
        else if (do_B) begin
            do_A <= 0;
            $display("B");
        end 
    end
endmodule

Спасибо, Весилий, следующие коды хорошо работают для достижения желаемых результатов.

always @(posedge clock) begin: Block_A
        if (reset) do_B = 0;
        else if (do_A) begin
            do_B = 0;
            $display("A");
        end 
        else do_B <= 1;
    end

    always @(posedge clock) begin:Block_B
        if (reset) do_A = 1;
        else if (do_B) begin
            do_A = 1;
            $display("B");
        end 
        else do_A <= 0;

Это кажется странным, но работает хорошо.


person gnoejh    schedule 01.07.2013    source источник


Ответы (1)


Во-первых, reset = 150; выглядит странно (опечатка?). Однако в данном контексте это работает.

У вас есть еще одна опечатка в первом последовательном always - вы (по-видимому) хотели написать:

else if (do_A) begin
    do_B <= 1;
    $display("A");
end 

Однако я считаю, что ваша главная проблема здесь заключается в том, что у вас нет предложений else (по умолчанию) в ваших последовательных блоках always.

Посмотрите на этот блок (например):

always @(posedge clock) begin:block_B
    if (reset) do_A <= 1;
    else if (do_B) begin
        do_A <= 0;
        $display("B");
    end 
end

После сброса сбросил do_A = 1; затем, предполагая, что вы исправили предыдущую опечатку, do_B станет 1, что приведет к тому, что do_A станет 0. После достижения этого состояния do_A застрянет на 0, пока вы не сбросите все.

Следующее дополнение должно исправить это (то же самое для первого блока always):

always @(posedge clock) begin:block_B
    if (reset) do_A <= 1;
    else if (do_B) begin
        do_A <= 0;
        $display("B");
    end
    else do_A <= 1; 
end

Я считаю, что ваш код с приведенными выше исправлениями будет работать, однако правильный способ описать эту функциональность — реализовать (простой) конечный автомат с 2 состояниями. Погугли это.

person Vasiliy    schedule 01.07.2013