Forum: FPGA, VHDL & Co. vhdl Anfang mal wieder


von Der Neue (Gast)


Lesenswert?

Hallo Ihr!
ich habe heute Nachmittag kein Eis gegessen, sondern mich mit 7-Segment 
Displays herumgeschlagen. Als vhdl Neuling ergaben sich Fragen und 
Probleme bei denen ihr mir vielleicht helfen mögt. Ich hänge den Code 
mit meinen Fragen als Kommentar hinten an. Ich kann mir denken, daß 
dererlei Fragen langsam allen aus dem Hals heraushängen erbitte dennoch 
Geduld.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity SevenSeg_vhd is
6
    Port ( clk : in  STD_LOGIC;
7
           dat : in  STD_LOGIC_VECTOR(15 downto 0);
8
           segments : out  STD_LOGIC_VECTOR (6 downto 0);
9
           anodes : out  STD_LOGIC_VECTOR (3 downto 0));
10
end SevenSeg_vhd;
11
12
architecture Behavioral of SevenSeg_vhd is
13
--ist es richtig, daß ich für solche Zähler integer verwenden sollte?
14
  signal anode_cnt : integer range 0 to 3 := 0;
15
  signal bcd_val : STD_LOGIC_VECTOR(3 downto 0);
16
begin
17
18
--Ist es wirklich so, daß ich bei einem integer range 0..3 den Überlauf
19
--"zu Fuß" machen muss, oder läuft der zu Null über?
20
anode_selector : process 
21
begin
22
  wait until rising_edge(clk);
23
  if anode_cnt < 3 then
24
    anode_cnt <= anode_cnt + 1;
25
  else
26
    anode_cnt <= 0;
27
  end if;
28
end process anode_selector;
29
30
segment_mux : process
31
begin
32
  wait until rising_edge(clk);
33
--nehme ich die Auswahl der Anode in den wait until mit auf, ich bin etwas
34
--eingeschüchtert, weil es heißt, ALLES vom Takt zu steuern.
35
  anodes <= (others=>'0');
36
  anodes(anode_cnt) <= '1';
37
--lässt sich der case (so integer für anode_cnt korrekt war) anders schreiben
38
--und vor ALLEM: warum ergibt das den Fehler 
39
--'type conversion of type std_logic_vector) is an unconstrained array.'
40
  case( std_logic_vector(to_unsigned(anode_cnt, 2)) ) is
41
    when "00" => bcd_val<=dat(3 downto 0);
42
    when "01" => bcd_val<=dat(7 downto 4);
43
    when "10" => bcd_val<=dat(11 downto 8);
44
    when others => bcd_val<=dat(15 downto 12);
45
  end case;
46
end process segment_mux;
47
48
with bcd_val select
49
     segments <= "1111110" when "0000",
50
      "0110000" when "0001",
51
      "1101101" when "0010",
52
      "1111001" when "0011",
53
      "0110011" when "0100",
54
      "1011011" when "0101",
55
      "1011111" when "0110",
56
      "1110000" when "0111",
57
      "1111111" when "1000",
58
      "1111011" when "1001",
59
      "1110111" when "1010",  
60
      "0011111" when "1011",
61
      "1001110" when "1100",
62
      "0111101" when "1101",
63
      "1001111" when "1110",
64
      "1000111" when others;
65
end Behavioral;
66
67
--Wenn das alles mal funktioniert und ich das Modul woanders benutze, kann ich dann jederzeit
68
--dat aktualisieren, oder sollte man das in ein internes FF speichern, wenn gerade ein neuer
69
--Zyklus bei anode 0 beginnt? Also damit alle Stellen für ein und dieselbe 16-bit Zahl 
70
--angezeigt werden.
71
72
73
74
--Habe ich noch etwas vergessen oder sinnentleert gemacht?
75
76
77
--vielen Dank!

von Jan M. (mueschel)


Lesenswert?

