Ich versuche, eine Digitaluhr auf VHDL für ein FPGA zu schreiben, das auf 100 MHz läuft. Ich kann es auf 4 Anoden schreiben, indem ich einen Zähler wie unten gezeigt erstelle (count1 = 249999), die Ziffern scheinen ziemlich klar zu sein. Wenn ich jedoch die Zeit im Format HH:MM:SS anzeigen möchte (wenn ich 6 Anoden anstelle von 4 verwenden möchte), konnte ich die Ziffern nicht klar anzeigen. Wenn ich den Wert von count1 stark erhöhe, beginnen die LEDs zu blinken, wenn ich den Wert von count1 verringere, sehen die Ziffern schwer zu identifizieren aus.
Gibt es eine theoretische Möglichkeit, diesen Zählerwert (Zähler1) zu bestimmen? Ist es möglich, 6 Ziffern so klar anzuzeigen, wie ich es versuche?
Danke ab sofort.
der Code, der für die Anzeige von 4 Anoden verantwortlich ist:
anode_clock : process(count1, clk_in, A_counter) -- counter to display all digits using anodes
begin
if(rising_edge(clk_in)) then
count1 <= count1 + 1;
if(count1 = 249999) then -- ATTENTION HERE
A_counter <= A_counter + 1;
count1 <= 0;
end if;
end if;
end process;
anode_display : process (A_counter, tmp_AN, min0, min1, hour0) begin -- matching anodes to display
AN <= tmp_AN;
case A_counter is
when 0 =>
tmp_AN <= "1110";
if (min0 = 0) then
DISP <= "1000000";
elsif min0 = 1 then
DISP <= "1111001";
elsif min0 = 2 then
DISP <= "0100100";
elsif min0 = 3 then
DISP <= "0110000";
elsif min0 = 4 then
DISP <= "0011001";
elsif min0 = 5 then
DISP <= "0010010";
elsif min0 = 6 then
DISP <= "0000010";
elsif min0 = 7 then
DISP <= "1111000";
elsif min0 = 8 then
DISP <= "0000000";
elsif min0 = 9 then
DISP <= "0010000";
end if;
when 1 =>
tmp_AN <= "1101";
if (min1 = 0) then
DISP <= "1000000";
elsif min1 = 1 then
DISP <= "1111001";
elsif min1 = 2 then
DISP <= "0100100";
elsif min1 = 3 then
DISP <= "0110000";
elsif min1 = 4 then
DISP <= "0011001";
elsif min1 = 5 then
DISP <= "0010010";
elsif min1 = 6 then
DISP <= "1000000";
end if;
when 2 =>
tmp_AN <= "1011";
if (hour0 = 0) then
DISP <= "1000000";
elsif hour0 = 1 then
DISP <= "1111001";
elsif hour0 = 2 then
DISP <= "0100100";
elsif hour0 = 3 then
DISP <= "0110000";
elsif hour0 = 4 then
DISP <= "0011001";
elsif hour0 = 5 then
DISP <= "0010010";
elsif hour0 = 6 then
DISP <= "0000010";
elsif hour0 = 7 then
DISP <= "1111000";
elsif hour0 = 8 then
DISP <= "0000000";
elsif hour0 = 9 then
DISP <= "0010000";
elsif hour0 = 10 then
DISP <= "1000000";
elsif hour0 = 11 then
DISP <= "1111001";
elsif hour0 = 12 then
DISP <= "0100100";
elsif hour0 = 13 then
DISP <= "1000000";
end if;
when 3 =>
tmp_AN <= "0111";
if (hour0 = 10) then
DISP <= "1111001";
elsif hour0 = 11 then
DISP <= "1111001";
elsif hour0 = 12 then
DISP <= "1111001";
else
DISP <= "1000000";
end if;
end case;
end process;
der Code, der für die Anzeige von 6 Anoden verantwortlich ist (Ziffern sind nicht klar lesbar):
anode_clock : process(count1, clk_in, A_counter) -- counter to display all digits using anodes
begin
if(rising_edge(clk_in)) then
count1 <= count1 + 1;
if(count1 = 125000) then -- experimental value: 249999
A_counter <= A_counter + 1;
count1 <= 0;
end if;
end if;
end process;
anode_display : process (A_counter, tmp_AN, sec0,sec1, min0, min1, hour0) begin -- matching anodes to display
AN <= tmp_AN;
case A_counter is
when 0 =>
tmp_AN <= "111110";
if (sec0 = 0) then
DISP <= "1000000";
elsif sec0 = 1 then
DISP <= "1111001";
elsif sec0 = 2 then
DISP <= "0100100";
elsif sec0 = 3 then
DISP <= "0110000";
elsif sec0 = 4 then
DISP <= "0011001";
elsif sec0 = 5 then
DISP <= "0010010";
elsif sec0 = 6 then
DISP <= "0000010";
elsif sec0 = 7 then
DISP <= "1111000";
elsif sec0 = 8 then
DISP <= "0000000";
elsif sec0 = 9 then
DISP <= "0010000";
end if;
when 1 =>
tmp_AN <= "111101";
if (sec1 = 0) then
DISP <= "1000000";
elsif sec1 = 1 then
DISP <= "1111001";
elsif sec1 = 2 then
DISP <= "0100100";
elsif sec1 = 3 then
DISP <= "0110000";
elsif sec1 = 4 then
DISP <= "0011001";
elsif sec1 = 5 then
DISP <= "0010010";
elsif sec1 = 6 then
DISP <= "1000000";
end if;
when 2 =>
tmp_AN <= "111011";
if (min0 = 0) then
DISP <= "1000000";
elsif min0 = 1 then
DISP <= "1111001";
elsif min0 = 2 then
DISP <= "0100100";
elsif min0 = 3 then
DISP <= "0110000";
elsif min0 = 4 then
DISP <= "0011001";
elsif min0 = 5 then
DISP <= "0010010";
elsif min0 = 6 then
DISP <= "0000010";
elsif min0 = 7 then
DISP <= "1111000";
elsif min0 = 8 then
DISP <= "0000000";
elsif min0 = 9 then
DISP <= "0010000";
end if;
when 3 =>
tmp_AN <= "110111";
if (min1 = 0) then
DISP <= "1000000";
elsif min1 = 1 then
DISP <= "1111001";
elsif min1 = 2 then
DISP <= "0100100";
elsif min1 = 3 then
DISP <= "0110000";
elsif min1 = 4 then
DISP <= "0011001";
elsif min1 = 5 then
DISP <= "0010010";
elsif min1 = 6 then
DISP <= "1000000";
end if;
when 4 =>
tmp_AN <= "101111";
if (hour0 = 0) then
DISP <= "1000000";
elsif hour0 = 1 then
DISP <= "1111001";
elsif hour0 = 2 then
DISP <= "0100100";
elsif hour0 = 3 then
DISP <= "0110000";
elsif hour0 = 4 then
DISP <= "0011001";
elsif hour0 = 5 then
DISP <= "0010010";
elsif hour0 = 6 then
DISP <= "0000010";
elsif hour0 = 7 then
DISP <= "1111000";
elsif hour0 = 8 then
DISP <= "0000000";
elsif hour0 = 9 then
DISP <= "0010000";
elsif hour0 = 10 then
DISP <= "1000000";
elsif hour0 = 11 then
DISP <= "1111001";
elsif hour0 = 12 then
DISP <= "0100100";
elsif hour0 = 13 then
DISP <= "1000000";
end if;
when 5 =>
tmp_AN <= "011111";
if (hour0 = 10) then
DISP <= "1111001";
elsif hour0 = 11 then
DISP <= "1111001";
elsif hour0 = 12 then
DISP <= "1111001";
else
DISP <= "1000000";
end if;
end case;
end process;
die Ausgabe (Ziffern sind nicht wie ich wollte, etwas sieht mit dem Anzeigezähler nicht richtig aus):
Dies ist eine inhärente Einschränkung des Multiplexing: Da Sie jeweils nur eine einzelne Ziffer ansteuern, wird Ihre Anzeige schwächer, wenn Sie die Anzahl der Ziffern erhöhen. Sie sollten jedoch in der Lage sein, 8-stellig zu fahren.
Ich würde versuchen, Ihren Zähler explizit zu umschließen, um sicherzustellen, dass Sie zu jedem Zeitpunkt eine bestimmte Ziffer fahren:
if(count1 = 249999) then -- ATTENTION HERE
A_counter <= A_counter + 1;
if(A_counter < 6) then -- 6 or 4, depending on how many digits you drive
A_counter <= A_counter + 1;
else
counter <= 0;
end if;
count1 <= 0;
end if;
Es sieht so aus, als ob Sie im 6-stelligen Code A_COUNTER kontinuierlich durchlaufen, was bedeutet, dass es mindestens 2 Zustände gibt, Zustand 6 und Zustand 7, die nicht explizit decodiert werden. Versuchen Sie, alle Segmente für die Zustände 6 und 7 explizit auszuschalten. Wenn A_COUNTER mehr als 3 Bits beträgt, müssen Sie herausfinden, was mit der Anzeige passiert, wenn A_COUNTER nicht 0 bis 5 ist.
Da die Anzeigeaktivierungen aktiv niedrig sind (0 = ein), ist es wahrscheinlich, dass alle Segmente standardmäßig eingeschaltet sind, wenn Sie ihnen nicht sagen, dass sie sich ausschalten sollen, wie dies in den Zuständen 6 und 7 passieren kann.
Als diagnostischen Ansatz können Sie COUNT1 vielleicht so weit erhöhen, dass sich die Ziffern extrem langsam ändern, sodass Sie die Beleuchtungsschritte in Zeitlupe beobachten können.
Ich bin mir nicht sicher, ob es die zusätzlichen Fälle 6 und 7 gibt. Aber da die 2 unbenutzten Ziffern (ganz links) mit allen leuchtenden Segmenten eingeschaltet sind, scheinen einige Ziffern/Segmente standardmäßig beleuchtet zu sein, wenn Sie sie nicht ausschalten. Wenn es nur 6 Fälle gibt und jeweils 1 Ziffer aktiviert ist, sollten die Ziffern 6 und 7 keine Zeit haben, eingeschaltet zu sein, aber sie sind eingeschaltet. Ich glaube, dass sowohl die Zeile als auch das Segment (00000000,00000000) standardmäßig für ein kurzes Intervall empfangen und alle Ziffern und alle Segmente einschalten.
Testen Sie dies, indem Sie Ziffernaktivierungswerte mit 8 Binärziffern (11xxxxxx) anstelle von 6 (xxxxxx) ausgeben, sodass die oberen 2 unbenutzten Ziffern ausgeschaltet sind. Die 2 Ziffern ganz links sind dunkler, aber immer noch teilweise beleuchtet.
Es gibt einige Probleme mit Ihrem Code, die Sie beheben sollten, um das Debuggen zu vereinfachen. Erstens haben Sie die Kathoden [Segment] -Decodierung mehrmals dupliziert - dies muss nur einmal durchgeführt werden - ich würde einen Prozess vorschlagen, der die aktuelle Dezimalstelle als Signal auf der Empfindlichkeitsliste hat und die Segmente setzt. Der durch den Haupttakt gesteuerte Prozess wäre dann ohne die duplizierte Decodierung viel einfacher. In der Praxis werden die Synthesewerkzeuge eine solche Dekodierung wahrscheinlich effizient einer RAM-Loop-Up-Tabelle auf dem FPGA zuordnen - sie sind möglicherweise nicht in der Lage, dies für Ihren Code zu tun, z
Das vom Haupttakt gesteuerte Routing dreht sich dann zyklisch und setzt das geeignete Dezimalsignal und das Anodensignal. Mein Ansatz wäre, den Anodenausgang auf "111110" zu initialisieren und diesen bei jedem Taktzyklus im getakteten Prozess zyklisch nach links zu verschieben und in eine Logik einzufügen, um das entsprechende Ziffernsignal zur Anzeige einzustellen.
Was nicht klar ist, ist, welche Uhr Sie verwenden, um diesen Prozess zu steuern. Es sollte wahrscheinlich nicht bei etwa 100 MHz Systemtakt liegen, wenn LEDs angesteuert werden - ich würde vorschlagen, es bei etwa 1 kHz oder so zu betreiben.
Das Photon
Tony Stewart EE75
ErenL
ErenL
Tony Stewart EE75
Tony Stewart EE75
ErenL
Das Photon