OpenCores
URL https://opencores.org/ocsvn/rs232_interface/rs232_interface/trunk

Subversion Repositories rs232_interface

[/] [rs232_interface/] [trunk/] [uart.vhd] - Blame information for rev 18

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 akram.mash
----------------------------------------------------------------------------------
2 6 akram.mash
-- Creation Date: 21:12:48 05/06/2010 
3
-- Module Name: RS232/UART Interface - Behavioral
4 3 akram.mash
-- Used TAB of 4 Spaces
5
----------------------------------------------------------------------------------
6
library IEEE;
7
use IEEE.STD_LOGIC_1164.ALL;
8
use IEEE.STD_LOGIC_ARITH.ALL;
9
use IEEE.STD_LOGIC_UNSIGNED.ALL;
10
 
11
entity uart is
12
generic (
13
        CLK_FREQ        : integer := 50;                -- Main frequency (MHz)
14 5 akram.mash
        SER_FREQ        : integer := 9600               -- Baud rate (bps)
15 3 akram.mash
);
16
port (
17
        -- Control
18 5 akram.mash
        clk                     : in    std_logic;              -- Main clock
19
        rst                     : in    std_logic;              -- Main reset
20 3 akram.mash
        -- External Interface
21 5 akram.mash
        rx                      : in    std_logic;              -- RS232 received serial data
22
        tx                      : out   std_logic;              -- RS232 transmitted serial data
23 7 akram.mash
        -- RS232/UART Configuration
24
        par_en          : in    std_logic;              -- Parity bit enable
25 3 akram.mash
        -- uPC Interface
26 5 akram.mash
        tx_req          : in    std_logic;                                              -- Request SEND of data
27
        tx_end          : out   std_logic;                                              -- Data SENDED
28
        tx_data         : in    std_logic_vector(7 downto 0);    -- Data to transmit
29
        rx_ready        : out   std_logic;                                              -- Received data ready to uPC read
30
        rx_data         : out   std_logic_vector(7 downto 0)     -- Received data 
31 3 akram.mash
);
32
end uart;
33
 
34
architecture Behavioral of uart is
35
 
36
        -- Constants
37 7 akram.mash
        constant UART_IDLE      :       std_logic := '1';
38
        constant UART_START     :       std_logic := '0';
39
        constant PARITY_EN      :       std_logic := '1';
40
        constant RST_LVL        :       std_logic := '1';
41 3 akram.mash
 
42
        -- Types
43 10 akram.mash
        type state is (idle,data,parity,stop1,stop2);                   -- Stop1 and Stop2 are inter frame gap signals
44 3 akram.mash
 
45 10 akram.mash
        -- RX Signals
46 7 akram.mash
        signal rx_fsm           :       state;                                                  -- Control of reception
47 10 akram.mash
        signal rx_clk_en        :       std_logic;                                              -- Received clock enable
48
        signal rx_rcv_init      :       std_logic;                                              -- Start of reception
49
        signal rx_par_bit       :       std_logic;                                              -- Calculated Parity bit
50 11 akram.mash
        signal rx_data_deb      :       std_logic;                                              -- Debounce RX data
51 10 akram.mash
        signal rx_data_tmp      :       std_logic_vector(7 downto 0);    -- Serial to parallel converter
52
        signal rx_data_cnt      :       std_logic_vector(2 downto 0);    -- Count received bits
53
 
54
        -- TX Signals
55 7 akram.mash
        signal tx_fsm           :       state;                                                  -- Control of transmission
56 10 akram.mash
        signal tx_clk_en        :       std_logic;                                              -- Transmited clock enable
57
        signal tx_par_bit       :       std_logic;                                              -- Calculated Parity bit
58
        signal tx_data_tmp      :       std_logic_vector(7 downto 0);    -- Parallel to serial converter
59
        signal tx_data_cnt      :       std_logic_vector(2 downto 0);    -- Count transmited bits
60 3 akram.mash
 
61
begin
62
 
63 10 akram.mash
        tx_clk_gen:process(clk)
64 3 akram.mash
                variable counter        :       integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
65
        begin
66
                if clk'event and clk = '1' then
67
                        -- Normal Operation
68
                        if counter = (CLK_FREQ*1_000_000)/SER_FREQ-1 then
69 10 akram.mash
                                tx_clk_en       <=      '1';
70 6 akram.mash
                                counter         :=      0;
71 3 akram.mash
                        else
72 10 akram.mash
                                tx_clk_en       <=      '0';
