mikrocontroller.net

Forum: FPGA, VHDL & Co. VHDL + RS232 Problem


Autor: fresh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo an alle

Habe derzeit ein grosses Problem mit einer RS232. Ich Taste den Eingang 
der Seriellen Schnittstelle mit den 8 fachen wert der Baudrate ab. Wenn 
sich über 5 Abtastungen der Wertnicht ändert gilt er und nach 8 
Abtastungen schaltet we weiter. Das ganze ist für 460,8 Kbit gedacht. In 
der Simulation schicke ich jedes Bit für 2,17us was passen sollte und in 
der Simulation mit Modelsim haut es auch super hin! Aber auf der 
HArdware nicht! Benutze ein Sparten 2 board und lass mir das empfangene 
Byte auf den Leds anzeigen und es kommt nie das richtige an! Weis jemand 
vielleicht nen Rat?!

Danke im vorhinein
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;


entity uart is
  
  port (
    clk             : in  std_logic;
    reset           : in  std_logic;
    seriell_in      : in  std_logic;
    seriell_out     : out std_logic_vector(7 downto 0) := (others => '0');
    seriell_ctr_out : out std_logic := '0';
    test_out        : out std_logic_vector(7 downto 0):= (others => '0'));

end uart;


architecture rtl of uart is

  --type and signal for the finit state machine
  type t_state is (IDLE, START, DATS, PARITY, STOP);
  signal presentstate : t_state;
  signal nextstate    : t_state;
  
  --Signal for the prescaler
  signal precount : std_logic := '0';

  --Signal for puffering the input
  signal mem_input : std_logic_vector(7 downto 0) := (others => '0');

  --constant for the baudrate
  constant baudrate : std_logic_vector(5 downto 0) := conv_std_logic_vector(13,6);--baudrate = 8*460,8kBit/s
  
begin  -- rtl

  -- purpose: Prescaler for the uart
  -- type   : sequential
  -- inputs : clk48, reset_n
  -- outputs: precount
  Prescaler: process (clk, reset)
    variable count : std_logic_vector(5 downto 0) := (others => '0');
  begin  -- process Prescaler
    if reset = '0' then                       -- asynchronous reset (active low)
      count := (others => '0');
      presentstate <= IDLE;
    elsif clk'event and clk = '1' then        -- rising clock edge
      presentstate <= nextstate;              -- set the presentstate to the nextstate
      precount <= '0';                        -- reset of the variable precount
      count := count + 1;
      if count = baudrate then
        count := (others => '0');
        precount <= '1';                      --set of the variable precount 
      end if;
      
    end if;
  end process Prescaler;


  -- purpose: Sequential Process for the fsm
  -- type   : sequential
  -- inputs : clk48, reset_n
  -- outputs: presentstate
  seqfsm2: process (clk, reset)

    variable count  : std_logic_vector(3 downto 0) := (others => '0');
    variable dat1  : std_logic_vector(2 downto 0) := (others => '0');
    variable dat0  : std_logic_vector(2 downto 0) := (others => '1');
    variable pos    : integer range 0 to 8 := 0;
    
  begin  -- process seqfsm2
    if reset = '0' then                       -- asynchronous reset (active low)
      
    elsif clk'event and clk = '1' then      -- rising clock edge
      seriell_ctr_out <= '0';
      if precount = '1' then
        case presentstate is
          -------------------------------------------------------------------------------
          -- IDLE State
          -------------------------------------------------------------------------------
          when IDLE =>                         
            mem_input <= (others => '0');
            if seriell_in = '0' then            -- if seriell_in = 0 the receiving starts 
              nextstate <= START;
            end if;
          -------------------------------------------------------------------
          -- START State
          -------------------------------------------------------------------
          when START =>                         
            pos := 0;
            if seriell_in = '0' then
              count := count + 1;
              if count = conv_std_logic_vector(7,4) then            -- when there were 8 zeros the startbit is finished
                nextstate <= DATS;
                dat1  := (others => '0') ;
                dat0  := (others => '1');
                count := (others => '0');
              end if;
            else
              nextstate <= IDLE;                -- when there is a error bei the startbis change back to IDLE Mode
            end if;       
          ---------------------------------------------------------------------
          -- DATS State
          ---------------------------------------------------------------------
          when DATS =>                          
            if seriell_in = '0' then
              dat0 := dat0 - 1;
              count := count + 1;
            end if;
            if seriell_in = '1' then
              dat1 := dat1 + 1;
              count := count + 1;
            end if;
            
            if count = conv_std_logic_vector(5,4) and dat1 = conv_std_logic_vector(5,3) then
              mem_input(pos) <= '1';    --when ther were five times a one the Bitis set to 1
            end if;
            if count = conv_std_logic_vector(5,4) and dat0 = conv_std_logic_vector(2,3) then
              mem_input(pos) <= '0';    --when there were five times a zero the Bit is set to 0
            end if;
            
            if count = conv_std_logic_vector(8,4) then
              pos := pos + 1; 
              dat1 := (others => '0');
              dat0 := (others => '1');
              count := (others => '0');
              if pos = 8 then           -- if 8 Bits are received he change to the STOP State
                nextstate <= PARITY;
              end if;
            end if;
          ---------------------------------------------------------------------
          -- PARITY State
          ---------------------------------------------------------------------  
          when PARITY =>
            --In this state you have the possibility to control the message
            --with the parity bit.
            count := count + 1;
            if count = conv_std_logic_vector(8,4) then    --if he received the Stopbit he change to the IDLE State
              nextstate <= STOP;
              count := (others => '0');
            end if;
          ---------------------------------------------------------------------
          -- STOP State
          ---------------------------------------------------------------------  
          when STOP =>                          -- STOP State
            if seriell_in = '1' then
              count := count + 1;
              if count = conv_std_logic_vector(8,4) then    --if he received the Stopbit he change to the IDLE State
                nextstate <= IDLE;
                count := (others => '0');
                dat1 := (others => '0');
                dat0 := (others => '1');
                seriell_out <= mem_input;
                test_out <= mem_input;
                seriell_ctr_out <= '1';
              end if;
            end if; 
          when others => nextstate <= IDLE;  --if there is an error the fsm go
                                             --back to the IDLE state
        end case;
      end if;
    end if;
  end process seqfsm2;
  

