Forum: FPGA, VHDL & Co. Probleme beim Einbinden einer Instanz


von Jan (Gast)


Lesenswert?

Hallo Leute,

ich stehe momentan auf dem Schlauch, es geht darum das ich eine simple 
Intanz in einer höhrer Ebene einbinden möchte. Ansich keine große Sache, 
hat bis dato auch immer geklappt. Jedoch ist bei diesem das Problem, 
dass sobal ich die Instanz programmiere, diese bei der RTL Shematik 
ansicht verschwindet. Ist Sie Leer bleibt sie erhalten. Folgenden 
Meldungen bzgl der Isntanz wurden angegeben:

WARNING:Xst:737 - Found 1-bit latch for signal <VERZÖGERUNG>. Latches 
may be generated from incomplete case or if statements. We do not 
recommend the use of latches in FPGA/CPLD designs, as they may lead to 
timing problems.

WARNING:Xst:1290 - Hierarchical block <Inst_MEM_PUFFER> is unconnected 
in block <Inst_MEM>.
   It will be removed from the design.

WARNING:Xst:2677 - Node <Inst_MEM/Inst_MEM_PUFFER/FERTIG> of sequential 
type is unconnected in block <DEFS>.

Der Quelltext:

entity MEM_PUFFER is
    Port ( CLK : in  STD_LOGIC;
           VERZÖGERUNG : in  STD_LOGIC;
           FERTIG : out  STD_LOGIC);
end MEM_PUFFER;

architecture Behavioral of MEM_PUFFER is

begin

process (CLK)
begin
    if rising_edge(CLK) then
      if VERZÖGERUNG = '1' then
        FERTIG <= '1';
        else
        FERTIG <= '0';
      end if;
    end if;
end process;


end Behavioral;


Wäre für Eure Meinung/Hilfe sehr dankbar.

LG
Jan

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


Lesenswert?

Der Fehler liegt nicht im geposteten Code.

Jan schrieb:
1
 process (CLK)
2
 begin
3
     if rising_edge(CLK) then
4
       if VERZÖGERUNG = '1' then
5
         FERTIG <= '1';
6
         else
7
         FERTIG <= '0';
8
       end if;
9
     end if;
10
 end process;
Das ginge auch kürzer:
1
 process (CLK)
2
 begin
3
     if rising_edge(CLK) then
4
       FERTIG <= VERZÖGERUNG;
5
     end if;
6
 end process;

Oder ganz ohne Prozess:
1
 FERTIG <= VERZÖGERUNG when rising_edge(CLK);

BTW:
VERZÖGERUNG
Ich würde Umlaute im VHDL-Code tunlichst meiden...

von Jan (Gast)


Lesenswert?

Aber woran kann das denn sonst liegen?

Erstaunlicherweise ist die Instanz ohne Code eingebunden (sichtbar) und 
mit Code wird sie wieder rausgeworfen. Also an der verdrahtung liegt es 
nicht.

PS: Danke für den TIPP mit der verkürzung des Codes.

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


Lesenswert?

Jan schrieb:
> Erstaunlicherweise ist die Instanz ohne Code eingebunden
Wo denn?

von Jan (Gast)


Lesenswert?

In einer höheren Instanz

ich hab z.B einen block MEM in dem viele Instanzen sind, unter anderem 
soll da auch die Instanz PUFFER rein

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


Lesenswert?

Jan schrieb:
> In einer höheren Instanz
Dann wird dort der Fehler passieren...

> dass sobal ich die Instanz programmiere, diese bei der RTL Shematik
> ansicht verschwindet.
Da wird irgendwas wegoptimiert. Probiers doch mal mit der Syntheseoption 
"Keep Hierarchy" (aber nur als Workaroud, dein Problem liegt offenbar 
woanders).
> Ist Sie Leer bleibt sie erhalten.
Als funktionslose Black-Box.

Jan schrieb:
> ich hab z.B einen block MEM in dem viele Instanzen sind
Das glaube ich dir sofort, wenn sogar so eine simple Funktion eine 
eigene VHDL-Datei bekommt... :-o

von Jan (Gast)


Lesenswert?

Lothar Miller schrieb:
> Das glaube ich dir sofort, wenn sogar so eine simple Funktion eine
> eigene VHDL-Datei bekommt... :-o

Das hat seinen Grund, wenn ich könnte würde ich das vermeiden, vll finde 
ich noch eine andere Lösung.

Prinzipiell geht es darum das ich einen Zeit-Puffer brauche der mit 
zwischen zwei Zuständen zeit verschafft.

genau:

RAM wird in addr 0 mit Wert geladen, danach einmal komplett ausgelesen. 
Problem dabei ist das zwischen dem Auslesen und Schreiben 
unglücklicherweise anscheinend nicht genug zeit liegt, sodass der Wert 
in addr. 0 undefeniert bleibt. Zumindest wird beim Auslesen an dieser 
addr. ein undefeniertert Wert ausgegeben (roter bindestrich).

Das obwohl das RAM eigentlich zuvor mit Nullen geladen wurde.

vermutung war halt das zwischen schreiben und auslesen nicht genug Zeit 
liegt.

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


Lesenswert?

Jan schrieb:
> Zumindest wird beim Auslesen an dieser
> addr. ein undefeniertert Wert ausgegeben (roter bindestrich).
Dann ist der Zustand an dieser Stelle undefiniert, und das kommt 
normalerweise daher, dass zwei Treiber auf das gleiche Signal arbeiten. 
Lass doch mal die Synthese über dein Design laufen, da sollte dann was 
von "Multiple Source" bei dem entsprechenden Signal stehen...

von Jan (Gast)


Lesenswert?

Ich bekomme einige Warning, das an einigen Instanzen Signale nicht 
verwendet werden.

z.B.

