Forum: FPGA, VHDL & Co. Using the 7-segment Displays/ 7 Segment Anzeige


von Manah (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle,

ich habe nachgeguckt und mir mehrere YouTube Videos angeguckt, bei denn 
Boards die ich in Internet gefunden habe, gibt es so was wie ein Input, 
welches Automatisch das Segment wechselt (mit einem Mux), ich glaube bei 
meinem Board ist das nicht der Fall, ich habe nichts in der Doku darüber 
gefunden.

d
d.h.:

Wenn ich 5 Segmente ansprechen möchte, brauche ich 5 Fälle (case)? Oder 
gibt es eine Anweisung, die automatisch die Pins des nächsten Segments 
adressiert? In der Dokumentation hat jedes Segment seine eigenen 
Ausgangspins.

English:
if i want to address 5 segments need 5 cases? Or is there an instruction 
that automatically addresses the pins of the next segment? In the 
documentation, each segment has its own output pins.


Board: Terasic Technologies DE10-Lite Boar
Sprache: VHDL
IDE: Quartus Prime Lite 2 - 18.1

Danke

von J. S. (engineer) Benutzerseite


Lesenswert?

In der "guten alten Zeit" haben wir das mit der Spannungsversorgung 
geregelt und das Display analog multiplexed. D.h. jeweils eines von 5en 
war "an". Richtig sauber geht das über ein Schieberegister mit Latch, 
wie z.B. das  165.

Es wäre also nachzusehen, WIE diese Anzeige verdrahtet ist und besaftet 
werden muss.

von Manah (Gast)


Lesenswert?

Hallo Jürgen,

danke für deine schnelle Rückmeldung,


das ist ein ausschnitt aus meinem Code, also besser gesagt, ein Standard 
Encoder für eine 7-Seg Anzeige.
1
  PROCESS (seg_coder_in_s)
2
  BEGIN
3
    case seg_coder_in_s_seg1 is
4
      when "0000"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '1'; f <= '1'; g <= '0';
5
      when "0001"     => a <= '0'; b <= '1'; c <= '1'; d <= '0'; e <= '0'; f <= '0'; g <= '0';
6
      when "0010"     => a <= '1'; b <= '1'; c <= '0'; d <= '1'; e <= '1'; f <= '0'; g <= '1';
7
      when "0011"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '0'; f <= '0'; g <= '1';
8
      when "0100"     => a <= '0'; b <= '1'; c <= '1'; d <= '0'; e <= '0'; f <= '1'; g <= '1';
9
      when "0101"     => a <= '1'; b <= '0'; c <= '1'; d <= '1'; e <= '0'; f <= '1'; g <= '1';
10
      when "0110"     => a <= '1'; b <= '0'; c <= '1'; d <= '1'; e <= '1'; f <= '1'; g <= '1';
11
      when "0111"      => a <= '1'; b <= '1'; c <= '1'; d <= '0'; e <= '0'; f <= '0'; g <= '0';
12
      when "1000"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '1'; f <= '1'; g <= '1';
13
      when "1001"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '0'; f <= '1'; g <= '1';
14
      when others     => a <= '0'; b <= '0'; c <= '0'; d <= '0'; e <= '0'; f <= '0'; g <= '1';
15
    END case;
16
  END PROCESS;
17
END Seg_Steuerung;

In dem Handbuch
https://www.manualslib.com/manual/1429115/Terasic-De10-Lite.html
steht: Für jede Led, eine Eigene Pin (je LED: PIN_C14, PIN_C15 
usw...),in dem Fall müsste ich 6 Decoder schreiben, wenn ich alle 6 
7-Segment Anzeigen ansprechen möchte oder? Weil ich ja 6*7 = 42 Output 
Pins ansprechen muss? und eine für denn DP Pin? Also insgesamt 43 Pins.

In jeden Foren Eintrage sehe ich halt in Beispiel jeweils 1 Decoder. Das 
verwirrt mich, wie man mit 1 Decoder 42 Pins adressieren kann, weil ja 
jede Pin einen Eigenen Output hat.

von Manah (Gast)


Lesenswert?

Nachtrag (Kurzfassung): Brauche ich für jedes Segment einen Eigenen 
Decoder?

von foobar (Gast)


Lesenswert?

Man multiplext, wenn man Pins sparen will.  Auf diesem Board wissen sie 
nicht, wohin mit den 360 I/O-Pins des Chips, also werden alle 6x8 LEDs 
einzeln angeschlossen.  Wie du diese 48 Pins nun ansteuerst, ist dir 
überlassen - wenn du willst, sogar über einen Multiplexer.

Aber ehrlich: wenn du bei sowas bereits nachfragen musst, was um Himmels 
willen willst du mit so einem FPGA-Board?  Meinst du nicht, du wärst mit 
einem einfachen Arduino erstmal besser bedient?

von Manah (Gast)


Lesenswert?

Ich muss das Board benutzten, sagen wir so :D @schöner name.
So wie ich dich Verstanden habe, muss ich alle Pins Einzel ansteuern und 
brauche dann jeweils 1 Decoder pro Segement.

In dem Fall muss ich das 6 mal kopieren:
1
  PROCESS (seg_coder_in_s)
2
  BEGIN
3
    case seg_coder_in_s_seg1 is
4
      when "0000"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '1'; f <= '1'; g <= '0';
5
      when "0001"     => a <= '0'; b <= '1'; c <= '1'; d <= '0'; e <= '0'; f <= '0'; g <= '0';
6
      when "0010"     => a <= '1'; b <= '1'; c <= '0'; d <= '1'; e <= '1'; f <= '0'; g <= '1';
7
      when "0011"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '0'; f <= '0'; g <= '1';
8
      when "0100"     => a <= '0'; b <= '1'; c <= '1'; d <= '0'; e <= '0'; f <= '1'; g <= '1';
9
      when "0101"     => a <= '1'; b <= '0'; c <= '1'; d <= '1'; e <= '0'; f <= '1'; g <= '1';
10
      when "0110"     => a <= '1'; b <= '0'; c <= '1'; d <= '1'; e <= '1'; f <= '1'; g <= '1';
11
      when "0111"      => a <= '1'; b <= '1'; c <= '1'; d <= '0'; e <= '0'; f <= '0'; g <= '0';
12
      when "1000"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '1'; f <= '1'; g <= '1';
13
      when "1001"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '0'; f <= '1'; g <= '1';
14
      when others     => a <= '0'; b <= '0'; c <= '0'; d <= '0'; e <= '0'; f <= '0'; g <= '1';
15
    END case;
16
  END PROCESS;
17
END Seg_Steuerung;
und dann statt a b c ... die jeweiligen pins ansteuern.

von J. S. (engineer) Benutzerseite


Lesenswert?

Manah schrieb:
> Nachtrag (Kurzfassung): Brauche ich für jedes Segment einen Eigenen
> Decoder?

In keinem Fall. Nur das Latch, also den gespeicherten Wert. Auch in dem 
Fall, dass wirklich alle LEDs einzeln explizit angeschlossen sind, kann 
man den Decoder per MUX wiederverwenden. Allerdings ist die Synthese 
schlau genug, das zu erkennen und vereinfacht den zu einer veringerten 
Menge, wenn man wirklich 5 identische Schaltungen instanziieren würde - 
egal, ob sie zeitgleich, oder zeitlich getrennt genutzt werden.

von Fpgakuechle K. (Gast)


Lesenswert?

Manah schrieb:
> Nachtrag (Kurzfassung): Brauche ich für jedes Segment einen Eigenen
> Decoder?

nein, es genügt wenn du einen Decoder mit dem passenden CE (Chip-Enable) 
nachenander einmultiplext. Die brauchst also einen Zähler bspw v. 0 bis 
5, der zum Zählerstand 0 den Wert von Ziffer 0 an den Eingang des 
decoders legt und gleichzeitig für einen Takt das Chip enable der 
Ausgangs-FF für dieses 7Segment aktiviert.

von foobar (Gast)


Lesenswert?

> muss ich das 6 mal kopieren

Na ja, kann man.  Üblich ist wohl eher, eine Entity 6 mal mit passenden 
port-maps zu instantiieren.  Näheres steht in deinem VHDL-Buch ...


PS: Ich kann kein VHDL, hab nur nen groben Überblick über die Konzepte.

von Manah (Gast)


Lesenswert?

Ich finde das einleuchtend, in den Youtube Vidoes habe ich genau das 
gleiche gesehen. Aber deren 7Seg Anzeigen haben 9 Pins, eine für denn 
DP, 7 für die jeweiligen Segmente und ein Cat Signal.

Das Cat Signal dient halt bei den 7 Segmenten Anzeigen dafür, um es um 
ein Segment weiter zu "schieben", aber in meinem Fall gibt es kein Cat 
Signal, also in Handbuch steht nur das es 8 Pins gibt und einen für den 
DP und für die 7 Segmente und jeder Pin hat seine Eigene Pin 
Adressierung.

Und Irgendwie muss ich ja sagen (Bei der Pin-Zuweisung), der Output von 
den Decoder ist der Pin.

Z.B.:
when "0000"     => a <= '1'; b <= '1'; c <= '1'; d <= '1'; e <= '1'; f 
<= '1'; g <= '0';

Pin-Zuweisung geht nur mit Outputs.
Output: a,b,c,...

a = PIN X
b = PIN Y
c = PIN Z
...


Das muss ich doch dann denn Decoder für jedes Segment extra schreiben, 
weil ich ja 42 Outputs benötige, da ich 42 Pins ansprechen will?

von Fpgakuechle K. (Gast)


Lesenswert?

Manah schrieb:

> Das muss ich doch dann denn Decoder für jedes Segment extra schreiben,
> weil ich ja 42 Outputs benötige, da ich 42 Pins ansprechen will?

Lt. Blockbild im Boardmanual hast du 48 pins (wegen dem dezimalpunkt)

und nein, du brauchst nicht einen Decoder für jedes Digit, sondern ein 
Chipenable für jedes der 6 Digits extra. einen Decoder-ausgang bspw (a) 
kannst du mit allen 6 Output-FF für das segment a in allen digits 
verbinden


schnippseltechnisch etwa so:
1
process(clk)
2
begin
3
if rising_edge(clk)
4
   if digit_count_q = 0 then
5
     digit_0_fpgaout_sega <= decoder_out_a; 
6
     digit_0_fpgaout_segb <= decoder_out_b;
7
    --  othe segements similar
8
   end if;
9
   if digit_count_q = 1 then
10
     digit_1_fpgaout_sega <= decoder_out_a; 
11
     digit_1_fpgaout_segb <= decoder_out_b;
12
    --  othe segements similar
13
   end if;
14
  --4 digits more
15
 end if;
16
end Process;

Natürlich kann man das mit Generate eleganter schreiben.

von foobar (Gast)


Lesenswert?

Mag ja sein, dass ich vollkommen daneben liege, aber warum sich mit 
Muxern rumplagen?  Der BCD-nach-7seg-Dekoder passt in ein 4LUT, d.h. an 
jedem der 6x7=42 Pins hängt ein 4LUT und man hat direkt nen 24-Bit 
BCD-Bus zu den LEDs.  Einstufig kombinatorisch.  Wird das mit Muxern 
wirklich einfacher?

Bei dem Author hapert es doch eher daran, wie er's in VHDL ausdrücken 
soll.  Da kann ich ihm auch nicht helfen (wie gesagt, kann kein VHDL), 
aber vom Prinzip her:
1
// pseudo-language, NOT VHDL!
2
define bcd7seg(in[4], out[7])
3
{
4
   out[0] = in==0 or in==2 or ...   // Segment A
5
   out[1] = in==1 or in==2 or ...   // Segment B
6
   ...
7
   out[6] = ...                     // Segment G
8
   // oder umgekehrt mittels case
9
}
10
11
instantiate bcd7seg(bcd[0..3],   port[0..6])  // port[7] is DP
12
instantiate bcd7seg(bcd[4..7],   port[8..14])
13
instantiate bcd7seg(bcd[8..11],  port[16..22)
14
instantiate bcd7seg(bcd[12..15], port[24..30])
15
instantiate bcd7seg(bcd[16..19], port[32..38])
16
instantiate bcd7seg(bcd[20..23], port[40..46])

von Steffen H. (avrsteffen)


Lesenswert?


von Fpgakuechle K. (Gast)


Angehängte Dateien:

Lesenswert?

foobar schrieb:
> Mag ja sein, dass ich vollkommen daneben liege, aber warum sich mit
> Muxern rumplagen?  Der BCD-nach-7seg-Dekoder passt in ein 4LUT, d.h. an
> jedem der 6x7=42 Pins hängt ein 4LUT und man hat direkt nen 24-Bit
> BCD-Bus zu den LEDs.  Einstufig kombinatorisch.  Wird das mit Muxern
> wirklich einfacher?

Das kommt auf einen Versuch an, weil Muxer nicht unbedingt nur mit LUT's 
gebaut werden, sondern auch mit den ohnehin vorhanden MUX5/Mux& 
primitiven.
Allerdings haste schon recht, eine Mehrfach-instanziierung ist hier der 
erfolgsversprechende Ansatz.


>
> Bei dem Author hapert es doch eher daran, wie er's in VHDL ausdrücken
> soll.  Da kann ich ihm auch nicht helfen (wie gesagt, kann kein VHDL),
> aber vom Prinzip her:

also etwa so

1
        architecture Behavioral of top is
2
          component seg_coder is
3
            port (
4
              a, b, c, d, e, f, g : out std_logic;
5
              bcd_i : in std_logic );
6
          end component seg_coder;
7
8
          signal s_led : std_logic_vector(47 downto 0);
9
        begin
10
11
          G_7seg : for idx in 0 to 5 Generate
12
            seg_coder_i : seg_coder    --im angehängten file ist diese Zeile anders
13
              port map (
14
                a => s_led(8*idx + 0),
15
                b => s_led(8*idx + 1),
16
                c => s_led(8*idx + 2),
17
                d => s_led(8*idx + 3),
18
                e => s_led(8*idx + 4),
19
                f => s_led(8*idx + 5),
20
                g => s_led(8*idx + 6),
21
                bcd_i => bcd_i(4*idx+3 downto 4*idx));
22
            S_LED(8*IDX + 7) <= '0'  -- DECIMAL POINT
23
          end generate;
24
      end architecture;


Ich hab mal das gesamtfile ungeprüft angehangen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Manah schrieb:
> und dann statt a b c ... die jeweiligen pins ansteuern.
Schlauer wäre es, wenn du einfach einen 7 bit breiten Vektor definieren 
und dort dein Bitmuster ablegen würdest. Denn dann musst du nur die 7 
Bits des Vektors dem passenden Pin zuordnen und hast einen kurzen und 
kompakten Code. Hier mal eine Stoppuhr, die die Zeit auf 4 
gemultiplexten Sieben-Segment-Anzeigen ausgibt:
http://www.lothar-miller.de/s9y/archives/88-VHDL-vs.-Verilog-am-Beispiel-einer-Stoppuhr.html

Aaaaaber:
foobar schrieb:
> Auf diesem Board wissen sie nicht, wohin mit den 360 I/O-Pins des Chips,
> also werden alle 6x8 LEDs einzeln angeschlossen.
Tragisch...
Ich würde da also einfach ein kleines ROM instantiieren, mit den 
Bitmustern füllen und über einen Index draufzugreifen:
1
:
2
  type Rom10x7 is array (0 to 9) of std_logic_vector (6 downto 0);
3
               -- Segment (low aktiv) abcdefg        Anzeige 
4
  constant SevenSegRom: Rom10x7 := ( "1000000",      -- 0
5
                                     "1111001",      -- 1
6
                                     "0100100",      -- 2
7
                                     "0110000",      -- 3
8
                                     "0011001",      -- 4
9
                                     "0010010",      -- 5
10
                                     "0000010",      -- 6
11
                                     "1111000",      -- 7
12
                                     "0000000",      -- 8
13
                                     "0010000" );    -- 9
14
:
15
:
16
  HEX0 <= SevenSegRom(to_integer(unsigned(slv_wert0)));
17
  HEX1 <= SevenSegRom(to_integer(unsigned(slv_wert1)));
18
  HEX2 <= SevenSegRom(to_integer(unsigned(slv_wert2)));
19
  HEX3 <= SevenSegRom(to_integer(unsigned(slv_wert3)));
20
:

Bei der Tabelle ist dann auch gleich beachtet, dass (wie im Schaltplan 
leicht zu erkennen) die LEDs low aktiv angeschlossen sind. Eine '0' 
bedeutet also "LED leuchtet".


Zuvor jedoch dürfte es vermutlich nötig sein, eine vorliegende binäre 
Zahl (z.B. Zählerwert) in die für die einzelnen Segmente nötige 
BCD-Darstellung umzuwandeln:
http://www.lothar-miller.de/s9y/categories/44-BCD-Umwandlung

: Bearbeitet durch Moderator
von Manah (Gast)


Lesenswert?

Hi alle,

ich habe die Antwort: Tatsächlich muss für das Board jede Pin 
Einzelangesprochen werden, es muss über Port Mapping gelöst werden.
So wie hier in Code zu sehen ist @fpgakuechle.

Danke für euren Support!

Liebe Grüße

Okan

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Manah schrieb:
> Tatsächlich muss für das Board jede Pin Einzelangesprochen werden
> es muss über Port Mapping gelöst werden.
Aber eben nicht über 4x7 = 28 einzelne 1-Bit Signale mit 28 
unterschiedlichen Namen. Es geht auch über 4 Vektoren mit je 7 Bit 
Breite.
Denn du kannst in den Constraints (Pin Assignment, LOC Constraints,...) 
eben auch einzelne Bits eines Vektors an bestimmte IO-Pins zuweisen.

von Manah (Gast)


Lesenswert?

ich werde mir beide Ansätze angucken. Danke euch allen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.