Hallo,
ich möchte über 2 Array`s eine Adresse auswählen und beschreiben.
Das ganze klappt auch, solange ich jede Adresse nur 1mal in den Array
belege.
Bsp:
Das ganze passiert über eine Statemaschine. Die StateMaschin selber ist
unabhängig vom Takt, allerdings der Zustandswechsel ist Taktabhängig(da
das aber nicht das Problem ist, hab ich es hier weggelassen).
Es gibt eine Variable h die hochgezählt wird um die einzelnen
Zuweisungen deer Array`s abzuarbeiten. Dies wird in einen externen
Process gemacht und mit "start" angestossen.
Wenn das Ende der Array`s erreicht ist, soll das ganze wieder in den
Zustand "idle" zurückgesetzt werden.
Der entsprechende Codeteil, sieht wie folgt aus.
Das h ist ein Signal, welches nicht direkt hochgezählt wird. Es wir
vielmehr eine variable i in einen anderen Prozess hochgezählt und
dauerhaft auf h übergeben.
Dann funktioniert das ganze,jede Adresse liegt an und wird entsprechend
beschrieben.
Was mich allerdings wundert, das hochgezählte h bzw. i gibt als letzte
Zahl nicht 8 sondern -8 aus.
Ich hab dann geschaut und ich binde diese Bibliothek ein.
1
useIEEE.std_logic_unsigned.all;
Daher wundere ich mich das am Ende -8 ausgegeben wird, kann das der
Fehler sein?
Ja unter ModelSim....wenn ich die Darstellung auf dezimal stelle wird
wie folgt gezählt: 0->1->2->3->4->5->6->7->-8
Das könnte der Grund meines Problemes sein, weiss aber nicht warum der
Fehler auftritt bzw. wie ich ihn beheben kann.
Hallo Neuling,
mach mal folgendes:
1) deklariere eine Konstante ARRAY_LENGTH vom Typ integer und setze sie
auf z.B. 8
2) deklariere die Arrays abh. von dieser Konstanten,also z.B. so:
type z_array is array (0 to ARRAY_LENGTH-1) of std_logic_vector (3
downto 0);
damit sind beide Arrays immer gleich lang und wenn Du die Länge ändern
willst musst Du nur ARRAY_LENGTH anpassen und die Konstenten hinzufügen.
3)in dem Prozess wo Du mit der Variablen i arbeitest:
ersetze i durch ein SIGNAL mit einem sinnvollen Namen, mach die
Deklaration wieder von ARRAY_LENGTH abhängig, also zb.
signal addr_index : integer range 0 to ARRAY_LENGTH-1;
Damit es keinen Überlauf gibt, schreibst Du die Sache so:
if addr_index = ARRAY_LENGTH-1 then
addr_index <= 0;
else
addr_index <= addr_index +1;
end if;
Mit diesem Signal addr_index gehst Du jetzt direkt in die Statemachine
rein.
Du hast einen Integer, also kannst Du dieses Signal direkt zur
Indizierung des Arrays verwenden. Schreib mir mal, ob sich jetzt was
verbessert hat.
NOCHWAS:
die -8 kommt sicher von Deiner Integer-Konvertierung.
Du musst schreiben :
conv_integer(unsigned(h));
sonst wird das MSB von h als Vorzeichen interpretiert und Du bekommst
zwangsläufig die -8!
Hallo Mark,
besten Dank dein Vorschlag hat das Problem eigentlich gelöst. Ich kann
jetzt ohne weiteres die Adressen am Stück , bis adress_index = 8,
beschreiben, auch wenn eine Adresse doppelt vorkommt.
Nun wollte ich, einen Wartezustand einfügen und das Problem tritt wieder
auf.
Es soll wie folgt laufen.
Zunächst werden die ertsten 2 Adressen beschrieben, danach wird in den
Zustand "s_wait" gegangen und bis zum Wert ENDE in einen anderen Process
gezählt,um danach weitere Adressen zu beschreiben.
Das ganze würde so aussehen:
Wenn ich die "Post-Route" Simulation ablaufen lasse, werden die ersten 2
Adressen beschrieben und der Wartezyklus wird auch abgearbeiten. Wenn es
dann aber vom Zustand "s-wait" zu Zustand "s3" übergeht, werden wieder
nur X Werte angezeigt.
Gibt es da eine Möglichkeit dies anderst zu realisieren?
Danke
Neuling
Hallo Neuling,
das sieht alles etwas chaotisch aus, ich verstehe aber was Du erreichen
willst. Erstmal: wenn Du addr_index als integer deklariert hast, kannst
Du
die Konvertierung conv_integer im s3 weglassen. Und nimm mal 'zaehl' aus
der Sensitivity-Liste vom process raus, das gehört da nicht hin.
Dass Du die Warteschleife auslagern musst ist eine Folge der Aufteilung
der FSM in Kombinatorik und State-Wechsel, klar. Dadurch wird es aber
auch etwas unübersichtlich. Du nimmst wieder eine Variable, die Du am
Ende einem Signal zuweist. Als Anfänger sollte man Variablen meiden,
glaub
mir. Nimm bitte ein Signal für den Wartezähler, auch wenn das vermutlich
nichts mit dem Problem zu tun hat.
Die Warteschleife würde ich vereinfachen:
process(clk)
begin
if rising_edge(clk) then
if start_wait then -- start-signal aus der FSM = TRUE?
cnt_q <= ENDE; -- Zähler mit Delay laden
waiting_q <= true; -- Flag für die FSM 'warten'
elsif cnt_q > 0 then
cnt_q <= cnt_q -1; -- runterzählen bis 0
else
waiting_q <= false; -- fertig
end if;
end process;
start_wait ist als signal vom Typ boolean zu deklarieren, ebenso
waiting_q.
Vor der statemachine setzt Du start_wait generell auf false und nur im
state s1 bei entspr. Bedingung wird start_wait auf true gesetzt.
Im s_wait fragst Du dann waiting_q ab, wenn es false wird geht es zum
nächsten State.
Ich vermute aber, dass das Problem immer noch mit dem Array-Index zu tun
hat, irgendwie kommen da falsche Werte rein.
Du kannst im VHDL-Code ein assert für die Simulation einbauen, z.B. so:
assert addr_idx >= 0 and addr_idx < ARRAY_LENGTH report '....' severity
error;
Wenn der addr_idx einen unzulässigen Wert annimmt bekommst Du dann
sofort
eine Meldung in der Simulation.
Hi,
hab meine StateMaschine jetzt erweitert und bin auf ein Problem
gestossen, welches ich nicht verstehe.
Kurz zur Erklärung:
Habe ein 2tes paar Array`s erstellt und dem ersten entsprechend
deklariert.
Die Array`s sehen dann wie folgt aus:
Dann wird vom Zustand s3 nicht mehr in idle, sondern in den Zustand
"param_1" von dem es dann in "param_2" geht. Zwischen diesen beiden
Zuständen wechselt es solange hin und her bis alle Parameter
beschrioeben werden.
1
whenparam_1=>if(addr_index2=31)then
2
WE<='0';
3
CS<='0';
4
RD<='0';
5
ADDR<="ZZZZ";
6
HDATA<="ZZZZZZZZZZZZZZZZ";
7
start<='0';
8
param_start<='0';
9
zaehl<='0';
10
rstn_cnt<='0';
11
rom_addr<="0000000000000000";
12
rom_read<='0';
13
ENDE<=x"0000";
14
next_state<=idle;
15
else
16
param_start<='1';
17
WE<='1';
18
CS<='1';
19
RD<='0';
20
ADDR<=param(addr_index2);
21
HDATA<=Werte1(addr_index2);
22
start<='0';
23
24
zaehl<='0';
25
rstn_cnt<='0';
26
rom_addr<="0000000000000000";
27
rom_read<='0';
28
next_state<=param_2;
29
ENDE<=x"0000";
30
31
endif;
32
whenparam_2=>WE<='0';
33
CS<='0';
34
RD<='0';
35
ADDR<="ZZZZ";
36
HDATA<="ZZZZZZZZZZZZZZZZ";
37
start<='0';
38
param_start<='0';
39
zaehl<='0';
40
rstn_cnt<='0';
41
rom_addr<="0000000000000000";
42
rom_read<='0';
43
next_state<=param_1;
44
ENDE<=x"0000";
Das Problem entsteht bei den param und dem dazugehörigen Wert an der
Stelle 18. (param= IADDR & Wert1=ATTRTYPE)
Bei der "Post-Route"-Simulation, entstehen an dieser Stelle X.
Wenn ich das ganze nur bis Wert 17 Abfrage funktioniert es Einwandfrei.
Daher hatte ich zu Testzwecken, das Array "param" bzw. "Werte1" auf 17
Stellen begrenzt.
Zu meiner grossen Verwunderung, kam dann an der Stelle 17 ebenfalls
X,obwohl es vorher funktionierte.
Stelle 17: Param = IDATA & Werte1 = x"0000"
Wenn ich allerdings einen anderen Wert als 0 drauf schreibe funktioniert
es!
Hat jemand eine Idee woran es liegen kann, das es einmal funktioniert
und dann nicht mehr?
Danke
Neuling