> --ist es richtig, daß ich für solche Zähler integer verwenden sollte?
>   signal anode_cnt : integer range 0 to 3 := 0;
Nein, ich würde hier unsigned benutzen. Dann brauchst du nur unten 
einmal eine Konversion.

> --Ist es wirklich so, daß ich bei einem integer range 0..3 den Überlauf
> --"zu Fuß" machen muss, oder läuft der zu Null über?
Ja. Bei einem unsigned(1 downto 0) ist er natürlich "kostenlos" dabei.

>   wait until rising_edge(clk);
> --nehme ich die Auswahl der Anode in den wait until mit auf, ich bin
> etwas
> --eingeschüchtert, weil es heißt, ALLES vom Takt zu steuern.
Nein, die Zuweisung soll immer, mit jeder Taktflanke stattfinden.


>   anodes <= (others=>'0');
>   anodes(anode_cnt) <= '1';
Hier bräuchtest du dann die Konvertierung zu integer, also
anodes(to_integer(anode_cnt))...

> --lässt sich der case (so integer für anode_cnt korrekt war) anders
> schreiben
> --und vor ALLEM: warum ergibt das den Fehler
> --'type conversion of type std_logic_vector) is an unconstrained array.'
>   case( std_logic_vector(to_unsigned(anode_cnt, 2)) ) is
Die Fehlermeldung verstehe ich ad hoc gerade nicht. Das to_unsigned() 
kann man sich dann auch sparen.

>     when "00" => bcd_val<=dat(3 downto 0);
>     when "01" => bcd_val<=dat(7 downto 4);
>     when "10" => bcd_val<=dat(11 downto 8);
>     when others => bcd_val<=dat(15 downto 12);
>   end case;
> end process segment_mux;
>
> Wenn das alles mal funktioniert und ich das Modul woanders benutze,
> kann ich dann jederzeit dat aktualisieren, oder sollte man das in ein
> internes FF speichern, wenn gerade ein neuer Zyklus bei anode 0 beginnt?
> Also damit alle Stellen für ein und dieselbe 16-bit Zahl angezeigt
> werden.
Das durchschalten der einzelnen Segmente passiert in der Regel ja sehr 
schnell, so dass man keinen Unterschied sehen wird - das von dir 
beschriebene Verhalten hast du ja in jedem Fall: Wenn die ersten beiden 
Segmente schon geändert sind haben die restlichen ja trotzdem noch 
kurzzeitig den alten Wert.

> Habe ich noch etwas vergessen oder sinnentleert gemacht?
Ich würde empfehlen, die Zuweisung an segements synchron zu machen. Du 
beschreibst ja einen Multiplexer der etwas Logik benötigt um das 
Ergebnis zu berechnen. Hier gibst du das Ergebnis ja direkt auf LEDs 
aus, da spielt das keine Rolle. In anderen Fällen könnte es ohne 
Register aber zu timing Problemen kommen, weil die Berechnung einige 
Zeit dauert und zusätzlich noch die Zeit bis zur Ausgabe durch 
Laufzeiten unterschiedlich ist.

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


Lesenswert?

> lässt sich der case anders schreiben
Ja, z.B. indem gleich der integer als Index verwendet wird:
1
  case anode_cnt is
2
    when 0 => bcd_val<=dat(3 downto 0);
3
    when 1 => bcd_val<=dat(7 downto 4);
4
    when 2 => bcd_val<=dat(11 downto 8);
5
    when 3 => bcd_val<=dat(15 downto 12);
6
  end case;
Dabei gibt es kein when-others, weil anode_cnt ja nur die Werte von 0..3 
annhemen kann.

Noch knackiger ginge es aber so:
1
  bcd_val <= dat(anode_cnt*4+3 downto anode_cnt*4);

Das hier....
1
     segments <= "1111110" when "0000",
2
      "0110000" when "0001",
3
      "1101101" when "0010",
4
      "1111001" when "0011",
5
      :
6
      "1001111" when "1110",
7
      "1000111" when others;
.... wäre auf diese Art einfacher lesbar:
1
     segments <= "1111110" when x"0",