73 6 akram.mash
                                counter         :=      counter + 1;
74 3 akram.mash
                        end if;
75
                        -- Reset condition
76 7 akram.mash
                        if rst = RST_LVL then
77 11 akram.mash
                                tx_clk_en       <=      '0';
78 3 akram.mash
                                counter         :=      0;
79
                        end if;
80
                end if;
81
        end process;
82
 
83
        tx_proc:process(clk)
84
                variable data_cnt       : std_logic_vector(2 downto 0);
85
        begin
86
                if clk'event and clk = '1' then
87 10 akram.mash
                        if tx_clk_en = '1' then
88 3 akram.mash
                                -- Default values
89 6 akram.mash
                                tx_end                                  <=      '0';
90 7 akram.mash
                                tx                                              <=      UART_IDLE;
91 3 akram.mash
                                -- FSM description
92
                                case tx_fsm is
93
                                        -- Wait to transfer data
94
                                        when idle =>
95
                                                -- Send Init Bit
96
                                                if tx_req = '1' then
97 7 akram.mash
                                                        tx                      <=      UART_START;
98 3 akram.mash
                                                        tx_data_tmp     <=      tx_data;
99 6 akram.mash
                                                        tx_fsm          <=      data;
100 7 akram.mash
                                                        tx_data_cnt     <=      (others=>'1');
101
                                                        tx_par_bit      <=      '0';
102 3 akram.mash
                                                end if;
103
                                        -- Data receive
104
                                        when data =>
105 7 akram.mash
                                                tx                              <=      tx_data_tmp(0);
106
                                                tx_par_bit              <=      tx_par_bit xor tx_data_tmp(0);
107
                                                if tx_data_cnt = 0 then
108
                                                        if par_en = PARITY_EN then
109
                                                                tx_fsm  <=      parity;
110
                                                        else
111
                                                                tx_fsm  <=      stop1;
112
                                                        end if;
113
                                                        tx_data_cnt     <=      (others=>'1');
114 3 akram.mash
                                                else
115
                                                        tx_data_tmp     <=      '0' & tx_data_tmp(7 downto 1);
116 7 akram.mash
                                                        tx_data_cnt     <=      tx_data_cnt - 1;
117 3 akram.mash
                                                end if;
118 7 akram.mash
                                        when parity =>
119
                                                tx                              <=      tx_par_bit;
120
                                                tx_fsm                  <=      stop1;
121 3 akram.mash
                                        -- End of communication
122
                                        when stop1 =>
123
                                                -- Send Stop Bit
124 7 akram.mash
                                                tx                              <=      UART_IDLE;
125 3 akram.mash
                                                tx_fsm                  <=      stop2;
126
                                        when stop2 =>
127
                                                -- Send Stop Bit
128 6 akram.mash
                                                tx_end                  <=      '1';
129 7 akram.mash
                                                tx                              <=      UART_IDLE;
130 3 akram.mash
                                                tx_fsm                  <=      idle;
131
                                        -- Invalid States
132
                                        when others => null;
133
                                end case;
134
                                -- Reset condition
135 7 akram.mash
                                if rst = RST_LVL then
136 3 akram.mash
                                        tx_fsm                          <=      idle;
137 7 akram.mash
                                        tx_par_bit                      <=      '0';
138 6 akram.mash
                                        tx_data_tmp                     <=      (others=>'0');
139 7 akram.mash
                                        tx_data_cnt                     <=      (others=>'0');
140 3 akram.mash
                                end if;
141
                        end if;
142
                end if;
143
        end process;
144
 
145 11 akram.mash
        rx_debounceer:process(clk)
146 10 akram.mash
                variable deb_buf        :       std_logic_vector(3 downto 0);
147
        begin
148
                if clk'event and clk = '1' then
149
                        -- Debounce logic
150
                        if deb_buf = "0000" then
151 11 akram.mash
                                rx_data_deb             <=      '0';
152 10 akram.mash
                        elsif deb_buf = "1111" then
153 11 akram.mash
                                rx_data_deb             <=      '1';
154 10 akram.mash
                        end if;
155
                        -- Data storage to debounce
156 11 akram.mash
                        deb_buf                         :=      deb_buf(2 downto 0) & rx;
157
                end if;
158
        end process;
159 10 akram.mash
 
160 11 akram.mash
        rx_start_detect:process(clk)
161
                variable rx_data_old    :       std_logic;
162
        begin
163
                if clk'event and clk = '1' then
