Forum: FPGA, VHDL & Co. UART Transmitter, FSM


von Daniel -. (root)


Lesenswert?

Hallo,

Mein UART Transmitter will irgendwie nicht recht.
Nach mehrmaligen Wieder/Wieder/Wieder-Drüberschauen
finde meinen Fehler nicht. Deswegen stelle ich es hierein
damit frische Köpfe sich an anschauen ...
Wer welche Teile auch immer kritisieren möchte, möge es auch tun :)

In der Simulation klappt alles wie soll.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
-- transmission 'least significant bit first'
6
7
entity transmitter is
8
    generic(freq: integer := 100e6;
9
    baud: integer := 115200;
10
    nticks: integer := 16;
11
    databits: integer := 8;    -- allowed values 5-8
12
    paritybit: integer := 0;   
13
                -- 0 = no parity, 1 = odd, 2 = even
14
    stopbits: integer := 2);   -- only full, 1 or 2
15
    port(clk: in std_logic;
16
    reset: in std_logic;
17
    tx: out std_logic;
18
    done: out std_logic;
19
    busy: out std_logic;
20
    data: in std_logic_vector(databits-1 downto 0);
21
    take_data_pulse: in std_logic);
22
end entity;
23
24
architecture behaviour of transmitter is
25
26
    constant oversample_freq: integer := baud * nticks;
27
    constant n: integer := freq / oversample_freq;
28
29
    type fsm is (idle, start_transmit, 
30
                data_transmit, parity_transmit, 
31
                stop_transmit, done_pulse);
32
    signal state_reg, state_next: fsm := idle;
33
    
34
    signal count_reg, count_next: integer range 0 to n := 0;
35
    signal data_reg, data_next: std_logic_vector(databits-1 downto 0);
36
    
37
    signal dbits_reg, dbits_next: integer range 0 to databits := 0;
38
    signal sbits_reg, sbits_next: integer range 0 to stopbits := 0;
39
    
40
    signal even_parity, odd_parity: std_logic := '0';
41
42
begin
43
44
    update: process(clk, reset)
45
    begin
46
    if reset = '1' then
47
      state_reg <= idle;
48
      count_reg <= 0;
49
      data_reg <= (others => '0');
50
      dbits_reg <= 0;
51
      sbits_reg <= 0;
52
    elsif rising_edge(clk) then
53
      state_reg <= state_next;
54
      count_reg <= count_next;
55
      data_reg <= data_next;
56
      dbits_reg <= dbits_next;
57
      sbits_reg <= sbits_next;
58
    end if;
59
    end process;
60
    
61
    logic: process(state_reg, take_data_pulse, 
62
                    count_reg, dbits_reg, sbits_reg,
63
                    data_reg, even_parity, odd_parity)
64
    begin
65
    tx <= '0';
66
    busy <= '1';
67
    done <= '0';
68
    state_next <= state_reg;
69
    data_next <= data_reg;
70
    sbits_next <= sbits_reg;
71
    dbits_next <= dbits_reg;
72
    count_next <= count_reg;
73
    case state_reg is
74
      when idle =>
75
        tx <= '1';
76
        busy <= '0';
77
        count_next <= 0;
78
        if take_data_pulse = '1' then
79
          data_next <= data;
80
          sbits_next <= 0;
81
          dbits_next <= 0;
82
          state_next <= start_transmit;
83
        end if;
84
      when start_transmit => 
85
        tx <= '0';
86
        count_next <= count_reg + 1;
87
        if count_reg = n-1 then
88
          count_next <= 0;
89
          state_next <= data_transmit;
90
        end if;
91
      when data_transmit => 
92
        count_next <= count_reg + 1;
93
        tx <= data_reg(dbits_reg);
94
        if count_reg = n-1 then
95
          count_next <= 0;
96
          dbits_next <= dbits_reg + 1;
97
          if dbits_reg = databits-1 then
98
            if paritybit = 0 then
