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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [peripherals/] [serial/] [uart.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 tarookumic
 
2
 
3
 
4
 
5
----------------------------------------------------------------------------
6
--  This file is a part of the LEON VHDL model
7
--  Copyright (C) 1999  European Space Agency (ESA)
8
--
9
--  This library is free software; you can redistribute it and/or
10
--  modify it under the terms of the GNU Lesser General Public
11
--  License as published by the Free Software Foundation; either
12
--  version 2 of the License, or (at your option) any later version.
13
--
14
--  See the file COPYING.LGPL for the full details of the license.
15
 
16
 
17
-----------------------------------------------------------------------------
18
-- Entity:      uart
19
-- File:        uart.vhd
20
-- Author:      Jiri Gaisler - ESA/ESTEC
21
-- Description: Asynchronous UART. Implements 8-bit data frame with one
22
--              stop-bit. Programmable options:
23
--              * parity bit (on/off)
24
--              * parity polarity (odd/even)
25
--              * baud-rate (12-bit programmable divider)
26
--              * hardware flow-control (CTS/RTS)
27
--              * Loop-back testing
28
 
29
--              Error-detection in receiver detects parity, framing
30
--              break and overrun errors. 
31
------------------------------------------------------------------------------
32
 
33
library IEEE;
34
use IEEE.std_logic_1164.all;
35
use IEEE.std_logic_unsigned."+";
36
use IEEE.std_logic_unsigned."-";
37
use work.leon_target.all;
38
use work.leon_config.all;
39
use work.peri_serial_comp.all;
40
use work.macro.all;
41
use work.amba.all;
42
--pragma translate_off
43
use ieee.std_logic_unsigned.conv_integer;
44
use STD.TEXTIO.all;
45
--pragma translate_on
46
 
47
entity uart is
48
  port (
49
    rst    : in  std_logic;
50
    clk    : in  std_logic;
51
    apbi   : in  apb_slv_in_type;
52
    apbo   : out apb_slv_out_type;
53
    uarti  : in  uart_in_type;
54
    uarto  : out uart_out_type
55
  );
56
end;
57
 
58
architecture rtl of uart is
59
 
60
 
61
type rxfsmtype is (idle, startbit, data, parity, stopbit);
62
type txfsmtype is (idle, data, parity, stopbit);
63
 
64
 
65
type uartregs is record
66
  rxen          :  std_logic;   -- receiver enabled
67
  txen          :  std_logic;   -- transmitter enabled
68
  rirqen        :  std_logic;   -- receiver irq enable
69
  tirqen        :  std_logic;   -- transmitter irq enable
70
  parsel        :  std_logic;   -- parity select
71
  paren         :  std_logic;   -- parity select
72
  flow          :  std_logic;   -- flow control enable
73
  loopb         :  std_logic;   -- loop back mode enable
74
  dready        :  std_logic;   -- data ready
75
  rsempty       :  std_logic;   -- receiver shift register empty (internal)
76
  tsempty       :  std_logic;   -- transmitter shift register empty
77
  thempty       :  std_logic;   -- transmitter hold register empty
78
  break         :  std_logic;   -- break detected
79
  ovf           :  std_logic;   -- receiver overflow
80
  parerr        :  std_logic;   -- parity error
81
  frame         :  std_logic;   -- framing error
82
  rtsn          :  std_logic;   -- request to send
83
  extclken      :  std_logic;   -- use external baud rate clock
84
  extclk        :  std_logic;   -- rising edge detect register
85
  rhold         :  std_logic_vector(7 downto 0);
86
  rshift        :  std_logic_vector(7 downto 0);
87
  tshift        :  std_logic_vector(10 downto 0);
88
  thold         :  std_logic_vector(7 downto 0);
89
 
90
  irq           :  std_logic;   -- tx/rx interrupt (internal)
91
  tpar          :  std_logic;   -- tx data parity (internal)
92
 
93
  txstate       :  txfsmtype;
94
 
95
  txclk         :  std_logic_vector(2 downto 0);  -- tx clock divider
96
  txtick        :  std_logic;   -- tx clock (internal)
97
 
98
 
99
  rxstate       :  rxfsmtype;
100
 
101
  rxclk         :  std_logic_vector(2 downto 0); -- rx clock divider
102
  rxdb          :  std_logic_vector(1 downto 0);  -- rx delay
103
  dpar          :  std_logic;   -- rx data parity (internal)
104
  rxtick        :  std_logic;   -- rx clock (internal)
105
 
106
  tick          :  std_logic;   -- rx clock (internal)
107
  scaler        :  std_logic_vector(11 downto 0);
108
  brate         :  std_logic_vector(11 downto 0);
109
  rxf           :  std_logic_vector(7 downto 0); --  rx data filtering buffer
110
 
111
end record;
112
 
113
 
114
signal r, rin : uartregs;
115
 
116
begin
117
 
118
  uartop : process(rst, r, apbi, uarti )
119
  variable rdata : std_logic_vector(31 downto 0);
120
  variable scaler : std_logic_vector(11 downto 0);
121
  variable rxclk, txclk : std_logic_vector(2 downto 0);
122
  variable rxd, ctsn : std_logic;
123
  variable v : uartregs;
124
--pragma translate_off
125
  variable L1 : line;
126
  variable CH : character;
127
  variable FIRST : boolean := true;
128
  variable pt : time := 0 ns;
129
--pragma translate_on
130
 
131
  begin
132
 
133
    v := r;
134
    v.irq := '0'; v.txtick := '0'; v.rxtick := '0'; v.tick := '0';
135
    rdata := (others => '0'); v.rxdb(1) := r.rxdb(0);
136
 
137
-- scaler
138
 
139
-- pragma translate_off
140
    if not is_x(r.scaler) then          -- avoid warnings at reset time
141
-- pragma translate_on
142
      scaler := r.scaler - 1;
143
-- pragma translate_off
144
    end if;
145
-- pragma translate_on
146
    if (r.rxen or r.txen) = '1' then
147
      v.scaler := scaler;
148
      v.tick := scaler(11) and not r.scaler(11);
149
      if v.tick = '1' then v.scaler := r.brate; end if;
150
    end if;
151
 
152
-- optional external uart clock
153
    v.extclk := uarti.scaler(3);
154
    if r.extclken = '1' then v.tick := r.extclk and not uarti.scaler(3); end if;
155
 
156
-- read/write registers
157
 
158
    case apbi.paddr(3 downto 2) is
159
    when "00" =>
160
      rdata(7 downto 0) := r.rhold;
161
      if (apbi.psel and apbi.penable and (not apbi.pwrite)) = '1' then
162
        v.dready := '0';
163
      end if;
164
    when "01" =>
165
      rdata(6 downto 0) := r.frame & r.parerr & r.ovf &
166
                r.break & r.thempty & r.tsempty & r.dready;
167
--pragma translate_off
168
      if DEBUGUART then rdata(2 downto 1) := "11"; end if;
169
--pragma translate_on
170
    when "10" =>
171
      rdata(8 downto 0) := r.extclken & r.loopb & r.flow & r.paren & r.parsel &
172
                r.tirqen & r.rirqen & r.txen & r.rxen;
173
    when others =>
174
      rdata(11 downto 0) := r.brate;
175
    end case;
176
 
177
    if (apbi.psel and apbi.penable and apbi.pwrite) = '1' then
178
      case apbi.paddr(3 downto 2) is
179
      when "01" =>
180
        v.frame  := apbi.pwdata(6);
181
        v.parerr := apbi.pwdata(5);
182
        v.ovf    := apbi.pwdata(4);
183
        v.break  := apbi.pwdata(3);
184
      when "10" =>
185
        v.extclken := apbi.pwdata(8);
186
        v.loopb  := apbi.pwdata(7);
187
        v.flow   := apbi.pwdata(6);
188
        v.paren  := apbi.pwdata(5);
189
        v.parsel := apbi.pwdata(4);
190
        v.tirqen := apbi.pwdata(3);
191
        v.rirqen := apbi.pwdata(2);
192
        v.txen   := apbi.pwdata(1);
193
        v.rxen   := apbi.pwdata(0);
194
      when "11" =>
195
        v.brate := apbi.pwdata(11 downto 0);
196
        v.scaler := apbi.pwdata(11 downto 0);
197
      when others =>
198
      end case;
199
    end if;
200
 
201
-- tx clock
202
 
203
-- pragma translate_off
204
    if not is_x(r.txclk) then           -- avoid warnings at reset time
205
-- pragma translate_on
206
      txclk := r.txclk + 1;
207
-- pragma translate_off
208
    else
209
      txclk := (others => 'X');
210
    end if;
211
-- pragma translate_on
212
    if r.tick = '1' then
213
      v.txclk := txclk;
214
      v.txtick := r.txclk(2) and not txclk(2);
215
    end if;
216
 
217
-- rx clock
218
 
219
-- pragma translate_off
220
    if not is_x(r.rxclk) then           -- avoid warnings at reset time
221
-- pragma translate_on
222
      rxclk := r.rxclk + 1;
223
-- pragma translate_off
224
    else
225
      rxclk := (others => 'X');
226
    end if;
227
-- pragma translate_on
228
    if r.tick = '1' then
229
      v.rxclk := rxclk;
230
      v.rxtick := r.rxclk(2) and not rxclk(2);
231
    end if;
232
 
233
-- filter rx data
234
 
235
    v.rxf := r.rxf(6 downto 0) & uarti.rxd;
236
    if ((r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) &
237
         r.rxf(7)) = r.rxf(6 downto 0))
