Hallo, wie sieht eine elegante Lösung aus einem 4Bit-Hex Wert das zugehörige 8-Bit ASCII Zeichen zuzuordnen? Das kriege ich zwar auch als VHDL-Anfänger hin, aber im Netz hab eich jetzt tatsächlich keinen Codeschnippsel dazu gefunden. Wollte mal sehen ob es da eine "elegante" Lösung gibt. Ich hab da eine if-Konstruktion die vermutlich weder besonders gut noch resourenschondend ist... Vielen Dank Randy
@Randy (Gast) >wie sieht eine elegante Lösung aus einem 4Bit-Hex Wert das zugehörige >8-Bit ASCII Zeichen zuzuordnen? Du meinst die Zahlen 0-9 und A-F? >Codeschnippsel dazu gefunden. Wollte mal sehen ob es da eine "elegante" >Lösung gibt. Gibt es, das ist ja eine einfache Tabelle. > Ich hab da eine if-Konstruktion die vermutlich weder >besonders gut noch resourenschondend ist... Naja, der Optimierer macht das schon. Aber es ist tonnenweise sinnlose Tipperei, und besonders übersichtlich ist es auch nicht. Gute Beispiele gibt es im Artikel TTL74185 MFG Falk
Randy schrieb: > wie sieht eine elegante Lösung aus einem 4Bit-Hex Wert das zugehörige > 8-Bit ASCII Zeichen zuzuordnen? Beschreib ein RAM:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity BCD_ASCII is |
6 | Port ( data : in STD_LOGIC_VECTOR (3 downto 0); |
7 | asciichar : out STD_LOGIC_VECTOR (7 downto 0)); |
8 | end BCD_ASCII; |
9 | |
10 | architecture Behavioral of BCD_ASCII is |
11 | type Rom16x8 is array (0 to 15) of std_logic_vector (7 downto 0); |
12 | constant BCDRom : Rom16x8 := ( |
13 | std_logic_vector(to_unsigned(character'pos('0'),8)), |
14 | std_logic_vector(to_unsigned(character'pos('1'),8)), |
15 | std_logic_vector(to_unsigned(character'pos('2'),8)), |
16 | std_logic_vector(to_unsigned(character'pos('3'),8)), |
17 | std_logic_vector(to_unsigned(character'pos('4'),8)), |
18 | std_logic_vector(to_unsigned(character'pos('5'),8)), |
19 | std_logic_vector(to_unsigned(character'pos('6'),8)), |
20 | std_logic_vector(to_unsigned(character'pos('7'),8)), |
21 | std_logic_vector(to_unsigned(character'pos('8'),8)), |
22 | std_logic_vector(to_unsigned(character'pos('9'),8)), |
23 | std_logic_vector(to_unsigned(character'pos('A'),8)), |
24 | std_logic_vector(to_unsigned(character'pos('B'),8)), |
25 | std_logic_vector(to_unsigned(character'pos('C'),8)), |
26 | std_logic_vector(to_unsigned(character'pos('D'),8)), |
27 | std_logic_vector(to_unsigned(character'pos('E'),8)), |
28 | std_logic_vector(to_unsigned(character'pos('F'),8))); |
29 | begin
|
30 | asciichar <= BCDRom(to_integer(unsigned(data))); |
31 | end Behavioral; |
Falls jetzt Fragen zum 'pos auftauchen: Siehe Beitrag "Re: String in std_logic_vector umwandeln"
OK, vielen Dank. Eine Tabelle ist also das Mittel der Wahl. Ich hatte eine if-Abfrage (48+Wert oder 55+Wert je nach Bereich, aber auch an jeder Stelle an der ich das gebraucht habe), ich bau das jetzt so um wie Lothar beschrieben hat. Eine Frage zur Struktur: Die Entity von Lothar kommt in eine eigene Datei? Oder füge ich die Entity anders ein? Zur allgemeinen Vorgehensweise: Würde man andere mehr oder weniger kleine Funktionsblöcke auch in eigene Dateien schreiben? Gäbe am Ende sehr viel Dateien mit je nur 20-50 Zeilen Code. Wird das so gemacht? Vom uC in C programmieren kenne ich es so dass man wegen einer popeligen Funktion kein extra Modul (oder extra c-Datei) gemacht hat. So dass ich am Ende eher nur 2 bis 6 Dateien mit je 100-1000 Zeilen Code hatte. Wie hält man das bei VHDL? Randy
@ Randy (Gast) >Funktion kein extra Modul (oder extra c-Datei) gemacht hat. So dass ich >am Ende eher nur 2 bis 6 Dateien mit je 100-1000 Zeilen Code hatte. Wie >hält man das bei VHDL? Meist genauso. MFG Falk
Hallo Randy, sorry, wenn ich mich mal wieder ungefragt einmische, aber wenn ich solche VHDL-Konstrukte sehe, dann tun mir immer die Augen weh. Ich empfehle eine lockere und leichte Beschreibungssprache, nämlich Verilog, und dann sähe die Entity (das Modul) so aus: module ascii ( input [3:0] hex_in, output [7:0] ascii_out ); assign ascii_out = (hex_in > 9) ? hex_in - 'ha + 'h61 : hex_in + 'h30; endmodule Ein 7-Zeiler also, mehr nicht. Aber zu deiner anderen Frage (wie viele Dateien?). Früher gab es mal eine aus der ASIC-Welt stammende Regel namens OMPF (one module per file). Die Regel war vor allem ein Zugeständnis an die Synthesetools, und in der FPGA-Welt muss man sich nicht unbedingt daran halten. Ich mach's trotzdem.
@ Harald Flügel (hfl) >sorry, wenn ich mich mal wieder ungefragt einmische, aber wenn ich >solche VHDL-Konstrukte sehe, dann tun mir immer die Augen weh. Mir auch, obwohl ich VHDLer bin ;-) Ich empfehle diese Version. http://www.mikrocontroller.net/articles/TTL74185#Konstanten_Array >Ein 7-Zeiler also, mehr nicht. Dito in VHDL. MFG Falk
Randy schrieb: > Vom uC in C programmieren kenne ich es so dass man wegen einer popeligen > Funktion kein extra Modul (oder extra c-Datei) gemacht hat. Ich treibe es gern sogar noch weiter und packe sehr viel in 1 Prozess hinein. So wird dann aus eine seriellen Schnittstelle, die bei anderen 4 Dateien braucht (siehe Beitrag "Re: VHDL zu Verilog" --> DeepLink), bei mir 1 Datei mit 2 Prozessen: http://www.lothar-miller.de/s9y/categories/42-RS232 Oder ähnliches bei einer PS/2 Schnittstelle: http://www.lothar-miller.de/s9y/categories/55-PS2 Und nein: ein VHDL-Code wird nicht durchschaubarer, wenn man 7 Editorfenster geöffnet haben muß, um ihn zu überblicken. Er sieht nur wichtiger aus... ;-) Ohne Glaubenskriege heraufzubeschwören: > assign ascii_out = (hex_in > 9) ? hex_in - 'ha + 'h61 : hex_in + 'h30; Zeig das mal bei unbedarften Elektronikern rum und frag, was da passiert. Und vor allem: was der Synthesizer evtl. draus macht. Und dann machst du das mit dem VHDL-Code... Aber bitte, es geht auch kürzer:
1 | library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; |
2 | entity BCD_ASCII is Port ( data : in unsigned (3 downto 0); |
3 | asciichar : out unsigned (7 downto 0)); |
4 | end BCD_ASCII; |
5 | architecture Behavioral of BCD_ASCII is begin |
6 | asciichar <= resize(data,8)+x"61" when data>9 else resize(data,8)+x"30"; |
7 | end Behavioral; |
Auch 7 Zeilen... ;-) BTW: das Fehlen des ? Operators bei VHDL ist eigentlich nicht schlecht... ;-) EDIT >> sorry, wenn ich mich mal wieder ungefragt einmische, aber wenn ich >> solche VHDL-Konstrukte sehe, dann tun mir immer die Augen weh. > Mir auch, obwohl ich VHDLer bin ;-) @ Falk: Meint er meine oder deine Konstrukte? @ Harald: Komm sags uns... ;-) Ich kann die Tabelle auch kompakter schreiben, aber irgendwie finde ich das oben trotz des Herumgecasts übersichtlicher, als nur Hex-Kolonnen dastehen zu haben...
Hallo Lothar, Hallo Falk, die Augenschmerzen bekam ich bei der Anreihung der std_logic_vector(to_unsigned(character'pos('*'),8)), -Statements. Der 7-Zeiler von Lothar mit der Zeile asciichar <= resize(data,8)+x"61" when data>9 else resize(data,8)+x"30"; ist schon wesentlich besser und fast baugleich zu dem Verilog-Code assign ascii_out = (hex_in > 9) ? hex_in - 'ha + 'h61 : hex_in + 'h30; Wenn ich diese Verilog-Zeile unbedarften Elektronikern zeige und dazu sage, dass 'h das Prefix für die hexidezimale Notation ist, dann verstehen die das, denn die können alle C. Das ist IMHO der größe Vorteil von Veriog überhaupt: Die syntaktische Nähe zu C. Aber nochmal zurück zur eigentlichen Aufgabenstellung. Die erste Lösung von Lothar legt den Schluss nahe, dass der Entwickler ein ROM (RAM) haben will, während Lothars zweite Lösung aussieht, als sollten das Logikelemente geben. Ich mache bei Altera Quartus die Erfahrung, dass der Synthesizer selbst entscheidet, was die bessere Lösung ist. Deckt sich das mit euren Beobachtungen?
Harald Flügel schrieb: > Wenn ich diese Verilog-Zeile unbedarften Elektronikern zeige und dazu > sage, dass 'h das Prefix für die hexidezimale Notation ist Neineinein, ich meinte, ohne was zu sagen... ;-) Zeig den Fragezeichen-Operator mal einem eingefleischten Basic-Programmierer... ;-) Und auch "übliche" C-Programmierer haben ihre liebe Not damit. > Die syntaktische Nähe zu C. Könnte dann aber auch zur C-Software-Denkweise verführen (mit Schleifen und delay() und all den Dingen)... > Ich mache bei Altera Quartus die Erfahrung, dass der Synthesizer > selbst entscheidet, was die bessere Lösung ist. > Deckt sich das mit euren Beobachtungen? Die Xilinx-Synthese XST macht daraus durchaus einmal ein BROM und einmal einen Addierer, allerdings sind beide Lösungen beim Ressourcenverbrauch und bei der Geschwindigkeit aufs Zehntel gleich...
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity BCD2ASCII is |
6 | Port ( di : in STD_LOGIC_VECTOR (3 downto 0); |
7 | do : out STD_LOGIC_VECTOR (7 downto 0)); |
8 | end BCD2ASCII; |
9 | |
10 | -- 1. Variante mit BROM
|
11 | -- Maximum combinational path delay: 7.276ns
|
12 | -- Number of Slices 3
|
13 | -- Number of 4 input LUTs 6
|
14 | architecture Behavioral of BCD2ASCII is |
15 | type Rom16x8 is array (0 to 15) of std_logic_vector (7 downto 0); |
16 | constant BCDRom : Rom16x8 := ( |
17 | std_logic_vector(to_unsigned(character'pos('0'),8)), |
18 | std_logic_vector(to_unsigned(character'pos('1'),8)), |
19 | :
|
20 | :
|
21 | std_logic_vector(to_unsigned(character'pos('F'),8))); |
22 | begin
|
23 | do <= BCDRom(to_integer(unsigned(di))); |
24 | end Behavioral; |
25 | |
26 | -- 2. Variante mit Addierer
|
27 | -- Maximum combinational path delay: 7.276ns
|
28 | -- Number of Slices 3
|
29 | -- Number of 4 input LUTs 6
|
30 | architecture Behavioral of BCD2ASCII is |
31 | begin
|
32 | do <= std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('A')-10,8)) when unsigned(di)>9 else |
33 | std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('0'),8)); |
34 | end Behavioral; |
35 | |
36 | -- 3. wie 2. aber -10 ungünstig platziert
|
37 | -- --> trotz Konstanten werden Addierer und Subtrahierer synthetisiert !!!
|
38 | -- Maximum combinational path delay: 10.471ns
|
39 | -- Number of Slices 6
|
40 | -- Number of 4 input LUTs 10
|
41 | architecture Behavioral of BCD2ASCII is |
42 | begin
|
43 | do <= std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('A'),8)-10) when unsigned(di)>9 else |
44 | std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('0'),8)); |
45 | end Behavioral; |
BTW: Es ist klar, dass VHDL durch die strengen Typkonvertierungen die "geschwätzigere" Sprache ist. Allerdings wird der Entwickler dadurch auch eher zum Nachdenken gezwungen...
Lothar Miller schrieb: > BTW: > Es ist klar, dass VHDL durch die strengen Typkonvertierungen die > "geschwätzigere" Sprache ist. Allerdings wird der Entwickler dadurch > auch eher zum Nachdenken gezwungen... Super Beitrag Lothar, Didaktisch fast eine genialer Schachstreich. Erst eine ROM Tabelle und dann der sieben Zeiler. Ich hätte es als Funktion geschieben. Vom Gedankenschmalz ein super Beitrag. Wenn ich einen Wunsch für den Weihnachtsmann hätte, dann eine Buch von Lothar Miller. Ein VHDL-Praxisbuch zum Mitdenken.
Hallo Lothar, ich hätte da noch eine Frage. Du weißt ja, Xilinx-Software ist nicht gerade mein Spezialgebiet. Ernst gemeint: Was bringt Dich zu der Annahme, dass... Lothar Miller schrieb: > Die Xilinx-Synthese XST macht daraus durchaus einmal ein BROM und einmal > einen Addierer... > -- 1. Variante mit BROM > -- Maximum combinational path delay: 7.276ns > -- Number of Slices 3 > -- Number of 4 input LUTs 6 > -- 2. Variante mit Addierer > -- Maximum combinational path delay: 7.276ns > -- Number of Slices 3 > -- Number of 4 input LUTs 6 Meiner Meinung nach macht XST in beiden Fällen eine kombinatorische Schaltung mit 6 LUTs, unabhängig davon, ob man das gewünschte Ergebnis als Tabelle oder als Ausdruck beschreibt. Was hab ich da übersehen? Und dann hätt' ich doch noch 'was zum Streiten. Basic? Geht's noch? Grüße, Harald
Harald Flügel schrieb: > Meiner Meinung nach macht XST in beiden Fällen eine kombinatorische > Schaltung mit 6 LUTs, unabhängig davon, ob man das gewünschte Ergebnis > als Tabelle oder als Ausdruck beschreibt. Was hab ich da übersehen? Du hast recht. Es wird kein BROM instatiiert, sondern nur ein "normales" Distributed ROM. Es kann auch gar kein BROM verwendet werden, weil weit&breit kein Takt zusehen ist... > Basic? Geht's noch? Oder Pascal? Modula? LOGO? ;-) BTW: Ich nehme in C auch mal gern den ? Operator, und sei es nur, um damit herumzuprotzen...
1 | dir = enable?endschalter?0:right^left?right?1:2:0:0; |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.