Forum: FPGA, VHDL & Co. Durch 10 teilen


von Bastelboy (Gast)


Lesenswert?

Hallo,

ich habe da eine 6 Bit Binärzahl, die will ich auf einer 2 stelligen 
7-Segment-Anzeige im Dezimalsystem ausgeben. Dazu brauche ich eine 
Modulo-10-Operation und eine Division durch 10. (4 Bit nach 7-Segment 
habe ich schon)
Wie geht man das an auf einem XC9572 CPLD?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

>  Dazu brauche ich eine Modulo-10-Operation und eine Division durch 10.
Das ist nicht sooo trivial.
Vergiss mal die Division auf dem CPLD. So geht das nicht.

Hast du einen Takt?
Dann könntest du evtl. ein BCD-Schieberegister einsetzen:
http://www.lothar-miller.de/s9y/categories/44-BCD-Umwandlung

Aber auf einen CPLD wird das schnell eng :-/

von ms (Gast)


Lesenswert?

Geht bei 6Bit eventuell noch mit nder LUT, aber das braucht auch einige 
Logic Cells im CPLD. Division ist wie Lothar schon angemerkt hat nicht 
Trivial. Außer eventuell durch 2er Potenzen

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lothar Miller schrieb:
> Aber auf einen CPLD wird das schnell eng :-/
Ich muß mich korrigieren. Mit diesem Code:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity BCD_ROM_6Bit is
6
    Port ( data   : in   STD_LOGIC_VECTOR (7 downto 0);
7
           dig1   : out  STD_LOGIC_VECTOR (3 downto 0);
8
           dig10  : out  STD_LOGIC_VECTOR (3 downto 0));
9
end BCD_ROM_6Bit;
10
11
architecture Behavioral of BCD_ROM_6Bit is
12
   type Rom128x8 is array (0 to 63) of std_logic_vector (7 downto 0);
13
   constant BCDRom : Rom128x8 := (
14
    x"00", x"01", x"02", x"03", x"04", x"05", x"06", x"07", x"08", x"09",  
15
    x"10", x"11", x"12", x"13", x"14", x"15", x"16", x"17", x"18", x"19",  
16
    x"20", x"21", x"22", x"23", x"24", x"25", x"26", x"27", x"28", x"29",  
17
    x"30", x"31", x"32", x"33", x"34", x"35", x"36", x"37", x"38", x"39",  
18
    x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47", x"48", x"49",  
19
    x"50", x"51", x"52", x"53", x"54", x"55", x"56", x"57", x"58", x"59",  
20
    x"60", x"61", x"62", x"63" );
21
   signal digits : std_logic_vector (7 downto 0);
22
begin
23
   digits <= BCDRom(to_integer(unsigned(data))); 
24
   dig1   <= digits (3 downto 0);
25
   dig10  <= digits (7 downto 4);
26
end Behavioral;

Gibts das Ergebnis:
1
Macrocells  Pterms        Registers   Pins        Function Block Inputs 
2
8/72 (12%)  39/360 (11%)  0/72 (0%)   14/34(42%)  15/216 (7%)
Das sieht gar nicht so schlecht aus.

EDIT:
Sogar einen ganzen 8 Bit Vektor kann man in diesem CPLD noch ohne 
weiteres wandeln (Code von meiner HP, Link siehe oben). Die Produktterme 
sind schön mächtig  :-)
1
Macrocells   Pterms         Registers   Pins         Function Block Inputs 
2
15/72 (21%)  130/360 (37%)  0/72 (0%)   20/34 (59%)  36/216 (17%)

von Der Besucher (Gast)


Lesenswert?

Elegant!

Der Besucher

von TobiFlex (Gast)


Lesenswert?

Der Byte zu 3xBCD Coder gefällt mir und erstaunt mich. Ich hätte einen 
viel größeren Resourcenverbrauch erwartet. Aber so kann ich das direkt 
gebrauchen und werds mal irgendwo einbauen.

Danke
TobiFlex

von Pedro (Gast)


Lesenswert?

Ist doch klar, viele therme innerhalb des mux treten mehrfach auf, 
werden aber nur einmal gebaut. Nimm Dir mal eine Sinustabelle, die in 
LUTs gebaut wird und nicht im RAM liegt. Die hat nur die halbe Zahl der 
LUTs die sie haben müsste, wenn alles parallel realisierrt wäre.

