www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Kleiner UART / Problem


Autor: TheMason (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich habe nun auch mal einen kleinen UART geschrieben. Er funktioniert 
leider nicht ganz. Er empfängt recht häufig falsche Zeichen. Das 
"falsche" Zeichen äußert sich in einem bit-versatz bzw. er "dichtet" 
sich ein paar bits dazu.
Es hängt allerdings auch vom Zeichen selbst ab. Wenn ich z.b. ein 'h' 
sende (binär : 01101000) empfängt er es immer richtig. Ein 'a' hingegen 
(binär : 01100001) wird fast immer falsch empfangen.
Wenn jemand Lust und Zeit hat kann er sich ja gerne mal die Komponente 
antun.
hier mal der quellcode des empfängers.
Wenn jemand eine idee hat warum es hapert, bzw. anderweitige 
verbesserungsvorschläge hat, immer her damit :-)

--------------------------------------------------------------------

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

--  Uncomment the following lines to use the declarations that are
--  provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;

entity uart_rx is
  port (clk         : in   std_logic;
        res         : in   std_logic;
        rx_in       : in   std_logic;
        baud_clk_16 : in   std_logic;
        busy         : out std_logic;
        out_buffer   : out std_logic_vector (7 downto 0);
        trg         : out std_logic);
end uart_rx;


architecture behave of uart_rx is

  signal state           : std_logic_vector (3 downto 0);
  signal count           : std_logic_vector (3 downto 0);
  signal baud_clk_16_z1 : std_logic;
  signal rx_buffer       : std_logic_vector (7 downto 0);
  signal err             : std_logic;
  signal trg_out        : std_logic;

  signal rx_in_z1        : std_logic;
  signal rx_in_z2        : std_logic;
  signal rx_in_z3        : std_logic;
  --signal rx_in_z4        : std_logic;


begin

  trg <= trg_out;

  process (clk,res, baud_clk_16_z1, baud_clk_16, state, count, rx_in_z3, 
rx_in_z2, rx_in_z1, rx_in, rx_buffer)
  begin
    if res = '1' then
      state           <= (others => '0');
      count           <= (others => '0');
      rx_buffer       <= (others => '0');
      baud_clk_16_z1   <= '0';
      err             <= '0';
      trg_out         <= '0';

    elsif clk'event and clk = '1' then
      baud_clk_16_z1 <= baud_clk_16;


      --rx_in_z4 <= rx_in_z3;

      if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then

        rx_in_z1 <= rx_in   ;
        rx_in_z2 <= rx_in_z1;
        rx_in_z3 <= rx_in_z2;

        count <= count + '1';

        if state = X"0" then
          if rx_in_z3 = '0' then
            --count <= count + '1';
            if count = X"F" then
              state <= X"1";
              --count <= (others => '0');
            end if;
          else
            count <= (others => '0');
          end if;
        else
          if count = X"8" then
            case state is
              when X"1" => rx_buffer (0) <= rx_in_z3; state <= X"2";
              when X"2" => rx_buffer (1) <= rx_in_z3; state <= X"3";
              when X"3" => rx_buffer (2) <= rx_in_z3; state <= X"4";
              when X"4" => rx_buffer (3) <= rx_in_z3; state <= X"5";
              when X"5" => rx_buffer (4) <= rx_in_z3; state <= X"6";
              when X"6" => rx_buffer (5) <= rx_in_z3; state <= X"7";
              when X"7" => rx_buffer (6) <= rx_in_z3; state <= X"8";
              when X"8" => rx_buffer (7) <= rx_in_z3; state <= X"9";
              when X"9" => if rx_in_z3 = '1' then
                             out_buffer <= rx_buffer;
                             err <= '0';
                             trg_out <= '1';
                           else
                             out_buffer <= (others => '0');
                             err <= '1';
                           end if;
                           state <= X"0";
              when others => NULL;
            end case;

          end if;

        end if;

      end if;

      if trg_out = '1' then
        trg_out <= '0';
      end if;

    end if;
  end process;

end architecture;

-----------------------------------------------------------------------

