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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [misclib/] [nasti_uart.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
-----------------------------------------------------------------------------
2
--! @file
3
--! @copyright  Copyright 2015 GNSS Sensor Ltd. All right reserved.
4
--! @author     Sergey Khabarov - sergeykhbr@gmail.com
5
--! @brief      RS-232 UART with the AXI4 interface.
6
------------------------------------------------------------------------------
7
 
8
library ieee;
9
use ieee.std_logic_1164.all;
10
library commonlib;
11
use commonlib.types_common.all;
12
--! AMBA system bus specific library.
13
library ambalib;
14
--! AXI4 configuration constants.
15
use ambalib.types_amba4.all;
16
library misclib;
17
use misclib.types_misc.all;
18
 
19
entity nasti_uart is
20
  generic (
21
    xaddr   : integer := 0;
22
    xmask   : integer := 16#fffff#;
23
    xirq    : integer := 0;
24
    fifosz  : integer := 16
25
  );
26
  port (
27
    clk    : in  std_logic;
28
    nrst   : in  std_logic;
29
    cfg    : out  nasti_slave_config_type;
30
    i_uart : in  uart_in_type;
31
    o_uart : out uart_out_type;
32
    i_axi  : in  nasti_slave_in_type;
33
    o_axi  : out nasti_slave_out_type;
34
    o_irq  : out std_logic
35
  );
36
end;
37
 
38
architecture arch_nasti_uart of nasti_uart is
39
 
40
  constant xconfig : nasti_slave_config_type := (
41
     descrtype => PNP_CFG_TYPE_SLAVE,
42
     descrsize => PNP_CFG_SLAVE_DESCR_BYTES,
43
     irq_idx => xirq,
44
     xaddr => conv_std_logic_vector(xaddr, CFG_NASTI_CFG_ADDR_BITS),
45
     xmask => conv_std_logic_vector(xmask, CFG_NASTI_CFG_ADDR_BITS),
46
     vid => VENDOR_GNSSSENSOR,
47
     did => GNSSSENSOR_UART
48
  );
49
 
50
  type fifo_type is array (0 to fifosz-1) of std_logic_vector(7 downto 0);
51
  type state_type is (idle, startbit, data, parity, stopbit);
52
 
53
  type bank_type is record
54
        tx_state  : state_type;
55
        tx_fifo   : fifo_type;
56
        tx_wr_cnt : std_logic_vector(log2(fifosz)-1 downto 0);
57
        tx_rd_cnt : std_logic_vector(log2(fifosz)-1 downto 0);
58
        tx_byte_cnt : std_logic_vector(log2(fifosz)-1 downto 0);
59
        tx_shift  : std_logic_vector(10 downto 0); --! stopbit=1,parity=xor,data[7:0],startbit=0
60
        tx_data_cnt : integer range 0 to 11;
61
        tx_scaler_cnt : integer;
62
        tx_level : std_logic;
63
        tx_irq_thresh : std_logic_vector(log2(fifosz)-1 downto 0);
64
        tx_more_thresh : std_logic_vector(1 downto 0);
65
 
66
        rx_state  : state_type;
67
        rx_fifo   : fifo_type;
68
        rx_wr_cnt : std_logic_vector(log2(fifosz)-1 downto 0);
69
        rx_rd_cnt : std_logic_vector(log2(fifosz)-1 downto 0);
70
        rx_byte_cnt : std_logic_vector(log2(fifosz)-1 downto 0);
71
        rx_shift  : std_logic_vector(7 downto 0);
72
        rx_data_cnt : integer range 0 to 7;
73
        rx_scaler_cnt : integer;
74
        rx_level : std_logic;
75
        rx_irq_thresh : std_logic_vector(log2(fifosz)-1 downto 0);
76
        rx_more_thresh : std_logic_vector(1 downto 0);
77
 
78
        scaler : integer;
79
        err_parity : std_logic;
80
        err_stopbit : std_logic;
81
        parity_bit : std_logic;
82
        tx_irq_ena : std_logic;
83
        rx_irq_ena : std_logic;
84
  end record;
85
 
86
  type registers is record
87
    bank_axi : nasti_slave_bank_type;
88
    bank0 : bank_type;
89
  end record;
90
 
91
signal r, rin : registers;
92
 
93
begin
94
 
95
  comblogic : process(nrst, i_uart, i_axi, r)
96
    variable v : registers;
97
    variable rdata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0);
98
    variable wstrb : std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0);
