2016-10-10 4 views
0

Ich habe folgendes MWE:Verilog: Draht-Wert nicht aktualisiert

module test(
    input wire clock, 
    input wire start 
); 

reg [7:0] x = 8'b10101010; 
reg processing = 0; 
wire [7:0] x_wire0 = x; 
wire [7:0] x_wire1 = {4'hf, x}; 
wire [11:0] x_wire2 = {4'hf, x}; 

always @(posedge clock) begin 
    if (start & ~processing) begin 
     x = 8'h0f; 
     processing = 1; 
    end 

    $display("---> x=%h x_wire0=%h x_wire1=%h x_wire2=%h", 
     x, x_wire0, x_wire1, x_wire2); 
end 
endmodule 

mit dem Prüfstand

module test_test(); 

reg clock = 0; 
reg start = 0; 

test test(
    .clock(clock), 
    .start(start) 
); 

always #5 clock = ~clock; 

initial begin 
    $monitor("%b %b", clock, start); 

    #20 start = 1; 
    #20 start = 0; 

    #200 $finish; 
end 
endmodule 

die Icarus Verilog 0.9.7 gibt mir die Ausgabe

0 0 
---> x=aa x_wire0=aa x_wire1=aa x_wire2=faa 
1 0 
0 0 
---> x=aa x_wire0=aa x_wire1=aa x_wire2=faa 
1 0 
0 1 
---> x=0f x_wire0=0f x_wire1=aa x_wire2=f0f 
1 1 
0 1 
---> x=0f x_wire0=0f x_wire1=0f x_wire2=f0f 
1 1 
0 0 
... 

Ich frage mich, warum x_wire1 erst beim nächsten Tick-Tick aktualisiert wird und ob es irgendwelche Regeln gibt, um diese Art von Situationen zu vermeiden. Wenn ich vor dem Anzeigebefehl eine "# 0" verwende, wird sie aktualisiert.

+0

Verwenden Sie nichtblockierende Zuweisungen in sequenzieller Logik: 'x <= 8'h0f; processing <= 1; ' – toolic

+0

Es gibt blockierende Zuweisungen im selben' always' Block, die 'x_wire1' auf ihrem RHS haben. Ich habe diesen Code nicht in den Beispielcode aufgenommen, um ihn minimal zu halten. Ich habe mal gelesen, dass nicht blockierende Zuweisungen und blockierende Zuweisungen nicht im selben "always" -Block gemischt werden sollten. – apriori

+0

Sie sollten blockierende und nicht blockierende Zuweisungen nicht mit der _same_Variablen mischen. –

Antwort

1

Wenn Sie Ihre zu $strobe ändern, erhalten Sie die Ergebnisse, die Sie suchen. Es ist wirklich eine Race-Bedingung in der Simulation, wenn die Drähte eine Chance haben, vor der aktualisiert werden. $strobe verzögert seine Ausgabe bis zum Ende des Zeitfensters, nachdem sich die Kabel stabilisiert haben. Die Zuordnungen zu den Leitungen sind im Wesentlichen unabhängige Prozesse.

Eine andere Option ist die Verwendung nicht blockierender Zuweisungen zu x. Sie sollten immer Nicht-Block-Zuweisungen zu Variablen in sequentieller Logik verwenden, die ohnehin von einem anderen Prozess gelesen werden. Dann druckt Ihr $ -Display immer Werte aus dem vorherigen Taktzyklus.

Und schließlich können Sie einen anderen always Block nur für die Anweisung verwenden, die die negative Flanke der Uhr verwendet.

+0

Mein Problem ist, dass ich (blockierend) 'x' zuweiße und unten Drähte benutze, die von' x' abhängen (wie 'x_wire1'). Es muss einen Weg geben zu wissen, wann die Drähte einen stabilen Zustand haben, bevor sie benutzt werden. – apriori

+0

Vielleicht müssen Sie erklären, warum Sie eine Aussage wie 'x_wire0 = x;' in Ihrem Entwurf benötigen. Vielleicht könnten Sie diese durch Funktionsaufrufe ersetzen. In SystemVerilog würden Sie eine Anweisung "let" verwenden. –