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/] [gaisler/] [uart/] [dcom_uart.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) 2003, 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
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------
19
-- Entity:      dcom_uart
20
-- File:        dcom_uart.vhd
21
-- Author:      Jiri Gaisler - Gaisler Research
22
-- Description: Asynchronous UART with baud-rate detection.
23
------------------------------------------------------------------------------
24
 
25
library ieee;
26
use ieee.std_logic_1164.all;
27
library grlib;
28
use grlib.amba.all;
29
use grlib.stdlib.all;
30
use grlib.devices.all;
31
library gaisler;
32
use gaisler.libdcom.all;
33
use gaisler.uart.all;
34
--pragma translate_off
35
use std.textio.all;
36
--pragma translate_on
37
 
38
entity dcom_uart is
39
  generic (
40
    pindex : integer := 0;
41
    paddr  : integer := 0;
42
    pmask  : integer := 16#fff#
43
  );
44
  port (
45
    rst    : in  std_ulogic;
46
    clk    : in  std_ulogic;
47
    ui     : in  uart_in_type;
48
    uo     : out uart_out_type;
49
    apbi   : in  apb_slv_in_type;
50
    apbo   : out apb_slv_out_type;
51
    uarti  : in  dcom_uart_in_type;
52
    uarto  : out dcom_uart_out_type
53
  );
54
end;
55
 
56
architecture rtl of dcom_uart is
57
 
58
constant REVISION : integer := 0;
59
 
60
constant pconfig : apb_config_type := (
61
 
62
  1 => apb_iobar(paddr, pmask));
63
 
64
type rxfsmtype is (idle, startbit, data, stopbit);
65
type txfsmtype is (idle, data, stopbit);
66
 
67
type uartregs is record
68
  rxen          :  std_ulogic;  -- receiver enabled
69
  dready        :  std_ulogic;  -- data ready
70
  rsempty       :  std_ulogic;  -- receiver shift register empty (internal)
71
  tsempty       :  std_ulogic;  -- transmitter shift register empty
72
  thempty       :  std_ulogic;  -- transmitter hold register empty
73
  break         :  std_ulogic;  -- break detected
74
  ovf           :  std_ulogic;  -- receiver overflow
75
  frame         :  std_ulogic;  -- framing error
76
  rhold         :  std_logic_vector(7 downto 0);
77
  rshift        :  std_logic_vector(7 downto 0);
78
  tshift        :  std_logic_vector(10 downto 0);
79
  thold         :  std_logic_vector(7 downto 0);
80
  txstate       :  txfsmtype;
81
  txclk         :  std_logic_vector(2 downto 0);  -- tx clock divider
82
  txtick        :  std_ulogic;  -- tx clock (internal)
83
  rxstate       :  rxfsmtype;
84
  rxclk         :  std_logic_vector(2 downto 0); -- rx clock divider
85
  rxdb          :  std_ulogic;   -- rx data filtering buffer
86
  rxtick        :  std_ulogic;  -- rx clock (internal)
87
  tick          :  std_ulogic;  -- rx clock (internal)
88
  scaler        :  std_logic_vector(17 downto 0);
89
  brate         :  std_logic_vector(17 downto 0);
90
  tcnt          :  std_logic_vector(1 downto 0); -- autobaud counter
91
  rxdb2         :  std_ulogic;   -- delayed rx data
92
  rxf           :  std_logic_vector(7 downto 0); --  rx data filtering buffer
93
  fedge         :  std_ulogic;   -- rx falling edge
94
end record;
95
 
96
signal r, rin : uartregs;
97
 
98
begin
99
 
100
  uartop : process(rst, r, apbi, uarti, ui )
101
  variable rdata : std_logic_vector(31 downto 0);
102
  variable scaler : std_logic_vector(17 downto 0);
103
  variable rxclk, txclk : std_logic_vector(2 downto 0);
104
  variable irxd : std_ulogic;
105
  variable v : uartregs;
106
 
107
  begin
108
 
109
    v := r;
110
    v.txtick := '0'; v.rxtick := '0'; v.tick := '0'; rdata := (others => '0');
111
 
112
-- scaler
113
 
114
    if r.tcnt = "11" then scaler := r.scaler - 1;