von J. S. (engineer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Man kann so ziemlich jede Funktion in VHDL formulieren und in LUTs 
realisieren, wenn man sich ein script macht, welches VHDL automatisch 
erzeugt. Ich mache das mit einer Accessdatenbank oder Excel unter 
Nutzung von VBA und den DDS-Abfragen. Ich habe anbei mal ein VHDL und 
eine Sample-Bank angefügt, die zeigen, wie das geht.

Man muss den Code dann nur noch minimal modifizieren, damit er 
compiliert.
(erstes ELSIF in IF tauschen etc..)
1
entity DIVIDER is
2
port(
3
    CLK    :  IN STD_LOGIC;
4
    MUL    :  IN STD_LOGIC_VECTOR( 7 downto 0);
5
    DIV    :  IN STD_LOGIC_VECTOR( 7 downto 0);
6
    QUO    : OUT STD_LOGIC_VECTOR(15 downto 0)
7
  );
8
end DIVIDER;
9
10
11
architecture A of DIVIDER is
12
13
begin
14
15
make_outs: process (CLK)
16
begin
17
  if rising_edge(CLK) then
18
19
20
   if ( (unsigned(MUL) = 30) and (unsigned(DIV) = 4) ) then QUO <= conv_std_logic_vector ( 3840 ,16);
21
   
22
elsif ( (unsigned(MUL) = 75) and (unsigned(DIV) = 10) ) then QUO <= conv_std_logic_vector ( 3840 ,16);
23
elsif ( (unsigned(MUL) = 60) and (unsigned(DIV) = 8) ) then QUO <= conv_std_logic_vector ( 3840 ,16);
24
elsif ( (unsigned(MUL) = 15) and (unsigned(DIV) = 2) ) then QUO <= conv_std_logic_vector ( 3840 ,16);
25
elsif ( (unsigned(MUL) = 45) and (unsigned(DIV) = 6) ) then QUO <= conv_std_logic_vector ( 3840 ,16);
26
elsif ( (unsigned(MUL) = 90) and (unsigned(DIV) = 12) ) then QUO <= conv_std_logic_vector ( 3840 ,16);
27
-- usw.

Heraus kommt ein Quotient mit der Skalierung 256.

Über die Primärtabellen in der Datenbank kann man sogar die 
Definitionsbereiche einschränken, um nur die möglichen Teiler zu 
bekommen.

von Jan M. (mueschel)


Lesenswert?

@Jürgen:
Für was benutzt du diesen Code?
Ich habe ihngerade mal in ise geladen. Die Synthese braucht eine knappe 
Stunde, benutzt fast 3000 LUTs und läuft selbst in einem Virtex 4 nur 
mit 70MHz - das klingt für mich nicht nach einer brauchbaren Lösung, 
zumal im Code auch nur eine relativ willkürlich erscheinende Auswahl an 
möglichen Input-Werten getroffen wird.

von Projektleiter (Gast)


Lesenswert?

Mich wundert es, dass überhaupt noch 70MHz rauskommen! Hört sich schon 
ziemlich schnell an für den Baum, der da gebaut werden muss...

von J. S. (engineer) Benutzerseite


Lesenswert?

>@Jürgen:
>Für was benutzt du diesen Code?

Der Code ist nur ein Beispiel, wie man das machen kann. Es ging mir 
darum, zu zeigen, wie man mit der Hilfe der Datenbankfunktionen in 
Access automatisch VHDL erzeugen lassen kann.

>Die Synthese braucht eine knappe Stunde
Habe das testsynthetisiert mit Quartus 9.0: <25 Min!

>benutzt fast 3000 LUTs

Das ist noch wenig :-)

Hast aber schon Recht: Es ist einseitiger Bau auf Geschwindigkeit auf 
Kosten des Platzbedarfes! Das wird man nur machen, wenn es arg schnell 
gehen muss, z.B. die schnelle Berechung innerhalb von Regelschleifen auf 
Hochgeschwindigkeit, wo man keine grosse Latenz verkraften kann.

Konkret wird man in der Regel auch keinen Divider bauen, aber mit einem 
Logarithmus, einem Sinus oder einer hyperbolischen Funktion böte sich 
das schon an. Ich habe es auch schon mit einem Gaussalgorithmus gemacht: 
4 Determinantenwerte werden flash berechnet und dann weiter verrechnet: 
Mit dem Divider oben ginge das ganze sogar in 10 Takten. Real braucht 
jede Determinante schon 15 und die gesamte Rechung über 100, wenn man es 
voll sequenziell macht. (Der Divider hat auf der hohen Breite schon 6 
Takte)

Aber je billiger die FPGAs werden und je mehr DSPs sie haben, desto mehr 
wird sowas wichtig.

P.S. Die Einschränkung, die oben im Code enhalten ist, ist auch ein 
Beispiel. Damit kann man aber sehr effektiv nur das aufbauen, was man 
auch braucht! Nicht jede mathematische Funktion wird ja durch den 
Definitionsbereich komplett angesteuert. Z.B. hatte ich mal eine 
Wurzel-aus-Sinus-berechung aus einem Zwischenergebnis, das überhaupt nur 
zwischen 257 und 3 x (k x 256  +  n x 255) liegen konnte.