99
    variable tmp : std_logic_vector(31 downto 0);
100
 
101
    variable posedge_flag : std_logic;
102
    variable negedge_flag : std_logic;
103
    variable tx_fifo_empty : std_logic;
104
    variable tx_fifo_full : std_logic;
105
    variable rx_fifo_empty : std_logic;
106
    variable rx_fifo_full : std_logic;
107
    variable t_tx, t_rx : std_logic_vector(7 downto 0);
108
    variable par : std_logic;
109
    variable irq_ena : std_logic;
110
  begin
111
 
112
    v := r;
113
 
114
    procedureAxi4(i_axi, xconfig, r.bank_axi, v.bank_axi);
115
 
116
    -- Check FIFOs counters with thresholds:
117
    v.bank0.tx_more_thresh := r.bank0.tx_more_thresh(0) & '0';
118
    if r.bank0.tx_byte_cnt > r.bank0.tx_irq_thresh then
119
      v.bank0.tx_more_thresh(0) := '1';
120
    end if;
121
 
122
    v.bank0.rx_more_thresh := r.bank0.rx_more_thresh(0) & '0';
123
    if r.bank0.rx_byte_cnt > r.bank0.rx_irq_thresh then
124
      v.bank0.rx_more_thresh(0) := '1';
125
    end if;
126
 
127
    irq_ena := '0';
128
    if (r.bank0.tx_more_thresh(1) and not r.bank0.tx_more_thresh(0)) = '1' then
129
       irq_ena := r.bank0.tx_irq_ena;
130
    end if;
131
    if (not r.bank0.rx_more_thresh(1) and r.bank0.rx_more_thresh(0)) = '1' then
132
       irq_ena := irq_ena or r.bank0.rx_irq_ena;
133
    end if;
134
 
135
    -- system bus clock scaler to baudrate:
136
    posedge_flag := '0';
137
    negedge_flag := '0';
138
    if r.bank0.scaler /= 0 then
139
        if r.bank0.tx_scaler_cnt = (r.bank0.scaler-1) then
140
            v.bank0.tx_scaler_cnt := 0;
141
            v.bank0.tx_level := not r.bank0.tx_level;
142
            posedge_flag := not r.bank0.tx_level;
143
        else
144
            v.bank0.tx_scaler_cnt := r.bank0.tx_scaler_cnt + 1;
145
        end if;
146
 
147
        if r.bank0.rx_state = idle and i_uart.rd = '1' then
148
            v.bank0.rx_scaler_cnt := 0;
149
            v.bank0.rx_level := '1';
150
        elsif r.bank0.rx_scaler_cnt = (r.bank0.scaler-1) then
151
            v.bank0.rx_scaler_cnt := 0;
152
            v.bank0.rx_level := not r.bank0.rx_level;
153
            negedge_flag := r.bank0.rx_level;
154
        else
155
            v.bank0.rx_scaler_cnt := r.bank0.rx_scaler_cnt + 1;
156
        end if;
157
    end if;
158
 
159
    -- Transmitter's FIFO:
160
    tx_fifo_full := '0';
161
    if (r.bank0.tx_wr_cnt + 1) = r.bank0.tx_rd_cnt then
162
        tx_fifo_full := '1';
163
    end if;
164
    tx_fifo_empty := '0';
165
    if r.bank0.tx_rd_cnt = r.bank0.tx_wr_cnt then
166
        tx_fifo_empty := '1';
167
        v.bank0.tx_byte_cnt := (others => '0');
168
    end if;
169
 
170
    -- Receiver's FIFO:
171
    rx_fifo_full := '0';
172
    if (r.bank0.rx_wr_cnt + 1) = r.bank0.rx_rd_cnt then
173
        rx_fifo_full := '1';
174
    end if;
175
    rx_fifo_empty := '0';
176
    if r.bank0.rx_rd_cnt = r.bank0.rx_wr_cnt then
177
        rx_fifo_empty := '1';
178
        v.bank0.rx_byte_cnt := (others => '0');
179
    end if;
180
 
181
    -- Transmitter's state machine:
182
    if i_uart.cts = '1' and posedge_flag = '1' then
183
        case r.bank0.tx_state is
184
        when idle =>
185
            if tx_fifo_empty = '0' then
186
                -- stopbit=1,parity=xor,data[7:0],startbit=0
187
                t_tx := r.bank0.tx_fifo(conv_integer(r.bank0.tx_rd_cnt));
188
                if r.bank0.parity_bit = '1' then
