Sequenzielle Logik mit immer
Ein früherer Artikel zeigte verschiedene Beispiele für die Verwendung eines always
Block, um kombinatorische Logik zu implementieren. Eine always
block wird auch hauptsächlich verwendet, um sequenziell zu implementieren Logik, die Speicherelemente wie Flip-Flops hat, die Werte halten können.
JK-Flip-Flop
Ein JK-Flip-Flop ist einer der vielen Typen von Flops, die zum Speichern von Werten verwendet werden, und hat zwei Dateneingänge j und k zusammen mit einem für das Zurücksetzen von rstn und einem anderen für den Takt clk. Die Wahrheitstabelle für ein JK-Flop ist unten dargestellt und wird typischerweise mit NAND-Gattern implementiert.
rstn | j | k | q | Kommentare |
---|---|---|---|---|
0 | 0 | 0 | 0 | Wenn Reset aktiviert ist, ist die Ausgabe immer null |
1 | 0 | 0 | Wert halten | Wenn sowohl j als auch k 0 sind, bleibt die Ausgabe die gleiche wie zuvor |
1 | 0 | 1 | 1 | Wenn k=1, wird die Ausgabe 1 |
1 | 1 | 0 | 0 | Wenn k=0, wird die Ausgabe 0 |
1 | 1 | 1 | Toggle-Wert | Wenn j=1, k=1 Ausgang schaltet aktuellen Wert um |
Der Verhaltens-Verilog-Code für ein JK-Flip-Flop kann wie unten gezeigt geschrieben werden
module jk_ff ( input j, // Input J
input k, // Input K
input rstn, // Active-low async reset
input clk, // Input clk
output reg q); // Output Q
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin
q <= 0;
end else begin
q <= (j & ~q) | (~k & q);
end
end
endmodule
Testbench
Deklarieren Sie zunächst alle in der Testbench verwendeten Variablen und starten Sie eine Uhr mit einem einfachen always
Block, der zum Design gefahren werden kann. Instanziieren Sie dann das Design und verbinden Sie seine Ports mit entsprechenden Testbench-Variablen. Beachten Sie, dass q vom Typ wire
ist weil es mit einem Ausgang des Designs verbunden ist, das es aktiv antreibt. Alle anderen Eingaben für das Design sind vom Typ reg
damit sie innerhalb eines prozeduralen Blocks wie initial
gefahren werden können .
Der Stimulus initialisiert zuerst alle Eingaben in das Design auf null und deaktiviert dann nach einiger Zeit das Zurücksetzen. Ein for
Schleife wird verwendet, um unterschiedliche Werte für j und k zu treiben, die zu zufälligen Zeiten getrieben werden. Wenn die Schleife fertig ist, warten Sie noch etwas und beenden Sie die Simulation.
module tb;
// Declare testbench variables
reg j, k, rstn, clk;
wire q;
integer i;
reg [2:0] dly;
// Start the clock
always #10 clk = ~clk;
// Instantiate the design
jk_ff u0 ( .j(j), .k(k), .clk(clk), .rstn(rstn), .q(q));
// Write the stimulus
initial begin
{j, k, rstn, clk} <= 0;
#10 rstn <= 1;
for (i = 0; i < 10; i = i+1) begin
dly = $random;
#(dly) j <= $random;
#(dly) k <= $random;
end
#20 $finish;
end
endmodule
Beachten Sie aus der Simulationswelle, dass der Ausgang q im Takt der Uhr seinen Wert basierend auf dem Zustand der Eingänge j und k ändert, wie in der Wahrheitstabelle angegeben.
Modulo-10-Zähler
Modulus(MOD)-Zähler zählen einfach bis zu einer bestimmten Zahl, bevor sie auf Null zurückgesetzt werden. Ein MOD-N-Zähler zählt von 0 bis N-1 und rollt dann auf Null zurück und beginnt erneut zu zählen. Solche Zähler erfordern normalerweise log2 N Anzahl von Flops zum Halten des Zählwerts. Unten ist der Verilog-Code für einen MOD-10-Zähler gezeigt, der bei jedem Clock-Clk hochzählt, solange reset rstn deaktiviert ist.
Verilog-Parameter können verwendet werden, um einen skalierbareren MOD-N-Zähler zu erstellen.
module mod10_counter ( input clk,
input rstn,
output reg[3:0] out);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
if (out == 10)
out <= 0;
else
out <= out + 1;
end
end
endmodule
Testbench
Die Testbench deklariert zuerst einige Variablen, denen einige Werte zugewiesen und zu den Designeingaben getrieben werden können. Das Zählermodul wird dann instanziiert und mit den Testbench-Signalen verbunden, die später mit einigen Werten im Stimulus angesteuert werden. Da der Zähler auch eine Uhr benötigt, wird die Testbench-Uhr mit einer always
modelliert Block. Der Stimulus setzt einfach Standardwerte zum Zeitpunkt 0 ns, deaktiviert dann das Zurücksetzen nach 10 ns und lässt das Design für einige Zeit laufen.
module tb;
reg clk, rstn;
reg [3:0] out;
mod10_counter u0 ( .clk(clk), .rstn(rstn), .out(out));
always #10 clk = ~clk;
initial begin
{clk, rstn} <= 0;
#10 rstn <= 1;
#450 $finish;
end
endmodule
Sehen Sie, dass das Zählermodul von Null bis 9 zählt, auf Null übergeht und erneut zu zählen beginnt.
Linkes 4-Bit-Schieberegister
Unten ist ein 4-Bit-Linksschieberegister gezeigt, das eine Eingabe d in LSB akzeptiert und alle anderen Bits um 1 nach links verschoben werden. Wenn beispielsweise d gleich Null ist und der Anfangswert des Registers 0011 ist, wird es 0110 bei die nächste Flanke der Uhr clk.
module lshift_4b_reg ( input d,
input clk,
input rstn,
output reg [3:0] out
);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
out <= {out[2:0], d};
end
end
endmodule
Testbench
Die Testbench folgt einer ähnlichen Vorlage wie der zuvor gezeigten, in der einige Variablen deklariert, das Designmodul instanziiert und mit den Testbench-Signalen verbunden wird. Dann wird eine Uhr gestartet und der Stimulus wird mit einem initial
zum Design getrieben Block. In diesem Testbench-Beispiel müssen verschiedene Werte von d ausgeübt werden und daher ein for
Schleife wird verwendet, um 20 Mal zu iterieren und zufällige Werte auf das Design anzuwenden.
module tb;
reg clk, rstn, d;
wire [3:0] out;
integer i;
lshift_4b_reg u0 ( .d(d), .clk(clk), .rstn(rstn), .out(out));
always #10 clk = ~clk;
initial begin
{clk, rstn, d} <= 0;
#10 rstn <= 1;
for (i = 0; i < 20; i=i+1) begin
@(posedge clk) d <= $random;
end
#10 $finish;
end
endmodule
Beachten Sie, dass jedes Bit um 1 nach links verschoben wird und der neue Wert von d auf LSB angewendet wird.
Verilog
- Tutorial - Schreiben von kombinatorischem und sequentiellem Code
- Schaltung mit Schalter
- Integrierte Schaltkreise
- Speicherprogrammierbare Steuerungen (SPS)
- Einführung in die Boolesche Algebra
- Logische Vereinfachung mit Karnaugh Maps
- Digitale Logik mit Feedback
- Verilog Mod-N-Zähler
- Verilog Grey Counter
- Immer ein glattes Finish mit Okamoto-Schleifmaschinen