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

Subversion Repositories uart_serial

[/] [uart_serial/] [trunk/] [sources/] [uart_serial.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 martin.xrm
-------------------------------------------------------------------------------
2
-- Use of this source code through a simulator and/or a compiler tool
3
-- is illegal if not authorised through Author License agreement.
4
-------------------------------------------------------------------------------
5
-- top level   : uart_serial.vhd
6
-- File        : uart_serial.vhd
7
-- Author      : Xavier Martin
8
-- Email       : 
9
-- Organization: 
10
-- Created     : 2008, june 30th
11
-- Last update :
12
-- Simulators  : ModelSim Altera 6.0c
13
-- Synthesizers: Quartus II 5.0
14
-- Targets     : 
15
-- Dependency  :
16
-------------------------------------------------------------------------------
17
-- Description : This entity is a generic UART block 
18
--               UART allows to work with one or two bits stop
19
--               baud : 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
20
--                      230400, 460800, 921600
21
--               Note:
22
--                   Br*br_divisor=921.600
23
--                   Fclk/921.600=clk_divisor
24
--                   => Br=Fclk/(clk_divisor*br_divisor)=1/((clk_divisor*Tclk)*br_divisor) 
25
-------------------------------------------------------------------------------
26
-- Version     : 1.0
27
-- Date        : 
28
-- Modifier    : 
29
-- Modif.      : 
30
-------------------------------------------------------------------------------
31
 
32
library ieee;
33
use ieee.std_logic_1164.all;
34
use ieee.std_logic_unsigned.all;
35
use ieee.numeric_std.all;
36
 
37
entity uart_serial is
38
  port(
39
    -- Global signal
40
    reset          : in  std_logic;                      -- reset control signal
41
    clk            : in  std_logic;                      -- 14.7456 Mhz Clock frequency
42
    -- Reception channel
43
    rx_data_serial : in  std_logic;                      -- Received Serial data from RS232
44
    rx_data_out    : out std_logic_vector(7 downto 0);   -- Received Data
45
    rx_data_en     : out std_logic;                      -- Received data enable control signal
46
    rx_ovf_err     : out std_logic;                      -- Received data over frame error detected
47
    rx_parity_err  : out std_logic;                      -- Received data parity error
48
    -- Transmition channel
49
    tx_data_serial : out std_logic;                      -- Transmited Serial data to RS232
50
    tx_data_in     : in  std_logic_vector(7 downto 0);   -- Transmited data 
51
    tx_data_en     : in  std_logic;                      -- Transmited data latch enable
52
    tx_ch_rdy      : out std_logic;                      -- Transmition channel ready status signal
53
    -- Control command
54
    baud_sel       : in  std_logic_vector(3 downto 0);   -- Baud value see Note   
55
    parity_en      : in  std_logic;                      -- Enable parity control signal active HIGH
56
    parity_type    : in  std_logic);                     -- 1:ODD parity / 0:EVEN parity 
57
end entity;
58
 
59
 
60
architecture rtl of uart_serial is
61
 
62
  -------------------------------------------------------------------------------
63
  -- CONSTANT DECLARATION
64
  -------------------------------------------------------------------------------
65
  constant ODD_PARITY        : std_logic := '1';
66
  constant EVEN_PARITY       : std_logic := '0';
67
  constant CLK_DIVISOR       : integer := 16;    -- clock divisor to obtain 921600 bauds - CLK_DIVISOR = Fclk/921600
68
  constant BR_DIVISOR_300    : integer := 3072;  --    300 bauds bit rate divisor value
69
  constant BR_DIVISOR_1200   : integer := 768;   --   1200 bauds bit rate divisor value
70
  constant BR_DIVISOR_2400   : integer := 384;   --   2400 bauds bit rate divisor value
71
  constant BR_DIVISOR_4800   : integer := 192;   --   4800 bauds bit rate divisor value
72
  constant BR_DIVISOR_9600   : integer := 96;    --   9600 bauds bit rate divisor value
73
  constant BR_DIVISOR_19200  : integer := 48;    --  19200 bauds bit rate divisor value
74
  constant BR_DIVISOR_38400  : integer := 24;    --  38400 bauds bit rate divisor value
75
  constant BR_DIVISOR_57600  : integer := 16;    --  57600 bauds bit rate divisor value
76
  constant BR_DIVISOR_115200 : integer := 8;     -- 115200 bauds bit rate divisor value
77
  constant BR_DIVISOR_230400 : integer := 4;     -- 230400 bauds bit rate divisor value
78
  constant BR_DIVISOR_460800 : integer := 2;     -- 460800 bauds bit rate divisor value
79
  constant BR_DIVISOR_921600 : integer := 1;     -- 921600 bauds bit rate divisor value
80
 
81
 
82
  -------------------------------------------------------------------------------
83
  -- SIGNAL DECLARATION
84
  -------------------------------------------------------------------------------
85
  type tx_state_m is (IDLE,LOAD_TX_DATA,TX_DATA,TX_STOP);
86
  type rx_state_m is (IDLE,START_RX,EDGE_RX,SHIFT_RX,STOP_RX,RX_OVF);
87
  signal tx_state      : tx_state_m;
88
  signal rx_state      : rx_state_m;
89
  signal br_divisor    : std_logic_vector(9 downto 0);   -- Bit rate divisor
90
  signal top_ref_baud  : std_logic;                      -- Top reference baud 921600
91
  signal tx_top_baud   : std_logic;                      -- Transmit Top selected baud
92
  signal rx_top_baud   : std_logic;                      -- Transmit Top selected baud
93
  signal tx_data_s     : std_logic_vector(7 downto 0);   -- Sample Transmited data input
94
  signal tx_data_reg   : std_logic_vector(10 downto 0);  -- Transmited data register
95
  signal rx_data_i     : std_logic_vector(7 downto 0);   -- Intermediary Received data
96
  signal rx_parity_err_i : std_logic;                    -- Intermediary parity error status signal
97
  signal clr_rx_baud   : std_logic;                      -- clear Receive baud counter divisor counter
98
 
99
  -------------------------------------------------------------------------------
100
  -- FUNCTION DECLARATION
101
  ------------------------------------------------------------------------------
102
  function parity (data: std_logic_vector; parity_type : std_logic) return std_logic is
103
    variable tmp : std_logic;
104
  begin
105
    if parity_type = EVEN_PARITY then    -- making the number of data even
106
      tmp := '0';
107
      for i in data'range loop
108
        tmp := tmp xor data(i);
109
      end loop;
110
    elsif parity_type = ODD_PARITY then  -- making the number of data odd
111
      tmp := '1';
112
      for i in data'range loop
113
        tmp := tmp xnor data(i);
114
      end loop;
115
    end if;
116
 
117
    return tmp;
118
  end function;
119
 
120
 
121
begin
122
 
123
 
124
  -------------------------------------------------------------------------------
125
  -- This process is used to select bit rate divisor associated to baud_sel
126
  -- vector value. The bit rate divisor is necessary to obtain the correct baud
127
  -- once the 921600 baud is obtain by clock division
128
  -------------------------------------------------------------------------------
129
  baud_sel_proc:
130
  process(reset, clk)
131
  begin
132
    if reset = '1' then
133
      br_divisor <= (others => '0');
134
    elsif rising_edge(clk) then
135
      case baud_sel is
136
           when x"0" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_300,br_divisor'length));       --    300 bauds
137
           when x"1" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_1200,br_divisor'length));      --   1200 bauds
138
           when x"2" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_2400,br_divisor'length));      --   2400 bauds
139
           when x"3" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_4800,br_divisor'length));      --   4800 bauds
140
           when x"4" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_9600,br_divisor'length));      --   9600 bauds
141
           when x"5" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_19200,br_divisor'length));     --  19200 bauds
142
           when x"6" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_38400,br_divisor'length));     --  38400 bauds
143
           when x"7" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_57600,br_divisor'length));     --  57600 bauds
144
           when x"8" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_115200,br_divisor'length));    -- 115200 bauds
145
           when x"9" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_230400,br_divisor'length));    -- 230400 bauds
146
           when x"A" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_460800,br_divisor'length));    -- 460800 bauds
147
           when x"B" =>   br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_921600,br_divisor'length));    -- 921600 bauds
148
           when others => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_115200,br_divisor'length));
149
      end case;
150
    end if;
151
  end process;
152
 
153
 
154
  -------------------------------------------------------------------------------
155
  -- This process is neccessary to obtain the 921600 baud. This baud is obtained by
156
  -- dividing clock frequency with the followed equation CLK_DIVISOR = Fclk/921600
157
  -- This baud will be the reference one to obtain others ones.
158
  -------------------------------------------------------------------------------
159
  baud_ref_proc:
160
  process(reset, clk)
161
    variable clk_divisor_cnt : integer range 0 to CLK_DIVISOR;  -- Clock divisier counter
162
  begin
163
    if reset = '1' then
164
      top_ref_baud     <= '0';
165
      clk_divisor_cnt := 0;
166
    elsif rising_edge(clk) then
167
      top_ref_baud    <= '0';
168
      clk_divisor_cnt := clk_divisor_cnt + 1;
169
 
170
      if clk_divisor_cnt = CLK_DIVISOR then
171
        top_ref_baud    <= '1';
172
        clk_divisor_cnt := 0;
173
      end if;
174
 
175
    end if;
176
  end process;
177
 
178
 
179
  -------------------------------------------------------------------------------
180
  -- This process is necessary to obtain the selected bit rate by divising the 
181
  -- 921600 reference baud with baud selected value.
182
  -------------------------------------------------------------------------------
183
  tx_baud_proc:
184
  process(reset, clk)
185
    variable tx_br_divisor_cnt : integer range 0 to BR_DIVISOR_300;
186
  begin
187
    if reset = '1' then
188
      tx_top_baud       <= '0';
189
      tx_br_divisor_cnt := 0;
190
    elsif rising_edge(clk) then
191
      tx_top_baud       <= '0';
192
      if top_ref_baud = '1' then
193
        tx_br_divisor_cnt := tx_br_divisor_cnt + 1;
194
 
195
        if tx_br_divisor_cnt = br_divisor then
196
          tx_top_baud       <= '1';
197
          tx_br_divisor_cnt := 0;
198
        end if;
199
 
200
      end if;
201
    end if;
202
  end process;
203
 
204
  rx_baud_proc:
205
  process(reset, clk)
206
    variable rx_br_divisor_cnt : std_logic_vector(9 downto 0);
207
  begin
208
    if reset = '1' then
209
      rx_top_baud       <= '0';
210
      rx_br_divisor_cnt := (others => '0');
211
    elsif rising_edge(clk) then
212
      rx_top_baud       <= '0';
213
      if clr_rx_baud = '1' then
214
        rx_br_divisor_cnt := (others => '0');
215
      elsif top_ref_baud = '1' and rx_state /= IDLE then
216
        rx_br_divisor_cnt := rx_br_divisor_cnt + 1;
217
 
218
        if rx_br_divisor_cnt(8 downto 0) = br_divisor(9 downto 1) then
219
          rx_top_baud       <= '1';
220
          rx_br_divisor_cnt := (others => '0');
221
        end if;
222
 
223
      end if;
224
    end if;
225
  end process;
226
 
227
 
228
  -------------------------------------------------------------------------------
229
  -- Transmition process
230
  -------------------------------------------------------------------------------
231
  tx_proc:
232
  process(reset, clk)
233
    variable tx_bit_cnt : integer;
234
  begin
235
    if reset = '1' then
236
      tx_data_s      <= (others => '0');
237
      tx_data_reg    <= (others => '1');
238
      tx_ch_rdy      <= '0';
239
    elsif rising_edge(clk) then
240
      case tx_state is
241
        when IDLE =>
242
             if tx_data_en = '1' then
243
               tx_data_s <= tx_data_in;
244
               tx_ch_rdy <= '0';
245
               tx_state  <= LOAD_TX_DATA;
246
             else
247
               tx_ch_rdy <= '1';
248
             end if;
249
 
250
        when LOAD_TX_DATA =>
251
             if tx_top_baud = '1' then
252
               if parity_en = '1' then
253
                 -- start + data + parity + stop
254
                 tx_bit_cnt  := 8 + 3;
255
                 tx_data_reg(10 downto 0) <= '1' & parity(tx_data_s,parity_type) & tx_data_s(7 downto 0) & '0';
256
               else
257
                 -- start + data + stop
258
                 tx_bit_cnt  := 8 + 2;
259
                 tx_data_reg(10 downto 0) <= "11" & tx_data_s(7 downto 0) & '0';
260
               end if;
261
               tx_state <= TX_DATA;
262
             end if;
263
 
264
        when TX_DATA =>
265
             if tx_top_baud = '1' then
266
               tx_data_reg(10 downto 0) <= '1' & tx_data_reg(10 downto 1);
267
               tx_bit_cnt  := tx_bit_cnt-1;
268
               if tx_bit_cnt = 1 then
269
                 tx_state <= TX_STOP;
270
               end if;
271
             end if;
272
 
273
        when TX_STOP => -- stop bit
274
             if tx_top_baud = '1' then
275
               tx_state <= IDLE;
276
             end if;
277
 
278
        when others =>
279
             null;
280
      end case;
281
    end if;
282
  end process;
283
 
284
  tx_data_serial <= tx_data_reg(0);
285
 
286
 
287
  -------------------------------------------------------------------------------
288
  -- Reception process
289
  -------------------------------------------------------------------------------
290
  process(reset, clk)
291
    variable rx_bit_cnt : integer;
292
  begin
293
    if reset = '1' then
294
      rx_data_out    <= (others => '0');
295
      rx_data_en     <= '0';
296
      rx_ovf_err     <= '0';
297
      rx_data_i      <= (others => '0');
298
      rx_parity_err  <= '0';
299
      rx_parity_err_i<= '0';
300
 
301
    elsif rising_edge(clk) then
302
 
303
      clr_rx_baud    <= '0';
304
      rx_ovf_err     <= '0';
305
      rx_parity_err  <= '0';
306
      rx_parity_err_i<= '0';
307
      rx_data_en     <= '0';
308
 
309
      case rx_state is
310
        when IDLE =>  -- Wait start bit
311
             if top_ref_baud = '1' then
312
               if rx_data_serial = '0' then
313
                 clr_rx_baud <= '1';
314
                 rx_state <= START_RX;
315
                 rx_bit_cnt := 1;
316
               end if;
317
             end if;
318
 
319
 
320
        when START_RX =>
321
             if rx_top_baud = '1' then
322
               if rx_data_serial = '1' then
323
                 rx_state <= RX_OVF;
324
               else
325
                 rx_state <= EDGE_RX;
326
               end if;
327
             end if;
328
 
329
 
330
        when EDGE_RX =>
331
             if rx_top_baud = '1' then
332
               if (parity_en = '1' and rx_bit_cnt = 10) or                             -- start + data + parity + stop
333
                  (parity_en = '0' and rx_bit_cnt = 9) then                            -- start + data + stop
334
                 rx_state <= STOP_RX;
335
               else                         -- data
336
                 rx_state <= SHIFT_RX;
337
               end if;
338
             end if;
339
 
340
        when SHIFT_RX =>
341
             if rx_top_baud = '1' then
342
               rx_bit_cnt := rx_bit_cnt + 1;
343
               if not((parity_en = '1' and rx_bit_cnt = 10)) then                      -- start + data + parity + stop
344
                 rx_data_i(7 downto 0) <= rx_data_serial & rx_data_i(7 downto 1);
345
               else
346
                 if parity(rx_data_i,parity_type) /= rx_data_serial then
347
                   rx_parity_err_i <= '1';
348
                 end if;
349
               end if;
350
               rx_state <= EDGE_RX;
351
             end if;
352
 
353
 
354
        when STOP_RX =>
355
--             if rx_top_baud = '1' then
356
               rx_data_out <= rx_data_i;
357
               rx_parity_err <= rx_parity_err_i;
358
               rx_ovf_err  <= '0';
359
               rx_data_en  <= '1';
360
               rx_state <= IDLE;
361
--             end if;
362
 
363
        when RX_OVF =>    -- Overframe error
364
             rx_ovf_err <= '1';
365
             if rx_data_serial = '1' then
366
               rx_state <= IDLE;
367
             end if;
368
 
369
        when others => null;
370
      end case;
371
    end if;
372
  end process;
373
 
374
end rtl;

powered by: WebSVN 2.1.0

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