Forum: FPGA, VHDL & Co. Xilinx ISE VHDL Input zu Signal


von Peter H. (Gast)


Lesenswert?

Servus und ein frohes Neues.
Ich versuche mich grad an VHDL und arbeite mit den Xilinx ISE Project 
Navigator.

Hab mir als kleines Projekt eine Digitaluhr ausgesucht mit diversen 
Funktionen.
Soweit so gut, die Funktionen gehen wunderbar nur bin ich an einer 
Stelle hängen geblieben. Blöd an der Sache, rein nach dem betrachten 
sollte es gehen und keiner konnte mir bisher sagen warum das in diesem 
Simulator nicht geht.

Und zwar habe ich diverse Input Variablen im Code deklariert und setze 
diese in der Testbench.
Danach möchte ich die in der Testbench vergebenen Werte in meine Signal 
Varibalen setzen um damit arbeiten zu können.
Genau meckert er beim ausführen und hat nur kaputte Werte oder gibt gar 
nichts auf meinen Signalen aus.

Ist das ein Problem von dem Simulator, muss ich noch etwas beachten?

Hier die Deklaration in der main:
entity Digitaluhr is
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
     stunde : in STD_LOGIC;
     mode : in STD_LOGIC_VECTOR (1 downto 0);
           o_std_z : out  STD_LOGIC_VECTOR (3 downto 0);
           o_std_e : out  STD_LOGIC_VECTOR (3 downto 0);
           o_min_z : out  STD_LOGIC_VECTOR (3 downto 0);
           o_min_e : out  STD_LOGIC_VECTOR (3 downto 0);
           o_sec_z : out  STD_LOGIC_VECTOR (3 downto 0);
           o_sec_e : out  STD_LOGIC_VECTOR (3 downto 0);
     i_std_z : in  STD_LOGIC_VECTOR (3 downto 0);
           i_std_e : in  STD_LOGIC_VECTOR (3 downto 0);
           i_min_z : in  STD_LOGIC_VECTOR (3 downto 0);
           i_min_e : in  STD_LOGIC_VECTOR (3 downto 0);
           i_sec_z : in  STD_LOGIC_VECTOR (3 downto 0);
           i_sec_e : in  STD_LOGIC_VECTOR (3 downto 0));
end Digitaluhr;

Die Signale: ( Habe es auch ohne "0000" setzen der Signale versucht)
architecture Behavioral of Digitaluhr is

     signal s_std_z :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
     signal s_std_e :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
     signal s_min_z :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
     signal s_min_e :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
     signal s_sec_z :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
     signal s_sec_e :  STD_LOGIC_VECTOR (3 downto 0) := "0000";

begin

Setzen des Inputs in der Testbench:
    i_sec_e <= "0010";
    i_sec_z <= "0001";
    i_min_e <= "0100";
    i_min_z <= "0010";
    i_std_e <= "0100";
    i_std_z <= "0000";

Zu guter Letzt, das befüllen der Signale in der main:
test: process(i_sec_e,i_sec_z,i_min_e,i_min_z,i_std_e,i_std_z)
begin

    s_sec_e <= i_sec_e;
    s_sec_z <= i_sec_z;
    s_min_e <= i_min_e;
    s_min_z <= i_min_z;
    s_std_e <= i_std_e;
    s_std_z <= i_std_z;

end process test;


Falls ich den ganzen Code noch dazu packen sollen, mache ich das noch!
Hoffe es hat jemand ein Tipp.

Gruß Peter H.

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


Lesenswert?

Peter H. schrieb:
> Falls ich den ganzen Code noch dazu packen sollen, mache ich das noch!
Mach das. Hänge einfach alle nötigen VHDL Dateien hier als einzelne 
Anhänge an.
Und gib den genauen Wortlaut der Fehlermeldungen an. Und sage noch, 
welchen Simulator in welcher Version du verwendest..

> Funktionen gehen wunderbar
> Input Variablen
Bist du sicher dass das die richtigen Begriffe sind?

: Bearbeitet durch Moderator
von Peter H. (Gast)


Angehängte Dateien:

Lesenswert?

Ist angehängt.
Version 14.7.

Fehlermeldung gibt es genau nicht.
Wenn ich die Simulation starte gibt es auf den Signalen kein Wert.
Entweder UUUU oder XXXX.