Wenn man sich das vorberechnet hat, fallen die Perioden des Sinus raus 
und dank der 25%igen Auslastung des Definitionsbereichens nochmal 50% 
der Wertmenge für die Wurzel. Das gab eine sehr übersichtliche Tabelle 
:-)

Vor allem können die Terme, die entstehen, oftmals noch mit 
vorangegangenen Berechungen zusammengefasst werden. Mit der Option 
"Register - Retiming" macht das die Synthese sogar automatisch. Da fällt 
vorne dann wider viel weg.

von Jan M. (mueschel)


Lesenswert?

Jürgen Schuhmacher schrieb:
>>@Jürgen:
>>Die Synthese braucht eine knappe Stunde
> Habe das testsynthetisiert mit Quartus 9.0: <25 Min!

Gut, mein Rechner war nicht der schnellste, das kommt schon hin auf 
einer aktuellen Maschine. Allerdings: Trotz komplexen Designs die viele 
Verknüpfungen aufweisen und >50.000 LUTs verwenden hat bei mir noch 
keine Synthese über 10 Minuten gedauert.

>>benutzt fast 3000 LUTs
>
> Das ist noch wenig :-)
Autsch.

> Hast aber schon Recht: Es ist einseitiger Bau auf Geschwindigkeit auf
> Kosten des Platzbedarfes! Das wird man nur machen, wenn es arg schnell
> gehen muss, z.B. die schnelle Berechung innerhalb von Regelschleifen auf
> Hochgeschwindigkeit, wo man keine grosse Latenz verkraften kann.
Optimiert auf Geschwindigkeit ist das aber sicherlich nicht, z.B. kann 
man einige einfache Fälle (hier: Divisionen durch 1,2,4,8) durchaus von 
Hand optimieren.

Eine viel kleinere Lösung für dein Beispiel wäre: Ein ROM, der die 
Ergebnisse von 1/n fuer alle 256 möglichen DIV enthält, mit 24bit 
Genauigkeit und dahinter geschaltet ein Multiplizierer, der den Wert aus 
dem ROM mit MUL multipliziert. Das sollte sicher eine höhere 
Taktfrequenz erreichen, wenn auch mit einem Takt Latenz.

>Aber je billiger die FPGAs werden und je mehr DSPs sie haben, desto mehr
>wird sowas wichtig.
Genau das ist in meinen Augen die falsche Einstellung - "Wir haben ja 
genügend Leistung, also schreiben wir einfach irgendeinen Code ohne auf 
Effizienz zu achten".

von J. S. (engineer) Benutzerseite


Lesenswert?

> z.B. kann man einige einfache Fälle (hier: Divisionen durch 1,2,4,8)
> durchaus von Hand optimieren.

Die Fallunterscheidung kostet Programmierarbeit, die die Synthese 
erledigt! Diese einfachen Fälle werden erkannt und wegoptimiert. In den 
Fallen, in denen die Architektur das nicht zu lässt, kosten die 
Fallunterscheidungen aber Rechenzeit, die der Vorgehensweise, alles in 
einem Clock zu erledigen, zuwider läuft.

> Eine viel kleinere Lösung für dein Beispiel wäre: Ein ROM, der die
> Ergebnisse von 1/n fuer alle 256 möglichen DIV enthält, mit 24bit
> Genauigkeit und dahinter geschaltet ein Multiplizierer,

Genau das ist ja der Denkansatz und läuft auf genau dasselbe hinaus, 
wenn das ROM und der Multiplizierer als LUT-array realisiert sind :-)

Aber:

1) Es braucht eine Auflösungsstufe mehr, wegen des Zwischenergebnisses - 
bilde Dir mal die Tabelle für das 1/n

2) Man verliert entweder Laufzeit oder einen Takt, in jedem Fall ist es 
langsamer (ich habe viel mit solchen Strukturen experientiert )

3) nur bei expliziter Darstellung können Terme mit Partiallösungen von 
Ergebnissen vorher zusammengealtet werden, die im gleichen Takt 
entstanden sind. (Man darf sowas nie isoliert sehen)

4) Die Definitionsmenge kann nicht so gut eingeschränkt werden


> Genau das ist in meinen Augen die falsche Einstellung
> - "Wir haben ja genügend Leistung, also schreiben wir einfach
>  irgendeinen Code ohne auf Effizienz zu achten".

Grundsätzlich bin ich auf Deiner Seite, nur muss man das Argument 
entsprechend anwenden: Normalerweise wird man gerade so schnell bauen, 
wie nötig und damit Platz und Leistung sparen. Aber in meinem Beispiel 
geht es wie gesagt um Tempolösungen!

Man muss sich ja immer überlegen, welche Randbedingung das FPGA gerade 
hat und wenn es um das Platz, Geld- und Energisparen geht, ist der DSP 
sowieos erstmal die bessere Wahl. Wenn aber ein FPGA zur Anwendung 
kommt, dann gibt es meist zwei Gründe:

a) Es muss schneller sein, als DSPs es können und gepipelined sind 
solche FPGA-Rechner x-mal schneller, man denke an viele Kanäle ...

b) Das FPGA ist aus anderen Gründen schon da und kann verwendet werden 
oder es kann kostengünstig ein größeres implementiert werden

Beide Fälle habe ich regelmässig und wenn Fall 2 zutrifft und ich die 
Möglichkeit habe, aufgrund der Leistungsreserven in das vorhandene FPGA 
etwas Rechnung einbauen und damit den DSP wegfallen lassen zu können, 
dann ist das zwingend die richtige Entscheidung, so vorzugehen.

... nud genau damit achte ich sehr genau auf (System-)effizienz :-)

von Jan M. (mueschel)


Lesenswert?

Jürgen Schuhmacher schrieb:
>> Eine viel kleinere Lösung für dein Beispiel wäre: Ein ROM, der die
>> Ergebnisse von 1/n fuer alle 256 möglichen DIV enthält, mit 24bit
>> Genauigkeit und dahinter geschaltet ein Multiplizierer,
>
> Genau das ist ja der Denkansatz und läuft auf genau dasselbe hinaus,
> wenn das ROM und der Multiplizierer als LUT-array realisiert sind :-)
Wer macht denn das? 1 BRAM und 2 Multiplizierer von vielen vs. 3k LUTs, 
was bei vielen Bausteinen schon ueber 10% sind.

> 1) Es braucht eine Auflösungsstufe mehr, wegen des Zwischenergebnisses -
> bilde Dir mal die Tabelle für das 1/n
Diese gibt es im Prinzip kostenlos dazu, ein memory Block hat ja gross 
genug.
>
> 2) Man verliert entweder Laufzeit oder einen Takt, in jedem Fall ist es
> langsamer (ich habe viel mit solchen Strukturen experientiert )
Ich bin ziemlich sicher dass die "einfache" Loesung hier insgesamt 
schneller ist. Sowohl ein ROM als auch ein 32x8 Multiplizierer laufen 
mit ueber 140 MHz. Das ist bei zwei Takten schneller als die 
"Brachialloesung"
>
> 3) nur bei expliziter Darstellung können Terme mit Partiallösungen von
> Ergebnissen vorher zusammengealtet werden, die im gleichen Takt
> entstanden sind. (Man darf sowas nie isoliert sehen)
>
> 4) Die Definitionsmenge kann nicht so gut eingeschränkt werden
Das ist dann auch gar nicht noetig, weil es ohnehin keine Ressourcen 
einspart.


> a) Es muss schneller sein, als DSPs es können und gepipelined sind
> solche FPGA-Rechner x-mal schneller, man denke an viele Kanäle ...
>
> b) Das FPGA ist aus anderen Gründen schon da und kann verwendet werden
> oder es kann kostengünstig ein größeres implementiert werden
>
> Beide Fälle habe ich regelmässig und wenn Fall 2 zutrifft und ich die
> Möglichkeit habe, aufgrund der Leistungsreserven in das vorhandene FPGA
> etwas Rechnung einbauen und damit den DSP wegfallen lassen zu können,
> dann ist das zwingend die richtige Entscheidung, so vorzugehen.

Natuerlich, da sind wir einer Meinung. Allerdings halte ich es fuer 
fragwuerdig, so massiv Hardware-Ressourcen zu verwenden und aeusserst 
lange Synthesezeiten zu produzieren, nur um sich ein wenig 
Entwicklungszeit zu sparen. Man muss sich ja auch ueberlegen, wieviel 
Zeit verloren geht durch die 10fach laengere Zeit zwischen Quellcode und 
Syntheseergebnis fuer Simulation oder Hardware.

von gagamel (Gast)


Lesenswert?

> Man muss sich ja auch ueberlegen, wieviel Zeit verloren geht
> durch die 10fach laengere Zeit zwischen Quellcode und
> Syntheseergebnis fuer Simulation oder Hardware.

Seit wann kostet denn die Synthesezeit Geld? Von mir aus kann der 
Rechner 4 Tage synthetisieren, wenn das Ergebnis besser ist und die 
FPGAs schnell.

>Sowohl ein ROM als auch ein 32x8 Multiplizierer laufen mit ueber 140 MHz.

Das sind aber in Kette deutlich weniger, als die Hälfte wegen dem 
Routing und das ROM liegt ja meistens im RAM und das hängt wo in der 
Ecke! Da darf man sich mit dem Routing nicht vertun.

Aber mal im Ernst: Ihr beiden spendiert ein fettes ROM für eine simple 
Division?

von Jan M. (mueschel)


Lesenswert?