164
                        -- Falling edge detection
165 18 akram.mash
                        if rx_data_old = '1' and rx_data_deb = '0' and rx_fsm = idle then
166 11 akram.mash
                                rx_rcv_init             <=      '1';
167 10 akram.mash
                        else
168
                                rx_rcv_init             <=      '0';
169
                        end if;
170 11 akram.mash
                        -- Default assignments
171
                        rx_data_old                     :=      rx_data_deb;
172 10 akram.mash
                        -- Reset condition
173
                        if rst = RST_LVL then
174 11 akram.mash
                                rx_data_old             :=      '0';
175 10 akram.mash
                                rx_rcv_init             <=      '0';
176
                        end if;
177
                end if;
178 11 akram.mash
        end process;
179 10 akram.mash
 
180
 
181
        rx_clk_gen:process(clk)
182
                variable counter        :       integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
183
        begin
184
                if clk'event and clk = '1' then
185
                        -- Normal Operation
186 11 akram.mash
                        if counter = (CLK_FREQ*1_000_000)/SER_FREQ-1 or rx_rcv_init = '1' then
187 10 akram.mash
                                rx_clk_en       <=      '1';
188
                                counter         :=      0;
189
                        else
190
                                rx_clk_en       <=      '0';
191
                                counter         :=      counter + 1;
192
                        end if;
193
                        -- Reset condition
194
                        if rst = RST_LVL then
195
                                rx_clk_en       <=      '0';
196
                                counter         :=      0;
197
                        end if;
198
                end if;
199
        end process;
200
 
201 3 akram.mash
        rx_proc:process(clk)
202
        begin
203
                if clk'event and clk = '1' then
204 11 akram.mash
                        -- Default values
205
                        rx_ready                <=      '0';
206
                        -- Enable on UART rate
207 10 akram.mash
                        if rx_clk_en = '1' then
208 3 akram.mash
                                -- FSM description
209
                                case rx_fsm is
210
                                        -- Wait to transfer data
211
                                        when idle =>
212 11 akram.mash
                                                if rx_data_deb = UART_START then
213 3 akram.mash
                                                        rx_fsm          <=      data;
214
                                                end if;
215 7 akram.mash
                                                rx_par_bit              <=      '0';
216
                                                rx_data_cnt             <=      (others=>'0');
217 3 akram.mash
                                        -- Data receive
218
                                        when data =>
219 7 akram.mash
                                                -- Check data to generate parity
220
                                                if par_en = PARITY_EN then
221
                                                        rx_par_bit              <=      rx_par_bit xor rx;
222
                                                end if;
223
 
224
                                                if rx_data_cnt = 7 then
225
                                                        -- Data path
226
                                                        rx_data(7)              <=      rx;
227 3 akram.mash
                                                        for i in 0 to 6 loop
228 7 akram.mash
                                                                rx_data(i)      <=      rx_data_tmp(6-i);
229 3 akram.mash
                                                        end loop;
230 7 akram.mash
 
231
                                                        -- With parity verification
232
                                                        if par_en = PARITY_EN then
233
                                                                rx_fsm          <=      parity;
234
                                                        -- Without parity verification
235
                                                        else
236
                                                                rx_ready        <=      '1';
237
                                                                rx_fsm          <=      idle;
238
                                                        end if;
239 3 akram.mash
                                                else
240 7 akram.mash
                                                        rx_data_tmp             <=      rx_data_tmp(6 downto 0) & rx;
241
                                                        rx_data_cnt             <=      rx_data_cnt + 1;
242 3 akram.mash
                                                end if;
243 7 akram.mash
                                        when parity =>
244
                                                -- Check received parity
245
                                                rx_fsm                          <=      idle;
246
                                                if rx_par_bit = rx then
247
                                                        rx_ready                <=      '1';
248
                                                end if;
249 3 akram.mash
                                        when others => null;
250
                                end case;
251
                                -- Reset condition
252 7 akram.mash
                                if rst = RST_LVL then
253 3 akram.mash
                                        rx_fsm                  <=      idle;
254 6 akram.mash
                                        rx_ready                <=      '0';
255
                                        rx_data                 <=      (others=>'0');
256
                                        rx_data_tmp             <=      (others=>'0');
257 7 akram.mash
                                        rx_data_cnt             <=      (others=>'0');
258 3 akram.mash
                                end if;
259
                        end if;
260
                end if;
261
        end process;
262
 
263
end Behavioral;
264
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.