Forum: FPGA, VHDL & Co. Variabler Clockdivider in Verilog


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Stefan A. (king-crash)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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?

von Duke Scarring (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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

von Vancouver (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Stefan A. (king-crash)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Stefan A. (king-crash)


Bewertung
0 lesenswert
nicht lesenswert
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?

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
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.

: Bearbeitet durch Moderator
von Stefan A. (king-crash)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Lattice User (Gast)


Bewertung
0 lesenswert
nicht lesenswert
initial Blocks sind im Allgemeinen nicht synthesierbar. (@VHDLer, das 
entspricht einem Process der nur einmal durchlaufen wird)

statt
1
reg [15:0] divider;
2
initial divider = 2000;
1
reg [15:0] divider = 0;
(Verilog 2001, sollten alle aktuellen FPGA Tools inzwischen können)

von Stefan A. (king-crash)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Weltbester FPGA-Pongo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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..."

von Weltbester FPGA-Pongo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
und? wie isses nun?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.