gruß
rene

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat denn keiner eine idee wo der fehler liegen könnte ?! :-((

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>        if state = X"0" then
>          if rx_in_z3 = '0' then
>            --count <= count + '1';
>            if count = X"F" then
>              state <= X"1";
>              --count <= (others => '0');
>            end if;
>          else
>            count <= (others => '0');
>          end if;

Erstze das mal durch

        if state = X"0" then
          if rx_in_z3 = '0' then
            count <= "0000";
            state <= X"1";
          end if;

MfG
Falk

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für den tip. werde es heute abend mal ausprobieren.
obwohl mir noch nicht so ganz klar ist warum es daran liegen könnte. ich 
muß ja erst ein rx-bit (16x baud_clk_16) abwarten nachdem ich die 0 
erkannt habe, oder sehe ich da was falsch ?!

gruß
rene

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk,

ich habs mal ausprobiert, aber es funktioniert leider nicht.
Mir ist nicht so ganz klar wieso das mit dieser Änderung laufen könnte. 
Ich muß doch erst mein Start-Bit abwarten (also 16 baud_clk_16 pulse 
zählen), bevor ich die eigentlichen nutzdaten in mein register packe ?
oder meintest du das so, das man noch einen zusätzlichen zustand 
einfügen muß  für das start-bit ?

gruß
rene

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TheMason

>Ich muß doch erst mein Start-Bit abwarten (also 16 baud_clk_16 pulse
>zählen), bevor ich die eigentlichen nutzdaten in mein register packe ?

Ja. Aber mit der fallenden Flanke von rx_in_z3 musst du deinen Zähler 
rücksetzen. Danach läuft er frei durch.

>oder meintest du das so, das man noch einen zusätzlichen zustand
>einfügen muß  für das start-bit ?

Ja.

MfG
Falk


Autor: Joerg Wolfram (joergwolfram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nach Erkennung des Startbits musst du 1,5 bitzeiten bis zur Abtastung 
des ersten Bits warten, damit der Pegel auch in der Mitte der Bits 
abgefragt wird. Ansonsten fragst Du die Bits immer am Anfang ab und das 
kann schon mal Fehler geben.

Gruß Jörg

Autor: Lothar (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Eines der Hauptprobleme, die es mit FPGAs gibt, sind asynchrone Signale 
von aussen. Die MÜSSEN immer erst mal synchronisiert werden (ich hätte 
auch schreiben können: die SOLLTEN immer erst mal synchronisiert werden, 
aber aus der alltäglichen Erfahrung ist ein zwingendes MUSS immer 
besser).

Denn ein asynchrones Signal geht z.B. auf mehrere LUTs/FFs im FPGA und 
kommt da aufgrund von Laufzeitunterschieden nicht bei allen gleichzeitig 
an. Daher weiß das halbe FPGA dann schon von dem neuen Zustand, die 
andere Hälfte bekommt die Änderung erst zum nächsten Takt mit.
Und dann gibt es solche Effekte, dass das Design so ein paar Minuten 
oder Zeichen lang gut funktioniert, dann gehts mal schief, dann 
funktionierts wieder ne Zeit lang usw. usf.

Du hast gleich zwei solcher Signale in deinem Design:
        rx_in       : in   std_logic;
        baud_clk_16 : in   std_logic;
Schau dir das mal genauer an.
Irgendwo dort liegt der Hund begraben (garantiert!).

Als Anhang habe ich ein kampferprobtes SIO-Design, schau dir mal die 
Entprellung des RX-Signals an (so gehts, auch garantiert!).

BTW: die sensitivity-List des Process braucht nur zwei Signale:
  process (clk,res)
Denn eine Änderung irgendeines anderen Signals aus deiner Liste führt 
nicht zu einer Ausgangs- oder Signaländerung. Das ist aber eh' nur für 
die Simulation interessant (reduziert die Simulationszeit), der 
Synthesizer schmeisst die Dinger sowieso weg.

Gruß Lothar

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@lothar

aber durch:

>    elsif clk'event and clk = '1' then
>      baud_clk_16_z1 <= baud_clk_16;
>
>      --rx_in_z4 <= rx_in_z3;
>
>      if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then
>
>        rx_in_z1 <= rx_in   ;
>        rx_in_z2 <= rx_in_z1;
>        rx_in_z3 <= rx_in_z2;

wird rx_in doch einsynchronisiert (es wird sonst nirgends das signal 
rx_in verwendet !). außerdem ist baud_clk_16 auch synchron zum clk (da 
dieser von clk abgeleitet wird).
oder sehe ich da was falsch ?!

gruß
rene

ps. danke für deine rs232-komponente. werde mir diese mal genauer 
anschauen. ist ja bald wochenende :-))

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TheMason

>wird rx_in doch einsynchronisiert (es wird sonst nirgends das signal
>rx_in verwendet !). außerdem ist baud_clk_16 auch synchron zum clk (da
>dieser von clk abgeleitet wird).
>oder sehe ich da was falsch ?!

Du siehst das vollkommen richtig. Alles im grünen Bereich.
Dein Problem liegt höchstwahrscheinlich in der State Machine.

MFG
Falk

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich glaub mir schwant was böses ...
ich habe vermutung das ihr beide recht habt.
mir ist nämlich gerade aufgefallen, das :

>      if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then
>
>        rx_in_z1 <= rx_in   ;
>        rx_in_z2 <= rx_in_z1;
>        rx_in_z3 <= rx_in_z2;

zwar meinen rx_in einsynchronisiert, ABER : eben nur mit dem baud_clk_16 
und nicht mit meinem systemtakt clk. dadurch kann natürlich meine 
statemachine nicht richtig funktionieren. schmärz lass nach ...

es ist denke ich ein problem des einsynchronisierens (falscher sync-clk) 
und der statemachine (durch zu langsam einsynchronisiertes signal)
kann es sein das es das ist ? (ich muß das gleich zuhause mal testen)

gruß
rene

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TheMason

>mir ist nämlich gerade aufgefallen, das :

>zwar meinen rx_in einsynchronisiert, ABER : eben nur mit dem baud_clk_16
>und nicht mit meinem systemtakt clk. dadurch kann natürlich meine

Das ist schon OK, deine State Machine reagiert ja auch nur im 
baud_clk_16 Takt, da müssen die Eingangssignale nicht schneller 
abgetastet werden.

>es ist denke ich ein problem des einsynchronisierens (falscher sync-clk)
>und der statemachine (durch zu langsam einsynchronisiertes signal)
>kann es sein das es das ist ? (ich muß das gleich zuhause mal testen)

Hier ist das kein Problem.

MFG
Falk

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@lothar

also ich habe mir mal deine einsychronisierung in meinen uart eingebaut. 
(um rx_in zu entprellen). es funktioniert. wobei mir noch nicht so ganz 
klar ist warum dem so ist. ob ich nun mit baud_clk_16 einclocke oder mit 
dem systemtakt sollte für den weiteren verlauf der statemachine doch 
unerheblich sein, oder ? und da das signal ja mehrfach abgetastet wird 
dürfte es doch spätestens nach dem 4. takt sauber anliegen. das einzige 
was ich bei meiner lösung nicht gemacht habe das ich mein rx-input aus 
allen 4 flip-flops generiere, sondern nur aus 2 flip-flops, und dies 
auch nur für die startbedingung (fallende flanke an rx).

ich wollte außerdem fragen ob ich dein einsynchronisieren so übernehmen 
und öffentlich verwenden darf. ich würde meine komponente gerne ausbauen 
und hier in der Codesammlung "verewigen". ist das mit einem 
entsprechenden vermerk auf dich ok ?

gruß
rene

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TheMason

>ich wollte außerdem fragen ob ich dein einsynchronisieren so übernehmen
>und öffentlich verwenden darf. ich würde meine komponente gerne ausbauen

Ersten sehe ich keine Code und zweites gibt darauf kein Patent ;-)

>und hier in der Codesammlung "verewigen". ist das mit einem
>entsprechenden vermerk auf dich ok ?

Wen meinst du mit "dich?". Das Entprellen ist prinzipiell nicht falsch, 
wird aber meist nicht gebraucht. Die Abtastung mit baud_clk_16 wirkt 
schon entprellend genug. Ausserdem verwenden alle professionellen UARTs 
auch nur die mit baud_clk_16 abgetasteten Werte (und bilden die 
Mehrheitseintscheidung aus Abtastwert 7,8 und 9. Wenn du dann noch das 
Startbit sowie Stopbit prüfst ist wasserdicht.

MfG
Falk

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@falk

es ging sich mir eigentlich nur um den code-schnipsel aus lothars 
rs232-komponente :

>   process (RESET, CLK)
>   begin
>      if (RESET='1') then
>         RX_SR <= "0000";
>      elsif (rising_edge(CLK)) then
>         RX_SR <= RX_SR(2 downto 0) & RX;
>         if (RX_SR = "1000") then   RX_Entprellt <= '0';   end if;
>         if (RX_SR = "0111") then   RX_Entprellt <= '1';   end if;
>      end if;
>   end process;

diesen teil wollte ich verwenden, da damit mein uart funktioniert (wie 
gesagt ich habe auch noch nicht ganz verstanden warum es damit 
funktioniert, aber das werde ich schon noch rauskriegen)

ich weiß das das nichts wildes ist oder etwaige patentrechtsverletzungen 
damit verbunden wären, möchte aber anstandshalber nachfragen ob es ok 
wäre, damit ich in der code-sammlung auchmal einen beitrag in form eines 
eigen geschriebenen uarts leisten kann. :-)
daher die frage (die an lothar gerichtet war :-)

>Das Entprellen ist prinzipiell nicht falsch,
>wird aber meist nicht gebraucht. Die Abtastung mit baud_clk_16 wirkt
>schon entprellend genug. Ausserdem verwenden alle professionellen UARTs
>auch nur die mit baud_clk_16 abgetasteten Werte (und bilden die
>Mehrheitseintscheidung aus Abtastwert 7,8 und 9. Wenn du dann noch das
>Startbit sowie Stopbit prüfst ist wasserdicht.

mir ist klar das es so funktionieren müsste, tut es aber leider nicht. 
und einen grund für das nicht-funktionieren habe ich leider auch keinen.
werde das nochmal genauer autesten müssen damit ich nicht dumm sterbe 
:-)

dank auch an dich falk für deine kompetenten beiträge und deine prompte 
hilfe

gruß
rene

Autor: Lothar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TheMason: Nimm den Code ruhig, wenn da was geschützt wäre, hätte ich es 
nicht veröffentlicht.

Was ich damit mache, ist ein gelatchtes Signal (RX_Entprellt), das den 
Zustand nur ändert, wenn eine richtige Flanke am Eingang anliegt.


Ehrlich gesagt ist mir auch nicht ganz klar, wieso das jetzt 
funktioniert. Evtl. liegt es an der zusätzlichen Latency von 2 
Taktzyklen.
Mit dem synchronisieren meinte ich eigentlich deinen baud_clk_16_z1, der 
war aus dem Code nicht als taktsynchron zu erkennen. Erst durch deine 
Bemerkung mit dem Ableiten aus dem clk wird das klar:

> außerdem ist baud_clk_16 auch synchron zum clk (da dieser von clk abgeleitet 
wird).

Ich mag solche Unklarheiten nicht. Deshalb habe ich mir deinen Code 
nochmal angeschaut (für was gibts Mittagspausen?).

Prinzipiell tut sich dein UART etwas schwer mit dem Start:
        count <= count + '1';

        if state = X"0" then        
          if rx_in_z3 = '0' then    -- solange Startbit aktiv (= 0)!!!
            if count = X"F" then    -- was passiert, wenn das Startbit mal
              state <= X"1";        -- nur 15 Takte lang aktiv ist??
            end if;                 -- -> das Startbit wird ignoriert
          else                      -- und auf einem nachfolgenden Bit gestartet
            count <= (others => '0');
          end if;
Hier würde ich sofort nach dem Erkennen eines Startbits (fallende 
Flanke) einen zusätzlichen Zustand einlegen, der auf das erste Bit 
wartet.

>Es hängt allerdings auch vom Zeichen selbst ab. Wenn ich z.b. ein 'h'
>sende (binär : 01101000) empfängt er es immer richtig. Ein 'a' hingegen
>(binär : 01100001) wird fast immer falsch empfangen.

Und jetzt wirds klar: bei einem 'a' kommt nach dem Startbit='0' gleich 
eine '1' (LSB zuerst) --> Fehlstart (oft, meistens?).
Ich denke, dass z.B. ein c, e, g, i... auch öfter mal falsch kommt.
Mit einem b, d, f, h, j... gehts dagegen.

Eine kleine Änderung in deinem Code könnte da helfen:
        count <= count + '1';

        if state = X"0" then
          if rx_in_z3 = '0' then
            if count = X"8" then       -- halbe Bitzeit vom Startbit abgewartet
              state <= X"11";          -- -> jetzt noch ein Bit abwarten
            end if;
          else
            count <= (others => '0');  
          end if;
        else
          if count = X"8" then
            case state is
              when X"11" => state <= X"1";  -- ein Bit warten
              when X"1" => rx_buffer (0) <= rx_in_z3; state <= X"2";
              when X"2" => rx_buffer (1) <= rx_in_z3; state <= X"3";
              when X"3" => rx_buffer (2) <= rx_in_z3; state <= X"4";
              when X"4" => rx_buffer (3) <= rx_in_z3; state <= X"5";
              when X"5" => rx_buffer (4) <= rx_in_z3; state <= X"6";
              when X"6" => rx_buffer (5) <= rx_in_z3; state <= X"7";
              when X"7" => rx_buffer (6) <= rx_in_z3; state <= X"8";
              when X"8" => rx_buffer (7) <= rx_in_z3; state <= X"9";
              when X"9" => if rx_in_z3 = '1' then
                             out_buffer <= rx_buffer;
                             err <= '0';
                             trg_out <= '1';
                           else
                             out_buffer <= (others => '0');
                             err <= '1';
                           end if;
                           state <= X"0";
              when others => NULL;
            end case;

          end if;
Wäre interessant, obs das war.

Lothar

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@lothar

erstmal danke für das snippet.

muß wohl eben anmerken das der code den ich zu anfang gepostet habe 
schon nicht mehr aktuell ist.

>if rx_in_z3 = '0' then
>  if count = X"F" then
>  state <= X"1";
>  end if;
>else

war nur der erste schuß. ich habe recht schnell gemerkt das das nicht 
funktionieren kann.
daher habe ich in meinem aktuell verwendeten code (habe diesen gerade 
nur zuhause rumfliegen) in etwa das verwendet :

if rx_in_z3 = '0' and rx_in_z2 = '1' then
  count <= X"0";
  state <= X"1";
end if;

um die fallende flanke zu erkennen. daraufhin verzweige ich in zustand 1 
der (und das ist auch wieder neuer code) bis zur bit-mitte wartet (also 
count = X"8") und dann das start-bit erneut prüft. ist dieses bit = 0, 
so gehe ich in zustand 2 der mir meine bits reinschiebt (auch immer nur 
in der bit-mitte).
habe ich stattdessen ein start-bit von 1 gehe ich zurück nach zustand 0.

und genau dieser code (ich poste ihn heute abend, damit wir nicht über 
alten code reden) funktioniert NUR dann wenn ich deine entprellung 
nehme. bei der methode die ich verwendet habe (4-flip-flops die per 
baud_clk_16 getaktet werden) empfange ich nichts.
irgendwie finde ich das merkwürdig, zumal (wie falk ja schon sagte) ich 
das signal ja auch mit baud_clk_16 einsynchen kann ...

gruß
rene

Autor: Lothar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TheMason: mit welchem Takt synchronisierst du das 
RX_IN-Schieberegister? Mit baud_clk_16 oder (dem wesetlich schnelleren) 
clk?


Nur auf ein einziges FF zu verwenden wie in
if rx_in_z3 = '0' and rx_in_z2 = '1' then  -- steigende Flanke, rx_in_z3 ist älter
bringt dir sicher auch interessante Effekte.
Das wird jetzt ein statistisches Problem: wenn du nicht so richtig 
schöne störfreie Signale hast, kann dir ein kurzer 1- oder 0-Spike in 
rx_in_z1 eingelesen werden und voila: zwei Takte später erkennst du eine 
Flanke und legst schon mal los.

Ich umgehe sowas über das 4-Bit Schieberegister.
Dein Code müsste ohne Schieberegister demnach etwa so aussehen (als 
3-Bit-SR):
if rx_in_z3 = '0' and rx_in_z2 = '1' and rx_in_z1 = '1' then -- steigende Flanke

Am Rande:
Ruhepegel ist normalerweise '1' auf der RX-Strippe.
Ich denke dein Code zuhause wartet auf die fallende Flanke des 
Startbits.
Im Text hast du es jedenfalls schon richtig beschrieben.

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@lothar

ich habe es mit beiden takten ausprobiert, klappte in keinem der fälle 
:-(

aber was du meintest mit den spikes und dem 4-bit-sr ist denke ich mein 
problem. ich habe mal bei einer spi-komponente die nicht laufen wollte 
meine bedingung (steigende oder fallende flanke) einfach mal über 3 ff 
anstatt über 2 gemacht und dann lief es auch. ich vermute das ich hier 
ein ähnliches problem habe bzw. das das das selbe problem ist.



Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Lothar

>Nur auf ein einziges FF zu verwenden wie inif rx_in_z3 = '0' and rx_in_z2 >= '1' 
then  -- steigende Flanke, rx_in_z3 ist älter
>bringt dir sicher auch interessante Effekte.
>Das wird jetzt ein statistisches Problem: wenn du nicht so richtig
>schöne störfreie Signale hast, kann dir ein kurzer 1- oder 0-Spike in
>rx_in_z1 eingelesen werden und voila: zwei Takte später erkennst du eine
>Flanke und legst schon mal los.

Und bricht bei der Prüfung des Startbits wieder ab.

MFG
Falk

Autor: TheMason (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
so !

nun hab ich das problem gefunden. durch eine schusseligkeit hab doch 
tatsächlich statt

if rx_in_z3 = '1' and rx_in_z2 = '0' then

if rx_in_z3 = '0' and rx_in_z2 = '1' then

zur erkennung der fallenden flanke verwendet ... :-(
konnte ja nicht funktionieren. kaum macht mans richtig. jetzt klappts 
auch wenn ich auf baud_clk_16 einsynche.

gruß
rene


Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein paar kleine Anmerkungen.

>  process (clk,res, baud_clk_16_z1, baud_clk_16, state, count, rx_in_z3, 
>rx_in_z2, rx_in_z1, rx_in, rx_buffer)

In einenm getakteten Prozess braucht man nur den Takt und das asynchrone 
Reset in der Sensitivity List.

>      baud_clk_16_z1 <= baud_clk_16;
>      if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then

Ist prinzipiell richtig, besser ist es aber, gleich im Baudgenerator ein 
entsprechendes Signal zu generieren (Clock enable, einen Takt breit). 
Macht das Ganze übersichtlicher.

>       if state = X"0" then
>         if rx_in_z3 = '0' and rx_in_z2 = '1' then
>           count <= (others => '0');
>           state <= X"1";
>         else
>           count <= (others => '0');
>         end if;

In beiden Zweigen ist die Zuweisung an count identisch. Also rausnehmen, 
der Übersicht wegen.


>       if trg_out = '1' then
>         trg_out <= '0';
>       end if;

Das soll sicher der Trigger für die nachfolgende Schaltung sein, dass 
ein neues Datenbyte angekommen ist. Das macht man sinnvollerwise anders. 
Man setzt ein Flag (Data available) und wartet auf das Handschake der 
Zielschaltung (Acknowledge). Dann löscht man das Flag wieder. Wenn das 
Flag nicht bis zum nächsten empfangenen Zeichen gelöscht wurde (State 
"a"), dann gibts nen Buffer Overflow.

Ausserdem solltest du für die States Namen verwenden, keine Zahlen. 
Dadurch hat der Compiler die Chance, die für die Zielarchitektur 
günstige Kodierung zu wählen (Binär, One-Hot, Gray etc.) Ausserdem wird 
es wieder lesbarer.

type state_type is (s_wait, s_start, s_0, s_1, s_2, s_3, s_4, s_5, s_6, 
s_7, s_stop);

signal state: state_type;

Aber alles in allem, gute Leistung, hast dich durchgekämpft.

MfG
Falk

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@falk

danke für die hinweise. habe diesen code nur mal schnell rausgekramt.
da waren dann noch so sachen drin, die den code nicht gerade "schön" 
machen, aber das ist alles in arbeit.

danke auch für das lob :-) aber eine gute leistung ist das nicht wenn 
man lediglich aus schusseligkeit auf die falsche flanke reagiert und da 
tagelang dran rumsucht ... :-(( vor allem weil ein uart ja echt simpel 
ist, und wenn man sich dann selbst so ein blödes "stop-bit" einbaut und 
es dann nicht findet ....
da frage ich mich dann schon wie ich es geschafft habe einen kleinen 
audio-prozessor zu schreiben (der dann auch noch funktioniert :-)) wenn 
ich bei solch blöden sachen schon ins trudeln komme ...

dank und gruß
rene




Autor: Lothar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TheMason: Freut mich, dass es doch noch geklappt hat, so kurz vorm 
Einschlafen. Dann war das doch kein Versehen mit der Flanke, ich dachte 
da schon an einen Tippfehler (wie weiter oben schon am Rande vermerkt).

Aber keine Sorge, den Fehler machst du nicht nochmal. Die 
Flankengeschichte  ist jetzt im Gehirn abgespeichert.

Gruß
Lothar

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@lothar

es war doch ein tipp-fehler (statt rx_in_z3 = '1' and rx_in_z2 = '0' 
habe ich rx_in_z3 = '0' and rx_in_z2 = '1' verwendet).
also schusseligkeit. das mit der flanken-erkennung hatte ich ja schon 
verstanden, nur halt eben einen dämlichen flüchtigkeitsfehler gemacht, 
der mich dann tage und nerven gekostet hat.

an dich auch noch einen recht herzlichen dank für deine komponente.
das einsynchen so zu machen find ich recht elegant (schön einfach). 
werde mir das mal merken. einfach und effektiv.

gruß
rene

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.