Что я делаю не так? Тестовый модуль не обновляется правильно

#verilog #fpga #quartus #intel-fpga

#verilog #fpga #quartus #intel-fpga

Вопрос:

Я пытаюсь реализовать тестовый стенд так, чтобы после 3 тиков каждый ввод получал новое указанное значение. Например, первые 3 секунды (или тики) A = 10, B = 0, а затем следующие 3 секунды (от 3 секунд до 6 секунд) A = 10, B = 16 и т.д. Однако на моем реальном тестовом стенде значения обновляются не так, как я хочу. Я неправильно понимаю синтаксис?

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

https://gyazo.com/f2c0cddc192d0d6734c98334cd377f12

 module ALU_tb();

reg [63:0] A, B;
reg [4:0] FS;
reg cin;

wire cout;
wire [63:0] resu<
wire [3:0] status;


     
     Final_ALU dut (
     .A(A),
     .B(B),
     .FS(FS),
     .cin(cin),
     .cout(cout),
     .result(result),
     .status(status)
                    );

initial begin //A 1 //A=10 B=0
A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
B <= 64'b0000000000000000000000000000000000000000000000000000000000000000;
FS <= 5'b01000;
cin <= 1'b1;
end

always begin //A B //A=10 B=16
#3
A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
B <= 64'b0000000000000000000000000000000000000000000000000000000000010000;
FS <= 5'b01000;
cin <= 1'd0;
#3;
end

always begin //A-B //A=10 B=16
#6
A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
B <= 64'b0000000000000000000000000000000000000000000000000000000000010000;
FS <= 5'b01001;
cin <= 1'd1;
#6; 
end

always begin //A-1 //A=10 , B=1
#9
A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
B <= 64'b0000000000000000000000000000000000000000000000000000000000000001;
FS <= 5'b01001;
cin <= 1'd1;
#9; 
end

always begin //-A //A=10 , B=0 (just twos complement of A)
#12
A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
B <= 64'b0000000000000000000000000000000000000000000000000000000000000000;
FS <= 5'b01010;
cin <= 1'd1;
#12; 
end


initial begin
#30 $finish;
end
endmodule
 

Ответ №1:

Вы не должны назначать один и тот же сигнал из нескольких always блоков.

Один из способов решить проблему — использовать a fork/join внутри initial блока an и избавиться от always ключевых слов. Это вносит минимальные изменения в ваш код:

 initial begin
    fork
        begin //A 1 //A=10 B=0
        A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
        B <= 64'b0000000000000000000000000000000000000000000000000000000000000000;
        FS <= 5'b01000;
        cin <= 1'b1;
        end

        begin //A B //A=10 B=16
        #3
        A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
        B <= 64'b0000000000000000000000000000000000000000000000000000000000010000;
        FS <= 5'b01000;
        cin <= 1'd0;
        #3;
        end

        begin //A-B //A=10 B=16
        #6
        A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
        B <= 64'b0000000000000000000000000000000000000000000000000000000000010000;
        FS <= 5'b01001;
        cin <= 1'd1;
        #6; 
        end

        begin //A-1 //A=10 , B=1
        #9
        A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
        B <= 64'b0000000000000000000000000000000000000000000000000000000000000001;
        FS <= 5'b01001;
        cin <= 1'd1;
        #9; 
        end

        begin //-A //A=10 , B=0 (just twos complement of A)
        #12
        A <= 64'b0000000000000000000000000000000000000000000000000000000000001010;
        B <= 64'b0000000000000000000000000000000000000000000000000000000000000000;
        FS <= 5'b01010;
        cin <= 1'd1;
        #12; 
        end
    join
end
 

Более традиционным подходом было бы избавиться от fork , и просто последовательно управлять всеми группами сигналов внутри initial блока. Тогда вам придется соответствующим образом скорректировать все свои # задержки.