189
                    par := t_tx(7) xor t_tx(6) xor t_tx(5) xor t_tx(4)
190
                         xor t_tx(3) xor t_tx(2) xor t_tx(1) xor t_tx(0);
191
                    v.bank0.tx_shift := '1' & par & t_tx & '0';
192
                else
193
                    v.bank0.tx_shift := "11" & t_tx & '0';
194
                end if;
195
 
196
                v.bank0.tx_state := startbit;
197
                v.bank0.tx_rd_cnt := r.bank0.tx_rd_cnt + 1;
198
                v.bank0.tx_byte_cnt := r.bank0.tx_byte_cnt - 1;
199
                v.bank0.tx_data_cnt := 0;
200
            end if;
201
        when startbit =>
202
            v.bank0.tx_state := data;
203
        when data =>
204
            if r.bank0.tx_data_cnt = 8 then
205
                if r.bank0.parity_bit = '1' then
206
                    v.bank0.tx_state := parity;
207
                else
208
                    v.bank0.tx_state := stopbit;
209
                end if;
210
            end if;
211
        when parity =>
212
            v.bank0.tx_state := stopbit;
213
        when stopbit =>
214
            v.bank0.tx_state := idle;
215
        when others =>
216
        end case;
217
 
218
        if r.bank0.tx_state /= idle then
219
            v.bank0.tx_data_cnt := r.bank0.tx_data_cnt + 1;
220
            v.bank0.tx_shift := '1' & r.bank0.tx_shift(10 downto 1);
221
        end if;
222
    end if;
223
 
224
    --! Receiver's state machine:
225
    if negedge_flag = '1' then
226
        case r.bank0.rx_state is
227
        when idle =>
228
            if i_uart.rd = '0' then
229
                v.bank0.rx_state := data;
230
                v.bank0.rx_shift := (others => '0');
231
                v.bank0.rx_data_cnt := 0;
232
            end if;
233
        when data =>
234
            v.bank0.rx_shift := i_uart.rd & r.bank0.rx_shift(7 downto 1);
235
            if r.bank0.rx_data_cnt = 7 then
236
                if r.bank0.parity_bit = '1' then
237
                    v.bank0.rx_state := parity;
238
                else
239
                    v.bank0.rx_state := stopbit;
240
                end if;
241
            else
242
                v.bank0.rx_data_cnt := r.bank0.rx_data_cnt + 1;
243
            end if;
244
        when parity =>
245
            t_rx := r.bank0.rx_shift;
246
            par := t_rx(7) xor t_rx(6) xor t_rx(5) xor t_rx(4)
247
               xor t_rx(3) xor t_rx(2) xor t_rx(1) xor t_rx(0);
248
            if par = i_uart.rd then
249
                v.bank0.err_parity := '0';
250
            else
251
                v.bank0.err_parity := '1';
252
            end if;
253
            v.bank0.rx_state := stopbit;
254
        when stopbit =>
255
            if i_uart.rd = '0' then
256
                v.bank0.err_stopbit := '1';
257
            else
258
                v.bank0.err_stopbit := '0';
259
            end if;
260
            if rx_fifo_full = '0' then
261
                v.bank0.rx_fifo(conv_integer(r.bank0.rx_wr_cnt)) := r.bank0.rx_shift;
262
                v.bank0.rx_wr_cnt := r.bank0.rx_wr_cnt + 1;
263
                v.bank0.rx_byte_cnt := r.bank0.rx_byte_cnt + 1;
264
            end if;
265
            v.bank0.rx_state := idle;
266
        when others =>
267
        end case;
268
    end if;
269
 
270
 
271
    o_uart.rts <= '1';
272
    if r.bank0.tx_state = idle then
273
        o_uart.td <= '1';
274
    else
275
        o_uart.td <= r.bank0.tx_shift(0);
276
    end if;
277
 
278
 
279
    for n in 0 to CFG_WORDS_ON_BUS-1 loop
280
 
281
       tmp := (others => '0');
282
       case conv_integer(r.bank_axi.raddr(n)(11 downto 2)) is
283
          when 0 =>
284
                tmp(1 downto 0) := tx_fifo_empty & tx_fifo_full;
285
                tmp(5 downto 4) := rx_fifo_empty & rx_fifo_full;
286
                tmp(9 downto 8) := r.bank0.err_stopbit & r.bank0.err_parity;
287
                tmp(13) := r.bank0.rx_irq_ena;