238
    then v.rxdb(0) := r.rxf(7); end if;
239
 
240
-- loop-back mode
241
    if r.loopb = '1' then
242
      v.rxdb(0) := r.tshift(0); ctsn := r.dready and not r.rsempty;
243
    else
244
      ctsn := uarti.ctsn;
245
    end if;
246
    rxd := r.rxdb(0);
247
 
248
-- transmitter operation
249
 
250
    case r.txstate is
251
    when idle =>        -- idle state
252
      if (r.txtick = '1') then v.tsempty := '1'; end if;
253
      if ((r.txen and (not r.thempty) and r.txtick) and
254
          ((not ctsn) or not r.flow)) = '1' then
255
        v.tshift := "10" & r.thold & '0'; v.txstate := data;
256
        v.tpar := r.parsel; v.irq := r.tirqen; v.thempty := '1';
257
        v.tsempty := '0'; v.txclk := "00" & r.tick; v.txtick := '0';
258
      end if;
259
    when data =>        -- transmitt data frame
260
      if r.txtick = '1' then
261
        v.tpar := r.tpar xor r.tshift(1);
262
        v.tshift := '1' & r.tshift(10 downto 1);
263
        if r.tshift(10 downto 1) = "1111111110" then
264
          if r.paren = '1' then
265
            v.tshift(0) := r.tpar; v.txstate := parity;
