SPI_DATA_H/L ist std_logic_vector (7 downto 0);
r_MemSegmentValue()() ist ein integer range 0 to 65535;
Es funktioniert in der Simulation. Vermutlich ja auch in HW.
Aber geht das evtl eleganter?
Danke schonmal.
Aber das gibt mir sowieso zu denken, dass du da so wahllos und direkt in
den Speicher greifst. Welche Art Speicher hast du da? Wie groß können
die Indices werden?
(*)das geht natürlich auch mit Signalen, aber dazu müsste mehr vom
Drumherum der obigen Codezeilen bekannt sein.
Kann man so machen, aber geht m.E. auch schöner (wobei Schönheit ja
immer im Auge des Betrachters liegt).
Das ist (wenn das Synthesetool damit umgehen kann, aber ich wüsste
keins, daß das nicht könnte) ein Lehrbeispiel für Aliase.
1
signalspitxdata:std_logic_vector(15downto0);
2
aliasspi_data_lowisspitxdata(7downto0);
3
aliasspi_data_highisspitxdata(15downto8);
Jetzt ist es egal, wo spitxdata zugewiesen wird - die Aliase haben
immer den richtigen Wert.
Thomas S. schrieb:> schon mal an sowas gedacht> typedef union
Hui, neue VHDL Schlüsselwörter?
Markus F. schrieb:> die Aliase haben immer den richtigen Wert.
Richtig, ich wollte das in die (*) mit reinpacken, dann kam mir aber die
Frage nach dem RAM-Typ in den Sinn.
Und letztendlich ging es darum, für die Berechnung nichts zu schieben,
sondern über die Bereiche das Zeug einfach nur anders zu verdrahten.
Lothar M. schrieb:> Man könnte es als Grund ansehen, eine Variable einzusetzen(*)... ;-)
Noch eleganter faende ich eine Funktion (entweder mit 2 Argumenten oder
2 Funktionen mit einem Argument), zumindest ist das fuer mich lesbarer.
Und hat den Vorteil, dass wenn man es oefters an verschiedene Stellen im
Code braucht besser wartbar ist.
Alte Informatik Regel: Sobald ich einmal Copy&Paste mache, gibt es
mindestens eine Loesung die besser waere. ;-)
Mal ganz naiv gefragt:
Was wird denn gebaut wenn man
SPI_DATA_H <= r_MemSegmentValue(SPI_TX_ROW)(SPI_TX_COL)/256
SPI_DATA_L <= r_MemSegmentValue(SPI_TX_ROW)(SPI_TX_COL)%256
schreibt? Das wären dann zwei Integer, aber ist doch eigentlich egal,
dann muss man die eben überall dort wo man sie verwendet in slvs
umwandeln wenn man das benötigt.
Gustl B. schrieb:> Mal ganz naiv gefragt:>> Was wird denn gebaut wenn man>> SPI_DATA_H <= r_MemSegmentValue(SPI_TX_ROW)(SPI_TX_COL)/256> SPI_DATA_L <= r_MemSegmentValue(SPI_TX_ROW)(SPI_TX_COL)%256>> schreibt? Das wären dann zwei Integer, aber ist doch eigentlich egal,> dann muss man die eben überall dort wo man sie verwendet in slvs> umwandeln wenn man das benötigt.
Das haengt vom Synthese Tool ab. Da hilft nur: Ausprobieren und das
Resultat ansehen.
Gustl B. schrieb:> Was wird denn gebaut wenn man> SPI_DATA_H <= r_MemSegmentValue(SPI_TX_ROW)(SPI_TX_COL)/256> SPI_DATA_L <= r_MemSegmentValue(SPI_TX_ROW)(SPI_TX_COL)%256> schreibt?
In erster Näherung eine Fehlermeldung wegen der nicht passenden
Datentypen.
Und praktisch wird das mit hoher Wahrscheinlichkeit einfach wie oben
verdrahtet. Und das obwohl die Division für negative Zahlen (also der
Hälfte des Zahlenbereichs des Integers und damit ein Viertel der
Integerzahlen) dann eigentlich falsch rundet.
Denn: was gibt bei Integer-Rechnung 5/2 und was gibt -5/2?
Richtig: 2 und -2 wegen des Abschneidens der Nachkommastellen.
Und was kommt bei der simplen Umverdrahtung statt -5/2 heraus?
Das ergibt -3!
1
bin dez /2 umverdrahtet ohne letztes Bit (=shift 1 nach rechts)
2
bin dez
3
0111 7 3 011 3
4
0110 6 3 011 3
5
0101 5 2 010 2
6
0100 4 2 010 2
7
0011 3 1 001 1
8
0010 2 1 001 1
9
0001 1 0 000 0
10
0000 0 0 000 0
11
1111 -1 0 111 -1 ***
12
1110 -2 -1 111 -1
13
1101 -3 -1 110 -2 ***
14
1100 -4 -2 110 -2
15
1011 -5 -2 101 -3 ***
16
1010 -6 -3 101 -3
17
1001 -7 -3 100 -4 ***
18
1000 -8 -4 100 -4
In den *** Zeilen passt das Ergebnis der mathematisch korrekten
Integer-Division nicht zur simplen "umverdrahteten" (oder eben
"geshifteten") Version. Trotzdem ersetzt der Synthesizer die
mathematisch korrekte Division (wenn Zahl negativ, dann mach eine
posizive Zahl daraus, teile die durch 2 und mach wieder eine negative
Zahl daraus) mit hoher Wahrscheinlichkeit durch die Umverdrahtung.
Ausprobieren macht hier schlau. Und man lernt daraus, dass man solches
Mapping besser direkt macht, als es irgendwelchen mathematischen
Operationen zuzumuten und sich drauf zu verlassen, dass die das schon so
können wie man es braucht.
Lothar M. schrieb:> negative ZahlenHolger K. schrieb:> r_MemSegmentValue()() ist ein integer range 0 to 65535;Lothar M. schrieb:> Und man lernt daraus, dass man solches> Mapping besser direkt macht, als es irgendwelchen mathematischen> Operationen zuzumuten und sich drauf zu verlassen, dass die das schon so> können wie man es braucht.
Ja, stimmt. Wobei ich finde, dass man solche Sachen schon machen darf
wenn man verstanden hat was dabei passiert.
Wie man sieht klappt es nicht nur mit "mod" die unteren Bits raus zu
ziehen, sondern sogar die Division über ein Signal(x_div) zu einem
conditional Shift zu machen, wenn der Wertebereich so eingegrenzt ist.
(Quartus 18.1)
Mit dem Cyclone 4 konnte man sogar noch das *4 und *8 in einem signal
zuweisen und damit das If contruct sparen:
Mit dem Cyclone 4 führt das zu einem conditional Shift, mit dem Cyclone
5 leider zu einem echten MUL (DSP Element), warum auch immer die
Synthese sowas macht.
Gustl B. schrieb:> Ja, stimmt. Wobei ich finde, dass man solche Sachen schon> machen darf wenn man verstanden hat was dabei passiert.
Und wenn man einigermaßen sicher sein kann, dass andere Nutzer des
Quellcodes das auch verstanden haben. Das ist je nach Umfeld
schwieriger.