Hallo,
ich bin relativ neu bei VHDL und bastle gerade an nem kleinen Prozessor.
Der kann im Moment nur logisch ODER und hat nur ein Register bzw. nen
Akku. Nun habe ich eine ROM-Komponente erstellt, in der ein kleines
Programm steht, bei dem er den kku vom LSB hin zum MSB mit 1 verodern
soll.
Das Problem: Bei der "Veroderung" werden im Akku nicht Einsen sondern
jeweils ein X gespeichert.
Als das ROM noch im Prozessor deklariert wurde ging es noch...
Ich habe leider keine Ahnung was ich da faalsch mache.
Hier mal der Code:
Task2.vhd:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.STD_LOGIC_ARITH.ALL;
4
useIEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
---- Uncomment the following library declaration if instantiating
Willst du das Ganze mal in ein FPGA reinstecken?
Falls ja:
Dieses X ist vorerst eines deiner kleinsten Probleme :-o
Knackiger ist das hier:
1)
1
waituntilclka'eventandclka='1';-- der Takt
2
ifreset='1'then
3
:
4
else
5
:
6
foriin1to4loop
7
waituntilclka'eventandclka='1';-- Aua, ein paar Takte im Takt :-/
8
endloop;
9
:
10
whenhalt=>
11
waituntilreset'eventandreset='1';-- hoppla, ein anderer Takt im Takt :-o
Sowas lässt sich garantiert nicht in Hardware abbilden.
Und: du solltest dir das Thema for-Schleifen in VHDL (und insbesondere
deren Umsetzung in Hardware) mal genauer anschauen.
2)
wait until clka'event and clka='1';
wait until clkrom'event and clkrom='1';
wait until reset'event and reset = '1';
Du hast viel zu viele Takte. Dein Design wird in der Realität nicht
zuverlässig laufen. Ein ideales FPGA-Design hat 1 Takt und 0 Resets. In
der Praxis muß man etwas von dieser strengen Regel abweichen, aber du
solltest dafür sehr gute Gründe angeben können.
3)
1
USEieee.std_logic_unsigned.all;
2
USEieee.numeric_std.ALL;
Entweder - Oder. Aber niemals zusammen.
Du solltest heutzutage für die Synthese auch eher die numeric_std
nehmen.
BTW:
Hallo Lothar,
danke für deine Antwort!
Lothar Miller schrieb:> 1)> ...> Sowas lässt sich garantiert nicht in Hardware abbilden.> Und: du solltest dir das Thema for-Schleifen in VHDL (und insbesondere> deren Umsetzung in Hardware) mal genauer anschauen.
Ok, ich habe das ganze schonmal angepasst, sieht noch nicht 100%ig gut
aus (besonders die Codeduplizierung bei reset und init, werde das wohl
noch in eine Funktion auslagern oder mir fällt nen schöneres Design ein
(theoretisch kann ich mir das Init auch sparen denke ich...).
Hier der Code:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.STD_LOGIC_ARITH.ALL;
4
useIEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
---- Uncomment the following library declaration if instantiating
7
---- any Xilinx primitives in this code.
8
--library UNISIM;
9
--use UNISIM.VComponents.all;
10
11
entityTask2is
12
Port(clka:inSTD_LOGIC;
13
procouta:outSTD_LOGIC_VECTOR(7downto0);
14
reset:inSTD_LOGIC
15
);
16
endTask2;
17
18
architectureBehavioralofTask2is
19
-- Breite des Adressbusses des ROMs (Index des MSB)
20
constantmaxPC:integer:=3;
21
componentextROM
22
generic(Adr_max:integer:=maxPC);
23
Port(
24
clkrom:inSTD_LOGIC;
25
addrinrom:inSTD_LOGIC_VECTOR(Adr_maxdownto0);
26
instructionoutrom:outSTD_LOGIC_VECTOR(11downto0)
27
);
28
endcomponent;
29
30
typeOP_typeis(
31
OP_OR,
32
OP_UNKNOWN
33
);
34
35
typestate_typeis(
36
init,
37
execute,
38
write_back,
39
advance_PC,
40
halt
41
);
42
43
signalinstruction:STD_LOGIC_VECTOR(11downto0);
44
signalaccu:STD_LOGIC_VECTOR(7downto0);
45
signalpc:integer;
46
signalmy_state:state_type:=init;
47
--Funktionen
48
49
-- Hole den Opcode
50
impurefunctiondecodeOp
51
(currOP:std_logic_vector(3downto0))
52
returnOP_typeis
53
variableresult:OP_type;
54
begin
55
casecurrOpis
56
when"0000"=>
57
result:=OP_OR;
58
whenothers=>
59
result:=OP_UNKNOWN;
60
endcase;
61
returnresult;
62
endfunctiondecodeOp;
63
64
-- Hole den Wert der Instruktion
65
impurefunctiongetValue
66
(currIn:std_logic_vector(11downto0))
67
returnSTD_LOGIC_VECTORis
68
variableresult:STD_LOGIC_VECTOR(7downto0);
69
begin
70
result:=currIn(7downto0);
71
returnresult;
72
endfunctiongetValue;
73
74
75
begin
76
ROM1:extROMportmap(
77
clkrom=>clka,
78
addrinrom=>conv_std_logic_vector(pc,maxPC+1),
79
instructionoutrom=>instruction
80
);
81
82
83
my_proc:process
84
begin
85
86
waituntilclka'eventandclka='1';
87
ifreset='1'then
88
my_state<=execute;
89
accu<="00000000";
90
procouta<="00000000";
91
instruction<="000000000000";
92
pc<=0;
93
else
94
casemy_stateis
95
wheninit=>
96
-- Initialisierung machen
97
my_state<=execute;
98
accu<="00000000";
99
procouta<="00000000";
100
instruction<="000000000000";
101
pc<=0;
102
whenexecute=>
103
--Bestimem Op-Code
104
casedecodeOp(instruction(11downto8))is
105
whenOP_OR=>
106
accu<=accuorgetValue(instruction);
107
my_state<=write_back;
108
whenothers=>
109
my_state<=halt;
110
endcase;
111
whenwrite_back=>
112
procouta<=accu;
113
my_State<=advance_PC;
114
whenadvance_PC=>
115
pc<=pc+1;
116
my_state<=execute;
117
whenhalt=>
118
endcase;
119
endif;
120
endprocessmy_proc;
121
endBehavioral;
Hoffe so ist es besser (bis auf die Duplizierung).
Lothar Miller schrieb:> 2)> wait until clka'event and clka='1';> wait until clkrom'event and clkrom='1';> wait until reset'event and reset = '1';> Du hast viel zu viele Takte. Dein Design wird in der Realität nicht> zuverlässig laufen. Ein ideales FPGA-Design hat 1 Takt und 0 Resets. In> der Praxis muß man etwas von dieser strengen Regel abweichen, aber du> solltest dafür sehr gute Gründe angeben können.
Ok, das wait fürs reset ist schonmaal raus, aber das clkrom ist doch
über die Portmap mit clka quasi fest verdrahtet oder? Ist das damit
nicht das gleiche Signal? Oder bezieht sich das auf die beiden waits und
welches Signbal das ist spielt keine Rolle? Wenn ja:
Wie kann man soetwas denn sonst lösen? Sorry, bin wirklich totler
Neuling :-(
Das rom wurde auch angepasst:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.STD_LOGIC_ARITH.ALL;
4
useIEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
---- Uncomment the following library declaration if instantiating
Wie gesagt, wie ich mir da das wait sparen kann weiß ich leider nicht...
Lothar Miller schrieb:> 3)USE ieee.std_logic_unsigned.all;> USE ieee.numeric_std.ALL;> Entweder - Oder. Aber niemals zusammen.> Du solltest heutzutage für die Synthese auch eher die numeric_std> nehmen.
Ok, da habe ich nun nur doch die numeric_std drin. Danke für den
Hinweis.
Lothar Miller schrieb:> BTW: result :=
(currIn(7)&currIn(6)&currIn(5)&currIn(4)&currIn(3)&currIn(2)&currIn(1)&c
urrIn(0));
> so geht das kürzer und leserlicher: result := currIn(7 downto 0);
Ahh habe ich mir schon gedacht das das auch komfortabler gehen muss :-)
Danke nochmal!
MfG Rene
Hallo,
konnte das Problem immernoch nicht beseitigen...
Habe im Netz etwas über resolution functions gefunden, bin mir aber
nicht sicher ob es genau das sit, was ich haben möchte?!
MfG Rene
Hallo,
tut mir leid, das ich schon wieder hier selbst antworte, habe aber aus
dem ROM nun auch den Takt entfernt, damit es synthetisierbar wird:
Danke nochmal Lothar...
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.STD_LOGIC_ARITH.ALL;
4
useIEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
---- Uncomment the following library declaration if instantiating
> Habe im Netz etwas über resolution functions gefunden, bin mir aber> nicht sicher ob es genau das sit, was ich haben möchte?!
Nein, die Auflösungsfunktion macht genau das X aus den Eingangswerten.
Wenn bei der 9-wertigen std_logic zwei gleich starke Pegel
aufeinandertreffen (z.B. 0 und 1 oder H und L), ist das Ergebnis X...
> Leider werden immernoch nur X in mein instructionoutrom geschrieben und> keine 1...> 0 geht immer wunderbar.
Das heißt, irgendwoher wird per default das ROM mit Nullen vorbelegt,
und dann ist das Ergebnis klar:
0 und 0 gibt 0
0 und 1 gibt X
Ein kurze Suche ergibt:
Hallo,
danke vielmals!! Jetzt gehts und der Proz rechnet auch schon nen bissl
was (hat nun auch Register etc).
Das Problem wurde gelöst, Thread kann geschlossen werden.
Danke nochmals!