266
          else
267
            v.tshift(0) := '1'; v.txstate := stopbit;
268
          end if;
269
        end if;
270
      end if;
271
    when parity =>      -- transmitt parity bit
272
      if r.txtick = '1' then
273
        v.tshift := '1' & r.tshift(10 downto 1); v.txstate := stopbit;
274
      end if;
275
    when stopbit =>     -- transmitt stop bit
276
      if r.txtick = '1' then
277
        v.tshift := '1' & r.tshift(10 downto 1); v.txstate := idle;
278
      end if;
279
 
280
    end case;
281
 
282
-- writing of tx data register must be done after tx fsm to get correct
283
-- operation of thempty flag
284
 
285
    if (apbi.psel and apbi.penable and apbi.pwrite) = '1' then
286
      case apbi.paddr(3 downto 2) is
287
      when "00" =>
288
        v.thold := apbi.pwdata(7 downto 0); v.thempty := '0';
289
--pragma translate_off
290
        if DEBUGUART then
291
          if first then L1:= new string'(""); first := false; end if; --'
292
--        if (pt + 20 ns) < now then
293
          if apbi.penable'event then    --'
294
            CH := character'val(conv_integer(apbi.pwdata(7 downto 0))); --'
295
            if CH = CR then std.textio.writeline(OUTPUT, L1);
296
            elsif CH /= LF then
297
              std.textio.write(L1,CH);
298
            end if;
299
            pt := now;
300
          end if;
301
        end if;
302
--pragma translate_on
303
      when others => null;
304
      end case;
305
    end if;
306
 