gagamel schrieb:
> Seit wann kostet denn die Synthesezeit Geld?
Sie kostet genau dann Geld, wenn man wegen einer (oftmals kleinen) 
Änderung im Code eine lange Wartezeit hat oder einen Fehler erst nach 
langer Synthesezeit im Report erkennt und beheben kann.

>>Sowohl ein ROM als auch ein 32x8 Multiplizierer laufen mit ueber 140 MHz.
> Das sind aber in Kette deutlich weniger, als die Hälfte wegen dem
> Routing und das ROM liegt ja meistens im RAM und das hängt wo in der
> Ecke! Da darf man sich mit dem Routing nicht vertun.

Wenn ich den floorplan eines Virtex4 noch richtig im Kopf habe, sind die 
Multiplier immer direkt neben BRAMs angeordnet und hart verdrahtet, 
insofern sollte sich die Laufzeit zwischen den Modulen in Grenzen 
halten. Außerdem kann man am Speicher dann auch die Ausgangs-FF 
verwenden, damit sollten die 140MHz erreichbar sein - was dann trotz 2 
Takten Latenz noch schneller ist als ein Takt bei 70 MHz.

> Aber mal im Ernst: Ihr beiden spendiert ein fettes ROM für eine simple
> Division?

Normalerweise würde man das über eine Pipeline mit wenig Logik und 
einigen Takten Latenz machen - wenn allerdings eine wirklich niedrige 
Latenz gefordert ist, dann sind große Lookup-Tables in einem ROM 
durchaus ein adäquates Mittel.

von gagamel (Gast)


Lesenswert?

Was heisst denn bei Dri "hart" verdrahtet?

BRAMs sind sau langsam, wegen der MUXER und haben immer mindestens 1 
Clock Latenz und brauchen sogar 2, wenn man auf Durchsatz kommen will.

von Jan M. (mueschel)


Lesenswert?

gagamel schrieb:
> Was heisst denn bei Dri "hart" verdrahtet?
Mit hart meinte ich durch dedizierte Leitungen verbunden, nicht durch 
normales Routing - damit habe ich mich aber geirrt:
Beim Virtex 4 trifft das nicht mehr zu, aber im Virtex 2 bestanden BRAM 
und Multiplier aus einem festen Block, die miteinander verbunden waren.

> BRAMs sind sau langsam, wegen der MUXER und haben immer mindestens 1
> Clock Latenz und brauchen sogar 2, wenn man auf Durchsatz kommen will.

Nun ja, laut Datenblatt 450 MHz im mittleren Speedgrade, 200 Mhz sind 
noch ohne jedwede Design-Tricks locker nutzbar. Die FF am Ausgang, und 
damit die 2 Takte Latenz, braucht man nur, wenn nach dem RAM noch 
größere Logik folgt oder man sehr hohe Taktraten erreichen will.

von bernd (Gast)


Lesenswert?

Coole lösung mit der LUT!

Die LUT von oben kann man noch um die hälfte auf 32 Werte schrumpfen 
weil div/mod 2 trivial ist und man dann nur für div/mod 5 ne tabelle 
braucht.

Dann mit data(7 downto 1) in die tabelle und:
dig1   <= digits (2 downto 0) & data(0);
dig10  <= digits (6 downto 3);

von bernd (Gast)


Lesenswert?

Frage mich, ob das Synthese-tool das evtl. selber erkennt und 
entsprechend optimiert.

von bernd (Gast)


Lesenswert?

Eigtl. muss erst ja merken wenn er die Terme zusammenbaut, dass dig1(0) 
= data(0)

von bernd (Gast)


Lesenswert?

Noch ne Frage. Die LUT mit konstantem Inhalt sollte man doch auch durch 
ne for-schleife ersetzen können, die die entsprechenden Werte ausrechnet 
und bei der Synthese ausgewertet wird - mit dem selben Ergebnis?

von Bastelboy (Gast)


Lesenswert?

Leider kriege ich dies nicht zum laufen:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
use IEEE.NUMERIC_STD.ALL;
6
7
entity Dezimalanzeige is
8
    Port (
9
        Generator    :  in bit;
10
    Switch    :  in std_logic_vector(5 downto 0);  -- Switch : in integer range 0 to 63;
11
    DISP0    : out bit;
12
    DISP1    : out bit;
13
    SEGA      : out std_logic;
14
    SEGB      : out std_logic;
15
    SEGC      : out std_logic;
16
    SEGD      : out std_logic;
17
    SEGE      : out std_logic;
18
    SEGF      : out std_logic;
19
    SEGG      : out std_logic
20
        );
