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
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.
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
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.
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...
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
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... ;-)
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
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
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...
>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
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)
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?
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.
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.
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" ?
#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.
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?
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.
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
WHEN0=>
3
READ_DONE_S<='1';
4
WHENOTHERS=>
5
READ_DONE_S<='0';
6
ENDCASE;
7
auslesen_addrb_s<=auslesen_addrb_s+1;
Ist nich ganz deins aber zum Testen sollts das tun.
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...
>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).
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...
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?
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...
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).
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
ifrising_edge(CLK)then
4
--auslesen_addrb_s <= AKTUELLE_ADDR;
5
ifREAD_DATA='1'then
6
foriin0to255loop
7
zaehlstand_lesen<=zaehlstand_lesen+1;
8
auslesen_addrb_s<=auslesen_addrb_s+1;
9
endloop;
Und dann ist klar: das hier passiert alle 256 Takte:
1
ifzaehlstand_lesen=256then
2
READ_DONE_S<='1';
3
zaehlstand_lesen<="000000000";
4
else
5
READ_DONE_S<='0';
6
endif;
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
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)
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.)
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...
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?
> 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
entityDEFSis
2
Port(CLK:inSTD_LOGIC;
3
VAL1:inSTD_LOGIC_VECTOR(7downto0);
4
VAL2:inSTD_LOGIC_VECTOR(7downto0);
5
VAL3:inSTD_LOGIC_VECTOR(7downto0);
6
VAL4:inSTD_LOGIC_VECTOR(7downto0);
7
NEW_DATA:inSTD_LOGIC;
8
MAX_VAL:outSTD_LOGIC_VECTOR(7downto0);
9
MIN_VAL:outSTD_LOGIC_VECTOR(7downto0);
10
CUR_VAL:outSTD_LOGIC_VECTOR(7downto0);
11
RESET:inSTD_LOGIC);
12
endDEFS;
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.
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.
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
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.
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.
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.
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
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
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:
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.
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... ;-)
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
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.
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?
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.
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.
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.
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.
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 überden 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... ;-)