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?
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
Qiu