Forum: FPGA, VHDL & Co. LUT erzeugen mit Encoderwerten


von Chris (Gast)


Lesenswert?

Hallo zusammen,

ich programmiere gerade mein erstes FPGA mit Smartfusion2 in VHDL. Bis 
jetzt habe ich die Auswertung des Encoders programmiert. Jetzt würde ich 
gerne unterhalb von 50 m/min 1 LED leuchten lassen und ab 50-100 m/min 
eine andere usw. Jedoch weiß ich nicht genau wie ich dies in VHDL 
umsetzen soll. Am liebsten würde ich eine LUT erstellen, dass immer wenn 
die Geschwindigkeit erreicht wird die richtige LED angeht. Zuerst wollte 
ich es mit < verwenden, jedoch habe ich gelesen, dass dies nicht optimal 
ist. Welche Varianten gibt es, dies umzusetzen?
Schon mal Danke für eure Antworten :)

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


Lesenswert?

Chris schrieb:
> Bis jetzt habe ich die Auswertung des Encoders programmiert.
Und was kommt aus dieser Auswertung heraus? Ein Zählerstand? Oder 
Zählimpulse?

> Zuerst wollte ich es mit < verwenden, jedoch habe ich gelesen, dass
> dies nicht optimal ist.
Wo und in welchem Zusammenhang? Was komt raus, wenn du selbst es auf 
deiner Zielplattform ausprobierst?

> jedoch habe ich gelesen, dass dies nicht optimal ist.
Was für das eine FPGA optimal ist, kann für das eines anderen Hersteller 
zu einer umständlichen Implementierung führen.

> Welche Varianten gibt es, dies umzusetzen?
Wenn du tatsächlich nur 2 LEDs hast, dann ist die Vergleichsvariante mit 
Sicherheit die beste Lösung.
Wenn du aber 32 LEDs hast, die gleiche Abstände mrakieren sollen 
(0..15..30..45..60..75.. oder 0..7..14..21..28..35.. m/min), dann wäre 
es einfacher, die Geschwindigkeit so zu berechnen, dass als Ergebnis 
genau der Index der anzuschaltenden LED herauskommt...

von Chris (Gast)


Lesenswert?

Lothar M. schrieb:
> Chris schrieb:
> Bis jetzt habe ich die Auswertung des Encoders programmiert.
>
> Und was kommt aus dieser Auswertung heraus? Ein Zählerstand? Oder
> Zählimpulse?
>
Ich habe eine feste Zeit die die Anzahl der Impulse in diesem Zeitraum 
misst.

> Zuerst wollte ich es mit < verwenden, jedoch habe ich gelesen, dass dies
> nicht optimal ist.
>
> Wo und in welchem Zusammenhang? Was komt raus, wenn du selbst es auf
> deiner Zielplattform ausprobierst?

Dies habe ich noch nicht ausprobiert werde es aber mal ausprobieren.
>
> jedoch habe ich gelesen, dass dies nicht optimal ist.
>
> Was für das eine FPGA optimal ist, kann für das eines anderen Hersteller
> zu einer umständlichen Implementierung führen.
>
> Welche Varianten gibt es, dies umzusetzen?
>
> Wenn du tatsächlich nur 2 LEDs hast, dann ist die Vergleichsvariante mit
> Sicherheit die beste Lösung.
> Wenn du aber 32 LEDs hast, die gleiche Abstände mrakieren sollen
> (0..15..30..45..60..75.. oder 0..7..14..21..28..35.. m/min), dann wäre
> es einfacher, die Geschwindigkeit so zu berechnen, dass als Ergebnis
> genau der Index der anzuschaltenden LED herauskommt...
Ich habe nicht nur 2 sondern 32 LEDs. Jedoch will ich nicht einen 
bestimmten Abstand der Geschwindigkeit haben sondern diesen Variable 
halten.

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


Lesenswert?