307
-- receiver operation
308
 
309
    case r.rxstate is
310
    when idle =>        -- wait for start bit
311
      if ((not r.rsempty) and not r.dready) = '1' then
312
        v.rhold := r.rshift; v.rsempty := '1'; v.dready := '1';
313
      end if;
314
      if (r.rxen and r.rxdb(1) and (not rxd)) = '1' then
315
        v.rxstate := startbit; v.rshift := (others => '1'); v.rxclk := "100";
316
        if v.rsempty = '0' then v.ovf := '1'; end if;
317
        v.rsempty := '0'; v.rxtick := '0';
318
      end if;
319
    when startbit =>    -- check validity of start bit
320
      if r.rxtick = '1' then
321
        if rxd = '0' then
322
          v.rshift := rxd & r.rshift(7 downto 1); v.rxstate := data;
323
          v.dpar := r.parsel;
324
        else
325
          v.rxstate := idle;
326
        end if;
327
      end if;
328
    when data =>        -- receive data frame
329
      if r.rxtick = '1' then
330
        v.dpar := r.dpar xor rxd;
331
        v.rshift := rxd & r.rshift(7 downto 1);
332
        if r.rshift(0) = '0' then
333
          if r.paren = '1' then v.rxstate := parity;
334
          else
335
            v.rxstate := stopbit; v.dpar := '0';
336
          end if;
337
        end if;
338
      end if;
339
    when parity =>      -- receive parity bit
340
      if r.rxtick = '1' then
341
        v.dpar := r.dpar xor rxd;
342
        v.rxstate := stopbit;
343
      end if;
344
    when stopbit =>     -- receive stop bit
345
      if r.rxtick = '1' then
346
        v.irq := v.irq or r.rirqen; -- make sure no tx irqs are lost !
347
        if rxd = '1' then
348
          v.parerr := r.dpar; v.rsempty := r.dpar;
349
          if v.dready = '0' then
350
            v.rhold := r.rshift; v.rsempty := '1'; v.dready := not r.dpar;
351
          end if;
352
        else
353
          if r.rshift = "00000000" then
354
            v.break := '1';              -- break
355
          else
356
            v.frame := '1';              -- framing error
357
          end if;
358
          v.rsempty := '1';
359
        end if;
360
        v.rxstate := idle;
361
      end if;
362
 
363
    end case;
364
 
365
    if r.rxtick = '1' then
366
      v.rtsn := (r.dready and not r.rsempty) or r.loopb;
367
    end if;
368
 
369
-- reset operation
370
 
371
    if rst = '0' then
372
      v.frame := '0'; v.rsempty := '1';
373
      v.parerr := '0'; v.ovf := '0'; v.break := '0'; v.thempty := '1';
374
      v.tsempty := '1'; v.dready := '0'; v.txen := '0'; v.rxen := '0';
375
      v.txstate := idle; v.rxstate := idle; v.tshift(0) := '1';
376
      v.extclken := '0';
377
      if BOOTOPT /= memory then
378
        if EXTBAUD then v.brate := "0000" & uarti.scaler;
379
        else v.brate := std_logic_vector(UPRESC(11 downto 0)); end if;
380
        v.scaler := v.brate;
381
--      else
382
--        v.brate := (others => '0');
383
      end if;
384
-- pragma translate_off
385
--      v.scaler := (others => '0');    -- only need this for simulation
386
-- pragma translate_on
387
      v.rtsn := '1'; v.flow := '0';
388
      v.txclk := (others => '0'); v.rxclk := (others => '0');
389
    end if;
390
 
391
-- update registers
392
 
393
    rin <= v;
394
 
395
-- drive outputs
396
    uarto.txd <= r.tshift(0) or r.loopb;
397
    uarto.irq <= r.irq;
398
    uarto.flow <= r.flow;
399
    uarto.rtsn <= r.rtsn;
400
    uarto.txen <= r.txen;
401
    uarto.rxen <= r.rxen;
402
    apbo.prdata <= rdata;
403
 
404
  end process;
405
 
406
  regs : process(clk)
407
  begin if rising_edge(clk) then r <= rin; end if; end process;
408
 
409
 
410
end;

powered by: WebSVN 2.1.0

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