Forum: FPGA, VHDL & Co. RS232 Kommandos auswerten


von Frank S. (karnikel)


Lesenswert?

Tach tach,

ich möchte gern über die RS232 Schnittstelle Befehle von einem 
Terminalprogramm an die RS232 Schnittstelle senden und auswerten. So 
z.B. möchte ich Kanal 1 auf 200ns Zeitverzögerung setzen 
(Beispielbefehl: "ch1delay_200").
Meine Idee mithilfe einer State Machine sieht wie folgt aus:
Ich dachte mir dass ich die Bitfolge bis "_" auswerte, zum 
entsprechenden case springe, dort die folgende Zahl auswerte und diese 
dann im FPGA auf Kanal 1 angewendet wird.
Ist dies überhaupt im FPGA "on the fly" möglich, oder kann ich nicht so 
einfach wie ich mir das denke die Parameter für ein bereits im FPGA 
laufendes Programm ändern?
Gibts von euch nen besseren Vorschlag wie man diese Sache implementieren 
könnte?

Die Programmierung erfolgt in VHDL und zur verfügung steht ein Spartan 
3AN. RS232 Daten kann ich bereits empfangen. Es geht nur um die 
Auswertung dieser Daten.

Vielen Dank

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


Lesenswert?

Karnikel S. schrieb:
> Gibts von euch nen besseren Vorschlag wie man diese Sache implementieren
> könnte?
Nicht einen langen Bitstrom auswerten, denn was machst du, wenn du mal 
eine kleine Pause in der Übertragung hast?

Machs so, wie es alle Welt macht: Ein Zeichen nach dem anderen 
empfangen, und auswerten.

Karnikel S. schrieb:
> Ist dies überhaupt im FPGA "on the fly" möglich, oder kann ich nicht so
> einfach wie ich mir das denke die Parameter für ein bereits im FPGA
> laufendes Programm ändern?
Du kannst in deinem FPGA machen, was du willst. Und natürlich lassen 
sich irgendwelche Zähler und Vergleichswerte zur Laufzeit ändern...

von Frank S. (karnikel)


Lesenswert?

Ok, danke für die schnelle Antwort.

Wie genau macht es denn "alle Welt"? Funktioniert es denn nur so:

if erstes Byte = "c" then
if zweites Byte = "h" then
if drittes Byte = "1" then
if usw.
else "mach nix"

oder gibt es da ne einfachere und kürzere Möglichkeit?

Wie bekomme ich denn raus ob das Kommando vollständig ist...es ist zwar 
möglich ein Symbol am ende anzuhängen das mir das ende anzeigt, oder ich 
könnte auch den Befehl auf genau z.b. 8 Byte beschränken aber irgednwie 
hätt ich gern was variables. Wahrscheinlich macht es am meisten sinn, 
wenn ich am Ende abfrage ob das Byte "11111111" ist oder?

von MW (Gast)


Lesenswert?

Eine Statemachine, die auf ein eingehendes Zeichen wartet, das dann z.B. 
in ein Schieberegister schiebt und auf das nächste wartet ist eine 
Variante. Damit vermeidet man lange if-else-Abfolgen.

Dann eine Art "Ende-Zeichen", nach dem der ganze Befehl im 
Schieberegister ausgewertet werden kann, bei serieller Übertragung nimmt 
dafür meist das CR/LF- Symbol.

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


Lesenswert?

Karnikel S. schrieb:
> Funktioniert es denn nur so:
Ja, wie denn sonst?
Uch wenn du z.B. in C einen schönen eleganten Funktionsaufruf wie 
strcmp() hinschreiben kannst, wird "ganz unten" nichts anderes 
gemacht...

von Harald F. (hfl)


Lesenswert?

Auch Tach!

Ich bin ein großer Freund davon, Hardware-Aufgaben in Hardware (Verilog, 
VHDL) zu lösen und Software-Aufgaben in Software (C). Das, was Du da 
machen wills, ist die Interpretierung eines seriellen Byte-Protokolls 
und somit meines Erachtens eine Aufgabe für einen Prozessor. Der würde 
dann auch einen Timeout feststellen, oder ein nicht gültiges Zeichen 
etc. Ich finde, Du solltest darüber nachdenken, einen Prozessor ins FPGA 
zu holen.

von Rene B. (themason) Benutzerseite


Lesenswert?

Also je nach Anzahl der Befehle wäre eine Statemachine am einfachsten.
Die Statemachine wird nur getriggert wenn ein neues Zeichen von der 
RS232 reinkommt und das nächste Zeichen verarbeitet. Wenn du die Befehle 
schön kurz hälst (2-3 Zeichen zum erkennen eines Befehls und) und statt 
Dezimal Hexadezimal verwendest sollte es auch nicht allzuviele 
Ressourcen verbrauchen. (Durch die Dezimale Schreibweise brauchst du 
evtl. einen Multiplizierer, bei Hexa schubst du einfach nur 4 Bit durch 
die gegend). Du könntest dir dann den erkannten Befehl und den 
dazugehörigen Parameter in einem Schattenregister speichern und wenn 
alles OK ist und Return gedrückt wird das Register dann zur Auswertung 
(bzw Befehlsausführung) in das Arbeitsregister kopiert.
Einen Timeout sollte man ebenfalls vorsehen, der die aktuelle Eingabe 
vewirft und die Statemachin zurücksetzt.