Chris schrieb:
> Jedoch will ich nicht einen bestimmten Abstand der Geschwindigkeit haben
> sondern diesen Variable halten.
Soll die Anzeige wenigstens stetig sein?

> Jedoch will ich nicht einen bestimmten Abstand der Geschwindigkeit haben
> sondern diesen Variable halten.
Wenn die Anzeige lediglich einstellbar linear sein muss, dann lässt 
sich sowas simpel durch eine Anpassung der Torzeit arrangieren. Dazu 
müsstest du nur deine "feste Zeit" in eine "variable Zeit" abändern.

Wenn der Abstand tatsächlich nichtlinear und nur für die Anzeige ist, 
dann würde ich ein RAM/ROM als LUT aufsetzen und das laufend 
durchhecheln oder mit dem Index den Eingangswert "verfolgen".

von uwe (Gast)


Lesenswert?

> Ich habe eine feste Zeit
Habe ich auch hier irgendwo...
Du hast eine zahl die irgendwo steht(Monitor), anliegt (digitaler 
paralleler Ausgang) etc.
Wo steht denn bei dir diese Zahl und wie willst oder hast du sie ins 
FPGA reinbekommen?

von Chris (Gast)


Lesenswert?

Lothar M. schrieb:
> Chris schrieb:
>> Jedoch will ich nicht einen bestimmten Abstand der Geschwindigkeit haben
>> sondern diesen Variable halten.
> Wenn die Anzeige lediglich einstellbar linear sein muss, dann lässt
> sich sowas simpel durch eine Anpassung der Torzeit arrangieren. Dazu
> müsstest du nur deine "feste Zeit" in eine "variable Zeit" abändern.
>
Ich zähle die Impulse, indem ich z.b. 10 Flanken vom Takt abwarte. Wie 
kann ich daraus eine Variable Zeit machen?
@Uwe ist hiermit deine Frage auch beantwortet?

> Wenn der Abstand tatsächlich nichtlinear und nur für die Anzeige ist,
> dann würde ich ein RAM/ROM als LUT aufsetzen und das laufend
> durchhecheln oder mit dem Index den Eingangswert "verfolgen".
Wie kann ich in einem RAM nach der Geschwindigkeit suchen? Oder wie 
meinst du das genau, oder hast du zufällig ein Beispiel, weil auf deiner 
Seite habe ich keins gefunden?

von Chris (Gast)


Lesenswert?

Ich habe mal etwas geschrieben. Könnte dies so funktionieren?

library IEEE;

use IEEE.std_logic_1164.all;

entity GeschwLED is
Generic (
       Addrbreite  : natural := 8;  -- Speicherlänge = 2^Addrbreite
       Wortbreite  : natural := 8
);
port (
    clk             : IN  std_logic;
    DrehrichtungOK  : IN  std_logic; -- überprüfung der Drehrichtung
    Geschwindigkeit : IN  std_logic_vector(7 downto 0);  -- 
Bahngeschwindigkeit
    LEDValue        : OUT std_logic_vector(7 downto 0)
);
end GeschwLED;
architecture architecture_GeschwLED of GeschwLED is
    type speicher is array(0 to (2**Addrbreite)-1) of 
std_logic_vector(Wortbreite-1 downto 0);
    signal sram : speicher;
    signal LED  : speicher;


begin
process
    begin
   wait until rising_edge(clk);
            if DrehrichtungOK = '1' then;
                for i in 0 downto ((2**Addrbreite)-1) loop
                    if sram(i) = Geschwindigkeit then
                        LEDValue <= LED(i);
                    end if;
                end loop;
            end if;
end process;
end architecture_GeschwLED;

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


Lesenswert?

