Generieren Sie einen 100-Hz-Takt aus einem 50-MHz-Takt in Verilog

Ich habe ein DE0-Board mit einem 50-MHz-Takt, den ich versuche, in Verilog auf 100 Hz zu bringen. Könnte mir jemand mit dem Code helfen, dies zu tun?

Sie können eine PLL (z. B. in Qsys) verwenden, um eine Uhr zu generieren, die Sie benötigen.

Antworten (1)

Erstellen Sie einen 18-Bit-Zähler. Jedes Mal, wenn es 250.000 erreicht, schalten Sie ein Flip-Flop um. 50 MHz / 250.000 = 200 Hz. Wenn Sie einen Pin bei 200 Hz umschalten, erhalten Sie 100 Hz mit einem Arbeitszyklus von 50 Prozent. Wenn Sie nur einen Impuls mit einer Wiederholungsfrequenz von 100 Hz benötigen, bauen Sie einen 19-Bit-Zähler und erzeugen Sie einen Impuls, wenn er 500.000 erreicht.

Glücklicherweise sind 250.000 und 500.000 beide gerade ganze Zahlen. Das Erzeugen eines perfekten 50-Prozent-Tastverhältnisses mit einem ungeraden Teiler bedeutet, dass Sie den Ausgang bei einer steigenden Flanke ein- und bei einer fallenden Flanke ausschalten müssen. Auf einem Xilinx-FPGA kann dies mit einem ODDR/ODDR2 und einem Zähler mit ein wenig Kopfkratzen erfolgen, um die D0/D1-Eingänge richtig einzustellen. Dies funktioniert jedoch nur, um das Signal über einen I/O-Pin aus dem Chip zu senden, da der Ausgang eines ODDR/ODDR2 nicht innerhalb eines Designs verwendet werden kann. Ein Impuls ist jedoch wirklich alles, was Sie in einem Design brauchen.

Etwas mit einem nicht ganzzahligen Verhältnis zu erzeugen ist komplizierter. Wenn es sich um einen rationalen Bruch handelt, können Sie möglicherweise einen PLL oder DDS verwenden, um zu helfen, entweder allein oder in Kombination mit einem Zähler. Wenn es kein rationaler Bruch ist, dann hast du mehr oder weniger Pech, es sei denn, du kannst es mit einem rationalen Bruch annähern. Wenn kein PLL verfügbar ist, nicht tief genug geht oder Sie aus einer Kombination aus PLL und Zähler nicht das richtige Verhältnis erhalten, können Sie einen fraktionierten DDS verwenden. Die Idee mit einem Bruch-DDS ist, dass Sie bei jedem Taktzyklus eine Konstante zu einem Akkumulator hinzufügen und den Ausgang umschalten, wenn der Akkumulator überrollt. Dies erzeugt eine Ausgabe mit etwas Jitter, kann aber im Durchschnitt eine präzise Frequenz erzeugen. Um mit einem 32-Bit-Akkumulator eine 100-Hz-Rechteckwelle mit 50 Prozent Tastverhältnis zu erzeugen, müssen Sie lediglich 100*2^32/50e6 = 8589 addieren. 93459 ~= 8590 pro Taktzyklus. Das MSB des Akkumulators schaltet bei 50e6/(2^32*8590) = 100,00076145 Hz um. Je größer der Akkumulator, desto genauer ist dies. Die Frequenzauflösung eines 32-Bit-Akkumulators ist ziemlich gut - wenn Sie um 1 LSB nach oben oder unten gehen, erhalten Sie entweder 98,989119 oder 100,012403 Hz. Sie erhalten jedoch +/- 1 Taktperiode von sogenanntem deterministischem Jitter. Mit anderen Worten, die Flanken werden durch die Taktperiode quantisiert und könnten so bis zu 1/2 Taktperiode zu früh oder zu spät sein. Im Gegensatz zu normalem Jitter sehen Sie, wenn Sie deterministischen Jitter auf einem Oszilloskop betrachten, eine sehr bimodale Verteilung der Zykluszeiten mit zwei oder mehr diskreten Mittelwerten im Gegensatz zu einer glatten Verteilung. Da 0,00076145 ein Offset und kein Durchschnitt ist, verschiebt sich die Phase auch langsam in Bezug auf den Systemtakt.

Beispiel-Verilog zur Erzeugung von 100 Hz aus 50 MHz mit einem Tastverhältnis von 50 %:

// generate 100 Hz from 50 MHz
reg [17:0] count_reg = 0;
reg out_100hz = 0;

always @(posedge clk_50mhz or posedge rst_50mhz) begin
    if (rst_50mhz) begin
        count_reg <= 0;
        out_100hz <= 0;
    end else begin
        if (count_reg < 249999) begin
            count_reg <= count_reg + 1;
        end else begin
            count_reg <= 0;
            out_100hz <= ~out_100hz;
        end
    end
end

Beispiel-Verilog zum Erzeugen eines 100-Hz-Wiederholungsimpulses von 10 ns aus einem 50-MHz-Takt:

// generate 100 Hz pulse chain from 50 MHz
reg [18:0] count_reg = 0;
reg out_100hz = 0;

always @(posedge clk_50mhz or posedge rst_50mhz) begin
    if (rst_50mhz) begin
        count_reg <= 0;
        out_100hz <= 0;
    end else begin
        out_100hz <= 0;
        if (count_reg < 499999) begin
            count_reg <= count_reg + 1;
        end else begin
            count_reg <= 0;
            out_100hz = 1;
        end
    end
end

Beispiel-Verilog zum Generieren eines 10-MHz-Ausgangs mit 50% Arbeitszyklus aus einem 250-MHz-Takt mit einem ODDR2 auf einem Spartan 6:

// generate 10 MHz from 250 MHz
// 25 cycle counter, falling edge interpolated
reg [4:0] count_reg = 0;
reg q0 = 0;
reg q1 = 0;

always @(posedge clk_250mhz or posedge rst_250mhz) begin
    if (rst_250mhz) begin
        count_reg <= 0;
        q0 <= 0;
        q1 <= 0;
    end else begin
        if (count_reg < 24) begin
            count_reg <= count_reg + 1;
        end else begin
            count_reg <= 0;
        end
        q0 <= count_reg < 12;
        q1 <= count_reg < 13;
    end
end

ODDR2
clk_10mhz_out_oddr2_inst
(
    .Q(clk_10mhz_out),
    .C0(clk_250mhz),
    .C1(~clk_250mhz),
    .CE(1),
    .D0(q0),
    .D1(q1),
    .R(0),
    .S(0)
);

Beispiel-Verilog-Code zum Generieren von 100 Hz aus 50 MHz mit einem Tastverhältnis von 50 % unter Verwendung eines Akkumulators:

// generate 100 Hz from 50 MHz
reg [31:0] count_reg = 0;
wire out_100hz = count_reg[31];

always @(posedge clk_50mhz or posedge rst_50mhz) begin
    if (rst_50mhz) begin
        count_reg <= 0;
    end else begin
        count_reg <= count_reg + 8590; //(((100 * 1 << 32) + 50000000/2) / 50000000)
    end
end
Ich bin mir ziemlich sicher, dass ein DDS auf rationale Vielfache der Referenzen beschränkt ist, genau wie eine PLL. Schon allein deshalb, weil die zum Programmieren verwendeten Register keine Möglichkeit haben, irrationale Zahlen auszudrücken. Die verfügbare Genauigkeit mag bei einem DDS größer sein, aber selbst eine Fractional-N-PLL mit einem 16-Bit-Nenner ergibt eine Genauigkeit von besser als 20 ppm, was besser ist als die Referenzgenauigkeit in vielen Designs.
Sie können mit einem DDS machen, was Sie wollen, wenn es nicht genau sein muss. Ein 32-Bit-DDS, das 100 Hz aus 50 MHz erzeugt, ergibt 100,00076145 Hz. Das sind 7,6 ppm. Nun, dies ist ein Offset und kein Durchschnitt, so dass dies je nach Anwendung ein Problem sein kann oder auch nicht - die Phase driftet sehr langsam bzgl. der Referenzoszillator.
Ja, aber es ist immer noch ein rationales Vielfaches der Referenz, oder? Ihre Antwort implizierte, dass DDSs nicht auf rationale Vielfache beschränkt sind. Wenn es eine Möglichkeit gibt, ein DDS zu programmieren f r e f / 2 oder f r e f / π Ausgangsfrequenz, würde mich interessieren.
Ah ja, jetzt verstehe ich worauf du hinaus willst. Ein DDS ist immer noch ein rationaler Bruch, aber normalerweise können Sie mit einem DDS viel mehr Bruchbits erhalten als mit einer FPGA-basierten Bruch-PLL.