Ich versuche, einen 40-MHz-Takt auf einem 100-MHz-FPGA zu generieren, und ich finde es eine Art Kampf mit Verilog-Code.
Ich habe die Uhr auf einen Pin umgeleitet, um die 100-MHz-Funktionalität zu überprüfen:
assign pin1= clock; //gives me a 100MHz clock
assign pin2= ~clock; //gives me a 100MHz inverse clock
Der always
Block:
reg clock1;
reg [4:0] prescaler1;
always @(posedge clk) begin
if(reset==1'b1)begin
clock1=1'b0;
prescaler1=2'b0;
end else begin
if(prescaler1==2'b01) begin
clock1=~clock1;
prescaler1=1'b0;
end else begin
prescaler1=prescaler1+1'b1;
clock1=clock1;
end
end
end
Das gibt mir 50, 25, 16,66 und 12,5 MHz, je nachdem, ob der Prescaler auf 0, 1, 2, 3 eingestellt ist.
Gibt es dafür einen Trick?
Es ist ein Zedboard Zynq-7000 Z-7020. Mit XPS können Sie 4 PL-Fabric-Clocks zuweisen, aber ich glaube, sie müssen in Vielfachen von 33 MHz liegen.
Was ist der Unterschied zwischen ARM_PLL, IO_PLL und DRR_PLL?
Der einfache Prescaler, den Sie implementiert haben, folgt der Formel
Viele FPGAs enthalten spezialisierte Takterzeugungsblöcke wie PLL (Phase-Locked Loop). Hierbei handelt es sich um eine spezialisierte analoge Schaltung, die in FPGA-Silizium implementiert ist und so konfiguriert werden kann, dass sie mit einem schnelleren internen Takt als dem angewendeten Master-Takt läuft. Der externe 100-MHz-Takt kann also auf 200 MHz oder vielleicht bis zu 400 MHz verdoppelt werden. Die PLL verwendet ein Regelkreisprinzip ähnlich dem eines Operationsverstärkers, um aus einer stabilen externen Referenz mit niedrigerer Frequenz eine stabile höhere interne Frequenz zu erzeugen.
Einige Xilinx-FPGAs verfügen über DCM (Digital Clock Manager). Altera nennt so etwas eine "Megafunktion", wenn ich mich richtig erinnere, sollte es eine Megafunktion für PLL geben. Hängt davon ab, welches FPGA Sie verwenden. Konsultieren Sie das Hauptdatenblatt des FPGA.
Wenn Sie keine PLL haben, benötigen Sie einen durch 5 teilenden Zähler (bis 20 MHz), eine um 1,5 Zyklen verzögerte Version desselben (verwenden Sie die entgegengesetzte Taktflanke für 0,5 Zyklen) und ein XOR-Gatter (mit der korrigierten Version , ein ODER-Gatter reicht aus, da beide Signale nie gleichzeitig '1' sind)
Dadurch erhalten Sie ein 40-MHz-Signal mit einem konstanten Tastverhältnis von 40 % (aber nicht 50 % ... bearbeitet!).
NB: Das ODER-Gatter fügt einer geraden Taktteilung einen gewissen Versatz hinzu. Wenn Ihr FPGA über DDR-Register verfügt, können Sie das bereinigen.
process(clk)
variable count : natural range 0 to 4;
begin
if rising_edge(clk) then
if count = 4 then
count := 0;
clk_20 <= '1';
else
count := count + 1;
clk_20 <= '0';
end if;
clk_20d1 <= clk_20; -- delay, thanks to signal assignment semantics
end if;
end process;
process(clk)
begin
if falling_edge(clk) then
clk_20d15 <= clk_20d1; -- +0.5 cycle delay
end if;
end process;
clk_40 <= clk20 or clk_20d15;
Sollte einfach in Verilog zu übersetzen sein.
Ja, dafür gibt es einen Trick. Dies wird als Fractional Clock Division bezeichnet und oft mit einem Dual-Modulus-Prescaler durchgeführt .
Hier ist eine Webseite mit Beispielcode in VHDL (sorry, kein Verilog): Fractional-Clock-Division-Dual-Modulus
Mit diesen Techniken können Sie ein 40-MHz-Signal aus Ihrem 100-MHz-Takt herausholen, aber beachten Sie, dass der Jitter zunimmt und Sie möglicherweise ein Signal erhalten, das kein Tastverhältnis von 50 % hat.
Da Sie an einem FPGA arbeiten: Prüfen Sie, ob Ihr FPGA einen Digitaluhr-Manager enthält. Dies sind Hardware-Blöcke, die aus einem vorhandenen Takt eine Vielzahl von Frequenzen erzeugen können, indem sie die Frequenz zuerst multiplizieren und dann dividieren. Sie erhalten eine bessere Leistung aus einem Digitaluhr-Manager als aus einem handgeschriebenen Dual-Modulus-Prescaler.
Der beste Weg wäre eine PLL, wie in den anderen Antworten erwähnt - mit 4 multiplizieren, dann durch 10 dividieren. Sie könnten x2/5 tun, aber das bringt Ihnen keine 50% Einschaltdauer (möglicherweise kein Problem).
Aber um diese hinzuzufügen, gibt es eine zweite Option, wenn keine PLL verfügbar ist, die nicht empfohlen wird, da sie auf asynchroner Logik beruht. Das würde ungefähr so gehen:
wire clock2x;
wire clock2xDelay;
assign clock2x = clock100M ^ clock2xDelay;
assign clock2xDelay = ...; //I need to be clock2x delayed by about 5ns
reg [2:0] divider;
always @ (posedge clock2x or posedge reset) begin
if (reset) begin
divider <= 3'b0;
end else if (divider == 3'd4) begin
divider <= 3'b0;
end else begin
divider <= divider + 3'b1
end
end
assign clock50M = divider[1]; // 40% Duty cycle, 50MHz clock
Der obige Code ist nicht ganz vollständig - Sie werden feststellen, dass clock2xDelay noch nicht fertig ist. Im Grunde muss hier das Interessante passieren und es hängt von Ihrem Gerät ab. Sie müssen grundsätzlich genügend Verzögerung hinzufügen (durch Carry-Chain-Verzögerung, LUT-Verzögerungen usw.), damit das XOR einen Impuls erzeugt, der breit genug ist, um keine Timing-Fehler mit minimaler Impulsbreite zu verursachen. Dem Synthesizer muss auch gesagt werden, dass er die Verzögerungskette nicht wegoptimieren soll.
Dieser Code wird nicht empfohlen, da die asynchrone Verzögerung mit der Temperatur und den Geräteeigenschaften variiert und somit zu einer zittrigen Uhr führt.
Andi aka
Polynom
Paebbels