Chris schrieb:
> Könnte dies so funktionieren?
Mal von ein paar syntaktischen Fehlern abgesehen:
1. du baust damit 256 parallele Vergleicher. In jedem Takt wird jede 
einzelne RAM-Telle gegen den Wert verglichen. In der Praxis wird da also 
kein RAM-Baustein genommen, sondern das RAM muss extrem aufwändig und 
ressourcenfressend mit Flipflops aufgebaut werden.
2. wofür eigentlich überhaupt eine Schleife und Vergleicher? Wenn du 
einen 8-Bit Eingangswert hast und einen 8-Bit Ausgangswert willst, dann 
musst du doch nur den Eingangswert als Adresse an das RAM legen und 
bekommst ohne jeglichen Vergleich oder sonstwas gleich das Ergebnis. Du 
musst einfach nur das Richtige ins RAM schreiben...

> LEDValue        : OUT std_logic_vector(7 downto 0)
Das sind jetzt aber keine 32 LEDs. Es sind entweder 8 LEDs mit 
beliebigem Muster oder eben eine einzelne indizierte LED aus 256 LEDs.

> Könnte dies so funktionieren?
Setz doch einfach mal kurz eine Testbench auf. Eine halbe Stunde später 
weißt du es sicher.

Chris schrieb:
> Ich zähle die Impulse, indem ich z.b. 10 Flanken vom Takt abwarte.
Dieses Verfahren ist für die Geschwindigkeitsmessung unpraktisch, weil 
du damit ja den Kehrwert der Geschwindigkeit als Ergebnis bekommst: je 
höher die Geschwindigkeit, umso kleiner wird die Zeit.

> Ich zähle die Impulse, indem ich z.b. 10 Flanken vom Takt abwarte. Wie
> kann ich daraus eine Variable Zeit machen?
Dreh den Spieß um: nimm eine definierte Zeit und zähle die währenddessen 
auftretenden Impulse.
Wenn du z.B. eine Achse mit 10 U/s und einen Impulsgeber mit 256 
Impulsen/U hast, dann bekommst du 2560 Impulse/s. Und wenn du deine 
Messdauer jetzt "geschickt" mit 3,9ms wählst und die Impulse während 
dieser Zeit zählst, dann bekommst du tollerweise genau den Zählerwert 10 
bei 10 U/s und den Wert 5 bei 5U/s usw...

Wenn du dann diese "definierte" Zeit umdefinierst, wirst du eine andere 
Skalierung bekommen.
Willst du z.B. bei gleicher Mechanik und gleichem Geber die Anzeige auf 
U/min umskalieren, dann musst du nur deine Messzeit umdefinieren und 60x 
länger und damit 234ms lang zählen.
Wenn damit 32 LEDs für Vollausschlag ansteuern musst, na dann muss der 
Zähler eben maximal auf 32 kommen und du musst 12,5 ms lang zählen...

: Bearbeitet durch Moderator
von Achim S. (Gast)


Lesenswert?

Chris schrieb:
> for i in 0 downto ((2**Addrbreite)-1) loop
>                     if sram(i) = Geschwindigkeit then
>                         LEDValue <= LED(i);
>                     end if;

Nö: so geht das nicht (auch wenn man erst mal die offensichtlichen 
Fehler korrigieren würde). Zumindest kannst du es so nicht mit einem 
RAM-Block realisieren. Denn bei dieser Implementierung müsste der Inhalt 
jeder einzelnen Speicherzelle im selben Taktzyklus überprüft werden. 
Beim RAM hast du pro Tatkzyklus aber immer nur Zugriff auf eine Adresse 
des RAM (nicht auf alle gleichzeitig).

Du kannst also 256 unterschiedliche Geschwindigkeitsstufen 
unterscheiden, richtig?

    Geschwindigkeit : IN  std_logic_vector(7 downto 0);  -

Dann benutzt du die Geschwindigkeit einfach als Adresse fürs RAM. Und 
bei jeder einzelnen Adresse legst du als Dateninhalt fest, welche LEDs 
leuchten sollen.

Also zusammengefasst: die Geschwindigkeit ist die Adresse des RAMs. Bei 
jeder Adresse steht im RAM, welche LED bei dieser Geschwindigkeit 
leuchten soll. Damit wird das RAM zu einer großen LUT.

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.