Hallo,
ich habe für einen Cyclone5 einen variablen Clockdivider geschrieben,
der leider nur bei statischer Vorgabe funktioniert.
Die Idee ist, ich habe einen Divider den ich über eine extern anlegbares
Bitmuster steuern kann.
Als Anhang habe ich die zwei verwendeten Dateien.
Das Ganze funktioniert, sobald ich in fpgatest.v:15 eine feste Zahl
anstatt der Speicherzelle vorgebe, was allerdings nicht Sinn und Zweck
der Sache ist. Der Crux ist dass es in der Simulation funktioniert. Wenn
ich es aber auf den FPGA spiele bekommt der Divider immer 0 als
Divisionswert.
Hat jemand eine Idee was ich da falsch mache?
Stefan A. schrieb:> Die Idee ist, ich habe einen Divider den ich über eine extern anlegbares> Bitmuster steuern kann.
Ok. Was willst Du mit dem resultierenden Takt anstellen?
Duke
Hm, Du deklarierst ein Register, das initial den Wert 2000 bekommt und
sonst nicht mehr verändert wird. Sprich, es ist eigentlich kein
Register. Das sollte zumindest eine Warning geben. Woher weißt Du, dass
divider immer 0 bleibt? Pack das Register mal in ein sequential
statement und schreib in jedem Takt 2000 hinein.
Das Ganze ist aus einem größeren Projekt, das einen konfigurierbaren
UART mit CRC hat. Dort kann man über ein Dual Port RAM vom Prozessor aus
Transferlänge und Clock einstellen.
Ich bin sicher, dass dort 0 steht, weil ohne das "if(divider == 0" kein
takt mehr kommt weil "if(divider /2 -1) -> 0/2 -1 = 0xFFFF und der
SignalTap Logic Analyzer von Quartus sagt das Gleiche.
Die Idee mit jeden Takt was reinschreiben war nicht schlecht.
Ich habe folgendes hinzugefügt:
1
always @ (posedge FPGA_CLK1_50)
2
begin
3
if(divider == 0)
4
divider <= 1000;
5
end
Und siehe da, ein Takt am Ausgang.
Allerdings nicht der für divider <= 1000, sondern divider <= 2000, wie
bei initial.
Gibt es da Optimizer, die Amok laufen können?
Stefan A. schrieb:> clock_out <= ~clock_out;> Hat jemand eine Idee was ich da falsch mache?
Du erzeugst Takte, wo du mit Clock-Enables arbeiten müsstest. Das ist
aber ein eher generelles Problem...
Stefan A. schrieb:> Das Ganze ist aus einem größeren Projekt, das einen konfigurierbaren> UART mit CRC hat. Dort kann man über ein Dual Port RAM vom Prozessor aus> Transferlänge und Clock einstellen.
Dann musst du diesen Teil mit dem DPRAM auch noch implementieren. Durch
das Weglassen dieses Interfaces beobachtest du hier ein simples
"Wegoptimieren": weil du das Register divider nie verwendest (in Form
von "verändern"), wird es hinfortoptimiert. Du solltest den Synthesizer
zwingen, indem du z.B. einen Reset für divider einführt. Und bei deren
Abwesenheit den Wert zuweist.
EDIT: schon gesehen, du hast es jetzt so gemacht... ;-)
Stefan A. schrieb:> Gibt es da Optimizer, die Amok laufen können?
Das steht im Handbuch der Toolchain. Und ja, das ist ein
Optimierungseffekt.
Ok ich konnte das in meinen großen Programm jetzt nachvollziehen.
Mit volgendem Code funktioniert es:
1
if(divider < 4)
2
begin
3
divider <= 1000;
4
end
Allerdings in meinem Fall seltsam, da es auch ohne nicht wegoptimiert
werden dürfte.
Ich habe kurz danach nämlich seit jeher folgendes Konstrukt:
1
control_verarbeiten <= control_verarbeiten +1;
2
case(control_verarbeiten)
3
...
4
...
5
// Lowbyte von Divider liegt an
6
7: begin
7
divider[7:0] <= mem_control_readdata;
8
mem_control_address <= 0;
9
end
10
// Highbyte von Divider liegt an
11
8: begin
12
divider[15:8] <= mem_control_readdata;
13
end
Der Witz ist, das hat auch schon einmal funktioniert. Erst seit ich die
CRC Funktion dazugebastelt habe klappt es nichtmehr. In der Simulation
allerdings kein Problem.
Meiner Ansicht nach ein klarer Bug, wundert mich allerdings nicht so
wirklich. Das Quartus ist allgemein sehr hakelig und stürzt auch
regelmäßig ab.
So, ich hab es gerade nochmal getestet.
Es gibt 2 Konstallationen die funktionieren:
1. Trivial
1
reg [15:0] divider = 2000;
2. Kurios
1
reg [15:0] divider;
2
initial divider = 2000;
3
4
always @ (posedge FPGA_CLK1_50)
5
begin
6
if(divider == 0)
7
divider <= 0;
8
end
Da wie in Version 2 ersichtlich die "initial" Anweisung offensichtlich
ausgewertet wird (Takt wird tatsächlich durch 2000 geteilt) und das if
an sich nutzlos ist, ist das meiner Auffassung nach ein Bug.
Besten Dank an Alle.
Stefan A. schrieb:> Da wie in Version 2 ersichtlich die "initial" Anweisung offensichtlich> ausgewertet wird (Takt wird tatsächlich durch 2000 geteilt) und das if> an sich nutzlos ist, ist das meiner Auffassung nach ein Bug.
Nö, weil Links die Zeit nach dem Takt und rechts die Zeit vor dem Takt.
Du verschleppst damit bei einem Zähler einen Takt und ob das hier
richtig ist, wage Ich mal zu bezweiffeln. Du muss mit einem Takt Vorlauf
denken, also:
"Wenn Zähler + Inkrement im nächsten Takt mehr als Limit, dann limit or
wrap etc..."
Eine eigene Frage?
Dieser Thread ist über 9 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.