WARNING:Xst:647 - Input <LOAD_DATA> is never used. This port will be 
preserved and left unconnected if it belongs to a top-level block or it 
belongs to a sub-block and the hierarchy of this sub-block is preserved.
Unit <MEM_MUX_DATA> synthesized.

Eigentlich bräuchte ich den Eingang LOAD_DATA nicht, die frage ist ob 
das fürs Programm schädlich ist wenn ich es so belasse?

Diese Meldung hab ich öfters, aber ich könnte es auch beheben, nur ist 
das notwendig?

Desweiteren:

WARNING:Xst:1780 - Signal <doutb> is never used or assigned. This 
unconnected signal will be trimmed during the optimization process.

WARNING:Xst:1780 - Signal <VAL_MTW> is never used or assigned. This 
unconnected signal will be trimmed during the optimization process.
Unit <DEFS> synthesized.


Diese Meldung kann ich nicht 100% verstehen, da beide Signale (ausgänge) 
während der Sim sich ändern. doutb ist das Signal am Ausgang des RAMs

Die Fehlermeldung/Warnung

mit Multiple Source erscheint nirgends

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


Lesenswert?

Jan schrieb:
> doutb ist das Signal am Ausgang des RAMs
Aber offenbar nirgends (sinnvoll) verwendet:
> Signal <doutb> is never used or assigned. This unconnected signal...

> Diese Meldung kann ich nicht 100% verstehen, da beide Signale (ausgänge)
> während der Sim sich ändern.
Die Simulation schert sich nicht drum, ob die Signale verwendet sind...

> Eigentlich bräuchte ich den Eingang LOAD_DATA nicht,
Warum machst du ihn dann nicht raus?
> die frage ist ob
> das fürs Programm schädlich ist wenn ich es so belasse?
Irgendwer wird den schon wegoptimieren... ;-)

von Jan (Gast)


Angehängte Dateien:

Lesenswert?

Hier nochmal 3 Bilder für der Sim

Schreiben:

Man sieht das addra auf 0 steht, welches die schreibadresse ist. Was ein 
wenig blöde ist, was ich auch nicht ganz in den Griff bekommen, ist das 
der LOAD_DATA_DONE einen Takt zu lange geht.

Auslesen_1:

man sieht das addrb auf 0 steht und somit eigentlich der vorher in addra 
0 geschriebene wert ausgelesen werden sollt. Die ausgelesenen Werte 
gehen gleich auf eine Einheit die aus alles Werte den aktuelle, 
minimalen und maximalen Wert ermittelt.
Was auffällgt ist das an data_in (von min_max_cur) der selbe Wert steht 
von addrb 0 und 1.

Auslesen_2:

hier sieht man mein eigentliches Problem. Kommt der zeiger addrb wieder 
an die Stelle 0 so wird angeblich ein nicht initialisierter Wert an die 
Einheit gegeben. Da diese unbestimmt ist wird dieser "Wert" als minimal 
Wert übernommen (Kann sich einer erklären warum?). Maximalwert und 
Minimalwert funktionieren noch

Ich weis das is viel aufeinmal aber vielleicht weis ja einer was da das 
problem sein könnte.

Danke im Voraus

von Jan (Gast)


Lesenswert?

Lothar Miller schrieb:
>> doutb ist das Signal am Ausgang des RAMs
> Aber offenbar nirgends (sinnvoll) verwendet:
>> Signal <doutb> is never used or assigned. This unconnected signal...

doutb geht an data_in (von min_max_cur), also laut sim wirds doch 
verwendet

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


Lesenswert?

Jan schrieb:
> Ich weis das is viel aufeinmal aber vielleicht weis ja einer was da das
> problem sein könnte.
Glückwunsch: Du hast entdeckt, was sich "Latency" nennt.

Offenbar setzt du ein Register namens read_data und bekommst erst einen 
Takt später tatsächlich deine Daten. Das ist irgendwo in deinem (bisher 
nicht veröffentlichten) Design aber tatsächlich genau so festgelegt.

Jan schrieb:
> also laut sim wirds doch verwendet
Da hat die Synthese offenbar eine andere Meinung. Und die Synthese ist 
für die Implementierung zuständig...
Evtl. wird data_in nicht verwendet, oder das Ergebnis von min_max_cur...

> Kann sich einer erklären warum?
Mangels Code: nein.
Mein vorschlag: pack doch alle deine VHDL-Module in eine einzige 
VHDL-Datei und poste die als Anhang...

von Jan O. (Firma: keine) (quamstar)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich hab mal das projekt mit den vhdl datein gezipt.

von TokyoDrift (Gast)


Lesenswert?

>Ich hab mal das projekt mit den vhdl datein gezipt.
Habs mal kurz teilweise überflogen. Wenn du mich fragst ist das kein 
Wunder, du mappst viele Ausgänge auf Signale die nie mehr verwendet 
werden, wieso sollte der das denn nicht rausoptimieren? Oo

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Ich kann die ja auch rausnehmen, aber würde das was an dem Problem 
ändern?
Ich hab bevor ich den Code geschrieben habe, zuvor mir alle bekannten 
Ein und Ausgänge im Module beschrieben, da war mir aber noch nicht klar 
das diese teilweise garnicht gebraucht werden (z.B bei den ganzen 
mutliplexern)

von TokyoDrift (Gast)


Lesenswert?

