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
War es hilfreich?

Lösung

Zunächst einmal, vergessen Sie nicht Ihren begin-ends 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 ...

betrachtet

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top