12.31 Signalbitbreitenkonvertierung (Ganzzahl, Nicht-Ganzzahl), Taktfrequenzteilung (ungerade Zahl, gerade Zahl, beliebige Dezimalzahl, Arbeitszyklus), Verkaufsautomat (1, 2), Spielekonsole

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

Supongo que te gusta

Origin blog.csdn.net/m0_73553411/article/details/135317971
Recomendado
Clasificación