Jan O. schrieb:
> Ich kann die ja auch rausnehmen, aber würde das was an dem Problem
> ändern?
> Ich hab bevor ich den Code geschrieben habe, zuvor mir alle bekannten
> Ein und Ausgänge im Module beschrieben, da war mir aber noch nicht klar
> das diese teilweise garnicht gebraucht werden (z.B bei den ganzen
> mutliplexern)
Was ist denn eigentlich dein Problem? Wenn du die Signale (und damit 
Module) weglässt dann tauchen sie doch auch nicht in der RTL auf.
Pass auf:
du beschreibst ganz viel Hardware, bestehend aus vielen vielen Flipflops 
und Latches. Allerdings lässt du dann so viele Ein/Ausgänge offen, dass 
in jedem Fall der Ausgang des Moduls zB 0 ist. Nun kannst du natürlich 
die ganze Hardware im FPGA auch "aufbauen", aber du kannst auch einfach 
ein Signal, dass immer auf 0 ist nutzen. Letzteres braucht eben viel 
viel weniger Ressourcen und es passt mehr andere Logik in den FPGA. 
Erkennen ob ein bestimmter Teil deiner Hardware nützlich ist oder nicht 
tut das Synthese Tool vollautomatisch und "optimiert" dann, also 
entfernt/vereinfacht unnütze Sachen. Ist doch alles super, oder?

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Mein Problem habe ich oben geschildert. Die Signale die nicht verwendet 
werden, habe ich nun rausgenommen, klar spart Ressourcen, daran besteht 
kein Zweifel. Ich habe nur zu begin, wie schon gesagt vorsichtshalber 
alle Signale in die Entitiy geschrieben, ohne zu wissen welche ich 
tatsächlich gebrauche.

Schau dir mal die Bilder an und dann siehst du wo das Problem liegt. 
Wenn man sich das anschaut schein der Wert an addr 0 undefeniert zu 
sein, und das obwohl er ja zuvor einen bestimmten Wert (Mittelwert aus 
VAL1-4) reingeschrieben hat.

von TokyoDrift (Gast)


Lesenswert?

U heißt undefined. X heißt, dass ein Ausgang mehrere Eingänge hat die 
ihn auf verschiedene Pegel ziehen. Sowas ist ganz schlecht.
Allerdings sehe ich in der RTL und auch im Code nichts was das triggern 
könnte. Evtl ist was in MEM_RAM, das ist bei mir nur ein Blackboxmodul.

von bko (Gast)


Lesenswert?

Wo ist denn der VHDL-code für das RAM (Instance "MEM_RAM") ?
In der Datei "TEST.rar" finde ich es nicht.

Bzw: welchen RAM typ verwendest du:
   "Dual-Port RAM With Synchronous Read (Read Through) and Two Clocks"
 oder "Dual-Port Block RAM With Different Clocks" ?

von TokyoDrift (Gast)


Lesenswert?

Soso, hier ist doch was interessantes
1
process (CLK)
2
begin
3
      if rising_edge (CLK) then
4
      --auslesen_addrb_s <= AKTUELLE_ADDR;
5
        if READ_DATA = '1' then
6
          for i in 0 to 255 loop
7
          zählstand_lesen <= zählstand_lesen + 1;
8
          auslesen_addrb_s <= auslesen_addrb_s + 1;    
9
          end loop;
10
            if zählstand_lesen = 256 then
11
              READ_DONE_S <= '1';
12
              zählstand_lesen <="000000000";
13
              else 
14
              READ_DONE_S <= '0';
15
            end if;
16
        end if;
17
      end if;
18
end process;

#1: Umlaute. Bitte keine Umlaute. Darf er das überhaupt ohne 
entsprechende Kennzeichnung des Signals
#2: for loop? Darf man das überhaupt Synchron? Mal ernsthaft, sowas ist 
doch grauenhaft.
#3: Soso. Nu sagst mir mal wann ein 8bit Wert 256 wird? Wenn er 0 ist, 
genau. Allerdings wird er dann auch in dem loop gesetzt. Viel spaß mit 
deinem X.

von TokyoDrift (Gast)


Lesenswert?

Ach, tut mir Leid, zählerstand_lesen ist ein 9bit Wert. Trozdem trau ich 
diesem Konstrukt nicht über den Weg. Kannst du das mal bisschen 
abändern, bitte?

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Also,

das RAM ist aus dem CORE manager: SIMPLE DUAL PORT

das mit den 256 habe ich machen müssen damit der zeiger auf der aktuelle 
addresse stehen bleibt. Es hat den anschein das der erste Wert der ja 
eigentlich in adresse 0 geladen werden soll in addresse 1 wird.

Es muss also irgendwie probleme mit den schreiben geben. Anscheinend 
wird die eins nicht in stelle 0 sondern in stelle 1 geschrieben, aber 
was mit der stelle 0 passiert ist mir schleierhaft.

von TokyoDrift (Gast)


Lesenswert?

Jan O. schrieb:
> das mit den 256 habe ich machen müssen damit der zeiger auf der aktuelle
> addresse stehen bleibt. Es hat den anschein das der erste Wert der ja
> eigentlich in adresse 0 geladen werden soll in addresse 1 wird.
>
> Es muss also irgendwie probleme mit den schreiben geben. Anscheinend
> wird die eins nicht in stelle 0 sondern in stelle 1 geschrieben, aber
> was mit der stelle 0 passiert ist mir schleierhaft.

Ich sag doch, for macht man nicht getaktet. Machs halt mal zu ner FSM
so von wegen
1
CASE (COUNTER) IS
2
   WHEN 0 =>
3
      READ_DONE_S <= '1';      
4
   WHEN OTHERS =>
5
      READ_DONE_S <= '0';
6
END CASE;
7
auslesen_addrb_s <= auslesen_addrb_s + 1;

Ist nich ganz deins aber zum Testen sollts das tun.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Keine Ahnung wie du das genau meinst,

aber wieso kann man for loops nicht taktgesteuert machen?

theoretisch kann ich dir foor loop auch rausnehmen:

process (CLK)
begin
      if rising_edge (CLK) then
      --auslesen_addrb_s <= AKTUELLE_ADDR;
        if READ_DATA = '1' then
          --for i in 0 to 255 loop
          zaehlstand_lesen <= zaehlstand_lesen + 1;
          auslesen_addrb_s <= auslesen_addrb_s + 1;
          --end loop;
            if zaehlstand_lesen = 256 then
              READ_DONE_S <= '1';
              zaehlstand_lesen <="000000000";
              else
              READ_DONE_S <= '0';
            end if;
        end if;
      end if;
