Hallo Leute, und meine Partner ich haben folgende Aufgabe zu lösen: Es ist eine Schaltung, 8 Bit breit, zu entwickeln, die immer dann, falls an einem der 8 Eingänge (E0 - E7) sich eine Änderung ergibt, den neuen Wert aller 8 Bit in ein Register schreibt. Die Ausgabe des Registerinhalts erfolgt über die Ausgänge A0 - A8. Freigegeben wird die Schaltung durch ein Enable-Bit CS. Insgesamt stehen 1024 Register zur Verfügung, die über die Adressen Z_i angesteuert werden. Inhalte sind nicht zu überschreiben. Bei Erreichen des letzten Registers ist ein Warnsignal auszugeben. Unser Lösungsansatz: -- library <LIB_NAME>; -- use <LIBNAME>.components.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- use ieee.std_logic_unsigned.all; entity counter is port( in_data: in std_logic_vector(7 downto 0); -- acht bit eingang out_data: out std_logic_vector(7 downto 0); -- acht bit ausgang z_i out std_logic_vector(9 downto 0) := "0000000000"; -- der Zi ausgang für die adressierung der Register value: Buffer std_logic_vector(9 downto 0) := "0000000000"; -- stellt den Zähler der Register dar warning_signal: out std_logic := "0"; -- warnsignal 1 wenn Reg 1024 angesprochen wurde, sonst 0 cs: in std_logic; -- der signal-geber fürs scharf schalten der schaltung, müssen wir hier speziell deklarieren ); end entity counter; ------------------------------------------------------------------------ --- architecture arch_up_count of counter is -- declarations begin process(cs, in_data) begin if cs = '0' then value <= "0000000000"; -- wenn cs 0 dann zähler auf Null stellen else if (in_data´event) and (value < "1111111111") then -- wenn cs 1 ist und sich was am Eingang getan hat und solange der zähler (=value) kleiner als 1024 ist dürfen wir speichern z_i <= value; -- den zähler-wert = Adresse der Register auf den zi-ausgang legen zum ansprechen der Register out_data <= in_data; -- hab den eingang jetzt gleich auf den ausgang gesetzt, statt -- das ganze in einen Puffer zu stecken, wie urschprünglich gedacht value <= value + 1; -- zähler um eins höher zählen end if; end process; warning_signal <= '1' when value = "1111111110" else '0'; -- wenn zähler gleich 1023 ist, haben wir -- das Register 1024 erreicht -- da wir ja von 0 aus starten end architecture arch_up_count; Folgender Denkprozess: Zu Beginn der architecture wird überprüft, ob die Schaltung von außen "scharf" gestellt wurde. Ist das nicht der Fall, resete Value. Jetzt kommt das Problem: " in_data'event " kann man das überhaupt so schreiben? Dieses if überprüft, ob sich an einem der Eingänge irgendetwas geändert hat und ob min. noch ein Register frei ist. Wird in das Register 1023, also in das 1024te, da von 0 aus gestartet wird, geschrieben, dann zählt value auf 1024 und der Prozess wird nicht mehr ausgeführt. Zeitgleich wird das Warnsignal ausgegeben. Das Warnsignal wird auch bei jedem weiteren Speicherversuch ausgegeben, solange, bis von außen keine Daten mehr kommen. Würde euch bitten, das einfach mal anzuschauen und eure Meinung dazu abzugeben. Schönen Gruß und danke, Bomi
> " in_data'event " > kann man das überhaupt so schreiben? Nur für die Simulation. In Hardware wirst du das niemals gegossen bekommen. > Es ist eine Schaltung, 8 Bit breit, zu entwickeln, die immer dann, falls > an einem der 8 Eingänge (E0 - E7) sich eine Änderung ergibt, den neuen > Wert aller 8 Bit in ein Register schreibt. Merk dir den vorigen Wert und vergleich ihn mit dem aktuellen Wert. Und für Anfänger: Nur 1 Takt im ganzen Design, kein asynchroner (oder gar kombinatorischer) Reset und keine Variablen. Dann hast du Chancen auf ein lauffähiges Design... Das wäre schon ein asynchroner (und mit ein wenig Glück sogar kombinatorischer) Reset:
1 | if cs = '0' then |
BTW: Hier im Forum kannst du VHDL-Quelltext mit den Tags [ vhdl ] und [ /vhdl ] formatieren lassen (ohne Leerzeichen).
hi michael, gibt es bei deinem projekt auch einen takt? komplett asyncron wird das nicht zu bewerkstelligen sein. optimal währe es, wenn die daten schon taktsyncron ankommen. anderenfalls musst du die daten erst einsyncronisieren. dann brauchst du einen takt der mindestens doppelt so groß ist wie der datentakt. damit keine daten verloren gehen. gruß sunny
thx, für die Antworten Das mit dem Takt ist eine gute Frage!! Außerhalb der Aufgabenstellung ist da leider nichts vorhanden! Werd aber mal nachfragen. @lothar: meinst du, dass man statt dieser "event"-Sache, besser einfach die Subtraktion Neuer Zustand - alter Zustand gleich/ungleich 0 setzen soll? schönen Gruß, Michael
Ihr braucht wie gesagt erstmal einen Takt und zudem sollte das Schreiben auf den externen Speicher auch noch definiert gesteuert werden. Ich habe hier jetzt einfach mal ein Write-Signal eingeführt.
1 | library ieee; |
2 | use ieee.std_logic_1164.all; |
3 | use ieee.numeric_std.all; |
4 | |
5 | entity counter is |
6 | port( |
7 | in_data: in std_logic_vector(7 downto 0); -- acht bit eingang |
8 | out_data: out std_logic_vector(7 downto 0); -- acht bit ausgang |
9 | z_i: out std_logic_vector(9 downto 0); -- Adressaugang |
10 | write: out std_logic; |
11 | warning_signal: out std_logic; |
12 | cs: in std_logic; |
13 | );
|
14 | end entity counter; |
15 | |
16 | ---------------------------------------------------------------------------
|
17 | |
18 | architecture arch_up_count of counter is |
19 | |
20 | signal addr: unsigned(9 downto 0) := "0000000000"; |
21 | signal in_data_old: std_logic_vector(7 downto 0); |
22 | |
23 | begin
|
24 | process(clk) |
25 | begin
|
26 | if rising_edge(clk)then |
27 | write <= '0'; |
28 | warning_signal <= '0'; |
29 | if cs = '0' then |
30 | addr <= "0000000000"; -- wenn cs 0 dann zähler auf Null stellen |
31 | in_data_old <= in_data; |
32 | else
|
33 | if (in_data != in_data_old) then |
34 | write <= '1'; |
35 | z_i <= std_logic_vector(addr); |
36 | out_data <= in_data; |
37 | in_data_old <= in_data; |
38 | if (addr < "1111111111") then |
39 | addr <= addr + 1; |
40 | else
|
41 | warning_signal <= '1'; |
42 | end if; |
43 | end if; |
44 | end if; |
45 | end process; |
46 | |
47 | end architecture arch_up_count; |
Das mit dem BUFFER tut man nicht ohne Not:
1 | value: Buffer std_logic_vector(9 downto 0) := "0000000000"; |
Besser ein lokales Signal definieren und das dann auf einen OUT-Port zuweisen (addr auf z_i).
Hallo Lothar, jetzt bin ich aber von den Socken. Wenn es dir nichts ausmacht, erklär mir doch bitte, was die ersten Zeilen des process machen!! Wenn ich das richtig interpretiere, setzt du write und warning_signal auf 0. Dann überprüfst du, ob CS gesetzt ist und warum kommt dann die Zeile "in_data_old <= in_data;" ? Schönen Gruß, michael
> Wenn es dir nichts ausmacht, erklär mir doch bitte, was die ersten > Zeilen des process machen!!
1 | process(clk) |
2 | begin
|
Das ist der übliche Prozess-Anfang... ;-) Die nachfolgenden finde ich für Anfänger interessanter:
1 | if rising_edge(clk)then |
2 | write <= '0'; |
3 | warning_signal <= '0'; |
> Wenn ich das richtig interpretiere, setzt du write und > warning_signal auf 0. Hier wird erstmal auf den Systemtakt (z.B. 50MHz) gewartet. Dann werden den Signalen Defaultwerte '0' zugewiesen, die im späteren Verlauf des Prozesses evtl. wieder mit einer '1' überschrieben werden. Und für einen Prozess gilt: die letzte Signalzuweisung gewinnt. > Dann überprüfst du, ob CS gesetzt ist Ja, das machst du doch auch... > und warum kommt dann die Zeile "in_data_old <= in_data;" ? Wenn beim Vergleich
1 | if (in_data != in_data_old) then |
bemerkt wird, dass sich was geändert hat, wird der aktuelle Wert für einen späteren Vergleich abgespeichert.
Danke dir Lothar, jetzt hab ich es verstanden. Mit den ersten Zeilen, meinte ich genau die Default-Werte. :) >> und warum kommt dann die Zeile "in_data_old <= in_data;" ? >Wenn beim Vergleich > > if (in_data != in_data_old) then > >bemerkt wird, dass sich was geändert hat, wird der aktuelle Wert für >einen späteren Vergleich abgespeichert. Ich Trottel hab das oberste if übersehen. So gibt das Sinn. :D Danke nochmal, michael
Thread bitte löschen!! Danke für die Tipps und Hilfestellungen. Schönen Gruß
>Thread bitte löschen!!
Wieso denn das?
ist doch absolutes Anfänger niveau.
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.