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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [esa/] [misc/] [l2uart.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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