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


von fresh (Gast)


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
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_unsigned.all;
4
use ieee.std_logic_arith.all;
5
6
7
entity uart is
8
  
9
  port (
10
    clk             : in  std_logic;
11
    reset           : in  std_logic;
12
    seriell_in      : in  std_logic;
13
    seriell_out     : out std_logic_vector(7 downto 0) := (others => '0');
14
    seriell_ctr_out : out std_logic := '0';
15
    test_out        : out std_logic_vector(7 downto 0):= (others => '0'));
16
17
end uart;
18
19
20
architecture rtl of uart is
21
22
  --type and signal for the finit state machine
23
  type t_state is (IDLE, START, DATS, PARITY, STOP);
24
  signal presentstate : t_state;
25
  signal nextstate    : t_state;
26
  
27
  --Signal for the prescaler
28
  signal precount : std_logic := '0';
29
30
  --Signal for puffering the input
31
  signal mem_input : std_logic_vector(7 downto 0) := (others => '0');
32
33
  --constant for the baudrate
34
  constant baudrate : std_logic_vector(5 downto 0) := conv_std_logic_vector(13,6);--baudrate = 8*460,8kBit/s
35
  
36
begin  -- rtl
37
38
  -- purpose: Prescaler for the uart
39
  -- type   : sequential
40
  -- inputs : clk48, reset_n
41
  -- outputs: precount
42
  Prescaler: process (clk, reset)
43
    variable count : std_logic_vector(5 downto 0) := (others => '0');
44
  begin  -- process Prescaler
45
    if reset = '0' then                       -- asynchronous reset (active low)
46
      count := (others => '0');
47
      presentstate <= IDLE;
48
    elsif clk'event and clk = '1' then        -- rising clock edge
49
      presentstate <= nextstate;              -- set the presentstate to the nextstate
50
      precount <= '0';                        -- reset of the variable precount
51
      count := count + 1;
52
      if count = baudrate then
53
        count := (others => '0');
54
        precount <= '1';                      --set of the variable precount 
55
      end if;
56
      
57
    end if;
58
  end process Prescaler;
59
60
61
  -- purpose: Sequential Process for the fsm
62
  -- type   : sequential
63
  -- inputs : clk48, reset_n
64
  -- outputs: presentstate
65
  seqfsm2: process (clk, reset)
66
67
    variable count  : std_logic_vector(3 downto 0) := (others => '0');
68
    variable dat1  : std_logic_vector(2 downto 0) := (others => '0');
69
    variable dat0  : std_logic_vector(2 downto 0) := (others => '1');
70
    variable pos    : integer range 0 to 8 := 0;
71
    
72
  begin  -- process seqfsm2
73
    if reset = '0' then                       -- asynchronous reset (active low)
74
      
75
    elsif clk'event and clk = '1' then      -- rising clock edge
76
      seriell_ctr_out <= '0';
77
      if precount = '1' then
78
        case presentstate is
79
          -------------------------------------------------------------------------------
80
          -- IDLE State
81
          -------------------------------------------------------------------------------
82
          when IDLE =>                         
83
            mem_input <= (others => '0');
84
            if seriell_in = '0' then            -- if seriell_in = 0 the receiving starts 
85
              nextstate <= START;
86
            end if;
87
          -------------------------------------------------------------------
88
          -- START State
89
          -------------------------------------------------------------------
90
          when START =>                         
91
            pos := 0;
92
            if seriell_in = '0' then
93
              count := count + 1;
94
              if count = conv_std_logic_vector(7,4) then            -- when there were 8 zeros the startbit is finished
95
                nextstate <= DATS;
96
                dat1  := (others => '0') ;
97
                dat0  := (others => '1');
98
                count := (others => '0');
99
              end if;
100
            else
101
              nextstate <= IDLE;                -- when there is a error bei the startbis change back to IDLE Mode
102
            end if;       
103
          ---------------------------------------------------------------------
104
          -- DATS State
105
          ---------------------------------------------------------------------
106
          when DATS =>                          
107
            if seriell_in = '0' then
108
              dat0 := dat0 - 1;
109
              count := count + 1;
110
            end if;
111
            if seriell_in = '1' then
112
              dat1 := dat1 + 1;
113
              count := count + 1;
114
            end if;
115
            