99
              state_next <= stop_transmit;
100
            else
101
              state_next <= parity_transmit;
102
            end if;
103
          end if;
104
        end if;
105
      when parity_transmit => 
106
        tx <= '0';
107
        count_next <= count_reg + 1;
108
        if count_reg = n-1 then
109
          count_next <= 0;
110
          state_next <= stop_transmit;
111
        end if;
112
        if paritybit = 1 then  -- should be made odd
113
          if even_parity = '1' then
114
            tx <= '1';
115
          else
116
            tx <= '0';
117
          end if;
118
        else      -- should be made even
119
          if even_parity = '1' then
120
            tx <= '0';
121
          else
122
            tx <= '1';
123
          end if;
124
        end if;
125
      when stop_transmit => 
126
        tx <= '1';
127
        count_next <= count_reg + 1;
128
        if count_reg = n-1 then
129
          count_next <= 0;
130
          sbits_next <= sbits_reg + 1;
131
          if sbits_reg = stopbits-1 then
132
            state_next <= done_pulse;
133
          end if;
134
        end if;
135
      when done_pulse => 
136
        tx <= '1';
137
        busy <= '0';
138
        done <= '1';
139
        state_next <= idle;
140
    end case;
141
    end process;
142
    
143
    parity: process(data_reg)
144
    variable even: std_logic;
145
  begin
146
    even := '1';
147
    for i in data_reg'range loop
148
      if data_reg(i) = '1' then
149
      even := not even;
150
      end if;
151
    end loop;
152
    even_parity <= even;
153
    odd_parity <= not even;
154
    end process;
155
156
end architecture;

von Jan M. (mueschel)


Lesenswert?

Wenn du diesen Code simulierst, kann alles moegliche passieren, das sich 
in der Wirklichkeit ganz anders verhaelt - die sensitivity list ist bei 
weitem nicht vollstaendig.

von Daniel (root) (Gast)


Lesenswert?

1
    logic: process(state_reg, take_data_pulse, 
2
                    count_reg, dbits_reg, sbits_reg,
3
                    data_reg, even_parity, odd_parity)

hmm .. sieht für mich vollständig aus. Alles worauf ich
lesend zugreife steht da.

Du hast mich auf die Frage gebracht ob generic Werte
auch in die sens. Liste reinsollen oder nicht. So wie
paritybit. Ich denke aber nicht, weil es eine Konstante ist.
Genauso wie n.

von Peter A. (Gast)


Lesenswert?

probier es mal mit
1
 logic : process( count_reg, data, data_reg, dbits_reg, even_parity,
2
                   sbits_reg, state_reg, take_data_pulse)

und nein, deine generics muessen nicht in die sen liste, da die als 
konstanten behandelt werden.

von Jan M. (mueschel)


Lesenswert?

Daniel (root) schrieb:
>
> hmm .. sieht für mich vollständig aus. Alles worauf ich
> lesend zugreife steht da.

z.B. data fehlt noch.

> Du hast mich auf die Frage gebracht ob generic Werte
> auch in die sens. Liste reinsollen oder nicht. So wie
> paritybit. Ich denke aber nicht, weil es eine Konstante ist.
> Genauso wie n.

Wie Peter schreibt, generics und Konstanten muessen nicht in die Liste.

von Daniel (root) (Gast)


Lesenswert?

Danke! tatsächlich data habe ich übersehen
in dem vorliegenden Fall hat es aber nichts ausgemacht, da auf
data nur in einem Taktzyklus zugegriffen wird, geschützt in if ...
im nächsten Zyklus ist FSM schon im anderen state und dann ist es
auch egal ob data sich ändert.

ich habe den Fehler gefunden!
wie immer sucht man erst woanders :)
es ist ein denkfehler gewesen
1
constant n: integer := freq / baud;

so sollte es ein. Die Überabtastung spielt nur im receiver eine Rolle
und denn habe ich zuerst geschrieben.

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.