21
end Dezimalanzeige;
22
23
architecture Behavioral of Dezimalanzeige is
24
signal count  : std_logic_vector (3 downto 0);
25
signal DIGIT  : std_logic_vector (6 downto 0);
26
signal bla  : std_logic_vector (7 downto 0);
27
signal X_index  : integer range 0 to 63;
28
type Rom128x8 is array (0 to 63) of std_logic_vector (7 downto 0);
29
constant BCDRom : Rom128x8 := (
30
x"00", x"01", x"02", x"03", x"04", x"05", x"06", x"07", x"08", x"09",  
31
x"10", x"11", x"12", x"13", x"14", x"15", x"16", x"17", x"18", x"19",  
32
x"20", x"21", x"22", x"23", x"24", x"25", x"26", x"27", x"28", x"29",  
33
x"30", x"31", x"32", x"33", x"34", x"35", x"36", x"37", x"38", x"39",  
34
x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47", x"48", x"49",  
35
x"50", x"51", x"52", x"53", x"54", x"55", x"56", x"57", x"58", x"59",  
36
x"60", x"61", x"62", x"63" );
37
begin
38
X_index <= Switch;
39
bla <= BCDRom(X_index); 
40
count <= bla(7 downto 4) when Generator = '1' else bla(3 downto 0);
41
42
with count select
43
  DIGIT <=  "1111110" when "0000",
44
       "0110000" when "0001",
45
      "1101101" when "0010",
46
      "1111001" when "0011",
47
      "0110011" when "0100",
48
      "1011011" when "0101",
49
       "1011111" when "0110",
50
      "1110010" when "0111",
51
      "1111111" when "1000",
52
      "1111011" when "1001",
53
       "0000000" when others;
54
55
SEGA <= DIGIT(6);
56
SEGB <= DIGIT(5);
57
SEGC <= DIGIT(4);
58
SEGD <= DIGIT(3);
59
SEGE <= DIGIT(2);
60
SEGF <= DIGIT(1);
61
SEGG <= DIGIT(0);
62
63
stellenauswahl: process (Generator)
64
begin
65
if Generator = '0'
66
then  
67
  DISP0 <= '1';
68
  DISP1 <= '0';
69
else
70
   DISP0 <= '0';  
71
  DISP1 <= '1';
72
end if;
73
end process stellenauswahl;
74
75
end Behavioral;
76
[/asvasm]
77
Fehlermeldung:
78
ERROR:HDLParsers:800 - C:/XilinxPLD12/Dezimalanzeige/Dezimalanzeige.vhd Line 38. Type of X_index is incompatible with type of Switch.
79
80
Wie kann ich den mein BCDRom adressieren?
81
[avrasm]
82
 bla <= BCDRom(to_integer(unsigned(Switch)));
hat auch nicht recht geklappt

von Jan M. (mueschel)


Lesenswert?

Ein std_logic ist kein integer, ergo kann man die nicht direkt zuweisen.
Mit numeric_std als library geht es so:

X_index <= to_integer(unsigned(Switch));


>library IEEE;
>use IEEE.STD_LOGIC_1164.ALL;
>use IEEE.STD_LOGIC_ARITH.ALL;
>use IEEE.STD_LOGIC_UNSIGNED.ALL;
>use IEEE.NUMERIC_STD.ALL;

Deine Wahl der Libaries ist nicht ganz gluecklich. Es reichen die erste 
und die letzte.

von J. S. (engineer) Benutzerseite


Lesenswert?

>Frage mich, ob das Synthese-tool das evtl. selber erkennt und
>entsprechend optimiert.
Jepp!

>Ich bin ziemlich sicher dass die "einfache" Loesung hier insgesamt
>schneller ist
Definitiv in der Regel nicht, sonst würde ich ja die Wege nicht gehen:-)

>Aber mal im Ernst: Ihr beiden spendiert ein fettes ROM für eine simple
>Division?

Wie ich bereits schrieb, ist das eigentliche Ziel der Vorgehensweise 
nicht primär, einfache Multiplikationen (oder hier Divisionen) zu 
ersetzen, die in den allermeisten Fällen schnell genug laufen werden, 
sondern Funktionen zusammenzufassen, bzw so zu formulieren, dass sie 
zusammenfassbar sind. Bei der ausdrücklichen Verwendung von RAM und MUL 
ist das kaum der Fall.

Die Methode ist aber auch bei einfachen Berechnungen sehr effektiv, wie 
z.B. das Beispiel "durch 10" zeigt (um das es hier mal ging :-)) und 
nur, bei ausdrücklicher Formulierung der Terme, können die Verknüpfungen 
mit anderen vorherstehenden Berechnungsergebnissen zusammengefasst und 
vereinfacht werden. Ich habe das bei meinem Neuronennetzwerk gesehen, wo 
eine Aneinanderreihung vieler Vergleiche, Elementarmultiplikationen (und 
auch Divisionen) zunächst zu einem scheinbar gewaltigen Baum auftürmen, 
hinterher jenachdem, was man in die Neuronen sonst noch reinstopft 
wieder in sich zusammenfallen (samt der komplexen 
Verschaltungsarchitektur).