end process;
addrb <= auslesen_addrb_s;
READ_DONE <= READ_DONE_S;
READ_DONE_ADDR <= READ_DONE_S;

ändert am ergebniss nix


Der hat nur probleme mit der Stelle 0 vom RAM, ich könnt brechen...

von Tokyo D. (tokyodrift)


Lesenswert?

>aber wieso kann man for loops nicht taktgesteuert machen?
>
>theoretisch kann ich dir foor loop auch rausnehmen:

Deswegen. Ich bin mir gerade nicht sicher aber ich denk nicht, dass for 
sequentiell ist. Und eben weil du es einfach weglassen kannst macht man 
das auch. Hab in der RTL nachgeschaut, der hats mit for auch gut 
umgesetzt.

Dein Code ist einfach sehr ausgedehnt und um ehrlich zu sein versteh ich 
nicht so recht wozu er gut sein soll (hab aber auch nur Teile 
angeschaut).

von berndl (Gast)


Lesenswert?

Julian X. schrieb:
> Deswegen. Ich bin mir gerade nicht sicher aber ich denk nicht, dass for
> sequentiell ist. Und eben weil du es einfach weglassen kannst macht man
> das auch. Hab in der RTL nachgeschaut, der hats mit for auch gut
> umgesetzt.

Die 'for' loop ist genau fuer sequentielle Prozesse gedacht. Waere es 
'concurrent' dann muesste er ein 'generate' nehmen.
Aber der Inhalt einer for-loop mit 256 Durchlaeufen erzeugt halt auch 
256 mal Hardware...

von Tokyo D. (tokyodrift)


Lesenswert?

berndl schrieb:
> Aber der Inhalt einer for-loop mit 256 Durchlaeufen erzeugt halt auch
> 256 mal Hardware...

Genau das meine ich. Es wird die Hardware für jeden Durchlauf erzeugt, 
anstatt eine Hardware die immer wieder genutzt wird. In diesem Fall ist 
der for loop doch einfach Quatsch, oder?

von berndl (Gast)


Lesenswert?

Julian X. schrieb:
> Genau das meine ich. Es wird die Hardware für jeden Durchlauf erzeugt,
> anstatt eine Hardware die immer wieder genutzt wird. In diesem Fall ist
> der for loop doch einfach Quatsch, oder?

ich hab' mir die HW nicht angeschaut, kann also nix dazu sagen. Aber 
wenn man was 256x einbaut sollte man sehr gute Gruende dafuer haben...

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Die For Schleife ist raus, wie schon geschrieben, ist diese völlig 
unnötig.

Das ganze ding dient zu einer Datenerfassung.

Es wird ein Wert in ein 256 Zeilen Rößes Ram geschrieben dann einmla 
komplett ausgelesen und somit der minimale und maximale Wert im RAM 
bestimmt. Zusätzliches wird der Aktuelle Wert ausgegeben, welcher ja dem 
Wert entspricht auf welcher die Leseadresse grade steht.

Zuvor wird das RAM mit Nullen initialisiert (RESET) und das kann es auch 
während der ganzen prozedur (mit einem erneuten RESET).

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


Lesenswert?

Jan O. schrieb:
> Es wird ein Wert in ein 256 Zeilen Rößes Ram geschrieben dann einmla
> komplett ausgelesen und somit der minimale und maximale Wert im RAM
> bestimmt.
So ein Ram gibt es gar nicht, auf das innerhalb eines Taktes mit der 
gesamten Adressbreite zugegriffen werden könnte...
Das kann alles sein, aber garantiert kein RAM mit einem Adress- und 
einem Datenbus.

> Zuvor wird das RAM mit Nullen initialisiert (RESET) und das kann es auch
> während der ganzen prozedur (mit einem erneuten RESET).
Suspekt, das. Sehr suspekt.

Jan O. schrieb:
1
process (CLK)
2
begin
3
      if rising_edge (CLK) then
4
      --auslesen_addrb_s <= AKTUELLE_ADDR;
5
        if READ_DATA = '1' then
6
          for i in 0 to 255 loop
7
            zaehlstand_lesen <= zaehlstand_lesen + 1;
8
            auslesen_addrb_s <= auslesen_addrb_s + 1;
9
           end loop;

Und dann ist klar: das hier passiert alle 256 Takte:
1
            if zaehlstand_lesen = 256 then
2
              READ_DONE_S <= '1';
3
              zaehlstand_lesen <="000000000";
4
              else
5
              READ_DONE_S <= '0';
6
            end if;
An diesem seltsamen Konstrukt schüttelt sich deer Synthesizer die grauen 
Haare aus dem Kopf. Eine for-Schleife mit zwei Signalen, sowas hat er 
noch nicht gesehen...
Nur mal kurz nachdenken: in einem Prozess gewinnt die letzte Zuweisung 
an ein Signal. Und welche ist das? Richtig, die hier:
1
            zaehlstand_lesen <= zaehlstand_lesen + 1;
2
            auslesen_addrb_s <= auslesen_addrb_s + 1;
Deshalb ist es auch schnurzegal, ob die Schleife drin ist oder nicht...
:-o

von berndl (Gast)


Lesenswert?

Lothar Miller schrieb:
> Nur mal kurz nachdenken: in einem Prozess gewinnt die letzte Zuweisung
> an ein Signal. Und welche ist das? Richtig, die hier: 
zaehlstand_lesen <= zaehlstand_lesen + 1;
>             auslesen_addrb_s <= auslesen_addrb_s + 1;
> Deshalb ist es auch schnurzegal, ob die Schleife drin ist oder nicht...
> :-o
>
>
>
>     Beitrag melden | Bearbeiten | Löschen |