end rtl;


Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ fresh (Gast)

>sich über 5 Abtastungen der Wertnicht ändert gilt er und nach 8

Man kanns auch übertreiben. Ausserdem arbeiten die meisten RS232 
Empfänger mit einer Mehrheitsentscheidung.

>Byte auf den Leds anzeigen und es kommt nie das richtige an! Weis jemand
>vielleicht nen Rat?!

Lass den Unsinn mit den Variablen. Nimm SIGNALE.
Deine Handhabung des Clock Enables ist schlecht. Einmal hast du die 
Speicherung des States mit vollem Takt im ersten Prozess.

>      presentstate <= nextstate;              -- set the presentstate to

Dann hast du NOCHMAL einen Zwischenspeicher, der aber mit dem clock 
enable getaktet ist.

>    elsif clk'event and clk = '1' then      -- rising clock edge
>      seriell_ctr_out <= '0';
>      if precount = '1' then
        case presentstate is
          ------------------------------------------------------------------------ 
-------
          -- IDLE State
          ------------------------------------------------------------------------ 
-------
          when IDLE =>
            mem_input <= (others => '0');
            if seriell_in = '0' then            -- if seriell_in = 0 the 
receiving starts
              nextstate <= START;
            end if;

Das ist Unsinn und kann wilde Nebeneffekte hervorrufen.

>              if count = conv_std_logic_vector(7,4) then            --

Hier kann man einfach schreiben

              if count = 4 then            --

Deine Datenerfassung ist ziemlich konfus. Und ich sehe kein 
Schieberegister. Schau dir mal im Netz an, wie so ein UART funktioniert. 
Und denk dran. Lass das mit den 5 Abtastungen erstmal sein. Taste in der 
Mitte des Bits ab und gut.

MfG
Falk

Autor: fresh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Danke für deine Konstruktive Antwort! Werde die Punkte mir alle ansehen 
und es dann nochmal versuchen!

MFG Fresh

Autor: fresh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

So habe nun die Vorschläge von Falk beachtet und das ganze neu codiert 
und jetzt gehts! Ich spiele das ganze per Xilinx ISE in den FPGA und 
dabei zeigt er noch einige Warnings an! Habe mir alle angesehen und die 
meisten sind zu missachten! Nur am Schluss kommen vier die mir sorgen 
machen aber ich nicht lösen kann!

WARNING:PhysDesignRules:372 - Gated clock. Clock net 
Transmitmodul/_n0029 is
   sourced by a combinatorial pin. This is not good design practice. Use 
the CE
   pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net Listenmodul/_n0018 