Oh verdammt, ja richtig. Das habe ich gar nicht bedacht.
Meine ausforumlierten Schritte der Uhr funktionieren.
Nur habe ich ein Prolbme mit dem mitgeben von Werten über die Testbench.

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


Lesenswert?

Peter H. schrieb:
> Wenn ich die Simulation starte gibt es auf den Signalen kein Wert.
> Entweder UUUU oder XXXX.
Na, das sind doch Werte: U=Uninitialized und X=Kollision
Also weißt du einmal keine Werte zu und einmal unterschiedliche von 
mindestens zwei Stellen...
1
     signal s_std_z :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
2
     signal s_std_e :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
3
     signal s_min_z :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
4
     signal s_min_e :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
5
     signal s_sec_z :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
6
     signal s_sec_e :  STD_LOGIC_VECTOR (3 downto 0) := "0000";
7
8
begin
9
modul: process(clk,reset)
10
  begin
11
  if ( reset = '1') then
12
    s_std_z <= "0000";
13
    s_std_e <= "0000";
14
    s_min_z <= "0000";
15
    s_min_e <= "0000";
16
    s_sec_z <= "0000";
17
    s_sec_e <= "0000";
18
  end if;
19
20
  if(clk'event and clk ='1' and mode = "00") then
21
    s_sec_e <= STD_LOGIC_VECTOR(unsigned(s_sec_e)+1);
22
    if(s_sec_e = "1001") then
23
      s_sec_e <= "0000";
24
      s_sec_z <= STD_LOGIC_VECTOR(unsigned(s_sec_z)+1);
Wozu ein so etwas seltsam beschreibener Reset, den du aber gar nicht 
verwendest? Und warum nimmst du nicht einfach Integer zum Zählen, dann 
liest sich das viel entspannter als mit "1001" und "0101" und so....
So beispielsweise wie im 
Beitrag "Re: kruder Fehler bei FPGA-Programmierung (ISE WEBpack-Schematic)"


Ich würde vorschlagen, du machst das Setzen der Zähler ans Ende deines 
getakteten Prozesses, aber natürlich noch in die getakteten Teil 
hinein. Es ist klar, dass du nicht "nebenher" den Wert eines Flipflops 
setzen kannst. Und deine Zähler bestehen alle aus jeweils 4 Flipflops...

Dazu musst du diese seltsam vielen Takte aus dem Prozess herausbekommen 
und wie alle Welt nur einen einzigen nehmen. Durch das Externe Setzen 
der Uhrzeit sparst du dir auch den unsinnigen Reset:
1
modul: process(clk)
2
begin
3
 if(clk'event and clk ='1') then
4
    if (mode = "00") then
5
      ...
6
    end if;
7
    if (mode = "01") then
8
    ...
9
    end if;
10
    if (mode = "10") then
11
    ...
12
    end if;
13
    if (set_time='1') then
14
      s_sec_e <= i_sec_e;
15
      s_sec_z <= i_sec_z;
16
      s_min_e <= i_min_e;
17
      s_min_z <= i_min_z;
18
      s_std_e <= i_std_e;
19
      s_std_z <= i_std_z;
20
    end if;
21
  end if;
22
end process modul;
Oder gleich so, wie ich das machen würde:
1
process begin
2
  wait until rising_edge(clk);
3
  if (mode = "00") then
4
      ...
5
  end if;
6
  if (mode = "01") then
7
    ...
8
  end if;
9
  if (mode = "10") then
10
    ...
11
  end if;
12
  if (set_time='1') then
13
    s_sec_e <= i_sec_e;
14
    s_sec_z <= i_sec_z;
15
    s_min_e <= i_min_e;
16
    s_min_z <= i_min_z;
17
    s_std_e <= i_std_e;
18
    s_std_z <= i_std_z;
19
  end if;
20
end process;
Der Trick in diesen beiden Beschreibungen ist das Verhalten von Signalen 
in Prozessen: die letzte Zuweisung "gewinnt". Egal, was vorher mit den 
Zählern gemacht wurde, wenn set_time='1' ist, dann werden die Zähler neu 
gesetzt.

: Bearbeitet durch Moderator
von Peter H. (Gast)


Lesenswert?

Genau, und ich verstehe nicht wie es dazu kommt.
Falls ich die Signale gleich 0 setze und etwas in der Testbench mitgebe, 
kommt es zur Kollision.
Falls ich die Signal Werte nicht gleich 0 setze. Habe ich ein 
Uninitiliasiert.

Wie setze ich es richtig, das die Input Signale, die ich in der 
Testbench setze, in meine SIgnale gesetzt werden und hergenommen werden?

Der Reset wird ja nur ausgeführt, falls der Parameter gesetzt wird. Auch 
wenn der auskommentiert ist, gibt es den selben Fehler.

Da hast du Recht, das werde ich noch ändern.

von VHDL hotline (Gast)


Lesenswert?

wahrscheinliche Ursache Kollision: Ein Signal wird in mehr als einem 
Prozess zugewiesen.

wahrscheinliche Ursache Unitialisiert: kein Resetwert zugewiesen.

Zwei Tipps:
Dein Reset ist im Design high active, in der TB wird es nie 1 gesetzt.
Deine Resetwerte im Design werden durch den nachfolgenden clk'event = 
'1'-Teil überschrieben, da dort nach dem reset block ein elsif und kein 
end if hingehört.

von Peter H. (Gast)


Lesenswert?

Schon mal vielen lieben Dank für die Antworten!

Habe den Reset rausgeschmissen und den set_time eingebaut.
alla:
process begin
  wait until rising_edge(clk);
  if (mode = "00") then
      ...
  end if;
  if (mode = "01") then
    ...
  end if;
  if (mode = "10") then
    ...
  end if;
  if (set_time='1') then
    s_sec_e <= i_sec_e;
    s_sec_z <= i_sec_z;
    s_min_e <= i_min_e;
    s_min_z <= i_min_z;
    s_std_e <= i_std_e;
    s_std_z <= i_std_z;
  end if;
end process;

Jetzt werden die Input Signale nach einem Takt übernommen.
Die andere Baustelle ergibt sich jetzt, dass er wahrscheinlich jeden 
Takt die Werte setzt und nicht mehr hoch bzw. hinunter zählt.

Mal schauen, ich probiere noch ein bisschen rum.

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


Lesenswert?

Peter H. schrieb:
> Die andere Baustelle ergibt sich jetzt, dass er wahrscheinlich jeden
> Takt die Werte setzt und nicht mehr hoch bzw. hinunter zählt.
Ja klar. Stell dir das einfach so vor wie das Stellen einer Uhr: so 
lange gestellt wird, steht die Uhr. Du musst also nach dem Stellen der 
Uhrzeit das set_time wieder auf 0 setzen.

: Bearbeitet durch Moderator
von Peter H. (Gast)


Angehängte Dateien:

Lesenswert?

So habe mal alle Bitweisen Abfragen durch Integer getauscht.

Ebenso die Testbench verändert, das nach einer Zeit das setzen aufgehört 
und es normal weiter gehen soll.

Ist das so korrekt?

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


Lesenswert?

Peter H. schrieb:
> use IEEE.STD_LOGIC_unsigned.ALL;
> use IEEE.NUMERIC_STD.ALL;
> Ist das so korrekt?
Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"

Peter H. schrieb:
> So habe mal alle Bitweisen Abfragen durch Integer getauscht.
Du sollst die Zähler als Integer ausführen. Dann sparst du dir das 
Zutodecastenundkonvertieren:
1
     ...
2
     signal s_sec_z :  integer range 0 to 5 := 0;
3
     signal s_sec_e :  integer range 0 to 9 := 0;
4
5
begin
6
7
modul: process begin
8
 wait until rising_edge(clk);
9
10
  if (mode = "00") then
11
    s_sec_e <= s_sec_e+1;
12
    if (s_sec_e=9) then
13
      s_sec_e <= 9;
14
      s_sec_z <= s_sec_z+1;
15
    end if;
16
    ....
Dann musst du nur ein einziges Mal zur Ausgabe diese Integer nach 
std_logic_vector konvertieren.

von Peter H. (Gast)


Lesenswert?

Das mit dem Interger schien mir auch am Anfang deutlich sinnvoller.
Das andere wurde mir dann eingeredet.

So geht das deutlich einfacher!

Habe es nun komplett am Laufen.
Ich kann mich nur herzlichst Bedanken für die Untersützung!!!

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.