:o)

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Lothar Miller schrieb:
> So ein Ram gibt es gar nicht, auf das innerhalb eines Taktes mit der
> gesamten Adressbreite zugegriffen werden könnte...

Wer sagt denn sowas? und natürlich gibt es RAMs mit 256 adresszeilen 
(8Bit)

Es wird nicht über einen Takt alles ausgelesen sondern mit Hilfe des 
taktes wird die addrb (welche zum auslesen des RAMs dient) immer um ein 
erhöht solange bis diese wieder auf der ausgangsadresse steht.

Das zählen bis 256 hat den Grund das der wieder mitunter eine andresse 
weiterrücke, da die nächste Schreibadresse auch um eines erhöht wird. 
Wenn er dann wieder ausliest ist somit gewährleistet das der Aktuelle 
Wert auch der Wert ist auf der Zeiger der Schreibadresse steht.

Die Loop geschichte ist mittlerweile 2 std alt und wurde schon längst 
aus dem Quellcode genommen (s.o.)

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


Lesenswert?

Jan O. schrieb:
> Wer sagt denn sowas? und natürlich gibt es RAMs mit 256 adresszeilen
> (8Bit)
Klar.

> Es wird nicht über einen Takt alles ausgelesen sondern mit Hilfe des
> taktes wird die addrb (welche zum auslesen des RAMs dient) immer um ein
> erhöht solange bis diese wieder auf der ausgangsadresse steht.
Ja, aber laut dem Text bei einem Reset alles im RAM gleichzeitig auf '0' 
gesetzt.
>>> Zuvor wird das RAM mit Nullen initialisiert (RESET) und das kann es auch
>>> während der ganzen prozedur (mit einem erneuten RESET).
Das wäre ein gleichzeitiges Beschreiben aller Zellen. So funktioniert 
kein RAM, wie ich es kenne. Die haben keine Reset-Leitung.

> Die Loop geschichte ist mittlerweile 2 std alt und wurde schon längst
> aus dem Quellcode genommen (s.o.)
Mich wundert, wie sie es überhaupt hineingeschafft hat...

Ich habe mir den Code angeschaut, aber offen und ehrlich: ich blicke da 
nicht durch. Und ich habe den strengen Verdacht, dass es wesentlich 
einfacher ginge. Warum wird denn da jeder Mikro-Funktionsblock in sich 
gekapselt? Mit dieser Beschreibungsart hat VHDL seinen Ruf bekommen, 
unübersichtlich zu sein...

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Lasst euch nicht von dem Wort RESET stören. RESET bedeutet nichts 
anderes das das RAM mit nullen aufgefüllt wird. Ich lasse die 
schreibadresse (addra) 255 mal jeweils mit dem Takt um eine stelle 
erhöhen und bei der stelle wird in dina (der Eingang des RAMs) eine Null 
gealaden.

Die Loop geschichte kommt aus der überlegung wie man am besten sowas 
auslesen kann, bzw. mit "Nullen" auffüllen kann. da denkt man sofort: 
Für/FOR 255 stellen muss ich auslesen/schreiben. Das das unnötig war ist 
mir später erst bewusst gerworden. Es kommt ja oft vor das man im 
Nachhinein erkennt das es auch einfacher geht. Das kann mir jetzt keiner 
sagen das, dieser Fall noch niemanden untergekommen ist.

Das das so komplex wirkt liegt wohl daran, das ich (wie schon erkannt) 
viele einzelne Instanzen gebildet habe. Klar kann man sich diese auch 
sparen nur mein Prof meinte wenn es geht machen Sie viele Instanzen, 
damit grade die Übersicht noch beibehällt.

Ich weis nicht, ob man diese Multiplex-Instanzen auch andersweitig 
einbinden kann?

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


Lesenswert?

> Es wird ein Wert in ein 256 Zeilen Rößes Ram geschrieben dann einmla
> komplett ausgelesen und somit der minimale und maximale Wert im RAM
> bestimmt.
Dafür bräuchte es noch kein RAM. Den Maximal- und Minimalwert kann man 
auch im laufenden Datenstrom bestimmen und per Reset zurücksetzen.

> Zusätzliches wird der Aktuelle Wert ausgegeben, welcher ja dem
> Wert entspricht auf welcher die Leseadresse grade steht.
Dieser Wert ist allerdings komplett uninteressant, weil die Top-Entity 
nicht mal die aktuelle Leseposition zurückgibt:
1
entity DEFS is
2
    Port ( CLK : in  STD_LOGIC;
3
           VAL1 : in  STD_LOGIC_VECTOR (7 downto 0);
4
           VAL2 : in  STD_LOGIC_VECTOR (7 downto 0);
5
           VAL3 : in  STD_LOGIC_VECTOR (7 downto 0);
6
           VAL4 : in  STD_LOGIC_VECTOR (7 downto 0);
7
           NEW_DATA : in  STD_LOGIC;
8
           MAX_VAL : out  STD_LOGIC_VECTOR (7 downto 0);
9
           MIN_VAL : out  STD_LOGIC_VECTOR (7 downto 0);
10
           CUR_VAL : out  STD_LOGIC_VECTOR (7 downto 0);
11
           RESET : in  STD_LOGIC);
12
end DEFS;
CUR_VAL kann also einfach jeder x-beliebige Wert im RAM sein.

> Zuvor wird das RAM mit Nullen initialisiert (RESET) und das kann es
> auch während der ganzen prozedur (mit einem erneuten RESET).
Das ist m.E. unnötiger Aufwand.

Für mich bleibt jetzt an Funktionalität übrig:
Ein Modul, das aus 4 Werten einen Mittelwert bildet, und dann aus den 
eingelesenen Mittelwerten nach 256 Takten den min und max Wert ausgibt.
Diese Architecture schreibe ich dir in 30 Zeilen und in 1 Modul... ;-)
Und: du kannst anschliessend problemlos erkennen, was damit gemeint war.


