Frage
Ich bin sehr neu zu HDL-Sprache. Ich habe eine Frage, wie ein Schieberegister zu programmieren. (Ich weiß, ich Verschiebung in die andere Richtung). Warum funktioniert die Verwendung wire[N-1:0] r_next
Buch? was Nachteil meiner Implementierung?
Dank
mein erster Versuch ist, wie folgend
module lesson04#(parameter N=8)(
input wire clk, reset,
input wire data,
output wire out
);
reg [N-1: 0] r_reg;
always @(posedge clk or negedge reset)
begin
if(!reset)
r_reg =0;
else
r_reg[0]=data;
r_reg = r_reg<<1;
end
assign out =r_reg[N-1];
endmodule
aber das Buch gibt:
module lesson04#(parameter N=8)(
input wire clk, reset,
input wire data,
output wire out
);
reg [N-1: 0] r_reg;
wire[N-1:0] r_next;
always @(posedge clk or negedge reset)
begin
if(!reset)
r_reg =0;
else
r_reg <= r_next;
end
assign r_next= {data, r_reg[N-1:1]};
assign out =r_reg[N-1];
endmodule
Lösung
Zunächst einmal, vergessen Sie nicht Ihren begin
-end
s um Codeabschnitte:
else begin
r_reg[0]=data;
r_reg = r_reg<<1;
end
Ohne diese nur r_reg[0]=data
wird in der else
Klausel der if
Anweisung sein. Dies funktioniert, ist aber schlechter Stil aufgrund der Sperrung Aussagen in einer sequentiellen Logikbeschreibung ...
Zweitens, für die Modellierung sequentielle Blöcke, die Verwendung nicht-blockierenden Zuweisungen (<=
) oder Ihre Berechnungen können ‚fallen durch‘ (google nicht blockierend vs für weitere Informationen zu blockieren). Ihr Beispiel kann sehr gut Arbeit (haben Sie es in einem Simulator versuchen?), Aber wenn die Dinge komplizierter und Variablen hinzugefügt Dinge brechen kann.
always @(posedge clk or negedge reset)
begin
if(!reset)
r_reg <= 0;
else begin // This is horrible! Don't write code like this!
r_reg[0] = data; // blocking
r_reg <= r_reg<<1; // non-blocking
end
end
Aus dem obigen Grunde ist es manchmal empfohlen, Combo-Logik von sequentieller Logik getrennt ist, so dass Sie Zuordnungen zu den Registern in aufeinanderfolgenden Blöcken nicht blockierend schreiben können, und in Combo-Blöcken blockieren und nie Sorgen über die Terminplanung haben.
Um Code auf diese Weise, müssen Sie berechnen, was die nächste Ausgabe soll den aktuellen Stand verwenden, damit die r_next
Bus in der Antwort. Ich denke, es neigt auch das Synthese-Tool, um zu helfen, wenn alle die Flip-Flops aus dem umliegenden Combo Logik auf diese Weise getrennt sind.
Auch, wenn Ihr Reset aktiv niedrig ist (dh LOW
Resets) sollte als solche, zB resetb
oder reset_n
genannt werden.
Andere Tipps
Ihre Implementierung erzeugt eine ganz andere Ausgabe aus dem Buch. Sie sollten dies durch die Konstruktion eines einfachen Prüfstand selbst nachprüfen, um Ihre Eingaben zu fahren und eine Simulation laufen. Sie werden sehen, dass die Eingangsdaten Ausgangsverschiebungen Buch von einem einzigen Taktzyklus, während die Ausgabe verschiebt die Eingangsdaten von acht Taktzyklen.
Durch die Art und Weise Sie Ihren always
Block eingekerbt haben, bin ich zu glauben, dass es nicht das, was Sie wollten. Dies ist, wie Sie Ihren Block wirklich verhält:
always @(posedge clk or negedge reset)
begin
if(!reset) begin
r_reg =0;
end else begin
r_reg[0]=data;
end
r_reg = r_reg<<1;
end
ich immer explizit die begin/end
Schlüsselwörter in if/else
Aussagen verwenden diese Verwirrung zu vermeiden.
Die Art und Weise simuliert, r_reg
ist immer 0, weil Sie die erste Zuordnung clobber (r_reg[0]=data;
) mit dem zweiten (r_reg = r_reg<<1;
). Ein weiterer Unterschied ist, dass die Buchabtretungsempfänger zu dem MSB des Schieberegisters data
, aber Sie weisen es den LSB.
Wenn Sie anständige Fusseln und die Synthese-Tools verwenden, würden Sie wahrscheinlich eine Reihe von Warnungen für Ihren Code. Dies würde alarmieren Sie einige Änderungen vornehmen.