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
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.
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.
Nachtrag (Kurzfassung): Brauche ich für jedes Segment einen Eigenen Decoder?
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?
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.
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.
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.
> 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.
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?
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.
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]) |
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.
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
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.