BTW: was passiert, wenn NEW_DATA z.B. 300 mal kommt?

Jan O. schrieb:
> mein Prof meinte wenn es geht machen Sie viele Instanzen,
> damit grade die Übersicht noch beibehällt.
Meinte er evtl. so was:
Wenn es geht machen Sie so viele Instanzen,
dass man grade noch die Übersicht bebehält.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

der aktuelle Wert ist gefordert. Wenn NEW_DATA öfters als 256 mal kommt 
wird der zu erst geschriebene Wert überschrieben.

Das Freut mich das du das in 30 Zeilen in einem Modul schreiben kannst. 
Ich kann es nicht, da ich noch nicht so viel Erfahrung gesammelt habe.

der RESET ist in sofern nötig, wenn ich z.B nach 200 schreibvörgängen 
das RAM mit Nullen füllen will. Somit ändern sich nach dem RESET 
sämtliche MAX MIN und CUR werte


Zumal ist die Diskussion über den Sinn der Aufgabe unnötig, da ich diese 
Aufgabeenstellung so zu lösen habe. Vielmehr würde mich interessieren 
warum scheinbar bei Auslesen der adresse 0 ein - erscheint und warum 
dieses dann für den MIN Wert so übernommen wird und sich mit keinem 
weiteren eingelesenen Wert ändert.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Hallo nochmal,

mal was anderes, kann mir einer vll. einer einen Verbesserungsvorschlag 
geben, sodass der MIN_VAL nicht einen Takt später ausgegeben wird als 
die beiden anderen?

entity MIN_MAX_CUR is
    Port ( CLK : in STD_LOGIC;
        DATA_IN : in  STD_LOGIC_VECTOR (7 downto 0);
           CALC_EN : in STD_LOGIC;
        MAX_VAL : out  STD_LOGIC_VECTOR (7 downto 0);
           MIN_VAL : out  STD_LOGIC_VECTOR (7 downto 0);
           CUR_VAL : out  STD_LOGIC_VECTOR (7 downto 0));
end MIN_MAX_CUR;

architecture Behavioral of MIN_MAX_CUR is

signal MAX_S : STD_LOGIC_VECTOR (7 downto 0):="00000000";
signal MIN_S : STD_LOGIC_VECTOR (7 downto 0):="11111111";
signal CUR_S : STD_LOGIC_VECTOR (7 downto 0);

begin


process (CLK)
begin

    if rising_edge (CLK) then

      if CALC_EN = '1' then
      CUR_S <= DATA_IN;

        if (MAX_S < DATA_IN)  then
        MAX_S <= DATA_IN;

          elsif (MIN_S > DATA_IN) then
          MIN_S <= DATA_IN;

        end if;
      end if;
  end if;

end process;
MIN_VAL <= MIN_S;
MAX_VAL <= MAX_S;
CUR_VAL <= CUR_S;

end Behavioral;


Danke im Voraus, ich hab nähmlich die befürchtung das es dazu zu dem 
oben besagten Fehler kommt

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


Angehängte Dateien:

Lesenswert?

Jan O. schrieb:
> sodass der MIN_VAL nicht einen Takt später ausgegeben wird als
> die beiden anderen?
Ich habe das mal simuliert. Und siehe da: alle Daten werden mit der 
steigenden Taktflanke aktualisiert. So wie es beschrieben ist.

> der aktuelle Wert ist gefordert. Wenn NEW_DATA öfters als 256 mal kommt
> wird der zu erst geschriebene Wert überschrieben.
Der aktuelle Wert ist aber nicht der, auf den der Lesepointer zeigt? Der 
aktuelle Wert ist doch der, der aus der Mittelwertbildung der 4 
Eingangswerte entsteht, oder?

Jan O. schrieb:
> der RESET ist in sofern nötig, wenn ich z.B nach 200 schreibvörgängen
> das RAM mit Nullen füllen will. Somit ändern sich nach dem RESET
> sämtliche MAX MIN und CUR werte
Ja, sie werden zurückgesetzt.
Wenn im Ram eine 0 steht ist MIN auch sofort 0...

Seis drum. Du willst das nicht hören...
Warum machst du diese min-max-Berechnung eigentlich getaktet?
Das ist doch eine rein kombinatorische Berechnung, da braucht es 
eigentlich keinen Takt.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Lothar Miller schrieb:
> Der aktuelle Wert ist aber nicht der, auf den der Lesepointer zeigt? Der
> aktuelle Wert ist doch der, der aus der Mittelwertbildung der 4
> Eingangswerte entsteht, oder?

Also wenn ich einen Wert einschreibe ist das der aktuelle Wert, lese ich 
nun aus bleibt der auslesezeiger ja wieder auf der adresse vor dem 
auslesen stehen, welche wiederrum die adresse ist wo der letzte Wert 
reingeschrieben wurde. Sicher ändern sich im Lauf der auslesezeit die 
Werte und auch der aktuelle, aber zwischen den NEW_DATA impulsen liegen 
ja auch gewisse Zeiten, sodass nach dem Auslesen der Punkt ist wo die 
Werte MIN MAX UND CUR von interesse sind.

Lothar Miller schrieb:
> Seis drum. Du willst das nicht hören...
> Warum machst du diese min-max-Berechnung eigentlich getaktet?
> Das ist doch eine rein kombinatorische Berechnung, da braucht es
> eigentlich keinen Takt.

Da geb ich dir recht, ich hatte diese Instanz schon vorher gemacht und 
war der Meinung das dies Tanktgesteuert sein müsse, aber es stimmt das 
dies rein kombinatorisch ist.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

So, also Takt ist raus und funzt super, allerdings gibts immer noch das 
Problem mit dem MIN Wert das der XXXXXXX (------) wird.