Für einen Satz paralleler Audio-DSPs (im Wesentlichen Mischer und 
einfache Filter) braucht Quartus im Übrigen 6-8h (je FPGA Derivat!).

von Bastelboy (Gast)


Lesenswert?

>Ein std_logic ist kein integer, ergo kann man die nicht direkt zuweisen.
>Mit numeric_std als library geht es so:

>X_index <= to_integer(unsigned(Switch));


>>library IEEE;
>>use IEEE.STD_LOGIC_1164.ALL;
>>use IEEE.STD_LOGIC_ARITH.ALL;
>>use IEEE.STD_LOGIC_UNSIGNED.ALL;
>>use IEEE.NUMERIC_STD.ALL;

>Deine Wahl der Libaries ist nicht ganz gluecklich. Es reichen die erste
>und die letzte.

Danke!

Als ich die beiden mittleren Libaries auskommentiert habe, ging es!
Warum? Wo lag da der Hund begraben?

von Gagamel (Gast)


Lesenswert?

Widersprüchlichkeit / Mehrdeutigkeit !

Nimm numeric.std - da geht alles mit zu machen und much easier!

von J. S. (engineer) Benutzerseite


Lesenswert?

Die numeric z.B enthält Definitionen, die auch in den anderen libs 
vorhanden sind.

von Peter Z. (Gast)


Lesenswert?

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
--use IEEE.STD_LOGIC_ARITH.ALL;
4
--use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
use IEEE.NUMERIC_STD.ALL;
6
7
entity Dezimalanzeige is
8
    Port (
9
    Switch    : in std_logic_vector(6 downto 0);
10
    Generator    :  in bit;
11
    DISP0    : out bit;
12
    DISP1    : out bit;
13
    SEGA      : out std_logic;
14
    SEGB      : out std_logic;
15
    SEGC      : out std_logic;
16
    SEGD      : out std_logic;
17
    SEGE      : out std_logic;
18
    SEGF      : out std_logic;
19
    SEGG      : out std_logic
20
        );
21
end Dezimalanzeige;
22
23
architecture Behavioral of Dezimalanzeige is
24
signal count  : std_logic_vector (3 downto 0);
25
signal DIGIT  : std_logic_vector (6 downto 0);
26
signal bla  : std_logic_vector (7 downto 0);
27
signal X_index  : integer range 0 to 99;
28
type Rom128x8 is array (0 to 99) of std_logic_vector (7 downto 0);
29
constant BCDRom : Rom128x8 := (
30
x"00", x"01", x"02", x"03", x"04", x"05", x"06", x"07", x"08", x"09",
31
x"10", x"11", x"12", x"13", x"14", x"15", x"16", x"17", x"18", x"19",  
32
x"20", x"21", x"22", x"23", x"24", x"25", x"26", x"27", x"28", x"29",  
33
x"30", x"31", x"32", x"33", x"34", x"35", x"36", x"37", x"38", x"39",  
34
x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47", x"48", x"49",  
35
x"50", x"51", x"52", x"53", x"54", x"55", x"56", x"57", x"58", x"59",  
36
x"60", x"61", x"62", x"63", x"64", x"65", x"66", x"67", x"68", x"69",  
37
x"70", x"71", x"72", x"73", x"74", x"75", x"76", x"77", x"78", x"79",  
38
x"80", x"81", x"82", x"83", x"84", x"85", x"86", x"87", x"88", x"89",  
39
x"90", x"91", x"92", x"93", x"94", x"95", x"96", x"97", x"98", x"99"
40
);
41
begin
42
X_index <= to_integer(unsigned(Switch));
43
44
bla <= BCDRom(X_index); 
45
count <= bla(7 downto 4) when Generator = '1' else bla(3 downto 0);
46
47
with count select
48
  DIGIT <=  "1111110" when "0000",
49
       "0110000" when "0001",
50
      "1101101" when "0010",
51
      "1111001" when "0011",
52
      "0110011" when "0100",
53
      "1011011" when "0101",
54
       "1011111" when "0110",
55
      "1110010" when "0111",
56
      "1111111" when "1000",
57
      "1111011" when "1001",
58
       "0000000" when others;
59
60
SEGA <= DIGIT(6);
61
SEGB <= DIGIT(5);
62
SEGC <= DIGIT(4);
63
SEGD <= DIGIT(3);
64
SEGE <= DIGIT(2);
65
SEGF <= DIGIT(1);
66
SEGG <= DIGIT(0);
67
68
stellenauswahl: process (Generator)
69
begin
70
if Generator = '0'
71
then  
72
  DISP0 <= '1';
73
  DISP1 <= '0';
74
else
75
   DISP0 <= '0';  
76
  DISP1 <= '1';
