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/] [misc/] [spictrl.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:     spictrl
20
-- File:       spictrl.vhd
21
-- Author:     Jan Andersson - Gaisler Research AB
22
--             jan@gaisler.com
23
--
24
-- Description: SPI controller with an interface compatible with MPC83xx SPI.
25
--              Relies on APB's wait state between back-to-back transfers.
26
--
27
-- Revision 1 of this core introduces 3-wire mode. The core can be placed in 3-wire
28
-- mode by writing bit 15 in the mode register.
29
 
30
library ieee;
31
use ieee.numeric_std.all;
32
use ieee.std_logic_1164.all;
33
 
34
library grlib;
35
use grlib.amba.all;
36
use grlib.devices.all;
37
use grlib.stdlib.all;
38
library gaisler;
39
use gaisler.misc.all;
40
 
41
entity spictrl is
42
  generic (
43
    -- APB generics
44
    pindex : integer := 0;                -- slave bus index
45
    paddr  : integer := 0;
46
    pmask  : integer := 16#fff#;
47
    pirq   : integer := 0;                -- interrupt index
48
 
49
    -- SPI controller configuration
50
    fdepth    : integer range 1 to 7  := 1;  -- FIFO depth is 2^fdepth
51
    slvselen  : integer range 0 to 1  := 0;  -- Slave select register enable
52
    slvselsz  : integer range 1 to 32 := 1;  -- Number of slave select signals
53
    oepol     : integer range 0 to 1  := 0); -- Output enable polarity 
54
  port (
55
    rstn   : in std_ulogic;
56
    clk    : in std_ulogic;
57
 
58
    -- APB signals
59
    apbi   : in  apb_slv_in_type;
60
    apbo   : out apb_slv_out_type;
61
 
62
    -- SPI signals
63
    spii   : in  spi_in_type;
64
    spio   : out spi_out_type;
65
    slvsel : out std_logic_vector((slvselsz-1) downto 0)
66
    );
67
end entity spictrl;
68
 
69
architecture rtl of spictrl is
70
 
71
  -----------------------------------------------------------------------------
72
  -- Constants
73
  -----------------------------------------------------------------------------
74
  constant SPICTRL_REV : integer := 1;
75
 
76
  constant PCONFIG : apb_config_type := (
77
 
78
  1 => apb_iobar(paddr, pmask));
79
 
80
  constant OEPOL_LEVEL : std_ulogic := conv_std_logic(oepol = 1);
81
 
82
 
83
  constant OUTPUT : std_ulogic := OEPOL_LEVEL;      -- Enable outputs
84
  constant INPUT : std_ulogic := not OEPOL_LEVEL;   -- Tri-state outputs
85
 
86
  constant FIFO_DEPTH  : integer := 2**fdepth;
87
  constant SLVSEL_EN   : integer := slvselen;
88
  constant SLVSEL_SZ   : integer := slvselsz;
89
 
90
  constant CAP_ADDR    : std_logic_vector(7 downto 2) := "000000";  -- 0x00
91
 
92
  constant MODE_ADDR   : std_logic_vector(7 downto 2) := "001000";  -- 0x20
93
  constant EVENT_ADDR  : std_logic_vector(7 downto 2) := "001001";  -- 0x24
94
  constant MASK_ADDR   : std_logic_vector(7 downto 2) := "001010";  -- 0x28
95
  constant COM_ADDR    : std_logic_vector(7 downto 2) := "001011";  -- 0x2C
96
  constant TD_ADDR     : std_logic_vector(7 downto 2) := "001100";  -- 0x30
97
  constant RD_ADDR     : std_logic_vector(7 downto 2) := "001101";  -- 0x34
98
  constant SLVSEL_ADDR : std_logic_vector(7 downto 2) := "001110";  -- 0x38
99
 
100
  constant SPICTRLCAPREG : std_logic_vector(31 downto 0) :=
101
    conv_std_logic_vector(SLVSEL_SZ,8) & conv_std_logic_vector(SLVSEL_EN,8) &
102
    conv_std_logic_vector(FIFO_DEPTH,8) & conv_std_logic_vector(SPICTRL_REV,8);
103
 
104
  -----------------------------------------------------------------------------
105
  -- Types
106
  -----------------------------------------------------------------------------
107
  type spi_mode_rec is record           -- SPI Mode register
108
    loopb : std_ulogic;  -- loopback mode
109
    cpol  : std_ulogic;  -- clock polarity
110
    cpha  : std_ulogic;  -- clock phase
111
    div16 : std_ulogic;  -- Divide by 16
112
    rev   : std_ulogic;  -- Reverse data mode
113
    ms    : std_ulogic;  -- Master/slave
114
    en    : std_ulogic;  -- Enable SPI
115
    len   : std_logic_vector(3 downto 0);  -- Bits per character
116
    pm    : std_logic_vector(3 downto 0);  -- Prescale modulus
117
    tw    : std_ulogic;  -- 3-wire mode 
118
    cg    : std_logic_vector(4 downto 0);  -- Clock gap
119
  end record;
120
 
121
  type spi_em_rec is record             -- SPI Event and Mask registers
122
    lt  : std_ulogic;  -- last character transmitted
123
    ov  : std_ulogic;  -- slave/master overrun
124
    un  : std_ulogic;  -- slave/master underrun
125
    mme : std_ulogic;  -- Multiple-master error
126
    ne  : std_ulogic;  -- Not empty
127
    nf  : std_ulogic;  -- Not full
128
  end record;
129
 
130
  type spi_fifo is array (0 to (FIFO_DEPTH-1)) of std_logic_vector(31 downto 0);
131
 
132
  -- Two stage synchronizers on each input coming from off-chip
133
  type spi_in_array is array (1 downto 0) of spi_in_type;
134
 
135
  type spi_reg_type is record
136
    -- SPI registers
137
    mode     : spi_mode_rec;  -- Mode register
138
    event    : spi_em_rec;    -- Event register
139
    mask     : spi_em_rec;    -- Mask register
140
    lst      : std_ulogic;    -- Only field on command register
141
    td       : std_logic_vector(31 downto 0);  -- Transmit register
142
    rd       : std_logic_vector(31 downto 0);  -- Receive register
143
    slvsel   : std_logic_vector((SLVSEL_SZ-1) downto 0);  -- Slave select register
144
    --
145
    uf       : std_ulogic;    -- Slave in underflow condition 
146
    ov       : std_ulogic;    -- Receive overflow condition 
147
    td_occ   : std_ulogic;    -- Transmit register occupied
148
    rd_free  : std_ulogic;    -- Receive register free (empty)
149
    txfifo   : spi_fifo;      -- Transmit data FIFO
150
    rxfifo   : spi_fifo;      -- Receive data FIFO
151
    toggle   : std_ulogic;    -- SCK has toggled 
152
    sc       : std_ulogic;    -- Sample/Change
153
    psck     : std_ulogic;    -- Previous value of SC
154
    running  : std_ulogic;
155
    twdir    : std_ulogic;    -- Direction in 3-wire mode
156
    -- counters
157
    tfreecnt : integer range 0 to FIFO_DEPTH; -- free td fifo slots
158
    rfreecnt : integer range 0 to FIFO_DEPTH; -- free td fifo slots
159
    tdfi     : integer range 0 to (FIFO_DEPTH-1);  -- First tx queue element
160
    rdfi     : integer range 0 to (FIFO_DEPTH-1);  -- First rx queue element
161
    tdli     : integer range 0 to (FIFO_DEPTH-1);  -- Last tx queue element
162
    rdli     : integer range 0 to (FIFO_DEPTH-1);  -- Last rx queue element
163
    bitcnt   : integer range 0 to 31;  -- Current bit
164
    divcnt   : unsigned(9 downto 0);   -- Clock scaler
165
    cgcnt    : unsigned(5 downto 0);   -- Clock gap counter
166
    --
167
    irq      :  std_ulogic;
168
    -- Sync registers for inputs
169
    spii     : spi_in_array;
170
    -- Output
171
    spio     : spi_out_type;
172
 end record;
173
 
174
  -----------------------------------------------------------------------------
175
  -- Sub programs
176
  -----------------------------------------------------------------------------
177
  -- Returns an integer containing the character length - 1 in bits as selected
178
  -- by the Mode field LEN. 
179
  function spilen (
180
    len : std_logic_vector(3 downto 0))
181
    return std_logic_vector is
182
  begin  -- spilen
183
    if len = zero32(3 downto 0) then
184
      return "11111";
185
    else
186
      return "0" & len;
187
    end if;
188
  end spilen;
189
 
190
  -- Write clear
191
  procedure wc (
192
    reg_o : out std_ulogic;
193
    reg_i : in  std_ulogic;
194
    b     : in  std_ulogic) is
195
  begin
196
    reg_o := reg_i and not b;
197
  end procedure wc;
198
 
199
  -- Reverses string. After this function has been called the first bit
200
  -- to send is always at position 0.
201
  function reverse(
202
    data : std_logic_vector)
203
    return std_logic_vector is
204
    variable rdata: std_logic_vector(data'reverse_range);
205
  begin
206
    for i in data'range loop
207
      rdata(i) := data(i);
208
    end loop;
209
    return rdata;
210
  end function reverse;
211
 
212
  -- Performs a HWORD swap if len /= 0
213
  function condhwordswap (
214
    data : std_logic_vector(31 downto 0);
215
    len  : std_logic_vector(4 downto 0);
216
    rev  : std_ulogic)
217
    return std_logic_vector is
218
    variable rdata : std_logic_vector(31 downto 0);
219
  begin  -- condhwordswap
220
    if len = one32(4 downto 0) then
221
      rdata := data;
222
    else
223
      rdata := data(15 downto 0) & data(31 downto 16);
224
    end if;
225
    return rdata;
226
  end condhwordswap;
227
 
228
  -- Zeroes out unused part of receive vector.
229
  function select_data (
230
    data : std_logic_vector(31 downto 0);
231
    len  : std_logic_vector(4 downto 0))
232
    return std_logic_vector is
233
    variable rdata : std_logic_vector(31 downto 0) := (others => '0');
234
    variable length : integer range 0 to 31 := conv_integer(len);
235
  begin  -- select_data
236
    -- Quartus can not handle variable ranges
237
    -- rdata(conv_integer(len) downto 0) := data(conv_integer(len) downto 0);
238
    case length is
239
      when 31 => rdata := data;
240
      when 30 => rdata(30 downto 0) := data(30 downto 0);
241
      when 29 => rdata(29 downto 0) := data(29 downto 0);
242
      when 28 => rdata(28 downto 0) := data(28 downto 0);
243
      when 27 => rdata(27 downto 0) := data(27 downto 0);
244
      when 26 => rdata(26 downto 0) := data(26 downto 0);
245
      when 25 => rdata(25 downto 0) := data(25 downto 0);
246
      when 24 => rdata(24 downto 0) := data(24 downto 0);
247
      when 23 => rdata(23 downto 0) := data(23 downto 0);
248
      when 22 => rdata(22 downto 0) := data(22 downto 0);
249
      when 21 => rdata(21 downto 0) := data(21 downto 0);
250
      when 20 => rdata(20 downto 0) := data(20 downto 0);
251
      when 19 => rdata(19 downto 0) := data(19 downto 0);
252
      when 18 => rdata(18 downto 0) := data(18 downto 0);
253
      when 17 => rdata(17 downto 0) := data(17 downto 0);
254
      when 16 => rdata(16 downto 0) := data(16 downto 0);
255
      when 15 => rdata(15 downto 0) := data(15 downto 0);
256
      when 14 => rdata(14 downto 0) := data(14 downto 0);
257
      when 13 => rdata(13 downto 0) := data(13 downto 0);
258
      when 12 => rdata(12 downto 0) := data(12 downto 0);
259
      when 11 => rdata(11 downto 0) := data(11 downto 0);
260
      when 10 => rdata(10 downto 0) := data(10 downto 0);
261
      when 9 => rdata(9 downto 0) := data(9 downto 0);
262
      when 8 => rdata(8 downto 0) := data(8 downto 0);
263
      when 7 => rdata(7 downto 0) := data(7 downto 0);
264
      when 6 => rdata(6 downto 0) := data(6 downto 0);
265
      when 5 => rdata(5 downto 0) := data(5 downto 0);
266
      when 4 => rdata(4 downto 0) := data(4 downto 0);
267
      when 3 => rdata(3 downto 0) := data(3 downto 0);
268
      when 2 => rdata(2 downto 0) := data(2 downto 0);
269
      when 1 => rdata(1 downto 0) := data(1 downto 0);
270
      when others => rdata(0) := data(0);
271
    end case;
272
    return rdata;
273
  end select_data;
274
 
275
   -- purpose: Returns true when a slave is selected and the clock starts
276
  function slv_start (
277
    signal spisel  : std_ulogic;
278
    signal cpol    : std_ulogic;
279
    signal sck     : std_ulogic;
280
    signal prevsck : std_ulogic)
281
    return boolean is
282
  begin  -- slv_start
283
    if spisel = '0' then          -- Slave is selected
284
      if (sck xor prevsck) = '1' then  -- The clock has changed
285
        return (cpol xor sck) = '1';    -- The clock is not idle 
286
      end if;
287
    end if;
288
    return false;
289
  end slv_start;
290
 
291
  -----------------------------------------------------------------------------
292
  -- Signals
293
  -----------------------------------------------------------------------------
294
 
295
  signal r, rin : spi_reg_type;
296
 
297
begin
298
 
299
  -- SPI controller, register interface and related logic
300
  comb: process (r, rstn, apbi, spii)
301
    variable v       : spi_reg_type;
302
    variable irq     : std_logic_vector((NAHBIRQ-1) downto 0);
303
    variable apbaddr : std_logic_vector(7 downto 2);
304
    variable apbout  : std_logic_vector(31 downto 0);
305
    variable len     : std_logic_vector(4 downto 0);
306
    variable indata  : std_ulogic;
307
    variable change  : std_ulogic;
308
    variable sample  : std_ulogic;
309
    variable reload  : std_ulogic;
310
  begin  -- process comb
311
    v := r;  v.irq := '0'; irq := (others=>'0'); irq(pirq) := r.irq;
312
    apbaddr := apbi.paddr(7 downto 2); apbout := (others => '0');
313
    len := spilen(r.mode.len); v.toggle := '0';
314
    indata := '0'; sample := '0'; change := '0'; reload := '0';
315
 
316
    -- read registers
317
    if (apbi.psel(pindex) and apbi.penable and (not apbi.pwrite)) = '1' then
318
      case apbaddr is
319
        when CAP_ADDR =>
320
          apbout := SPICTRLCAPREG;
321
        when MODE_ADDR =>
322
          apbout := zero32(31) & r.mode.loopb & r.mode.cpol & r.mode.cpha &
323
                    r.mode.div16 & r.mode.rev & r.mode.ms & r.mode.en &
324
                    r.mode.len & r.mode.pm & r.mode.tw & zero32(14 downto 12) &
325
                    r.mode.cg & zero32(6 downto 0);
326
        when EVENT_ADDR =>
327
          apbout := zero32(31 downto 15) & r.event.lt & zero32(13) &
328
                    r.event.ov & r.event.un & r.event.mme & r.event.ne &
329
                    r.event.nf & zero32(7 downto 0);
330
        when MASK_ADDR =>
331
          apbout := zero32(31 downto 15) & r.mask.lt & zero32(13) &
332
                    r.mask.ov & r.mask.un & r.mask.mme & r.mask.ne &
333
                    r.mask.nf & zero32(7 downto 0);
334
        when RD_ADDR  =>
335
          apbout := condhwordswap(r.rd, len, r.mode.rev);
336
          v.rd_free := '1';
337
        when SLVSEL_ADDR =>
338
         if SLVSEL_EN /= 0 then apbout((SLVSEL_SZ-1) downto 0) := r.slvsel;
339
         else null; end if;
340
         when others => null;
341
      end case;
342
    end if;
343
 
344
    -- write registers
345
    if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
346
      case apbaddr is
347
        when MODE_ADDR =>
348
          v.mode.loopb := apbi.pwdata(30);
349
          v.mode.cpol  := apbi.pwdata(29);
350
          v.mode.cpha  := apbi.pwdata(28);
351
          v.mode.div16 := apbi.pwdata(27);
352
          v.mode.rev   := apbi.pwdata(26);
353
          v.mode.ms    := apbi.pwdata(25);
354
          v.mode.en    := apbi.pwdata(24);
355
          v.mode.len   := apbi.pwdata(23 downto 20);
356
          v.mode.pm    := apbi.pwdata(19 downto 16);
357
          v.mode.tw  := apbi.pwdata(15);
358
          v.mode.cg    := apbi.pwdata(11 downto 7);
359
        when EVENT_ADDR =>
360
          wc(v.event.lt, r.event.lt, apbi.pwdata(14));
361
          wc(v.event.ov, r.event.ov, apbi.pwdata(12));
362
          wc(v.event.un, r.event.un, apbi.pwdata(11));
363
          wc(v.event.mme, r.event.mme, apbi.pwdata(10));
364
        when MASK_ADDR =>
365
          v.mask.lt  := apbi.pwdata(14);
366
          v.mask.ov  := apbi.pwdata(12);
367
          v.mask.un  := apbi.pwdata(11);
368
          v.mask.mme := apbi.pwdata(10);
369
          v.mask.ne  := apbi.pwdata(9);
370
          v.mask.nf  := apbi.pwdata(8);
371
        when COM_ADDR =>
372
          v.lst := apbi.pwdata(22);
373
        when TD_ADDR =>
374
          -- The write is lost if the transmit register is written when
375
          -- the not full bit is zero.
376
          if r.event.nf = '1' then
377
            v.td := apbi.pwdata;
378
            v.td_occ := '1';
379
          end if;
380
        when SLVSEL_ADDR =>
381
          if SLVSEL_EN /= 0 then v.slvsel := apbi.pwdata((SLVSEL_SZ-1) downto 0);
382
          else null; end if;
383
        when others => null;
384
      end case;
385
    end if;
386
 
387
    -- Handle transmit FIFO
388
    if r.td_occ = '1' and r.tfreecnt /= 0 then
389
      if r.mode.rev = '0' then
390
        v.txfifo(r.tdli) := r.td;
391
      else
392
        v.txfifo(r.tdli) := reverse(r.td);
393
      end if;
394
      v.tdli := (r.tdli + 1) mod FIFO_DEPTH;
395
      v.tfreecnt := r.tfreecnt - 1;
396
      -- Safe since APB has one wait state between writes
397
      v.td_occ := '0';
398
    end if;
399
 
400
    -- Update receive register and FIFO
401
    if r.rd_free = '1' and r.rfreecnt /= FIFO_DEPTH then
402
      if r.mode.rev = '0' then
403
        v.rd := reverse(select_data(r.rxfifo(r.rdfi), len));
404
      else
405
        v.rd := select_data(r.rxfifo(r.rdfi), len);
406
      end if;
407
      v.rdfi := (r.rdfi + 1) mod FIFO_DEPTH;
408
      v.rfreecnt := r.rfreecnt + 1;
409
      v.rd_free := '0';
410
    end if;
411
 
412
    if r.mode.en = '1' then             -- Core is enabled
413
      -- Not full detection
414
      if r.tfreecnt /= 0 or r.td_occ /= '1' then
415
        v.event.nf := '1';
416
        if (r.mask.nf and not r.event.nf) = '1' then
417
          v.irq := '1';
418
        end if;
419
      else
420
        v.event.nf := '0';
421
      end if;
422
 
423
      -- Not empty detection
424
      if r.rfreecnt /= FIFO_DEPTH or r.rd_free /= '1' then
425
        v.event.ne := '1';
426
        if (r.mask.ne and not r.event.ne) = '1' then
427
          v.irq := '1';
428
        end if;
429
      else
430
        v.event.ne := '0';
431
      end if;
432
    end if;
433
 
434
    ---------------------------------------------------------------------------
435
    -- SPI bus control
436
    ---------------------------------------------------------------------------
437
    if (r.mode.en and not r.running) = '1' then
438
      if r.mode.ms = '1' then
439
        if r.divcnt = 0 then
440
          v.spio.sck := r.mode.cpol;
441
        end if;
442
        v.spio.misooen := INPUT;
443
        if r.mode.tw = '0' then
444
          v.spio.mosioen := r.mode.loopb xor OEPOL_LEVEL;
445
        else
446
          v.spio.mosioen := INPUT;
447
        end if;
448
        v.spio.sckoen := r.mode.loopb xor OEPOL_LEVEL;
449
        v.twdir := OUTPUT;
450
      else
451
        if (r.spii(1).spisel or r.mode.tw) = '0' then
452
          v.spio.misooen := r.mode.loopb xor OEPOL_LEVEL;
453
        else
454
          v.spio.misooen := INPUT;
455
        end if;
456
        v.spio.mosioen := INPUT;
457
        v.spio.sckoen := INPUT;
458
        v.twdir := INPUT;
459
      end if;
460
      if ((r.mode.ms = '1' and r.tfreecnt /= FIFO_DEPTH) or
461
          slv_start(r.spii(1).spisel, r.mode.cpol, r.spii(1).sck, r.psck)) then
462
        -- Slave underrun detection
463
        if r.tfreecnt = FIFO_DEPTH then
464
          v.uf := '1';
465
          if (r.mask.un and not v.event.un) = '1' then
466
            v.irq := '1';
467
          end if;
468
          v.event.un := '1';
469
        end if;
470
        v.running := '1';
471
        if r.mode.ms = '1' then
472
          v.spio.mosioen := r.mode.loopb xor OEPOL_LEVEL;
473
        end if;
474
        change := not r.mode.cpha;
475
        -- Insert cycles when cpha = '0' to ensure proper setup
476
        -- time for first MOSI value in master mode.
477
        reload := r.mode.ms and not r.mode.cpha;
478
      end if;
479
      v.bitcnt := 0;
480
      v.cgcnt := (others => '0');
481
      if r.mode.ms = '0' then
482
        change := not (r.mode.cpha or (r.spii(1).sck xor r.mode.cpol));
483
      end if;
484
      -- sc should not be changed on b2b
485
      if r.spii(1).spisel /= '0' then
486
        v.sc := not r.mode.cpha;
487
        v.psck := r.mode.cpol;
488
      end if;
489
    end if;
490
 
491
    ---------------------------------------------------------------------------
492
    -- Clock generation, only in master mode
493
    ---------------------------------------------------------------------------
494
    if r.mode.ms = '1' and (r.running = '1' or r.divcnt /= 0) then
495
      -- The frequency of the SPI clock relative to the system clock is
496
      -- determined by the div16 and pm inputs. They have the same meaning as in
497
      -- the MPC83xx register interface. The clock is divided by 4*([PM]+1) and
498
      -- if div16 is set the clock is divided by 16*(4*([PM]+1)). The duty cycle
499
      -- is 50%.  
500
      if r.divcnt = 0 then
501
        -- Toggle SCK unless we are in a clock gap
502
        if r.cgcnt = 0 or r.spio.sck /= r.mode.cpol then
503
          v.spio.sck := not r.spio.sck;
504
          v.toggle := r.running;
505
        end if;
506
        if r.cgcnt /= 0 then
507
          v.cgcnt := r.cgcnt - 1;
508
        end if;
509
        reload := '1';
510
      else
511
        v.divcnt := r.divcnt - 1;
512
      end if;
513
    else
514
      v.divcnt := (others => '0');
515
    end if;
516
 
517
    if reload = '1' then
518
      -- Reload clock scale counter
519
      v.divcnt(4 downto 0) := unsigned('0' & r.mode.pm) + 1;
520
      if r.mode.div16 = '1' then
521
        v.divcnt := shift_left(v.divcnt, 5) - 1;
522
      else
523
        v.divcnt := shift_left(v.divcnt, 1) - 1;
524
      end if;
525
    end if;
526
 
527
    ---------------------------------------------------------------------------
528
    -- Handle master operation.
529
    ---------------------------------------------------------------------------
530
    if r.mode.ms = '1' then
531
      -- The sc bit determines if the core should read or change the data on
532
      -- the upcoming flank.
533
      if r.toggle = '1' then
534
        v.sc := not r.sc;
535
      end if;
536
 
537
      -- Sample data
538
      if (r.toggle and r.sc) = '1' then
539
        sample := '1';
540
      end if;
541
 
542
      -- Change data on the clock flank...
543
      if (v.toggle and not r.sc) = '1' then
544
        change := '1';
545
      end if;
546
 
547
      -- Detect multiple-master errors (mode-fault)
548
      if r.spii(1).spisel = '0' then
549
        v.mode.en := '0';
550
        v.mode.ms := '0';
551
        v.event.mme := '1';
552
        if (r.mask.mme and not r.event.mme) = '1' then
553
          v.irq := '1';
554
        end if;
555
        v.running := '0';
556
      end if;
557
      if r.mode.tw = '1' then
558
        indata := spii.mosi;
559
      else
560
        indata := spii.miso;
561
      end if;
562
    end if;
563
 
564
    ---------------------------------------------------------------------------
565
    -- Handle slave operation
566
    ---------------------------------------------------------------------------
567
    if (r.mode.en and not r.mode.ms) = '1' then
568
      if r.spii(1).spisel = '0' then
569
        v.psck := r.spii(1).sck;
570
        if (r.psck xor r.spii(1).sck) = '1' then
571
          if r.sc = '1' then
572
            sample := '1';
573
          else
574
            change := '1';
575
          end if;
576
          v.sc := not r.sc;
577
        end if;
578
        indata := r.spii(1).mosi;
579
      end if;
580
    end if;
581
 
582
    ---------------------------------------------------------------------------
583
    -- Used in both master and slave operation
584
    ---------------------------------------------------------------------------
585
    if sample = '1' then
586
      -- Detect receive overflow
587
      if (r.rfreecnt = 0 and r.rd_free = '0') or r.ov = '1' then
588
        if r.mode.tw = '0' or r.twdir = INPUT then
589
          v.ov := '1';
590
          -- Overflow event and IRQ
591
          if r.ov = '0' then
592
            if (r.mask.ov and not r.event.ov) = '1' then
593
              v.irq := '1';
594
            end if;
595
            v.event.ov := '1';
596
          end if;
597
        end if;
598
      else
599
        if r.mode.loopb = '1' then
600
          v.rxfifo(r.rdli)(0) := r.spio.mosi;
601
        else
602
          v.rxfifo(r.rdli)(0) := indata;
603
        end if;
604
        v.rxfifo(r.rdli)(31 downto 1) := r.rxfifo(r.rdli)(30 downto 0);
605
      end if;
606
      if r.bitcnt = conv_integer(len) then
607
        if r.ov = '0' and (r.mode.tw = '0' or r.mode.loopb = '1' or
608
                           (r.mode.tw = '1' and r.twdir = INPUT)) then
609
          v.rdli := (r.rdli + 1) mod FIFO_DEPTH;
610
          v.rfreecnt := v.rfreecnt - 1;
611
        end if;
612
        v.bitcnt := 0;
613
        v.twdir := r.twdir xor not r.mode.loopb;
614
        v.cgcnt := unsigned(r.mode.cg & '0');
615
        if r.uf = '0' and (r.mode.tw = '0' or r.mode.loopb = '1' or
616
                           r.twdir = OUTPUT) then
617
          v.tfreecnt := v.tfreecnt + 1;
618
          v.tdfi := (v.tdfi + 1) mod FIFO_DEPTH;
619
          v.txfifo(r.tdfi)(0) := '1';
620
        end if;
621
        if v.tfreecnt /= FIFO_DEPTH then
622
          if not (r.mode.tw = '1' and r.mode.loopb = '0' and
623
                  r.mode.ms = '0' and r.twdir = INPUT) then
624
            v.running := r.mode.ms;
625
          end if;
626
        else
627
          if r.mode.tw = '1' and r.mode.loopb = '0' then
628
            if ((r.mode.ms = '1' and r.twdir = INPUT) or
629
                (r.mode.ms = '0' and r.twdir = OUTPUT)) then
630
              v.running := '0';
631
            end if;
632
          else
633
            v.running := '0';
634
          end if;
635
          if v.running = '0' then
636
            -- LST detection
637
            if r.lst = '1' then
638
              v.event.lt := '1';
639
              if (r.mask.lt and not r.event.lt) = '1' then
640
                v.irq := '1';
641
              end if;
642
            end if;
643
            v.lst := '0';
644
          end if;
645
        end if;
646
        v.ov := '0';
647
        if (r.mode.tw = '0' or (r.mode.ms = '0' and r.twdir = OUTPUT)) then
648
          v.uf := '0';
649
        end if;
650
      else
651
        v.bitcnt := r.bitcnt + 1;
652
      end if;
653
    end if;
654
 
655
    if change = '1' then
656
      if v.uf = '0' then
657
        v.spio.miso := r.txfifo(r.tdfi)(r.bitcnt);
658
        v.spio.mosi := r.txfifo(r.tdfi)(r.bitcnt);
659
      else
660
        v.spio.miso := '1';
661
        v.spio.mosi := '1';
662
      end if;
663
      if (r.mode.tw and not r.mode.loopb) = '1' then
664
        v.spio.mosioen := r.twdir;
665
      end if;
666
    end if;
667
 
668
    if r.mode.en = '0' then             -- Core is disabled
669
      v.tfreecnt := FIFO_DEPTH;
670
      v.rfreecnt := FIFO_DEPTH;
671
      v.tdfi := 0; v.rdfi := 0;
672
      v.tdli := 0; v.rdli := 0;
673
      v.rd_free := '1';
674
      v.td_occ := '0';
675
      v.lst := '0';
676
      v.uf := '0';
677
      v.ov := '0';
678
      v.running := '0';
679
      v.twdir := INPUT;
680
      v.spio.miso := '1';
681
      v.spio.mosi := '1';
682
      v.spio.misooen := INPUT;
683
      v.spio.mosioen := INPUT;
684
      v.spio.sckoen := INPUT;
685
      -- Need to assign sc and psck here if spisel is low when the core is
686
      -- enabled
687
      v.sc := not r.mode.cpha;
688
      v.psck := r.mode.cpol;
689
      -- Set all first bits in txfifo to idle value
690
      for i in 0 to (FIFO_DEPTH-1) loop
691
        v.txfifo(i)(0) := '1';
692
      end loop;  -- i
693
    end if;
694
 
695
    if rstn = '0' then
696
      v.mode := ('0','0','0','0','0','0','0',"0000","0000",'0',"00000");
697
      v.event := ('0','0','0','0','0','0');
698
      v.mask := ('0','0','0','0','0','0');
699
      v.lst := '0';
700
      v.slvsel := (others => '1');
701
    end if;
702
 
703
    -- Synchronize inputs
704
    v.spii(0) := spii;
705
    v.spii(1) := r.spii(0);
706
 
707
    -- Update registers
708
    rin <= v;
709
 
710
    -- Update outputs
711
    apbo.prdata <= apbout;
712
    apbo.pirq <= irq;
713
    apbo.pconfig <= PCONFIG;
714
    apbo.pindex <= pindex;
715
 
716
    slvsel <= r.slvsel;
717
 
718
    spio <= r.spio;
719
 
720
  end process comb;
721
 
722
  reg: process (clk)
723
  begin  -- process reg
724
    if rising_edge(clk) then
725
      r <= rin;
726
    end if;
727
  end process reg;
728
 
729
  -- Boot message
730
  -- pragma translate_off
731
  bootmsg : report_version
732
    generic map (
733
      "spictrl" & tost(pindex) & ": SPI controller rev " &
734
      tost(0) & ", irq " & tost(pirq));
735
  -- pragma translate_on
736
 
737
end architecture rtl;

powered by: WebSVN 2.1.0

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