Ne blöde Frage, aber was genau bedeutet das eigentlich? Undefinded ist 
ja UUUUU.

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


Lesenswert?

U heißt undefiniert, ein X ist eine Kollision, da versuchen 2 Prozesse 
gleichzeitig zu treiben...
http://www.cs.sfu.ca/~ggbaker/reference/std_logic/1164/std_logic.html

von gnihihi (Gast)


Lesenswert?

jan <= lutscher;

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


Lesenswert?

gnihihi schrieb:
> jan <= lutscher;
Nein, das wird ja erst am Ende des gesamten Prozesses aktualisiert.
Ich wäre für
 jan := lutscher;

;-)

von gnihihi (Gast)


Lesenswert?

agree g

von Kiki (Gast)


Lesenswert?

gnihihi schrieb:
> jan <= lutscher;

Lothar Miller schrieb:
> gnihihi schrieb:
>> jan <= lutscher;
> Nein, das wird ja erst am Ende des gesamten Prozesses aktualisiert.
> Ich wäre für
>  jan := lutscher;
>
> ;-)



welch Geistreiche Kommentare...

Ich habe mal deinen Code überflogen, ich rate dir mal zu schauen welche 
Prozesse möglicherweise gleichzeitig (siehe Kommentar L.M) einwirken, 
allerdings kann ich nicht erkennen wo das der Fall ist, und zudem werden 
die anderen Werte (MAX und CUR (CUR kurzzeitig)) nicht davon beeinflusst

LG

von zischer (Gast)


Lesenswert?

ich hab in den code natürlich NICHT reingeschaut und kann nur auf eine 
gescheite resolution funktion hinweisen wenn mehrere treiber auf einem 
signal liegen.. sollte mit ner stinknormalen "case" gehen

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


Lesenswert?

Kiki schrieb:
> allerdings kann ich nicht erkennen wo das der Fall ist
Das ist bei dem geposteten Projekt ja das Problem, auf das ich mir dann 
einen kleinen verbalen Seitenhieb genehmigt hatte. Es ist so unglaublich 
unüberschaubar...

Da kam die Aussage:
Jan O. schrieb:
> Zumal ist die Diskussion über den Sinn der Aufgabe unnötig, da ich diese
> Aufgabeenstellung so zu lösen habe.
Aber ein gut Stück früher hieß es noch:
Jan O. schrieb:
> Das das so komplex wirkt liegt wohl daran, das ich (wie schon erkannt)
> viele einzelne Instanzen gebildet habe.
Die Unübersichtlichkeit war aber offenbar nicht das ziel des Projekts:
> Klar kann man sich diese auch sparen nur mein Prof meinte wenn es
> geht machen Sie viele Instanzen, damit grade die Übersicht noch
> beibehällt.

Ich habe mir das nochmal angeschaut und hege den Verdacht, dass an der 
Adresse 255 einfach nichts im RAM steht, weil nichts reingeschrieben 
wird.
Ich vermute also, es geht da im MEM_MUX_ADDRA schief:
1
  if LOAD_NULL = '1' then
2
    addra <= RESET_ADDRB;
3
  else 
4
    addra <= NEXT_ADDR_B;
5
  end if;

von Kiki (Gast)


Lesenswert?

Lothar Miller schrieb:
> Ich habe mir das nochmal angeschaut und hege den Verdacht, dass an der
> Adresse 255 einfach nichts im RAM steht, weil nichts reingeschrieben
> wird.
> Ich vermute also, es geht da im MEM_MUX_ADDRA schief:

if LOAD_NULL = '1' then
>     addra <= RESET_ADDRB;
>   else
>     addra <= NEXT_ADDR_B;
>   end if;

Anfänglich wird doch durch den "RESET" vorgang das RAM mit Nullen 
geladen, wenn ich die Signale anschaue, dann scheint die addresse 255 
auch eine "0" zu bekommen.

Danach scheint der adresszähler auf addresse 0 zu springen und dann soll 
in dieser addresse der erste Wert eingeschrieben werde.

Beim Auslesen scheinen die nachvollge adressen (1,2,3...) auch mit Null 
beschrieben worden zu sein. Wie du schon erkannt hast wird ja einen Takt 
später dann der Calculierter Wert/Werte ausgegeben, folglich scheint was 
mit der addr 255 nicht zu stimmen.

Der Code da oben ist ja nix anderes als ein Schalter der entweder zum 
Null auffüllen oder zum Wert einschreiben dienen soll, zumindest würd 
ich das so sehen.

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


Lesenswert?

Kiki schrieb:
> dann scheint die addresse 255 auch eine "0" zu bekommen.
(Wie) hast du das kontrolliert? Das Auslesen ist ja ziemlich 
Straight-Forward, das Schreiben habe ich noch nicht durchschaut...  ;-)

von Kiki (Gast)


Lesenswert?

im Zustand init (state) wird als allererste addra im takt erhöht und das 
so lange bis alles adressen einmal durchlaufen sind. Am dina (wird der 
Eingang des RAMs sein) liegt zu diesem Zeitpunkt "0" an. Wenn der 
durchlaufen ist, kommt ein Signal das bestätigt das der "RESET" erfolgt 
ist und es kann somit in den Zustand "IDLE" gehen, wo auf ein NEW_DATA 
impuls gewartet wird. Der Zeiger addra zeigt zu diesem Zeitpunkt wieder 
auf die Stelle 0

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Danke Kiki das du dir die Mühe gemacht hast. Du hast das prinzip wie das 
gehen soll verstanden, und es ist mir eine große Hilfe. Somit weis ich 
zumindest genauer wo ich zu schauen habe.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Ich hab hier nochmal eine interessante Meldung von Modelsim, kann sich 
die vll jmd erklären:

 ** Note: Block Memory Generator CORE Generator module is using a 