77
end if;
78
end process stellenauswahl;
79
80
end Behavioral;

So, das geht jetzt!

von Peter Z. (Gast)


Lesenswert?

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity Dezimalanzeige2 is
7
    Port (
8
        Takt      :  in bit;
9
    Switch    :  in std_logic_vector(7 downto 0);
10
    DISP0    : out bit;
11
    DISP1    : out bit;
12
    Led_10    : out std_logic_vector(1 downto 0);
13
    SEGA      : out std_logic;
14
    SEGB      : out std_logic;
15
    SEGC      : out std_logic;
16
    SEGD      : out std_logic;
17
    SEGE      : out std_logic;
18
    SEGF      : out std_logic;
19
    SEGG      : out std_logic
20
        );
21
end Dezimalanzeige2;
22
23
architecture Behavioral of Dezimalanzeige2 is
24
signal Bin_zahl    : std_logic_vector(7 downto 0);
25
signal Hunderter    : std_logic_vector(1 downto 0);
26
signal Zehner      : std_logic_vector(3 downto 0);
27
signal Hunderter_buff  : std_logic_vector(1 downto 0);
28
signal Zehner_buff    : std_logic_vector(3 downto 0);
29
signal Einer_buff    : std_logic_vector(3 downto 0);
30
signal BCD      : std_logic_vector(3 downto 0);
31
signal Digit      : std_logic_vector(6 downto 0);
32
begin
33
34
bin_to_dez: process (Takt,Hunderter_buff,Zehner_buff)
35
begin
36
if (Takt ='1' and Takt'event) then
37
  if Bin_zahl >= 100 then
38
    Bin_zahl <= Bin_zahl - 100;
39
    Hunderter <= Hunderter + 1;
40
  elsif Bin_zahl >= 10 then
41
    Bin_zahl <= Bin_zahl - 10;
42
    Zehner <= Zehner + 1;
43
  else
44
    Led_10 <= Hunderter;
45
    Hunderter_buff <= Hunderter;
46
    Zehner_buff <= Zehner;
47
    Einer_buff <= Bin_zahl(3 downto 0);
48
    Hunderter <= "00";
49
    Zehner <= "0000";
50
    Bin_zahl <= Switch(7 downto 4) * Switch(3 downto 0);
51
  end if;
52
end if;
53
if Hunderter_buff = "00" and Zehner_buff = "0000" then Zehner_buff <= "1010";--"1010" ist Leerzeichen => führende Nullen unterdrücken 
54
end if;
55
56
end process bin_to_dez;
57
58
BCD <= Zehner_buff when Takt = '1' else Einer_buff;
59
60
with BCD select Digit <=
61
  "1111110" when "0000",
62
  "0110000" when "0001",
63
  "1101101" when "0010",
64
  "1111001" when "0011",
65
  "0110011" when "0100",
66
  "1011011" when "0101",
67
  "1011111" when "0110",
68
  "1110010" when "0111",
69
  "1111111" when "1000",
70
  "1111011" when "1001",
71
  "0000000" when others;
72
73
SEGA <= Digit(6);
74
SEGB <= Digit(5);
75
SEGC <= Digit(4);
76
SEGD <= Digit(3);
77
SEGE <= Digit(2);
78
SEGF <= Digit(1);
79
SEGG <= Digit(0);
80
81
stellenauswahl: process (Takt)
82
begin
83
if Takt = '0'
84
then  
85
  DISP0 <= '1';
86
  DISP1 <= '0';
87
else
88
   DISP0 <= '0';  
89
  DISP1 <= '1';
90
end if;
91
end process stellenauswahl;
92
93
end Behavioral;
So, und dieses geht auch.
Die Frage ist jetzt, welche Lösung ist effizienter, und verbraucht 
weniger Logikzellen auf meinem CPLD XC9572 ???

von Modelsimmer (Gast)


Lesenswert?

Die erste ist die moderne und verbraucht sicher nicht mehr Zellen.

Aber lass es doch mal probesynthetisieren und erzähle uns das Ergebnis,

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

@  Peter Zz (bastelboy)
Ressourcenverbrauch (bezogen auf ein XC9572XL)
Variante 1 aus Beitrag "Re: Durch 10 teilen"
1
Macrocells Used  Pterms Used     Registers Used  Pins Used     Function Block Inputs Used 
2
12/72  (17%)     160/360  (45%)  0/72  (0%)      17/34  (50%)  36/216  (17%)
Variante 2 aus Beitrag "Re: Durch 10 teilen"
1
Macrocells Used  Pterms Used     Registers Used  Pins Used     Function Block Inputs Used 
2
39/72  (55%)     328/360  (92%)  24/72  (34%)    20/34  (59%)  100/216  (47%)
Du darfst jetzt selber abschätzen, was effizienter ist ;-)

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
Noch kein Account? Hier anmelden.