Forum: FPGA, VHDL & Co. Hilfestellung bei Projekt


von Michael K. (bomi)


Lesenswert?

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

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


Lesenswert?

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

von sunny (Gast)


Lesenswert?

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

von Michael K. (bomi)


Lesenswert?

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

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


Lesenswert?

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

von Michael K. (bomi)


Lesenswert?

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

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


Lesenswert?

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

von Michael K. (bomi)


Lesenswert?

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

von Michael K. (bomi)


Lesenswert?

Thread bitte löschen!!
Danke für die Tipps und Hilfestellungen.


Schönen Gruß

von löschi (Gast)


Lesenswert?

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