116
            if count = conv_std_logic_vector(5,4) and dat1 = conv_std_logic_vector(5,3) then
117
              mem_input(pos) <= '1';    --when ther were five times a one the Bitis set to 1
118
            end if;
119
            if count = conv_std_logic_vector(5,4) and dat0 = conv_std_logic_vector(2,3) then
120
              mem_input(pos) <= '0';    --when there were five times a zero the Bit is set to 0
121
            end if;
122
            
123
            if count = conv_std_logic_vector(8,4) then
124
              pos := pos + 1; 
125
              dat1 := (others => '0');
126
              dat0 := (others => '1');
127
              count := (others => '0');
128
              if pos = 8 then           -- if 8 Bits are received he change to the STOP State
129
                nextstate <= PARITY;
130
              end if;
131
            end if;
132
          ---------------------------------------------------------------------
133
          -- PARITY State
134
          ---------------------------------------------------------------------  
135
          when PARITY =>
136
            --In this state you have the possibility to control the message
137
            --with the parity bit.
138
            count := count + 1;
139
            if count = conv_std_logic_vector(8,4) then    --if he received the Stopbit he change to the IDLE State
140
              nextstate <= STOP;
141
              count := (others => '0');
142
            end if;
143
          ---------------------------------------------------------------------
144
          -- STOP State
145
          ---------------------------------------------------------------------  
146
          when STOP =>                          -- STOP State
147
            if seriell_in = '1' then
148
              count := count + 1;
149
              if count = conv_std_logic_vector(8,4) then    --if he received the Stopbit he change to the IDLE State
150
                nextstate <= IDLE;
151
                count := (others => '0');
152
                dat1 := (others => '0');
153
                dat0 := (others => '1');
154
                seriell_out <= mem_input;
155
                test_out <= mem_input;
156
                seriell_ctr_out <= '1';
157
              end if;
158
            end if; 
159
          when others => nextstate <= IDLE;  --if there is an error the fsm go
160
                                             --back to the IDLE state
161
        end case;
162
      end if;
163
    end if;
164
  end process seqfsm2;
165
  
166
167
end rtl;

von Falk B. (falk)


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

von fresh (Gast)


Lesenswert?

Hallo

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

MFG Fresh

von fresh (Gast)


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

von Falk B. (falk)


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

von fresh (Gast)


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!
1
architecture twoproc of listen_unit is
2
   signal r, rin          : listen_reg_type;
3
   signal prebit          : std_logic := '1';
4
   signal tmp_list_en_out : std_logic := '0';
5
   
6
begin  -- twoproc
7
8
  -- purpose: combinatorial process of the two-process design
9
  -- type   : combinational
10
  -- inputs : list_en_in, r
11
  -- outputs: list_en_out
12
  comb: process(list_en_in, r, data_in, prebit)
13
     variable tmp    : listen_reg_type;
14
  begin  -- process comb
15
    tmp := r;
16
      if (list_en_in = '1') then
17
        if(tmp.precount = conv_std_logic_vector(0,13)) then
18
          prebit <= data_in;
19
          if (data_in = prebit and prebit = '1') then
20
            tmp.bitcount := tmp.bitcount + 1;
21
          else  
22
            tmp.bitcount := (others => '0');
23
          end if;
24
          --looks if 6 same bits were come
25
          tmp_list_en_out <= '0';
26
          if (tmp.bitcount = conv_std_logic_vector(6,3)) then
27
            tmp_list_en_out <= '1';
28
          end if;
29
          tmp.precount := precount_value;
30
        else
31
          tmp.precount := tmp.precount - 1;
32
        end if;  
33
      end if;
34
    rin <= tmp;
35
  end process comb;
36
37
  list_en_out <= tmp_list_en_out;
38
  
39
  -- purpose: sequential process or the two-process design
40
  -- type   : sequential
41
  -- inputs : clk, reset, rin
42
  -- outputs: r
43
  seq: process (clk, reset)
44
  begin  -- process seq
45
    if reset = '0' then                 -- asynchronous reset (active low)
46
      r.bitcount  <= (others => '0');
47
      r.precount  <= (others => '0');
48
    elsif clk'event and clk = '1' then  -- rising clock edge
49
      r <= rin;
50
    end if;
51
  end process seq;
52
  
53
54
end twoproc;

von Falk B. (falk)


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

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.