115
    else scaler := r.scaler + 1; end if;
116
 
117
    v.rxdb2 := r.rxdb;
118
    if r.tcnt /= "11" then
119
      if (r.rxdb2 and not r.rxdb) = '1' then v.fedge := '1'; end if;
120
      if (r.fedge) = '1' then
121
        v.scaler := scaler;
122
        if (v.scaler(17) and not r.scaler(16)) = '1' then
123
          v.scaler := "111111111111111011";
124
          v.fedge := '0'; v.tcnt := "00";
125
        end if;
126
      end if;
127
      if (r.rxdb2 and r.fedge and not r.rxdb) = '1' then
128
        if (r.brate(17 downto 4)> r.scaler(17 downto 4)) then
129
          v.brate := r.scaler; v.tcnt := "00";
130
        end if;
131
        v.scaler := "111111111111111011";
132
        if (r.brate(17 downto 4) = r.scaler(17 downto 4)) then
133
          v.tcnt := r.tcnt + 1;
134
          if r.tcnt = "10" then
135
            v.brate := "0000" & r.scaler(17 downto 4);
136
            v.scaler := v.brate; v.rxen := '1';
137
          end if;
138
        end if;
139
      end if;
140
    else
141
      if (r.break and r.rxdb2) = '1' then
142
        v.scaler := "111111111111111011";
143
        v.brate := (others => '1'); v.tcnt := "00";
144
        v.break := '0'; v.rxen := '0';
145
      end if;
146
    end if;
147
 
148
    if r.rxen = '1' then
149
      v.scaler := scaler;
150
      v.tick := scaler(15) and not r.scaler(15);
151
      if v.tick = '1' then v.scaler := r.brate; end if;
152
    end if;
153
 
154
-- read/write registers
155
 
156
    if uarti.read = '1' then v.dready := '0'; end if;
157
 
158
    case apbi.paddr(3 downto 2) is
159
    when "01" =>
160
      rdata(6 downto 0) := r.frame & '0' & r.ovf &
161
                r.break & r.thempty & r.tsempty & r.dready;
162
    when "10" =>
163
      rdata(1 downto 0) := (r.tcnt(1) or r.tcnt(0)) & r.rxen;
164
    when others =>
165
      rdata(17 downto 0) := r.brate;
166
    end case;
167
 
168
    if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
169
      case apbi.paddr(3 downto 2) is
170
      when "01" =>
171
        v.frame  := apbi.pwdata(6);
172
        v.ovf    := apbi.pwdata(4);
173
        v.break  := apbi.pwdata(3);
174
      when "10" =>
175
        v.tcnt   := apbi.pwdata(1) & apbi.pwdata(1);
176
        v.rxen   := apbi.pwdata(0);
177
      when "11" =>
178
        v.brate := apbi.pwdata(17 downto 0);
179
        v.scaler := apbi.pwdata(17 downto 0);
180
      when others =>
181
      end case;
182
    end if;
183
 
184
-- tx clock
185
 
186
    txclk := r.txclk + 1;
187
    if r.tick = '1' then
188
      v.txclk := txclk; v.txtick := r.txclk(2) and not txclk(2);
189
    end if;
190
 
191
-- rx clock
192
 
193
    rxclk := r.rxclk + 1;
194
    if r.tick = '1' then
195
      v.rxclk := rxclk; v.rxtick := r.rxclk(2) and not rxclk(2);
196
    end if;
197
 
198
-- filter rx data
199
 
200
    v.rxf := r.rxf(6 downto 0) & ui.rxd;
201
    if ((r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) &
202
         r.rxf(7)) = r.rxf(6 downto 0))
203
    then v.rxdb := r.rxf(7); end if;
204
 
205
    irxd := r.rxdb;
206
 
207
-- transmitter operation
208
 
209
    case r.txstate is
210
    when idle =>        -- idle state
211
      if (r.txtick = '1') then v.tsempty := '1'; end if;
212
      if (r.rxen and (not r.thempty) and r.txtick) = '1' then
213
        v.tshift := "10" & r.thold & '0'; v.txstate := data;
214
        v.thempty := '1';
215
        v.tsempty := '0'; v.txclk := "00" & r.tick; v.txtick := '0';
