weiß jemand ob es ein TTL IC der 74er Reihe gibt, womit man BCD zu Binär konvertieren kann? Der 74184 kann das zwar, jedoch ist der BCD Code als 5-4-2-1. Ich brauch jedoch als Eingang den üblicheren Code 8-4-2-1. Ich möchte mit dem in Altera Quartus ein 12 Bit BCD-Binär Converter erstellen. Da ich in VHDL noch nichts gemacht habe, möchte ich das im Blockschaltbild umsetzten.
wenn es unbedingt "old school" sein soll: nehme ein Eprom, lege den BCD-Code als Adressen an und hinterlege an den (wenigen) benutzten Speicherzellen den dazugehörenden Binär-Code. Programmieren kann man das im HEX-Editor des Programmiergerätes, ist nichts großes (wenn man noch eines auftreibt...). Aha, habe gerade gesehen, dass du das als Harware wohl garnicht brauchst (?), sondern nur die Funktion kopieren willst.
:
Bearbeitet durch User
Na ja, das läuft wahrscheinlich auf eine Multiplikation der höherwertigen Digits mit 10 und 100 und Addition der 3 Werte hinaus. Google nach "BCD to binary VHDL".
Wenn es nicht super schnell sein muss, geht vielleicht diese serielle Variante 12bit BCD<>BIN: https://www.edn.com/design/systems-design/4369038/Conversion-circuit-handles-binary-or-BCD
pegel schrieb: > diese serielle Variante 12bit BCD<>BIN Ich bevorzuge zeitlich deterministischere Versionen: http://www.lothar-miller.de/s9y/categories/44-BCD-Umwandlung Harald G. schrieb: > Da ich in VHDL noch nichts gemacht habe, möchte ich das im > Blockschaltbild umsetzten. Ich sag da jetzt mal besser nix zu diesem eigenartigen logischen Kurzschluss, sondern verweise nur auf den Beitrag "kruder Fehler bei FPGA-Programmierung (ISE WEBpack-Schematic)"
:
Bearbeitet durch Moderator
ich mach' das so:
1 | function bcd2bin(bcd_value : unsigned) return natural is |
2 | constant v_left : integer := bcd_value'length - 1; |
3 | variable bcd : unsigned(v_left downto 0); |
4 | variable mul, |
5 | ret : natural; |
6 | begin
|
7 | bcd := bcd_value; |
8 | mul := 1; |
9 | ret := 0; |
10 | |
11 | for i in bcd_value'length / 4 - 1 downto 0 loop |
12 | ret := ret + |
13 | to_integer(bcd(3 downto 0)) * |
14 | mul; |
15 | bcd := shift_right(bcd, 4); |
16 | mul := mul * 10; |
17 | end loop; |
18 | return ret; |
19 | end function bcd2bin; |
Markus F. schrieb: > ich mach' das so Und was kommt dabei raus? Macht der da tatsächlich für jede Stelle einen Multiplizierer?
Lothar M. schrieb: > Markus F. schrieb: >> ich mach' das so > Und was kommt dabei raus? > Macht der da tatsächlich für jede Stelle einen Multiplizierer? Das Design braucht 37 LUTs und schafft über 100 MHz (Cyclone III). Finde ich passend, dafür dass man lesen kann, was gemeint ist. P.S.: in dem Fall habe ich 16 bit unsigned benutzt. P.P.S: tatsächlich degeneriert der (ursprünglich eingesetzte) lpm_mult zur Lookup-Tabelle.
:
Bearbeitet durch User
Beitrag "Re: 8-Bit als Dezimalzahlen" Nostalgie... mit TTL- oder CMOS-Addierern geht es auch, es muss kein 74184 sein
Ja der 74184 würde ja funktionieren, wenn er nicht einen BCD im 5421 Code benötigen würde. Meine Codierschalter 3 x 4bit haben jedoch 8421. Somit müsste ich erst von 8421 auf 5421 BCD Code wandeln, um dann mit den 74184 von BCD auf Binär zukommen. Gibt es kein Old School IC der das vom 8421 direkt in Binär wandeln kann. Dann würde ich das in Quartus raussuchen und entsprechend verschalten. Ich bin in Quartus noch nicht so geschult, dass ich VHLD Skripte einfügen kann, somit programmiere ich noch in old School Blockschaltbild.
Harald G. schrieb: > Da ich in VHDL noch nichts gemacht habe, möchte ich das im > Blockschaltbild umsetzten. Harald G. schrieb: > Ich bin in Quartus noch nicht so geschult, dass ich VHLD Skripte > einfügen kann, somit programmiere ich noch in old School > Blockschaltbild. Und was ist dein mittelfristiges Ziel? VHDL oder Verilog zu lernen? Falls ja, dann wäre das doch jetzt der ideale Zeitpunkt, damit anzufangen.... oder nicht? Oder muss das "Projekt" ganz schnell fertig werden?
Ist es in Quartus nicht auch so, dass man ein Symbol für den Schaltplan aus einer VHDL Datei erstellen kann?
Harald G. schrieb: > Ja der 74184 würde ja funktionieren, wenn er nicht einen BCD im 5421 > Code benötigen würde. Meine Codierschalter 3 x 4bit haben jedoch 8421. > Somit müsste ich erst von 8421 auf 5421 BCD Code wandeln, um dann mit > den 74184 von BCD auf Binär zukommen. > Wie kommst Du übrigens da drauf? Schau' dir mal die Wahrheitstabelle auf Seite 5 des Datenblatts und die BCD-Binary-Beschaltung auf derselben Seite genau an (beachte, dass Bit0 "durchgereicht" wird). Für mich sieht das jedenfalls nach reinrassigem 8-4-2-1 aus.
Also der 74184 in Quartus, welchen man als vorprogrammierte Funktionen aus der Bibliothek nutzen kann, nutzt doch den Code 8421. Die alte TTL Version nutzt, laut Datenblatt, zwar den 5421 Code, aber das hat Altera so nicht übernommen. Somit funktioniert meine Umwandelung nun Richtig. Letztendlich möchte ich mit den MaxV CPLD von Altera ein einstellbaren Impulsgenerator bauen. 3 BCD Codierschalter habe ich, welche eine Frequenz vom 100Hz (entspricht die einer Stelle) bis 99900Hz einstellbar machen soll. Das Funktioniert auch zwar, aber bei den höheren Frequenzen ist es, wegen der Rundungsfehler, ungenau. Ich nehme ein 20Mhz Oszillator. 100000 teile ich durch den eingestellten Wert. Mit dem Ergebnis lade ich ein Zähler und zähle rückwärts auf 0. Dann toggele ich ein FlipFlop, damit Impuls und Pausenzeit gleich lang werden, daher die 20Mhz Taktfrequenz beim Zähler und keine 10Mhz. Nun reicht, wie ich rechne, die Auflösung von 10Mhz nicht aus, um einen unterschied ersichtlich zu machen, z.B wenn ich 901,902,903,904 einstelle, ist das Ergebis jedesmal gleich und gibt immer 90900Hz aus. Wo liegt mein Denkfehler? Oder muss ich Faktor 10 höher gehen mit meiner Taktfrequenz (100MHz)? Klar dass man sowas einfacher mit ein Mikroprozessor machen kann, aber der CPLD ist gerade in der Schaltung enthalten und noch genug Platz im CPLD frei. @Schlumpf, ja das Projekt soll zeitnah fertig werden, und bisher hat die Blockschaltbildmethode immer ausgereicht. Ich habe ja noch in der Ausbildung TTL richtig gelernt und da ist dann die Blockschaltbildprogrammierung fast 1 zu 1 gleich. Ich weiß noch nicht was sinniger ist VHDL oder Verilog. Ich vermute mal, ich werde VHDL mal anschauen. Q Markus F. -- Laut Datenblatt ist als Input bei BCD als 5 eine 01000 und nicht 00101. Wenn man die Warheitstabelle weiter sich anschaut, ist der Input ein 5421 BCD Code.
:
Bearbeitet durch User
Kannst du mal nen Screenshot von deinem Schaltplan posten? Ganz abgesehen davon klingt das so, als würdest du mit abgeleiteten Takten arbeiten. Und da ist weiterer Ärger vorprogrammiert.
Harald G. schrieb: > Ich habe ja noch in der > Ausbildung TTL richtig gelernt und da ist dann die > Blockschaltbildprogrammierung fast 1 zu 1 gleich. Da hast du Recht. Aber dann hast du sicher auch gelernt, was Setup- und Hold-Zeiten sind. Solange du reine kombinatorik zusammenbaust, brauchst du dich darum nicht zu kümmern. Aber wenn Takte und Register (FlipFlops) im Spiel sind, wird das zum Thema. Solange in deinem Design alle Register mit dem gleichen Takt arbeiten, kann die Synthese das für dich lösen. Wenn du dir aber Takte kombinatorisch baust und damit Register taktest und aus den Ergebnissen vielleicht wieder Takte für andere Register generierst, musst du dich selbst darum kümmern, dass es keine Timingverletzungen gibt. Auf einer Leiterplatte macht man das unter anderem über das Layout. In einem FPGA sind deine Eingriffsmöglichkeiten aber eingeschränkter. So eine Schaltung kann funktionieren, kann aber auch immer wieder ungewolltes Verhalten zeigen.
Klar Holdzeiten, Gatterlaufzeiten kennt man. Also der Systemtakt sind die 20Mhz. Ich löse das Problem so, dass ich mit der positiven Flanke zähle und mit der negativen flanke das FF Toggele, bzw den Zähler neu vorlade. Somit habe ich immer 1/2 Taktzeit von 20Mhz zeit, bis sich alle FlipFlops eingeschwungen haben. Die Schaltung läuft auch soweit bis halt auf diese Rundungsfehler. Je größer der eingestellt Wert ist je mehr machen sich die Rundungsfehler bemerkbar.
:
Bearbeitet durch User
Harald G. schrieb: > Q Markus F. -- Laut Datenblatt ist als Input bei BCD als 5 eine 01000 > und nicht 00101. Wenn man die Warheitstabelle weiter sich anschaut, ist > der Input ein 5421 BCD Code. Laut Datenblatt ist der Input für 5 (und 4) 10x (Bit 0 wird ja "aussenrum" verdrahtet) und der binary output ebenso 10x. Hast Du ein anderes Datenblatt als ich? Ich weiss nicht, wo Du liest, aber ich beziehe mich auf die Tabelle auf Seite 5 oben links ("BCD-to-Binary Converter").
Harald G. schrieb: > Somit habe ich immer 1/2 Taktzeit > von 20Mhz zeit, bis sich alle FlipFlops eingeschwungen haben. Ok, das klingt vernünftig. Nun, wie gesagt, wäre ein Schaltplan hilfreich.
Anbei mal der Schaltplan. Das Signal intern_clk_enable einfach nicht beachten. Damit wird nur der Zähler vorgeladen befor das ganze gestartet wird. Genauso die Ausgangsbeschaltung. Damit kann ich den erzeugten Takt oder ein anderen Takt nach außen leiten.
:
Bearbeitet durch User
Das scheint mir an simpler Arithmetik zu hapern ;) 100000 DIV 999 bis runter zu 100000 DIV 991 gibt bei mir immer dasselbe Ergebnis, nämlich 100.
Ja so ist es, je größer der eingestellte Wert ist, je mehr machen sich die Rundungsfehler bemerkbar. Ich habe dazu noch keine Lösung gefunden außer statt 20Mhz auf 200Mhz zugehen. Q Markus F. Ja genau Datenblatt Seite 5 oben links die Tabelle. Ja ich habe übersehen wie es gemeint ist. Klar Bit0 wird durchgereicht und somit ist die ganze Tabelle verschoben und das Bit 0 muss man sich dazudenken. Also Bit 0 vom Eingang kommt sozusagen als Spalte vor dem A in der Tabelle. Hatte ich erst falsch verstanden. Also doch Code 8421. http://www.utm.edu/staff/leeb/DM74185.pdf
:
Bearbeitet durch User
Harald G. schrieb: > Ich habe dazu noch keine Lösung gefunden außer statt 20Mhz auf 200Mhz > zugehen. Nimm Excel und rechne dir's aus: 89 MHz würden reichen, damit deine Schaltstufen gerade noch auflösen.
Harald G. schrieb: > Hatte ich erst falsch verstanden. > Also doch Code 8421. Beides, je nach Beschaltung.
Ja wenn ich 100MHz Oszillator nehme dann sind es effektiv nur 50Mhz zum Auflösen, da ich Puls- und Pausenzeit mit den Takt erzeuge. Somit bin ich etwas bezüglich Auflösung drunter aber evtl. noch vertretbar. 200Mhz Oszillator fällt raus da der MaxV 5M570ZT100C5N laut Datenblatt bei 152MHz schluss ist.
Daran habe ich auch schon gedacht, beide Flanken auszuwerten, so wie beim DDR Ram. Nur habe ich solche FlipFlops bei Quartus noch nicht gefunden.
Ich habe nun folgenden VHDL Code gefunden und statt dem gebastelten Blöcken, aus den 74184, ersetzt. Verbrauchen tut der VHDL Code auch weniger Logikblöcke: http://vhdlguru.blogspot.com/2015/04/vhdl-code-for-bcd-to-binary-conversion.html library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; --this module is for converting a 4 digit BCD number into binary number. --the range of the input in decimal is 0 to 9999. entity bcd_2_bin is Port ( bcd_in_0 : in STD_LOGIC_VECTOR (3 downto 0); bcd_in_10 : in STD_LOGIC_VECTOR (3 downto 0); bcd_in_100 : in STD_LOGIC_VECTOR (3 downto 0); bcd_in_1000 : in STD_LOGIC_VECTOR (3 downto 0); bin_out : out STD_LOGIC_VECTOR (13 downto 0) := (others => '0')); end bcd_2_bin; architecture Behavioral of bcd_2_bin is begin bin_out <= (bcd_in_0 * "01") --multiply by 1 + (bcd_in_10 * "1010") --multiply by 10 + (bcd_in_100 * "1100100") --multiply by 100 + (bcd_in_1000 * "1111101000"); --multiply by 1000 end Behavioral;
Harald G. schrieb: > + (bcd_in_10 * "1010") --multiply by 10 > + (bcd_in_100 * "1100100") --multiply by 100 > + (bcd_in_1000 * "1111101000"); --multiply by 1000 Man kann die Multiplikationen übrigens auch in Multiplikationen mit Zweierpotenzen aka "Linksshifts" (--> andere Verdrahtung) und Additionen auflösen:
1 | bin_out <= |
2 | bcd_in_1 -- es gibt keine 0er-Stelle... |
3 | + bcd_in_10*8 + bcd_in_10*2 |
4 | + bcd_in_100*64 + bcd_in_100*32 + bcd_in_100*4 |
5 | + bcd_in_1000*1024 - bcd_in_1000*16 - bcd_in_1000*8 |
BTW: das Rechnen mit den std_logic_vector findet man gern in alten Büchern oder im amerikanischen Raum. Besser als dieser Stil aus dem letzten Jahrtausend ist die Verwendung des numeric_std Package...
:
Bearbeitet durch Moderator
Und wie dieht dann der ganze Code mit numeric_std aus? Würde ich gerne mal ausprobieren.
Harald G. schrieb: > Und wie dieht dann der ganze Code mit numeric_std aus? Würde ich gerne > mal ausprobieren. der steht oben (Beitrag "Re: BCD zu Binär Konverter 74er Reihe?"). Das ist - mehr oder weniger - dasselbe. Bloss dass man bei meinem Code gleich sieht, was der tut ;)
Habe gerade mein Post mal wieder gefunden. Also ich habe keine dual-edge FFs im MaxV CPLD gefunden. Somit geht bei 100MHz effektiv nur die 50MHz. Ich nehme zwar den 5M570Z und der kann maximal 152MHz. Jedoch habe ich bei 100Mhz schon Probleme mit Laufzeit und muss ein paar Takte Pause einbauen bei z.B. mehrbittigen Multiplexer (19Bit).
Harald G. schrieb: > Gibt es kein Old School IC der das vom 8421 direkt in Binär wandeln > kann. Warum keine Look-up-Tabelle? Sind doch nur 4 Bits!
Beitrag "BCD zu Binär Konverter 74er Reihe?" Lothar M. schrieb: > bin_out <= > bcd_in_1 -- es gibt keine 0er-Stelle... > + bcd_in_10*8 + bcd_in_10*2 > + bcd_in_100*64 + bcd_in_100*32 + bcd_in_100*4 > + bcd_in_1000*1024 - bcd_in_1000*16 - bcd_in_1000*8 > > BTW: das Rechnen mit den std_logic_vector findet man gern in alten > Büchern oder im amerikanischen Raum. Besser als dieser Stil aus dem > letzten Jahrtausend ist die Verwendung des numeric_std Package... Dann sind wir aber wieder bei diesem Problem Beitrag "rechnen mit unsigned" was die Formulierung aufbläht. Dann lieber die Shifts mit den &'0'. Finde ich immer noch durchsichtiger.
Rudi schrieb: > Dann sind wir aber wieder bei diesem Problem > Beitrag "rechnen mit unsigned" > was die Formulierung aufbläht. Kommt drauf an. Wenn man um die unschönen Eigenheiten dieser Berechnungen weiß, dann muss man das mit den Bitbreiten der Toolchain entsprechend beibiegen und kann die Vektorbreiten schon vor der Berechnung passend machen:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity BCD2BIN is |
6 | Port ( bcd1 : in std_logic_vector (3 downto 0); |
7 | bcd10 : in std_logic_vector (3 downto 0); |
8 | bcd100 : in std_logic_vector (3 downto 0); |
9 | bcd1000 : in std_logic_vector (3 downto 0); |
10 | result : out std_logic_vector (15 downto 0)); |
11 | end BCD2BIN; |
12 | |
13 | architecture Behavioral of BCD2BIN is |
14 | signal bcd_in_1, bcd_in_10, bcd_in_100, bcd_in_1000, bin_out: unsigned (15 downto 0); |
15 | begin
|
16 | bcd_in_1 <= resize(unsigned(bcd1),16); |
17 | bcd_in_10 <= resize(unsigned(bcd10),16); |
18 | bcd_in_100 <= resize(unsigned(bcd100),16); |
19 | bcd_in_1000 <= resize(unsigned(bcd1000),16); |
20 | |
21 | bin_out <= bcd_in_1 -- es gibt keine 0er-Stelle... |
22 | + bcd_in_10*8 + bcd_in_10*2 |
23 | + bcd_in_100*64 + bcd_in_100*32 + bcd_in_100*4 |
24 | + bcd_in_1000*1024 - bcd_in_1000*16 - bcd_in_1000*8; |
25 | |
26 | result <= std_logic_vector(resize(bin_out,16)); |
27 | end Behavioral; |
Oder man zwingt das Ergebnis der Multiplikation auf 16 Bit, indem man aus der UNSIGNED*INTEGER Operation (die als Ergebnis ja nur 2*UNSIGNED als Vektorbreite zurückgibt) eine UNSIGNED*UNSIGNED Operation macht, die fürs Ergebnis die beiden Vektorbreiten addiert:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity BCD2BIN is |
6 | Port ( bcd_in_1 : in UNSIGNED (3 downto 0); |
7 | bcd_in_10 : in UNSIGNED (3 downto 0); |
8 | bcd_in_100 : in UNSIGNED (3 downto 0); |
9 | bcd_in_1000 : in UNSIGNED (3 downto 0); |
10 | bin_out : out UNSIGNED (15 downto 0)); |
11 | end BCD2BIN; |
12 | |
13 | architecture Behavioral of BCD2BIN is |
14 | begin
|
15 | |
16 | |
17 | bin_out <= bcd_in_1 -- es gibt keine 0er-Stelle... |
18 | + bcd_in_10*to_unsigned(8,12) + bcd_in_10*to_unsigned(2,12) |
19 | + bcd_in_100*to_unsigned(64,12) + bcd_in_100*to_unsigned(32,12) + bcd_in_100*to_unsigned(8,12) |
20 | + bcd_in_1000*to_unsigned(1024,12) - bcd_in_1000*to_unsigned(16,12) - bcd_in_1000*to_unsigned(8,12); |
21 | |
22 | end Behavioral; |
Aber richtig: "schön" ist anders...
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.