2
      "0110000" when x"1",
3
      "1101101" when x"2",
4
      "1111001" when x"3",
5
      :
6
      "1001111" when x"E",
7
      "1000111" when others;

von Der Neue (Gast)


Lesenswert?

Ich danke euch vielmals - solche Hilfe ist doch hilfreich. Möglichst 
viel an Denkweisen und Schreibweisen kennenlernen ist doch optimal wenn 
man keine Vorlesung mit Menschen im Rücken hat.
Ich werde sacken lassen und mich bei Problemen später nochmals melden.

von Der Neue (Gast)


Angehängte Dateien:

Lesenswert?

Darf ich euch noch mals um Hilfe bitten?

Ich habe die Anzeige prima hinbekommen. In einer entity an einen Zähler 
gehängt etc. pp. Nun dachte ich versuche mich an der component 
Schreibweise da geht ja ohnehin kein Weg dran vorbei.
Klappt aber leider nicht und ich kann das Problem nicht finden. Ich habe 
die Mux-Zeit für die Segmente und die Zählgeschwindigkeit zu hoch für 
das Testboard - das habe ich gemacht, in der Hoffnung beim Simulieren 
etwas zu finden. Außer daß die Segmente durchdrehen kann ich aber nichts 
daraus ziehen :-(
Vielleicht darf man bei dem port map keine umwandlung in 
std_logic_vector(unsigned) machen?

Vielleicht kann mir ja einer meinen Fehler erklären.

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


Lesenswert?

> Vielleicht darf man bei dem port map keine umwandlung in
> std_logic_vector(unsigned) machen?
Ob daran was ist, das kannst du ja leicht selber ausprobieren. Einfach 
ein signal std_logic_vector definieren und das als Übergabeschnittstelle 
verwenden. Aber wenn der Fehler da wäre, hätte die Synthese dir schon 
eine Warnung ums Ohr gehauen...

Was ist deine Taktfrequenz?
Was die Zielplattform?
Welche Toolchain?

von Der Neue (Gast)


Lesenswert?

Also Zielplatform spartan3 auf einem Nexys2 Board, sowie ise 11.1.

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


Lesenswert?

> Außer daß die Segmente durchdrehen kann ich aber nichts daraus ziehen :-(
So wie es aussieht, zählen die einfach mit 500Hz hoch:
1
    generic map(DIV_GEN => 500) --500 Hz damit ich mal sehe, ob dat_s überhaupt zählt
Das ist ziemlich knackig fürs Auge.

Trag da doch mal einen gemächlicheren Takt von z.B. 2 Hz ein...

von Der Neue (Gast)


Lesenswert?

Grausam das alles, mir fiel jetzt folgende Warnung auf:

"Due to other FF/Latch trimming, FF/Latch <bcd_val_14> (without init 
value) has a constant value of 0 in block <SevenSeg_vhd>. This FF/Latch 
will be trimmed during the optimization process."

Also scheint da grob was nicht zu stimmen? Und vor allem ist doch 
bcd_val nur 4 bits lang wie kommt da _14 etc zustande? Die _14 kann man 
nämlich durch _4..._14 ersetzen?

von Der Neue (Gast)


Lesenswert?

Ich denke nich sollte wenigstens den Zwischenstand verkünden:
Ich konnte gesten Abend noch wenigstens ein Problem im Zusammenhang mit 
der wirren Anzeige finden und zwar beim Auswählen der aktuellen Stelle - 
falsche Transistoren :-(.

Es zeigt sich mir nur wieder a) Fehler können so(!) dämlich sein und an 
ganz anderer Stelle stecken als vermutet und b) es ist wahrscheinlich 
annährend aussichtslos für Andere so etwas in Form eines Forenposts zu 
finden.
Von daher werde ich in Zukunft versuchen, meine Anfragen so zu 
reduzieren, daß es auf allgemeine und ganz spezielle vhdl/fpga Fragen 
reduziert wird, die ja einige wirklich erstklassig beantworten können.

schönen Tag an alle

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.