216
      end if;
217
    when data =>        -- transmitt data frame
218
      if r.txtick = '1' then
219
        v.tshift := '1' & r.tshift(10 downto 1);
220
        if r.tshift(10 downto 1) = "1111111110" then
221
        v.tshift(0) := '1'; v.txstate := stopbit;
222
        end if;
223
      end if;
224
    when stopbit =>     -- transmitt stop bit
225
      if r.txtick = '1' then
226
        v.tshift := '1' & r.tshift(10 downto 1); v.txstate := idle;
227
      end if;
228
 
229
    end case;
230
 
231
-- writing of tx data register must be done after tx fsm to get correct
232
-- operation of thempty flag
233
 
234
    if uarti.write = '1' then
235
      v.thold := uarti.data(7 downto 0); v.thempty := '0';
236
    end if;
237
 
238
-- receiver operation
239
 
240
    case r.rxstate is
241
    when idle =>        -- wait for start bit
242
      if ((not r.rsempty) and not r.dready) = '1' then
243
        v.rhold := r.rshift; v.rsempty := '1'; v.dready := '1';
244
      end if;
245
      if (r.rxen and r.rxdb2 and (not irxd)) = '1' then
246
        v.rxstate := startbit; v.rshift := (others => '1'); v.rxclk := "100";
247
        if v.rsempty = '0' then v.ovf := '1'; end if;
248
        v.rsempty := '0'; v.rxtick := '0';
249
      end if;
250
    when startbit =>    -- check validity of start bit
251
      if r.rxtick = '1' then
252
        if irxd = '0' then
253
          v.rshift := irxd & r.rshift(7 downto 1); v.rxstate := data;
254
        else
255
          v.rxstate := idle;
256
        end if;
257
      end if;
258
    when data =>        -- receive data frame
259
      if r.rxtick = '1' then
260
        v.rshift := irxd & r.rshift(7 downto 1);
261
        if r.rshift(0) = '0' then
262
        v.rxstate := stopbit;
263
        end if;
264
      end if;
265
    when stopbit =>     -- receive stop bit
266
      if r.rxtick = '1' then
267
        if irxd = '1' then
268
          v.rsempty := '0';
269
          if v.dready = '0' then
270
            v.rhold := r.rshift; v.rsempty := '1'; v.dready := '1';
271
          end if;
272
        else
273
          if r.rshift = "00000000" then
274
            v.break := '1';              -- break
275
          else
276
            v.frame := '1';              -- framing error
277
          end if;
278
          v.rsempty := '1';
279
        end if;
280
        v.rxstate := idle;
281
      end if;
282
 
283
    end case;
284
 
285
-- reset operation
286
 
287
    if rst = '0' then
288
      v.frame := '0'; v.rsempty := '1';
289
      v.ovf := '0'; v.break := '0'; v.thempty := '1';
290
      v.tsempty := '1'; v.dready := '0'; v.fedge := '0';
291
      v.txstate := idle; v.rxstate := idle; v.tshift(0) := '1';
292
      v.scaler := "111111111111111011"; v.brate := (others => '1');
293
      v.rxen := '0'; v.tcnt := "00";
294
      v.txclk := (others => '0'); v.rxclk := (others => '0');
295
    end if;
296
 
297
-- update registers
298
 
299
    rin <= v;
300
 
301
-- drive outputs
302
    uo.txd <= r.tshift(0);
303
    uo.scaler <= r.brate;
304
    uo.rtsn <= '0';
305
    uarto.dready <= r.dready;
306
    uarto.tsempty <= r.tsempty;
307
    uarto.thempty <= r.thempty;
308
    uarto.lock <= r.tcnt(1) and  r.tcnt(0);
309
    uarto.enable <= r.rxen;
310
    uarto.data <= r.rhold;
311
 
312
    apbo.prdata <= rdata;
313
 
314
  end process;
315
 
316
  apbo.pirq <= (others => '0');
317
  apbo.pconfig <= pconfig;
318
  apbo.pindex <= pindex;
319
 
320
  regs : process(clk)
321
  begin if rising_edge(clk) then r <= rin; end if; end process;
322
 
323
end;

powered by: WebSVN 2.1.0

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