Ein Softcore-Prozessor ist da sicherlich auch eine denkbare Alternative, 
nur wenn es nur 2-3 Befehle sind die immer/annähernd gleich sind ist ein 
Softcore denke ich übertrieben. Oder wenn du wirklich eine richtige 
Eingabeaufforderung haben willst mit Zwischenspeicher, schöner Ausgabe 
usw., vielen Befehlen, Dezimale oder Hexa Schreibweise automatisch 
unterscheiden soll wäre ein Softcore geeignet.

Kommt halt immer auf den Zweck bzw die Komplexität an.

von Frank S. (karnikel)


Lesenswert?

Hi, vielen dank für die Anregungen. Ich hätte da aber noch ne allgemeine 
VHDL Frage:

Bisher habe ich den time_delay-Wert fest eingestellt und mein Programm 
in der Top-entity wie folgt bekannt gemacht:
1
architecture Behavioral of main is
2
:
3
:
4
component Delay_1 is
5
  generic 
6
    (
7
    system_speed     : integer := 50000000;            
8
    bitrate         : integer := 1000000;            
9
    time_delay       : integer := 2000
10
    );
11
  port
12
    (
13
    RESET          : in std_logic;              
14
    clk_i          : in std_logic;              
15
    start_1        : in std_logic;
16
    valid_bitwise_1  : in std_logic;
17
    get_fifo_data_1  : out std_logic;
18
    not_save_1      : out std_logic;
19
    bitwise_delay_in_1: in std_logic_vector(21 downto 0);
20
    dat_delay_in_1    : in std_logic_vector(21 downto 0);
21
    dat_delay_out_1  : out std_logic_vector(21 downto 0)
22
    );
23
end component Delay_1;
24
:
25
:
26
begin
27
:
28
:
29
Delay_1_inst : Delay_1
30
  generic map
31
    (
32
    system_speed         => 50000000,            
33
    bitrate             => 1000000,            
34
    time_delay           => 2000
35
    )
36
  port map
37
    (
38
    RESET              => RESET_i,
39
    clk_i              => CLK_50M_i,
40
    start_1            => REC_1_TIMER_STARTxDELAY_1_START,
41
    valid_bitwise_1      =>  REC_1_VALID_BITWISExDELAY_1_VALID_BITWISE,
42
    get_fifo_data_1      => FIFO_1_RD_ENxDELAY_1_GET_FIFO_DATA,
43
    not_save_1          => DELAY_1_NOT_SAVExRECEIVE_1_NOT_SAVE,
44
    bitwise_delay_in_1    => REC_1_BW_DAT1xDELAY_1_BITWISE_IN,
45
    dat_delay_in_1        => FIFO_1_DOUTxDELAY_1_DAT_DELAY_IN,
46
    dat_delay_out_1      => DELAY_1_DATOUTxSEND_1_DAT_IN
47
    );

Wenn ich nun "time_delay" variabel machen möchte, muss dann time_delay 
in "port / port map" mit rein?Oder reicht es, wenn ich die 2000 durch 
eine Variable ersetze und diese dann mit meinen Werten die ich per RS232 
erhalte beschreibe?

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


Lesenswert?

Karnikel S. schrieb:
> Oder reicht es, wenn ich die 2000 durch eine Variable ersetze
Nein.
Über Ports kommen veränderliche Werte/Signale.
Über Generics nur Konstanten...

> wenn ich die 2000 durch eine Variable ersetze
Variablen sind sowieso nur innerhalb eines Prozesses gültig. Und fang 
mir bloß nicht mit den Shared Variables an. Das sind solche 
nachgebastelten Kostrukte für Softwareprogrammierer, die jetzt Hardware 
machen müssen/wollen/sollen...

Karnikel S. schrieb:
> Wenn ich nun "time_delay" variabel machen möchte, muss dann time_delay
> in "port / port map" mit rein?
Ja.
Am besten (bzw. portabelsten) über einen Vektor, der danach wieder in 
einen integer konvertiert wird.

von Frank S. (karnikel)


Lesenswert?

Vielen vielen Dank für eure Hilfe. Ich kann jetz jedem meiner 4 Kanäle 
einen Verzögerungswert per RS232 übergeben.

Ich hätt aber noch ne weiterführende Frage:
Ich kann ja mein Programm in den SPI Prom schreiben, so dass mein 
Programm geladen wird, sobald ich das Board einschalte. Jedoch lädt der 
FPGA jedes mal die Verzögerungszeiten mit den fest eingestellten 
Default-Werten. Wenn ich nun per RS232 diese Zeiten ändere übernimmt er 
diese zwar, "vergisst" diese aber wieder, sobald ich das Board 
ausschalte. Gibt es eine Möglichkeit, dass diese gespeichert werden? 
Wenn ja wie?
Ich hab zwar mehrere ROMs auf dem Board, kann diese aber jweils nur 
ansteuern, wenn ich Jumper umstecke (soweit ich weiß). Also kann es 
anscheinend nur so gehen, dass ich die Werte im gleichen Speicher ablege 
wo das Prog gespeichert ist, oder das komplette Programm immer wieder 
neu in den ROM geschrieben wird, wenn ein neuer Verzögerungswert 
eingegeben wird.
Oder gibt es da noch ne einfachere Möglichkeit?
Es handelt sich dabei um 4 integer Werte, jeweils im Bereich von 100 bis 
100000000.
PS: ich hab das Spartan 3AN eval Board mit einem xc3s700an FPGA.

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


Lesenswert?

Karnikel S. schrieb:
> Gibt es eine Möglichkeit, dass diese gespeichert werden?
> Wenn ja wie?
Du brauchst irgendeinen externen Speicher (EEPROM/Flash)...

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.