288
                tmp(14) := r.bank0.tx_irq_ena;
289
                tmp(15) := r.bank0.parity_bit;
290
          when 1 =>
291
                tmp := conv_std_logic_vector(r.bank0.scaler,32);
292
          when 4 =>
293
                if rx_fifo_empty = '0' and r.bank_axi.rstate = rtrans then
294
                    tmp(7 downto 0) := r.bank0.rx_fifo(conv_integer(r.bank0.rx_rd_cnt));
295
                    v.bank0.rx_rd_cnt := r.bank0.rx_rd_cnt + 1;
296
                    v.bank0.rx_byte_cnt := r.bank0.rx_byte_cnt - 1;
297
                end if;
298
          when others =>
299
       end case;
300
       rdata(8*CFG_ALIGN_BYTES*(n+1)-1 downto 8*CFG_ALIGN_BYTES*n) := tmp;
301
    end loop;
302
 
303
 
304
    if i_axi.w_valid = '1' and
305
       r.bank_axi.wstate = wtrans and
306
       r.bank_axi.wresp = NASTI_RESP_OKAY then
307
 
308
      wstrb := i_axi.w_strb;
309
      for n in 0 to CFG_WORDS_ON_BUS-1 loop
310
 
311
         if conv_integer(wstrb(CFG_ALIGN_BYTES*(n+1)-1 downto CFG_ALIGN_BYTES*n)) /= 0 then
312
           tmp := i_axi.w_data(8*CFG_ALIGN_BYTES*(n+1)-1 downto 8*CFG_ALIGN_BYTES*n);
313
           case conv_integer(r.bank_axi.waddr(n)(11 downto 2)) is
314
             when 0 =>
315
                    v.bank0.parity_bit := tmp(15);
316
                    v.bank0.tx_irq_ena := tmp(14);
317
                    v.bank0.rx_irq_ena := tmp(13);
318
             when 1 =>
319
                    v.bank0.scaler     := conv_integer(tmp);
320
                    v.bank0.rx_scaler_cnt := 0;
321
                    v.bank0.tx_scaler_cnt := 0;
322
             when 4 =>
323
                    if tx_fifo_full = '0' then
324
                        v.bank0.tx_fifo(conv_integer(r.bank0.tx_wr_cnt)) := tmp(7 downto 0);
325
                        v.bank0.tx_wr_cnt := r.bank0.tx_wr_cnt + 1;
326
                        v.bank0.tx_byte_cnt := r.bank0.tx_byte_cnt + 1;
327
                    end if;
328
             when others =>
329
           end case;
330
         end if;
331
      end loop;
332
    end if;
333
 
334
    if nrst = '0' then
335
        v.bank_axi := NASTI_SLAVE_BANK_RESET;
336
        v.bank0.tx_state := idle;
337
        v.bank0.tx_level := '0';
338
        v.bank0.tx_scaler_cnt := 0;
339
        v.bank0.tx_rd_cnt := (others => '0');
340
        v.bank0.tx_wr_cnt := (others => '0');
341
        v.bank0.tx_byte_cnt := (others => '0');
342
        v.bank0.tx_irq_thresh := (others => '0');
343
        v.bank0.tx_more_thresh := (others => '0');
344
 
345
        v.bank0.rx_state := idle;
346
        v.bank0.rx_level := '1';
347
        v.bank0.rx_scaler_cnt := 0;
348
        v.bank0.rx_rd_cnt := (others => '0');
349
        v.bank0.rx_wr_cnt := (others => '0');
350
        v.bank0.rx_byte_cnt := (others => '0');
351
        v.bank0.rx_irq_thresh := (others => '0');
352
        v.bank0.rx_more_thresh := (others => '0');
353
 
354
        v.bank0.scaler := 0;
355
        v.bank0.err_parity := '0';
356
        v.bank0.err_stopbit := '0';
357
        v.bank0.parity_bit := '0';
358
        v.bank0.tx_irq_ena := '1';
359
        v.bank0.rx_irq_ena := '1';
360
    end if;
361
 
362
    o_axi <= functionAxi4Output(r.bank_axi, rdata);
363
    o_irq <= irq_ena;
364
    rin <= v;
365
  end process;
366
 
367
  cfg <= xconfig;
368
 
369
  -- registers:
370
  regs : process(clk)
371
  begin
372
     if rising_edge(clk) then
373
        r <= rin;
374
     end if;
375
  end process;
376
 
377
end;

powered by: WebSVN 2.1.0

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