behavioral model FOR simulation which will not precisely model memory 
collision behavior.
#    Time: 20 ns  Iteration: 1  Instance: 
/tb_defs/uut/inst_mem/inst_mem_ram/u0/mem_module
# ** Warning: blk_mem_gen_v4_2 WARNING: Address 255 is outside range FOR 
A Write
#    Time: 5100 ns  Iteration: 1  Instance: 
/tb_defs/uut/inst_mem/inst_mem_ram/u0/mem_module
# ** Warning: blk_mem_gen_v4_2 WARNING: collision detected: A write 
address: 00000000, B read address: 00000000

Genau da liegt der Hund begraben, nur leider kann ich die Fehlermeldung 
nicht 100% deuten.

Scheinbar kommt zum einem gleichem Zeitpunkt es zu der Situation das die 
andresse 00000000 gleichzeitig gelesen und beschrieben wird oder sehe 
ich das Falsch?

von T.M. (Gast)


Lesenswert?

Das siehst du richtig, bei 5100ns scheint die gleiche Adresse 
geschrieben & gelesen zu werden. Das Verhalten in so einem Fall in der 
Simulation hängt von dem Verhaltensmodell des RAMs ab. Wenn man sich im 
RAM-Generator einen Dualport-RAM erstellen lässt, kann man oft 
einstellen, was in einem solchen Fall passieren soll. Dass der Leseport 
da "XXXX..." zeigt ist zB. eins der Möglichkeiten. Das von dir genutzte 
RAM-Modell scheint sich genau so zu verhalten, zumindestens das 
Verhaltensmodell kann mit einem solchen Fall nicht umgehen. Du musst 
diese Situation also umgehen.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Ich habe jetzt rumprobiert und im Datasheet sind einige interessante 
Infos, ich habe jetzt empirisch erstmal den PORT B auf READ-First 
gestellt und bisher siehts gut aus, es kommen zwar noch Warnungen (wie 
oben) aber es wird der Richtige Wert ausgegeben. Momentan ist das 
Problem das wenn der RESET kommt das RAM nicht mit Nullen 
vollgeschrieben wird. Aber das wird sicher ne weitere kleinigekeit sein.

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


Lesenswert?

Jan O. schrieb:
> Momentan ist das Problem das wenn der RESET kommt das RAM nicht mit
> Nullen vollgeschrieben wird.
> Aber das wird sicher ne weitere kleinigekeit sein.
Ja, ist es sicher, denn dein Design braucht ja derzeit gerade mal ca. 0% 
des FPGAs:
1
Device Utilization Summary (estimated values)
2
Logic Utilization          Used  Available   Utilization
3
Number of Slices            71    8672         0%
4
Number of Slice Flip Flops  88    17344        0%
5
Number of 4 input LUTs      122   17344        0%

Aber weil es so unglaublich verwinkelt ist, dass nur Kiki da nach 2 
Tagen durchblickt, tust du dir sogar bei so einem simplen Fehler schwer, 
obwohl dein FPGA-Design noch nicht mal 1% des FPGAs ausnutzt... :-o

Ich habe Projekte, da ist bei so einem Projektbaum das FPGA voll.

Warum willst du nicht einfach (wie schon des öfteren angeboten) deine 
Projektanforderungen hier mal einstellen. Evtl könnte man dann ein paar 
Vereinfachungen vornehmen/vorschlagen.

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


Angehängte Dateien:

Lesenswert?

Lothar Miller schrieb:
> Ich habe Projekte, da ist bei so einem Projektbaum das FPGA voll.
Schlags kaputt, Anhang vergessen...

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Wenn du aufmerksam lesen würdest, hättest du festgestellt das diese hier 
schon mehrfach aufgeführt wurde.

nochmal:

Mittelwertbestimmung aus vier 8 Bit Zahlen:
im Zustand INIT wird das RAM durch einen synchronen RESET mit NULLEN 
vollgeschrieben. Danach zustand IDLE wo auf NEW_DATA gewartet wird und 
dann der errechnete Mittelwert in die erste adresse des RAM geschrieben 
wird (SCHREIBEN). Hiernach geht FSM ist den Zustand CALCULATE wo das 
gesamte RAM ausgelesen wird und durch eine Einheit am Ausgang so der 
MIN-, MAX -und CUR Wert ausgegeben wird. Nach dem Auslesen wird die 
schreibadresse um eine Stelle erhöht und es wird in den Zustand IDLE 
wieder auf eine NEW_DATA Impuls gewartet. (Diese Werte von dem AVARAGE 
Modul können WIllkürlich sein)

Verwendet habe ich eine CORE_Generated RAM (Simple Dual Port).

Da sich aber mittlerweile (auch teils durch Eure Hilfe) viel 
verändert/vereinfacht hat, ist das Projekt was ich Euch gezipt habe 
verwerflich.

Momentan läuft das Ding, einen kleinen Fehler habe ich noch drinne, aber 
wie dein vorgänger schon geschrieben hat, schien das generiert RAM 
falsch eingestellt gewesen zu sein.

Danke für Eure Mühen.

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


Lesenswert?

Jan O. schrieb:
> nochmal:
Ich wollte nicht wissen, wie du das lösen willst, sondern was da 
weshalb passieren soll...

> Wenn du aufmerksam lesen würdest, hättest du festgestellt das diese hier
> schon mehrfach aufgeführt wurde.
Wenn du aufmerksam gelesen hättest, dann hättest du gemerkt, dass die 
Frage an sich noch nicht beantwortet wurde, und du den Blick über
den Tellerrand nicht wagst.
Die Frage war:
WARUM muß das genauso passieren?
WESHALB darfst du das nicht einfacher lösen?
Stell dir mal diese Fragen selber und dann deinem Betreuer...

> Momentan läuft das Ding,
Gut so.

> Danke für Eure Mühen.
De nada... ;-)

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.