is
   sourced by a combinatorial pin. This is not good design practice. Use 
the CE
   pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net Buffermodul/_n0178 
is
   sourced by a combinatorial pin. This is not good design practice. Use 
the CE
   pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net mem_next_inout is 
sourced
   by a combinatorial pin. This is not good design practice. Use the CE 
pin to
   control the loading of data into the flip-flop.

Vielleicht kann mir jemand erklären was die Fehler genau bedeuten!?

MFG Fresh

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ fresh (Gast)

>So habe nun die Vorschläge von Falk beachtet und das ganze neu codiert
>und jetzt gehts!

Schön zu hören. ;-)

>dabei zeigt er noch einige Warnings an! Habe mir alle angesehen und die
>meisten sind zu missachten!

Sagt wer?

> Nur am Schluss kommen vier die mir sorgen
>machen aber ich nicht lösen kann!

>WARNING:PhysDesignRules:372 - Gated clock. Clock net
>Transmitmodul/_n0029 is
>   sourced by a combinatorial pin. This is not good design practice. Use
>the CE
>   pin to control the loading of data into the flip-flop.

Tstststs, du hast wohl den Artikel nicht gründlich gelesen. Nochmal. Und 
dann ein Clock Enable verwenden.

>Vielleicht kann mir jemand erklären was die Fehler genau bedeuten!?

Taktung FPGA/CPLD

MfG
Falk

Autor: fresh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk

Erstens Danke wiedermal für die Antwort! Habe jetzt mal mein Listenmodul 
genommen und diesen Fehler gesucht! Nur irgendwie versteh ich noch nicht 
ganz wo der Fehler ist! Liegt es daran das ein combinatorischer Prozess 
vorhanedn ist! Das ganze ist im 2 Prozess Modell aufgebaut!
architecture twoproc of listen_unit is
   signal r, rin          : listen_reg_type;
   signal prebit          : std_logic := '1';
   signal tmp_list_en_out : std_logic := '0';
   
begin  -- twoproc

  -- purpose: combinatorial process of the two-process design
  -- type   : combinational
  -- inputs : list_en_in, r
  -- outputs: list_en_out
  comb: process(list_en_in, r, data_in, prebit)
     variable tmp    : listen_reg_type;
  begin  -- process comb
    tmp := r;
      if (list_en_in = '1') then
        if(tmp.precount = conv_std_logic_vector(0,13)) then
          prebit <= data_in;
          if (data_in = prebit and prebit = '1') then
            tmp.bitcount := tmp.bitcount + 1;
          else  
            tmp.bitcount := (others => '0');
          end if;
          --looks if 6 same bits were come
          tmp_list_en_out <= '0';
          if (tmp.bitcount = conv_std_logic_vector(6,3)) then
            tmp_list_en_out <= '1';
          end if;
          tmp.precount := precount_value;
        else
          tmp.precount := tmp.precount - 1;
        end if;  
      end if;
    rin <= tmp;
  end process comb;

  list_en_out <= tmp_list_en_out;
  
  -- purpose: sequential process or the two-process design
  -- type   : sequential
  -- inputs : clk, reset, rin
  -- outputs: r
  seq: process (clk, reset)
  begin  -- process seq
    if reset = '0' then                 -- asynchronous reset (active low)
      r.bitcount  <= (others => '0');
      r.precount  <= (others => '0');
    elsif clk'event and clk = '1' then  -- rising clock edge
      r <= rin;
    end if;
  end process seq;
  

end twoproc;



Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ fresh (Gast)

>Erstens Danke wiedermal für die Antwort! Habe jetzt mal mein Listenmodul
>genommen und diesen Fehler gesucht!

Was soll das darstellen? Alles recht akademisch geschrieben.

> Nur irgendwie versteh ich noch nicht
>ganz wo der Fehler ist!

Du hast dir da ein Latch gebastelt. Das müsste auch der Compiler 
bemängeln.

> Liegt es daran das ein combinatorischer Prozess
>vorhanedn ist!

Schau dir mal deinen kombinatorischen Prozess an. Wenn list_en_in = '1' 
nicht erfüllt ist, wird rin mit r zugewiesen. Das ist a) falsch (weil es 
ein Latch erzeugt) und b) unsinnig, weil die Speicherung im anderen 
Prozess erfolgt. Ein Grund mehr, die Methode mit zwei Prozessen nicht 
anzuwenden, sie hat IMO nur Nachteile.

MfG
Falk

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.