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.
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
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.
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
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.
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.
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.
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
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.