Nicht-ganzzahlige Konvertierung mehrerer Datenbitbreiten von 8 zu 12
Das sogenannte nicht ganzzahlige Vielfache besteht darin, einen cnt zu verwenden, um regelmäßig zu bestimmen, wie das Register ausgegeben wird. Der Wert dieses cnt ist das kleinste gemeinsame Vielfache.
Das Register wird normal registriert. Wie erfolgt die Eingabe und Registrierung?
`timescale 1ns/1ns
module width_8to12(
input clk ,
input rst_n ,
input valid_in ,
input [7:0] data_in ,
output reg valid_out,
output reg [11:0] data_out
);
reg[7:0]data_lock;
reg[1:0]valid_cnt;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
data_lock<=0;
else if(valid_in)
data_lock<=data_in;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
valid_cnt<=0;
else if(valid_in)begin
if(valid_cnt==2'd2)
valid_cnt<=0;
else
valid_cnt<=valid_cnt+1;
end
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
valid_out<=0;
else if(valid_in&&valid_cnt==1)
valid_out<=1;
else if(valid_in&&valid_cnt==2)
valid_out<=1;
else
valid_out<=0;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
data_out<=0;
else if(valid_in&&valid_cnt==1)
data_out<={data_lock,data_in[7:4]};
else if(valid_in&&valid_cnt==2)
data_out<={data_lock[3:0],data_in};
end
endmodule
Warum brauchen Sie nicht zwei 8-Bit-Register für das Daten-Caching:
Gemäß dem Zeitdiagramm generiert data_out im nächsten Taktzyklus nach zwei Dateneingaben eine Ausgabe. Wenn zwei Register zum Zwischenspeichern von zwei Daten verwendet werden, müssen die Daten ausgegeben werden, bevor die zweiten Daten im Register zwischengespeichert werden. Dies kann die Anforderungen nicht erfüllen . Datenausgabe für Timing-Anforderungen.
Gemäß dem Zeitdiagramm werden Daten ausgegeben, nachdem die zweiten Daten eintreffen. Wenn nur ein Datenwert eintrifft, wird keine Ausgabe generiert, sodass intern ein Zähler (valid_cnt) entwickelt wird, der den Datenempfangsstatus anzeigt. Wenn erkannt wird, dass valid_in auf High gesetzt wird, erhöht sich valid_cnt um 1, valid_cnt wechselt zwischen 0 und 2 und der Rücksetzwert von valid_cnt ist 0. Wenn valid_cnt 1 oder 2 ist und valid_in hoch ist, werden Daten ausgegeben und valid_out auf hoch gesetzt.
Wenn valid_cnt==1 und valid_in hoch ist, ist data_out <= {data_lock, data_in[7:4]}; wenn valid_cnt==2 und valid_in hoch ist, ist data_out <= {data_lock[3:0], data_in}.
Das heißt, beim Zurücksetzen befindet sich niemand im Register und kann daher nicht ausgegeben werden. Nach dem Speichern ist es 1 und kann dann ausgegeben werden. Zu diesem Zeitpunkt werden die 8 gespeicherten ausgegeben und die ersten 4 neu eingegebenen. Und geben Sie 2 ein, was bedeutet, dass die zweite Eingabe zu diesem Zeitpunkt im Register gespeichert wird und die erste Hälfte ausgegeben wurde und die letzten vier ausgegeben werden sollten, sodass die Ausgabe zu diesem Zeitpunkt erfolgt Die letzten vier des Ausgaberegisters und die neue Eingabe. Zu diesem Zeitpunkt ist das Innere des Registers tatsächlich gleichbedeutend mit Leersein.
Mit anderen Worten, valid_cnt bestimmt das Ausgangssignal und wie das Signal im Register verarbeitet wird
Schaltplan
Das heißt, die sequentielle Logik erfordert die Verwendung von Flip-Flops. <=Das direkteste ist das D-Flip-Flop.
Ganzzahlige Konvertierung mehrerer Datenbitbreiten von 8 bis 16
`timescale 1ns/1ns
module width_8to16(
input clk ,
input rst_n ,
input valid_in ,
input [7:0] data_in ,
output reg valid_out,
output reg [15:0] data_out
);
reg[0:0]cnt;
reg[7:0]ram;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
cnt<=0;
else if(valid_in)
cnt<=(cnt)?0:1;
else
cnt<=cnt;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
ram<=0;
else if(valid_in)
ram<=data_in;
else
ram<=ram;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
data_out<=0;
valid_out<=0;
end
else if(cnt&&valid_in)begin
data_out<={ram,data_in};
valid_out<=1;
end
else begin
data_out<=data_out;
valid_out<=0;
end
end
endmodule
Beachten Sie, dass der Status vor dem Latch automatisch generiert wird, wenn die if-Bedingung weggelassen wird.
Schaltplan
QN steht für Antistaat, also Negation
Eine leere Zeile bedeutet, dass das entsprechende Signal nicht verwendet wird, also keine Folgeausgabe erfolgt.
Die einfache Logik besteht darin, ein einfaches D-Flip-Flop zu erzeugen
Das D-Signal ist hier das Signal, das den aktuellen Q-Zustand des Flip-Flops steuert. Nach einiger Verarbeitung wird es zu einem Zwei-Wege-Selektor, und dann befindet sich darüber ein UND-Gatter; darüber gibt es kein Signal, da es sich um ein zwischengespeichertes Signal handelt ist ein 8-Bit-Signal, nicht 0 oder 1.
Taktteiler (gerade
`timescale 1ns/1ns
module even_div
(
input wire rst ,
input wire clk_in,
output wire clk_out2,
output wire clk_out4,
output wire clk_out8
);
//*************code***********//
reg clk2,clk4,clk8;
always@(posedge clk_in,negedge rst)begin
if(!rst)
clk2<=0;
else
clk2<=~clk2;
end
always@(posedge clk2,negedge rst)begin
if(!rst)
clk4<=0;
else
clk4<=~clk4;
end
always@(posedge clk4,negedge rst)begin
if(!rst)
clk8<=0;
else
clk8<=~clk8;
end
assign clk_out8=clk8;
assign clk_out4=clk4;
assign clk_out2=clk2;
//*************code***********//
endmodule
D-Flip-Flop
Das D-Flip-Flop erstellt einen Schaltplan, der <= Die rechte Seite ist das Eingangs-D-Signal und die linke Seite ist das Ausgangs-Q-Stromsignal.
Die D-Flip-Flop-Schnittstelle verfügt über das Taktsignal, das die Auslösung des Flip-Flops steuert, und das D-Signal, das das Signal auf der rechten Seite der Gleichung ist, und der Ausgang ist das umgewandelte Signal.
Ungerade Frequenzteilung mit 50 % Tastverhältnis
`timescale 1ns/1ns
module odo_div_or
#(parameter N = 7)
(
input wire rst ,
input wire clk_in,
output wire clk_out7
);
reg [3:0] cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
cnt <= 'b0 ;
end
else if (cnt == N-1) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
reg clkp ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clkp <= 1'b0 ;
end
else if (cnt == (N>>1)) begin
clkp <= 1 ;
end
else if (cnt == N-1) begin
clkp <= 0 ;
end
end
reg clkn ;
always @(negedge clk_in or negedge rst) begin
if (!rst) begin
clkn <= 1'b0 ;
end
else if (cnt == (N>>1) ) begin
clkn <= 1 ;
end
else if (cnt == N-1) begin
clkn <= 0 ;
end
end
assign clk_out7 = clkp | clkn ;
endmodule
Bei ungeraden Frequenzteilungsschaltungen liegt die Hauptschwierigkeit in der Realisierung eines Tastverhältnisses von 50 %. Es gibt keine Möglichkeit, ein Tastverhältnis von 50 % mit einer einzelnen Triggerflanke in einem ungeradzahligen Frequenzteiler zu erreichen. Daher müssen Sie die Verwendung von Doppelflanken plus kombinatorischer Logik in Betracht ziehen, um ein Tastverhältnis von 50 % zu erreichen.
Der erste Flip von clkout7 erfolgt an der steigenden Flanke und das zweite Mal an der fallenden Flanke.
Jede dezimale Frequenzteilung
Bitte entwerfen Sie einen Taktteiler, der eine beliebige dezimale Frequenzteilung erreichen kann, z. B. ein Taktsignal geteilt durch 8,7
Beachten Sie, dass es sich beim ersten Mal um einen Low-Level-Reset handelt
Hinweis:
Tatsächlich handelt es sich im Wesentlichen um ein einfaches mathematisches Problem, nämlich wie man das kleinste gemeinsame Vielfache verwendet, um das Frequenzverhältnis des Taktzyklus zu erhalten.
Die Dezimalzahl sei nn, hier nehmen wir als Beispiel den Taktzyklus geteilt durch 8,7.
Da Dezimaloperationen nicht auf Hardware ausgeführt werden können (z. B. sind 2,1 Takte unrealistisch und es gibt keine 3,3 Register), kann mit der fraktionierten Frequenzteilung nicht erreicht werden, dass nach der Teilung jeder Taktzyklus nn des Quelltakts entspricht. Mal, Es ist unmöglich, ein Tastverhältnis von 1/2 zu erreichen. Daher sollte die Implementierung unter Berücksichtigung der fraktionalen Frequenzteilung 53 clkout-Taktzyklen betragen, was dem 8,7-fachen von 10 clkin-Taktzyklen entspricht.
Tatsächlich ist es fast dasselbe wie die nicht ganzzahlige Mehrfachdatentranspositionsbreite.
Nicht ganzzahlige Vielfache der Datentranspositionsbreite verwenden einen Zähler, um aufzuzeichnen, in welcher Stufe sich die aktuelle Ausgabe befindet.
Verwenden Sie ein Register, zeichnen Sie dann das aktuelle Eingangssignal auf und führen Sie schließlich die entsprechende Ausgabe basierend auf dem Signal des Zählers in Kombination mit dem zu diesem Zeitpunkt ausgegebenen Signal aus.
Der Unterschied besteht darin, dass bei der Umwandlung nicht ganzzahliger Daten mit mehreren Bitbreiten in jedem Taktzyklus ein Signal ausgegeben wird
Der Dezimalteiler ist innerhalb einer bestimmten Zeitspanne 1 und innerhalb einer bestimmten Zeitspanne 0.
Der Frequenzteiler verlangsamt die Signalfrequenz. Früher sprang sie in 10 Sekunden zehnmal, jetzt springt sie nur noch einmal.
Die Idee besteht darin, die Simulation anzunähern. Für große Perioden wird eine dezimale Frequenzteilung verwendet. Für kleine Perioden werden ungerade Frequenzteilung und gerade Frequenzteilung zur Näherung verwendet. Anschließend wird ein Zähler verwendet, um die großen Perioden aufzuzeichnen, und ein Zähler wird verwendet, um die Simulation zu simulieren Realisieren Sie jede kleine Periode. Der Frequenzteiler im großen Zyklus bestimmt, welcher Frequenzteiler im kleinen Zyklus zu diesem Zeitpunkt verwendet wird, ob es sich um eine ungerade Zahl oder eine gerade Zahl handelt. Anschließend wird ein FLAG-Flag verwendet, um aufzuzeichnen, ob der ungerade Zahlenteiler verwendet wird oder der gerade Zahlenteiler wird derzeit verwendet. Gerät wird dieses FLAG an einem bestimmten Punkt in der Mitte und am Ende des gesamten großen Zyklus ersetzt. Ein bestimmter Punkt in der Mitte wird berechnet.
`timescale 1ns/1ns
module div_M_N(
input wire clk_in,
input wire rst,
output wire clk_out
);
parameter M_N = 8'd87;
parameter c89 = 8'd24; // 8/9时钟切换点
parameter div_e = 5'd8; //偶数周期
parameter div_o = 5'd9; //奇数周期
//*************code***********//
reg [3:0] clk_cnt;
reg [6:0] cyc_cnt;
reg div_flag;
reg clk_out_r;
always@(posedge clk_in or negedge rst) begin
if(~rst)
clk_cnt <= 0;
else if(~div_flag)
clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;
else
clk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;
end
always@(posedge clk_in or negedge rst) begin
if(~rst)
cyc_cnt <= 0;
else
cyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;
end
always@(posedge clk_in or negedge rst) begin
if(~rst)
div_flag <= 0;
else
div_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(c89-1)? ~div_flag: div_flag;
end
always@(posedge clk_in or negedge rst) begin
if(~rst)
clk_out_r <= 0;
else if(~div_flag)
clk_out_r <= clk_cnt<=((div_e>>2)+1);
else
clk_out_r <= clk_cnt<=((div_o>>2)+1);
end
assign clk_out = clk_out_r;
//*************code***********//
endmodule
Wenn Sie im Schaltplan ein Flip-Flop zeichnen, müssen Sie sich zunächst das Taktsignal ansehen und es anschließen. Anschließend müssen Sie sich das Rücksetzsignal ansehen und es anschließen. Anschließend müssen Sie entsprechend dem D-Signal das Flip-Flop auswählen -Flop. Verwenden Sie für <= das D-Flip-Flop. Die linke Seite ist das Ausgangs-Q-Stromsignal und die rechte Seite ist das Eingangs-D-Signal. Wenn Sie auf einen ternären Ausdruck oder eine Auswahl stoßen, ist es der Selektor, der wählt ein Signal aus und verbindet es mit dem D-Signal.
An den ungeraden Teiler geht kein Arbeitszyklus
Der sogenannte Duty Cycle ist das Verhältnis von 0 und 1 in einem Zyklus.
Nehmen Sie als Beispiel die Frage nach einem dezimalen Frequenzteiler. Um einen dezimalen Frequenzteiler zu implementieren, wird in einem großen Zyklus das Flag am Ende der Periode und an einem bestimmten Punkt in der Mitte aktualisiert. Der bestimmte Punkt in der Mitte bestimmt wann umgekehrt werden soll, und bestimmt auch die Belegung der Flagge. Leerverhältnis
In ähnlicher Weise entspricht im Frequenzteiler das ausgegebene Frequenzteilungssignal, wenn es umgekehrt wird, einem bestimmten Punkt in der Mitte, wird jedoch am Ende des Zyklus definitiv umgekehrt , dh wenn cnt == Frequenzteilungszahl.
Bei der Wahl des Mittelpunkts beträgt das Tastverhältnis fünfzig Prozent
`timescale 1ns/1ns
module odd_div (
input wire rst ,
input wire clk_in,
output wire clk_out5
);
//*************code***********//
reg[2:0]cnt;
reg clko;
always@(posedge clk_in,negedge rst)begin
if(!rst)
cnt<=0;
else
cnt<=cnt==4?0:cnt+1;
end
always@(posedge clk_in,negedge rst)begin
if(!rst)
clko<=0;
else
clko<=cnt<=1;
end
assign clk_out5=clko;
//*************code***********//
endmodule
Verkaufsautomat 1
Zustandsmaschine
`timescale 1ns/1ns
module seller1(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire d3 ,
output reg out1,
output reg [1:0]out2
);
parameter s0=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6;
reg[2:0]cs;
reg[2:0]ns;
wire[2:0]is;
assign is={d1,d2,d3};//将输入的控制信号并在一起
always@(posedge clk,negedge rst)begin
if(!rst)
cs<=s0;
else
cs<=ns;
end
always@(*)begin
case(cs)
s0:begin
case(is)
3'b100:ns=s1;
3'b010:ns=s2;
3'b001:ns=s4;
default:ns=ns;
endcase
end
s1:begin
case(is)
3'b100:ns=s2;
3'b010:ns=s3;
3'b001:ns=s5;
default:ns=ns;
endcase
end
s2:begin
case(is)
3'b100:ns=s3;
3'b010:ns=s4;
3'b001:ns=s6;
default:ns=ns;
endcase
end
default:begin
ns=s0;
end
endcase
end
always@(posedge clk,negedge rst)begin
if(!rst)begin
out1<=0;
out2<=0;
end
else begin
case(ns)
s3:begin
out1<=1;
out2<=0;
end
s4:begin
out1<=1;
out2<=1;
end
s5:begin
out1<=1;
out2<=2;
end
s6:begin
out1<=1;
out2<=3;
end
default:begin
out1<=0;
out2<=0;
end
endcase
end
end
endmodule
Verkaufsautomat 2
Wenn sel 0 ist, kaufen Sie das erste Getränk, und wenn sel 1 ist, kaufen Sie das zweite Getränk. Sie können es bei s3 kaufen, aber Sie können nur das erste Getränk kaufen.
Sobald es gekauft werden kann, kann der Sekundärstatus nur noch 0 sein, was die Beendigung dieser Zahlung anzeigt, und dann wird die Änderung am Ausgang ausgeführt.
Der Ausgang kann nur eine MEALY-Maschine sein, das heißt, der Ausgang bezieht sich auf den aktuellen Zustand und das Eingangssignal. Es kann keine MOORE-Maschine sein, sonst gibt es zu viele Zustände.
Es handelt sich um eine MEALY-Maschine, was bedeutet, dass der Ausgang einerseits vom aktuellen Zustand und andererseits vom Eingangssignal abhängt. Hier ist das SEL-Signal, oder Sie können eine zweistufige Formel schreiben:
Wenn Sie eine MOORE-Maschine verwenden und den sekundären Status zur Bestimmung der Ausgabe verwenden, können Sie nicht sicher sein, was Sie kaufen möchten. Sie benötigen SEL und den aktuellen Status, um gemeinsam einen Status zu bestimmen.
`timescale 1ns/1ns
module seller2(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire sel ,
output reg out1,
output reg out2,
output reg out3
);
//*************code***********//
parameter S0=0, S0_5=1, S1=2, S1_5=3, S2=4, S2_5=5, S3=6;
reg[2:0] state, nstate;
always@(posedge clk or negedge rst) begin
if(~rst)
state <= 0;
else
state <= nstate;
end
always@(*) begin
case(state)
S0 : nstate = d1? S0_5:
d2? S1:
nstate;
S0_5 : nstate = d1? S1:
d2? S1_5:
nstate;
S1 : nstate = d1? S1_5:
d2? S2:
nstate;
S1_5 : nstate = ~sel? S0:
d1? S2:
d2? S2_5:
nstate;
S2 : nstate = ~sel? S0:
d1? S2_5:
d2? S3:
nstate;
default: nstate = S0;
endcase
end
always@(*) begin
if(~rst) begin
{out1, out2, out3} = 3'b000;
end
else begin
case(state)
S0, S0_5, S1: {out1, out2, out3} = 0;
S1_5 : {out1, out2, out3} = ~sel? 3'b100: 3'b000;
S2 : {out1, out2, out3} = ~sel? 3'b101: 3'b000;
S2_5 : {out1, out2, out3} = ~sel? 3'b101: 3'b010;
S3 : {out1, out2, out3} = ~sel? 3'b101: 3'b011;
default : {out1, out2, out3} = 3'b000;
endcase
end
end
//*************code***********//
endmodule
Abrechnungsprogramm für Spielekonsolen
`timescale 1ns/1ns
module game_count
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input [9:0]money,
input set,
input boost,
output reg[9:0]remain,
output reg yellow,
output reg red
);
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
yellow <= 0;
red <= 0;
end
else begin
yellow <= remain<10&&remain;
red <= boost? remain<2: remain<1;
end
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
remain <= 0;
else if(boost)
remain <= set ? remain+money:
remain<2? remain:
remain-2;
else
remain <= set ? remain+money:
remain<1? remain:
remain-1;
end
endmodule
`timescale 1ns/1ns
module game_count
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input [9:0]money,
input set,
input boost,
output reg[9:0]remain,
output reg yellow,
output reg red
);
always@(posedge clk or negedge rst_n)begin
if(~rst_n)
remain <= 0;
else begin
if(boost==0)
remain <= set==1? remain+money: remain-1;
else if(boost==1)
remain <= set==1? remain+money: remain-2;
end
end
always@(posedge clk or negedge rst_n)begin
if(~rst_n)begin
yellow <= 0;
red <= 0;
end
else begin
if(remain < 1)begin
yellow <= 0;
red <= 1;
end
else if(remain < 10)begin
yellow <= 1;
red <= 0;
end
else begin
yellow <= 0;
red <= 0;
end
end
end
endmodule