www.mikrocontroller.net

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


Autor: Der Neue (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity SevenSeg_vhd is
    Port ( clk : in  STD_LOGIC;
           dat : in  STD_LOGIC_VECTOR(15 downto 0);
           segments : out  STD_LOGIC_VECTOR (6 downto 0);
           anodes : out  STD_LOGIC_VECTOR (3 downto 0));
end SevenSeg_vhd;

architecture Behavioral of SevenSeg_vhd is
--ist es richtig, daß ich für solche Zähler integer verwenden sollte?
  signal anode_cnt : integer range 0 to 3 := 0;
  signal bcd_val : STD_LOGIC_VECTOR(3 downto 0);
begin

--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?
anode_selector : process 
begin
  wait until rising_edge(clk);
  if anode_cnt < 3 then
    anode_cnt <= anode_cnt + 1;
  else
    anode_cnt <= 0;
  end if;
end process anode_selector;

segment_mux : process
begin
  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.
  anodes <= (others=>'0');
  anodes(anode_cnt) <= '1';
--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
    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;

with bcd_val select
     segments <= "1111110" when "0000",
      "0110000" when "0001",
      "1101101" when "0010",
      "1111001" when "0011",
      "0110011" when "0100",
      "1011011" when "0101",
      "1011111" when "0110",
      "1110000" when "0111",
      "1111111" when "1000",
      "1111011" when "1001",
      "1110111" when "1010",  
      "0011111" when "1011",
      "1001110" when "1100",
      "0111101" when "1101",
      "1001111" when "1110",
      "1000111" when others;
end Behavioral;

--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.



--Habe ich noch etwas vergessen oder sinnentleert gemacht?


--vielen Dank!

Autor: Jan M. (mueschel)
Datum:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> lässt sich der case anders schreiben
Ja, z.B. indem gleich der integer als Index verwendet wird:
  case anode_cnt is
    when 0 => bcd_val<=dat(3 downto 0);
    when 1 => bcd_val<=dat(7 downto 4);
    when 2 => bcd_val<=dat(11 downto 8);
    when 3 => bcd_val<=dat(15 downto 12);
  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:
  bcd_val <= dat(anode_cnt*4+3 downto anode_cnt*4);

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

Autor: Der Neue (Gast)
Datum:

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

Autor: Der Neue (Gast)
Datum:
Angehängte Dateien:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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

Autor: Der Neue (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also Zielplatform spartan3 auf einem Nexys2 Board, sowie ise 11.1.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Außer daß die Segmente durchdrehen kann ich aber nichts daraus ziehen :-(
So wie es aussieht, zählen die einfach mit 500Hz hoch:
    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...

Autor: Der Neue (Gast)
Datum:

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

Autor: Der Neue (Gast)
Datum:

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

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.