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

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [rtl/] [vhdl/] [spwamba.vhd] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 jorisvr
--
2
--  SpaceWire core with AMBA interface.
3
--
4
--  APB registers:
5
--
6
--      Address 0x00: Control Register
7
--          bit 0     Reset spwamba core (auto-clear)
8
--          bit 1     Reset DMA engines (auto-clear)
9
--          bit 2     Link start
10
--          bit 3     Link autostart
11
--          bit 4     Link disable
12
--          bit 5     Enable timecode transmission through tick_in signal
13
--          bit 6     Start RX DMA (auto-clear)
14
--          bit 7     Start TX DMA (auto-clear)
15
--          bit 8     Cancel TX DMA and discard TX data queue (auto-clear)
16
--          bit 9     Enable interrupt on link up/down
17
--          bit 10    Enable interrupt on time code received
18
--          bit 11    Enable interrupt on RX descriptor
19
--          bit 12    Enable interrupt on TX descriptor
20
--          bit 13    Enable interrupt on RX packet
21
--          bit 27:24 desctablesize (read-only)
22
--
23
--      Address 0x04: Status Register
24
--          bit 1:0   Link status: 0=off, 1=started, 2=connecting, 3=run
25
--          bit 2     Got disconnect error (sticky)
26
--          bit 3     Got parity error (sticky)
27
--          bit 4     Got escape error (sticky)
28
--          bit 5     Got credit error (sticky)
29
--          bit 6     RX DMA enabled
30
--          bit 7     TX DMA enabled
31
--          bit 8     AHB error occurred (reset DMA engine to clear)
32
--          bit 9     Reserved
33
--          bit 10    Received timecode (sticky)
34
--          bit 11    Finished RX descriptor with IE='1' (sticky)
35
--          bit 12    Finished TX descriptor with IE='1' (sticky)
36
--          bit 13    Received packet (sticky)
37
--          bit 14    RX buffer empty after packet
38
--
39
--          Sticky bits are reset by writing a '1' bit to the corresponding
40
--          bit position(s).
41
--
42
--      Address 0x08: Transmission Clock Scaler
43
--          bit 7:0   txclk division factor minus 1
44
--
45
--      Address 0x0c: Timecode Register
46
--          bit 5:0   Last received timecode value (read-only)
47
--          bit 7:6   Control bits received with last timecode (read-only)
48
--          bit 13:8  Timecode value to send on next tick_in (auto-increment)
49
--          bit 15:14 Reserved (write as zero)
50
--          bit 16    Write '1' to send a timecode (auto-clear)
51
--
52
--      Address 0x10: Descriptor pointer for RX DMA
53
--          bit 2:0                 Reserved, write as zero
54
--          bit desctablesize+2:3   Descriptor index (auto-increment)
55
--          bit 31:desctablesize+3  Fixed address bits of descriptor table
56
--
57
--          For example, if desctablesize = 10, a 8192-byte area is
58
--          determined by bits 31:13. This area has room for 1024 descriptors
59
--          of 8 bytes each. Bits 12:3 point to the current descriptor within
60
--          the table.
61
--      
62
--      Address 0x14: Descriptor pointer for TX DMA
63
--          bit 2:0                 Reserved, write as zero
64
--          bit desctablesize+2:3   Descriptor index (auto-increment)
65
--          bit 31:desctablesize+3  Fixed address bits of descriptor table
66
--
67
 
68
library ieee;
69
use ieee.std_logic_1164.all;
70
use ieee.numeric_std.all;
71
library techmap;
72
use techmap.gencomp.all;
73
library grlib;
74
use grlib.amba.all;
75
use grlib.devices.all;
76
use grlib.stdlib.all;
77
use work.spwpkg.all;
78
use work.spwambapkg.all;
79
 
80
entity spwamba is
81
 
82
    generic (
83
        -- Technology selection for FIFO memories.
84
        tech:           integer range 0 to NTECH := DEFFABTECH;
85
 
86
        -- AHB master index.
87
        hindex:         integer;
88
 
89
        -- APB slave index.
90
        pindex:         integer;
91
 
92
        -- Bits 19 to 8 of the APB address range.
93
        paddr:          integer;
94
 
95
        -- Mask for APB address bits 19 to 8.
96
        pmask:          integer := 16#fff#;
97
 
98
        -- Index of the interrupt request line.
99
        pirq:           integer;
100
 
101
        -- System clock frequency in Hz.
102
        -- This must be set to the frequency of "clk". It is used to setup
103
        -- counters for reset timing, disconnect timeout and to transmit
104
        -- at 10 Mbit/s during the link handshake.
105
        sysfreq:        real;
106
 
107
        -- Transmit clock frequency in Hz (only if tximpl = impl_fast).
108
        -- This must be set to the frequency of "txclk". It is used to
109
        -- transmit at 10 Mbit/s during the link handshake.
110
        txclkfreq:      real := 0.0;
111
 
112
        -- Selection of a receiver front-end implementation.
113
        rximpl:         spw_implementation_type := impl_generic;
114
 
115
        -- Maximum number of bits received per system clock
116
        -- (must be 1 in case of impl_generic).
117
        rxchunk:        integer range 1 to 4 := 1;
118
 
119
        -- Selection of a transmitter implementation.
120
        tximpl:         spw_implementation_type := impl_generic;
121
 
122
        -- Enable capability to generate time-codes.
123
        timecodegen:    boolean := true;
124
 
125
        -- Size of the receive FIFO as the 2-logarithm of the number of words.
126
        -- Must be at least 6 (64 words = 256 bytes).
127
        rxfifosize:     integer range 6 to 12 := 8;
128
 
129
        -- Size of the transmit FIFO as the 2-logarithm of the number of words.
130
        txfifosize:     integer range 2 to 12 := 8;
131
 
132
        -- Size of the DMA descriptor tables as the 2-logarithm of the number
133
        -- of descriptors.
134
        desctablesize:  integer range 4 to 14 := 10;
135
 
136
        -- Maximum burst length as the 2-logarithm of the number of words (default 8 words).
137
        maxburst:       integer range 1 to 8 := 3
138
    );
139
 
140
    port (
141
        -- System clock.
142
        clk:        in  std_logic;
143
 
144
        -- Receiver sample clock (only for impl_fast)
145
        rxclk:      in  std_logic;
146
 
147
        -- Transmit clock (only for impl_fast)
148
        txclk:      in  std_logic;
149
 
150
        -- Synchronous reset (active-low).
151
        rstn:       in  std_logic;
152
 
153
        -- APB slave input signals.
154
        apbi:       in  apb_slv_in_type;
155
 
156
        -- APB slave output signals.
157
        apbo:       out apb_slv_out_type;
158
 
159
        -- AHB master input signals.
160
        ahbi:       in  ahb_mst_in_type;
161
 
162
        -- AHB master output signals.
163
        ahbo:       out ahb_mst_out_type;
164
 
165
        -- Pulse for TimeCode generation.
166
        tick_in:    in  std_logic;
167
 
168
        -- Data In signal from SpaceWire bus.
169
        spw_di:     in  std_logic;
170
 
171
        -- Strobe In signal from SpaceWire bus.
172
        spw_si:     in  std_logic;
173
 
174
        -- Data Out signal to SpaceWire bus.
175
        spw_do:     out std_logic;
176
 
177
        -- Strobe Out signal to SpaceWire bus.
178
        spw_so:     out std_logic
179
    );
180
 
181
end entity spwamba;
182
 
183
architecture spwamba_arch of spwamba is
184
 
185
    -- Reset time (6.4 us) in system clocks
186
    constant reset_time:        integer := integer(sysfreq * 6.4e-6);
187
 
188
    -- Disconnect time (850 ns) in system clocks
189
    constant disconnect_time:   integer := integer(sysfreq * 850.0e-9);
190
 
191
    -- Initial tx clock scaler (10 Mbit).
192
    type impl_to_real_type is array(spw_implementation_type) of real;
193
    constant tximpl_to_txclk_freq: impl_to_real_type :=
194
        (impl_generic => sysfreq, impl_fast => txclkfreq);
195
    constant effective_txclk_freq: real := tximpl_to_txclk_freq(tximpl);
196
    constant default_divcnt:    std_logic_vector(7 downto 0) :=
197
        std_logic_vector(to_unsigned(integer(effective_txclk_freq / 10.0e6 - 1.0), 8));
198
 
199
    -- Registers.
200
    type regs_type is record
201
        -- packet state
202
        rxpacket:       std_logic;      -- '1' when receiving a packet
203
        rxeep:          std_logic;      -- '1' when rx EEP character pending
204
        txpacket:       std_logic;      -- '1' when transmitting a packet
205
        txdiscard:      std_logic;      -- '1' when discarding a tx packet
206
        -- RX fifo state
207
        rxfifo_raddr:   std_logic_vector(rxfifosize-1 downto 0);
208
        rxfifo_waddr:   std_logic_vector(rxfifosize-1 downto 0);
209
        rxfifo_wdata:   std_logic_vector(35 downto 0);
210
        rxfifo_write:   std_ulogic;
211
        rxfifo_empty:   std_ulogic;
212
        rxfifo_bytemsk: std_logic_vector(2 downto 0);
213
        rxroom:         std_logic_vector(5 downto 0);
214
        -- TX fifo state
215
        txfifo_raddr:   std_logic_vector(txfifosize-1 downto 0);
216
        txfifo_waddr:   std_logic_vector(txfifosize-1 downto 0);
217
        txfifo_empty:   std_ulogic;
218
        txfifo_nxfull:  std_ulogic;
219
        txfifo_highw:   std_ulogic;
220
        txfifo_bytepos: std_logic_vector(1 downto 0);
221
        -- APB registers
222
        ctl_reset:      std_ulogic;
223
        ctl_resetdma:   std_ulogic;
224
        ctl_linkstart:  std_ulogic;
225
        ctl_autostart:  std_ulogic;
226
        ctl_linkdis:    std_ulogic;
227
        ctl_ticken:     std_ulogic;
228
        ctl_rxstart:    std_ulogic;
229
        ctl_txstart:    std_ulogic;
230
        ctl_txcancel:   std_ulogic;
231
        ctl_ielink:     std_ulogic;
232
        ctl_ietick:     std_ulogic;
233
        ctl_ierxdesc:   std_ulogic;
234
        ctl_ietxdesc:   std_ulogic;
235
        ctl_ierxpacket: std_ulogic;
236
        sta_link:       std_logic_vector(1 downto 0);
237
        sta_errdisc:    std_ulogic;
238
        sta_errpar:     std_ulogic;
239
        sta_erresc:     std_ulogic;
240
        sta_errcred:    std_ulogic;
241
        sta_gottick:    std_ulogic;
242
        sta_rxdesc:     std_ulogic;
243
        sta_txdesc:     std_ulogic;
244
        sta_rxpacket:   std_ulogic;
245
        sta_rxempty:    std_ulogic;
246
        txdivcnt:       std_logic_vector(7 downto 0);
247
        time_in:        std_logic_vector(5 downto 0);
248
        tick_in:        std_ulogic;
249
        rxdesc_ptr:     std_logic_vector(31 downto 3);
250
        txdesc_ptr:     std_logic_vector(31 downto 3);
251
        -- APB interrupt request
252
        irq:            std_ulogic;
253
    end record;
254
 
255
    constant regs_reset: regs_type := (
256
        rxpacket        => '0',
257
        rxeep           => '0',
258
        txpacket        => '0',
259
        txdiscard       => '0',
260
        rxfifo_raddr    => (others => '0'),
261
        rxfifo_waddr    => (others => '0'),
262
        rxfifo_wdata    => (others => '0'),
263
        rxfifo_write    => '0',
264
        rxfifo_empty    => '1',
265
        rxfifo_bytemsk  => "111",
266
        rxroom          => (others => '1'),
267
        txfifo_raddr    => (others => '0'),
268
        txfifo_waddr    => (others => '0'),
269
        txfifo_empty    => '1',
270
        txfifo_nxfull   => '0',
271
        txfifo_highw    => '0',
272
        txfifo_bytepos  => "00",
273
        ctl_reset       => '0',
274
        ctl_resetdma    => '0',
275
        ctl_linkstart   => '0',
276
        ctl_autostart   => '0',
277
        ctl_linkdis     => '0',
278
        ctl_ticken      => '0',
279
        ctl_rxstart     => '0',
280
        ctl_txstart     => '0',
281
        ctl_txcancel    => '0',
282
        ctl_ielink      => '0',
283
        ctl_ietick      => '0',
284
        ctl_ierxdesc    => '0',
285
        ctl_ietxdesc    => '0',
286
        ctl_ierxpacket  => '0',
287
        sta_link        => "00",
288
        sta_errdisc     => '0',
289
        sta_errpar      => '0',
290
        sta_erresc      => '0',
291
        sta_errcred     => '0',
292
        sta_gottick     => '0',
293
        sta_rxdesc      => '0',
294
        sta_txdesc      => '0',
295
        sta_rxpacket    => '0',
296
        sta_rxempty     => '1',
297
        txdivcnt        => default_divcnt,
298
        time_in         => (others => '0'),
299
        tick_in         => '0',
300
        rxdesc_ptr      => (others => '0'),
301
        txdesc_ptr      => (others => '0'),
302
        irq             => '0' );
303
 
304
    signal r: regs_type := regs_reset;
305
    signal rin: regs_type;
306
 
307
    -- Component interface signals.
308
    signal recv_rxen:       std_logic;
309
    signal recvo:           spw_recv_out_type;
310
    signal recv_inact:      std_logic;
311
    signal recv_inbvalid:   std_logic;
312
    signal recv_inbits:     std_logic_vector(rxchunk-1 downto 0);
313 6 jorisvr
    signal xmit_rst:        std_logic;
314 5 jorisvr
    signal xmiti:           spw_xmit_in_type;
315
    signal xmito:           spw_xmit_out_type;
316
    signal xmit_divcnt:     std_logic_vector(7 downto 0);
317 6 jorisvr
    signal link_rst:        std_logic;
318 5 jorisvr
    signal linki:           spw_link_in_type;
319
    signal linko:           spw_link_out_type;
320
    signal msti:            spw_ahbmst_in_type;
321
    signal msto:            spw_ahbmst_out_type;
322
    signal ahbmst_rstn:     std_logic;
323
 
324
    -- Memory interface signals.
325
    signal s_rxfifo_raddr:  std_logic_vector(rxfifosize-1 downto 0);
326
    signal s_rxfifo_rdata:  std_logic_vector(35 downto 0);
327
    signal s_rxfifo_wen:    std_logic;
328
    signal s_rxfifo_waddr:  std_logic_vector(rxfifosize-1 downto 0);
329
    signal s_rxfifo_wdata:  std_logic_vector(35 downto 0);
330
    signal s_txfifo_raddr:  std_logic_vector(txfifosize-1 downto 0);
331
    signal s_txfifo_rdata:  std_logic_vector(35 downto 0);
332
    signal s_txfifo_wen:    std_logic;
333
    signal s_txfifo_waddr:  std_logic_vector(txfifosize-1 downto 0);
334
    signal s_txfifo_wdata:  std_logic_vector(35 downto 0);
335
 
336
 
337
    -- APB slave plug&play configuration
338
    constant REVISION:      integer := 0;
339
    constant pconfig:       apb_config_type := (
340
 
341
        1 => apb_iobar(paddr, pmask) );
342
 
343
    -- AHB master plug&play configuration
344
    constant hconfig:       ahb_config_type := (
345
 
346
        others => zero32 );
347
 
348
begin
349
 
350
    -- Instantiate link controller.
351
    link_inst: spwlink
352
        generic map (
353
            reset_time  => reset_time )
354
        port map (
355
            clk         => clk,
356 6 jorisvr
            rst         => link_rst,
357 5 jorisvr
            linki       => linki,
358
            linko       => linko,
359
            rxen        => recv_rxen,
360
            recvo       => recvo,
361
            xmiti       => xmiti,
362
            xmito       => xmito );
363
 
364
    -- Instantiate receiver.
365
    recv_inst: spwrecv
366
        generic map(
367
            disconnect_time => disconnect_time,
368
            rxchunk     => rxchunk )
369
        port map (
370
            clk         => clk,
371
            rxen        => recv_rxen,
372
            recvo       => recvo,
373
            inact       => recv_inact,
374
            inbvalid    => recv_inbvalid,
375
            inbits      => recv_inbits );
376
 
377
    -- Instantiate receiver front-end.
378
    recvfront_sel0: if rximpl = impl_generic generate
379
        recvfront_generic_inst: spwrecvfront_generic
380
            port map (
381
                clk         => clk,
382
                rxen        => recv_rxen,
383
                inact       => recv_inact,
384
                inbvalid    => recv_inbvalid,
385
                inbits      => recv_inbits,
386
                spw_di      => spw_di,
387
                spw_si      => spw_si );
388
    end generate;
389
    recvfront_sel1: if rximpl = impl_fast generate
390
        recvfront_fast_inst: spwrecvfront_fast
391
            generic map (
392
                rxchunk     => rxchunk )
393
            port map (
394
                clk         => clk,
395
                rxclk       => rxclk,
396
                rxen        => recv_rxen,
397
                inact       => recv_inact,
398
                inbvalid    => recv_inbvalid,
399
                inbits      => recv_inbits,
400
                spw_di      => spw_di,
401
                spw_si      => spw_si );
402
    end generate;
403
 
404
    -- Instantiate transmitter.
405
    xmit_sel0: if tximpl = impl_generic generate
406
        xmit_inst: spwxmit
407
            port map (
408
                clk     => clk,
409 6 jorisvr
                rst     => xmit_rst,
410 5 jorisvr
                divcnt  => xmit_divcnt,
411
                xmiti   => xmiti,
412
                xmito   => xmito,
413
                spw_do  => spw_do,
414
                spw_so  => spw_so );
415
    end generate;
416
    xmit_sel1: if tximpl = impl_fast generate
417
        xmit_fast_inst: spwxmit_fast
418
            port map (
419
                clk     => clk,
420
                txclk   => txclk,
421 6 jorisvr
                rst     => xmit_rst,
422 5 jorisvr
                divcnt  => xmit_divcnt,
423
                xmiti   => xmiti,
424
                xmito   => xmito,
425
                spw_do  => spw_do,
426
                spw_so  => spw_so );
427
    end generate;
428
 
429
    -- Instantiate RX FIFO.
430
    rxfifo: syncram_2p
431
        generic map (
432
            tech        => tech,
433
            abits       => rxfifosize,
434
            dbits       => 36,
435
            sepclk      => 0 )
436
        port map (
437
            rclk        => clk,
438
            renable     => '1',
439
            raddress    => s_rxfifo_raddr,
440
            dataout     => s_rxfifo_rdata,
441
            wclk        => clk,
442
            write       => s_rxfifo_wen,
443
            waddress    => s_rxfifo_waddr,
444
            datain      => s_rxfifo_wdata );
445
 
446
    -- Instantiate TX FIFO.
447
    txfifo: syncram_2p
448
        generic map (
449
            tech        => tech,
450
            abits       => txfifosize,
451
            dbits       => 36,
452
            sepclk      => 0 )
453
        port map (
454
            rclk        => clk,
455
            renable     => '1',
456
            raddress    => s_txfifo_raddr,
457
            dataout     => s_txfifo_rdata,
458
            wclk        => clk,
459
            write       => s_txfifo_wen,
460
            waddress    => s_txfifo_waddr,
461
            datain      => s_txfifo_wdata );
462
 
463
    -- Instantiate AHB master.
464
    ahbmst: spwahbmst
465
        generic map (
466
            hindex      => hindex,
467
            hconfig     => hconfig,
468
            maxburst    => maxburst )
469
        port map (
470
            clk         => clk,
471
            rstn        => ahbmst_rstn,
472
            msti        => msti,
473
            msto        => msto,
474
            ahbi        => ahbi,
475
            ahbo        => ahbo );
476
 
477
 
478
    --
479
    -- Combinatorial process
480
    --
481
    process (r, linko, msto, s_rxfifo_rdata, s_txfifo_rdata, rstn, apbi, tick_in)  is
482
        variable v:             regs_type;
483
        variable v_tmprxroom:   unsigned(rxfifosize-1 downto 0);
484
        variable v_prdata:      std_logic_vector(31 downto 0);
485
        variable v_txfifo_bytepos: integer range 0 to 3;
486
    begin
487
        v           := r;
488
        v_tmprxroom := to_unsigned(0, rxfifosize);
489
        v_prdata    := (others => '0');
490
 
491
        -- Convert RX/TX byte index to integer.
492
        v_txfifo_bytepos := to_integer(unsigned(r.txfifo_bytepos));
493
 
494
        -- Reset auto-clearing registers.
495
        v.ctl_reset     := '0';
496
        v.ctl_resetdma  := '0';
497
        v.ctl_rxstart   := '0';
498
        v.ctl_txstart   := '0';
499
 
500
        -- Register external timecode trigger (if enabled).
501
        if timecodegen and r.ctl_ticken = '1' then
502
            v.tick_in   := tick_in;
503
        else
504
            v.tick_in   := '0';
505
        end if;
506
 
507
        -- Auto-increment timecode counter.
508
        if r.tick_in = '1' then
509
            v.time_in   := std_logic_vector(unsigned(r.time_in) + 1);
510
        end if;
511
 
512
        -- Keep track of whether we are sending and/or receiving a packet.
513
        if linko.rxchar = '1' then
514
            -- got character
515
            v.rxpacket  := not linko.rxflag;
516
        end if;
517
        if linko.txack = '1' then
518
            -- send character
519
            v.txpacket  := not s_txfifo_rdata(35-v_txfifo_bytepos);
520
        end if;
521
 
522
        -- Accumulate a word to write to the RX fifo.
523
        -- Note: If the EOP/EEP marker falls in the middle of a word,
524
        -- subsequent bytes must be a copy of the marker, otherwise
525
        -- the AHB master may not work correctly.
526
        v.rxfifo_write  := '0';
527
        for i in 3 downto 0 loop
528
            if (i = 0) or (r.rxfifo_bytemsk(i-1) = '1') then
529
                if r.rxeep = '1' then
530
                    v.rxfifo_wdata(32+i)             := '1';
531
                    v.rxfifo_wdata(7+8*i downto 8*i) := "00000001";
532
                else
533
                    v.rxfifo_wdata(32+i)             := linko.rxflag;
534
                    v.rxfifo_wdata(7+8*i downto 8*i) := linko.rxdata;
535
                end if;
536
            end if;
537
        end loop;
538
        if linko.rxchar = '1' or (r.rxeep = '1' and unsigned(r.rxroom) /= 0) then
539
            v.rxeep     := '0';
540
            if r.rxfifo_bytemsk(0) = '0' or linko.rxflag = '1' or r.rxeep = '1' then
541
                -- Flush the current word to the FIFO.
542
                v.rxfifo_write   := '1';
543
                v.rxfifo_bytemsk := "111";
544
            else
545
                -- Store one byte.
546
                v.rxfifo_bytemsk := '0' & r.rxfifo_bytemsk(2 downto 1);
547
            end if;
548
        end if;
549
 
550
        -- Read from TX fifo.
551
        if (r.txfifo_empty = '0') and (linko.txack = '1' or r.txdiscard = '1') then
552
            -- Update byte pointer.
553
            if r.txfifo_bytepos = "11" or
554
               s_txfifo_rdata(35-v_txfifo_bytepos) = '1' or
555
               (v_txfifo_bytepos < 3 and
556
                s_txfifo_rdata(34-v_txfifo_bytepos) = '1' and
557
                s_txfifo_rdata(23-8*v_txfifo_bytepos) = '1') then
558
                -- This is the last byte in the current word;
559
                -- OR the current byte is an EOP/EEP marker;
560
                -- OR the next byte in the current work is a non-EOP end-of-frame marker.
561
                v.txfifo_bytepos := "00";
562
                v.txfifo_raddr  := std_logic_vector(unsigned(r.txfifo_raddr) + 1);
563
            else
564
                -- Move to next byte.
565
                v.txfifo_bytepos := std_logic_vector(unsigned(r.txfifo_bytepos) + 1);
566
            end if;
567
            -- Clear discard flag when past EOP.
568
            if s_txfifo_rdata(35-v_txfifo_bytepos) = '1' then
569
                v.txdiscard := '0';
570
            end if;
571
        end if;
572
 
573
        -- Update RX fifo pointers.
574
        if msto.rxfifo_read = '1' then
575
            -- Read one word.
576
            v.rxfifo_raddr  := std_logic_vector(unsigned(r.rxfifo_raddr) + 1);
577
        end if;
578
        if r.rxfifo_write = '1' then
579
            -- Write one word.
580
            v.rxfifo_waddr  := std_logic_vector(unsigned(r.rxfifo_waddr) + 1);
581
        end if;
582
 
583
        -- Detect RX fifo empty (using new value of rxfifo_raddr).
584
        -- Note: The FIFO is empty if head and tail pointer are equal.
585
        v.rxfifo_empty  := conv_std_logic(v.rxfifo_raddr = r.rxfifo_waddr);
586
 
587
        -- Indicate RX fifo room for SpaceWire flow control.
588
        -- The flow control window is normally expressed as a number of bytes,
589
        -- but we don't know how many bytes we can fit in each word because
590
        -- some words are only partially used. So we report FIFO room as if
591
        -- each FIFO word can hold only one byte, which is an overly
592
        -- pessimistic estimate.
593
        -- (Use the new value of rxfifo_waddr.)
594
        v_tmprxroom     := unsigned(r.rxfifo_raddr) - unsigned(v.rxfifo_waddr) - 1;
595
        if v_tmprxroom > 63 then
596
            -- at least 64 bytes room.
597
            v.rxroom    := "111111";
598
        else
599
            -- less than 64 bytes room.
600 6 jorisvr
            -- If linko.rxchar = '1', decrease rxroom by one to account for
601
            -- the pipeline delay through r.rxfifo_write.
602
            v.rxroom    := std_logic_vector(v_tmprxroom(5 downto 0) -
603
                             to_unsigned(conv_integer(linko.rxchar), 6));
604 5 jorisvr
        end if;
605
 
606
        -- Update TX fifo write pointer.
607
        if msto.txfifo_write = '1' then
608
            -- write one word.
609
            v.txfifo_waddr  := std_logic_vector(unsigned(r.txfifo_waddr) + 1);
610
        end if;
611
 
612
        -- Detect TX fifo empty.
613
        -- Note: The FIFO may be either full or empty if head and tail pointer
614
        -- are equal, hence the additional test for txfifo_nxfull.
615
        v.txfifo_empty  := conv_std_logic(v.txfifo_raddr = r.txfifo_waddr) and not r.txfifo_nxfull;
616
 
617
        -- Detect TX fifo full after one more write.
618
        if unsigned(r.txfifo_raddr) - unsigned(r.txfifo_waddr) = to_unsigned(2, txfifosize) then
619
            -- currently exactly 2 words left.
620
            v.txfifo_nxfull := msto.txfifo_write;
621
        end if;
622
 
623 6 jorisvr
        -- Detect TX fifo high water mark.
624
        if txfifosize > maxburst then
625
            -- Indicate high water when there is no room for a maximum burst.
626
            if unsigned(r.txfifo_raddr) - unsigned(r.txfifo_waddr) = to_unsigned(2**maxburst + 1, txfifosize) then
627
                -- currently room for exactly one maximum burst.
628
                v.txfifo_highw  := msto.txfifo_write;
629
            end if;
630
        else
631
            -- Indicate high water when more than half full.
632
            if unsigned(r.txfifo_raddr) - unsigned(r.txfifo_waddr) = to_unsigned(2**(txfifosize-1), txfifosize) then
633
                -- currently exactly half full.
634
                v.txfifo_highw  := msto.txfifo_write;
635
            end if;
636 5 jorisvr
        end if;
637
 
638
        -- Update descriptor pointers.
639
        if msto.rxdesc_next = '1' then
640
            if msto.rxdesc_wrap = '1' then
641
                v.rxdesc_ptr(desctablesize+2 downto 3) := (others => '0');
642
            else
643
                v.rxdesc_ptr(desctablesize+2 downto 3) :=
644
                    std_logic_vector(unsigned(r.rxdesc_ptr(desctablesize+2 downto 3)) + 1);
645
            end if;
646
        end if;
647
        if msto.txdesc_next = '1' then
648
            if msto.txdesc_wrap = '1' then
649
                v.txdesc_ptr(desctablesize+2 downto 3) := (others => '0');
650
            else
651
                v.txdesc_ptr(desctablesize+2 downto 3) :=
652
                    std_logic_vector(unsigned(r.txdesc_ptr(desctablesize+2 downto 3)) + 1);
653
            end if;
654
        end if;
655
 
656
        -- If the link is lost, set a flag to discard the current packet.
657
        if linko.running = '0' then
658
            v.rxeep     := v.rxeep or v.rxpacket;       -- use new value of rxpacket
659
            v.txdiscard := v.txdiscard or v.txpacket;   -- use new value of txpacket
660
            v.rxpacket  := '0';
661
            v.txpacket  := '0';
662
        end if;
663
 
664
        -- Clear the discard flag when the link is explicitly disabled.
665
        if r.ctl_linkdis = '1' then
666
            v.txdiscard := '0';
667
        end if;
668
 
669
        -- Extend TX cancel command until TX DMA has stopped.
670
        if msto.txdma_act = '0' then
671
            v.ctl_txcancel  := '0';
672
        end if;
673
 
674
        -- Update status registers.
675
        v.sta_link(0)   := linko.running or linko.started;
676
        v.sta_link(1)   := linko.running or linko.connecting;
677
        if linko.errdisc  = '1' then v.sta_errdisc := '1'; end if;
678
        if linko.errpar   = '1' then v.sta_errpar  := '1'; end if;
679
        if linko.erresc   = '1' then v.sta_erresc  := '1'; end if;
680
        if linko.errcred  = '1' then v.sta_errcred := '1'; end if;
681
        if linko.tick_out = '1' then v.sta_gottick := '1'; end if;
682
        if msto.int_rxdesc   = '1' then v.sta_rxdesc   := '1'; end if;
683
        if msto.int_txdesc   = '1' then v.sta_txdesc   := '1'; end if;
684
        if msto.int_rxpacket = '1' then v.sta_rxpacket := '1'; end if;
685
        if msto.int_rxpacket = '1' and r.rxfifo_empty = '1' then
686
            v.sta_rxempty   := '1';
687
        elsif r.rxfifo_empty = '0' then
688
            v.sta_rxempty   := '0';
689
        end if;
690
 
691
        -- Generate interrupt requests.
692
        v.irq       :=
693
            (r.ctl_ielink     and (linko.running xor (r.sta_link(0) and r.sta_link(1)))) or
694
            (r.ctl_ietick     and linko.tick_out) or
695
            (r.ctl_ierxdesc   and msto.int_rxdesc) or
696
            (r.ctl_ietxdesc   and msto.int_txdesc) or
697
            (r.ctl_ierxpacket and msto.int_rxpacket);
698
 
699
        -- APB read access.
700
        if apbi.psel(pindex) = '1' then
701
            case apbi.paddr(4 downto 2) is
702
                when "000" =>   -- read control register
703
                    v_prdata(0)     := '0';
704
                    v_prdata(1)     := '0';
705
                    v_prdata(2)     := r.ctl_linkstart;
706
                    v_prdata(3)     := r.ctl_autostart;
707
                    v_prdata(4)     := r.ctl_linkdis;
708
                    v_prdata(5)     := r.ctl_ticken;
709
                    v_prdata(6)     := '0';
710
                    v_prdata(7)     := '0';
711
                    v_prdata(8)     := r.ctl_txcancel;
712
                    v_prdata(9)     := r.ctl_ielink;
713
                    v_prdata(10)    := r.ctl_ietick;
714
                    v_prdata(11)    := r.ctl_ierxdesc;
715
                    v_prdata(12)    := r.ctl_ietxdesc;
716
                    v_prdata(13)    := r.ctl_ierxpacket;
717
                    v_prdata(27 downto 24) := std_logic_vector(to_unsigned(desctablesize, 4));
718
                when "001" =>   -- read status register
719
                    v_prdata(1 downto 0)    := r.sta_link;
720
                    v_prdata(2)     := r.sta_errdisc;
721
                    v_prdata(3)     := r.sta_errpar;
722
                    v_prdata(4)     := r.sta_erresc;
723
                    v_prdata(5)     := r.sta_errcred;
724
                    v_prdata(6)     := msto.rxdma_act;
725
                    v_prdata(7)     := msto.txdma_act;
726
                    v_prdata(8)     := msto.ahberror;
727
                    v_prdata(10)    := r.sta_gottick;
728
                    v_prdata(11)    := r.sta_rxdesc;
729
                    v_prdata(12)    := r.sta_txdesc;
730
                    v_prdata(13)    := r.sta_rxpacket;
731
                    v_prdata(14)    := r.sta_rxempty;
732
                when "010" =>   -- read transmission clock scaler
733
                    v_prdata(7 downto 0)    := r.txdivcnt;
734
                when "011" =>   -- read timecode register
735
                    v_prdata(5 downto 0)    := linko.time_out;
736
                    v_prdata(7 downto 6)    := linko.ctrl_out;
737
                    v_prdata(13 downto 8)   := r.time_in;
738
                    v_prdata(16 downto 14)  := "000";
739
                when "100" =>   -- read rx descriptor pointer
740
                    v_prdata(2 downto 0)    := (others => '0');
741
                    v_prdata(31 downto 3)   := r.rxdesc_ptr;
742
                when "101" =>   -- read tx descriptor pointer
743
                    v_prdata(2 downto 0)    := (others => '0');
744
                    v_prdata(31 downto 3)   := r.txdesc_ptr;
745
                when others =>
746
                    null;
747
            end case;
748
        end if;
749
 
750
        -- APB write access.
751
        if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
752
            case apbi.paddr(4 downto 2) is
753
                when "000" =>   -- write control register
754
                    v.ctl_reset     := apbi.pwdata(0);
755
                    v.ctl_resetdma  := apbi.pwdata(1);
756
                    v.ctl_linkstart := apbi.pwdata(2);
757
                    v.ctl_autostart := apbi.pwdata(3);
758
                    v.ctl_linkdis   := apbi.pwdata(4);
759
                    v.ctl_ticken    := apbi.pwdata(5);
760
                    v.ctl_rxstart   := apbi.pwdata(6);
761
                    v.ctl_txstart   := apbi.pwdata(7);
762
                    if apbi.pwdata(8) = '1' then v.ctl_txcancel := '1'; end if;
763
                    v.ctl_ielink    := apbi.pwdata(9);
764
                    v.ctl_ietick    := apbi.pwdata(10);
765
                    v.ctl_ierxdesc  := apbi.pwdata(11);
766
                    v.ctl_ietxdesc  := apbi.pwdata(12);
767
                    v.ctl_ierxpacket := apbi.pwdata(13);
768
                when "001" =>   -- write status register
769
                    if apbi.pwdata(2) = '1' then v.sta_errdisc := '0'; end if;
770
                    if apbi.pwdata(3) = '1' then v.sta_errpar  := '0'; end if;
771
                    if apbi.pwdata(4) = '1' then v.sta_erresc  := '0'; end if;
772
                    if apbi.pwdata(5) = '1' then v.sta_errcred := '0'; end if;
773
                    if apbi.pwdata(10) = '1' then v.sta_gottick := '0'; end if;
774
                    if apbi.pwdata(11) = '1' then v.sta_rxdesc := '0'; end if;
775
                    if apbi.pwdata(12) = '1' then v.sta_txdesc := '0'; end if;
776
                    if apbi.pwdata(13) = '1' then v.sta_rxpacket := '0'; end if;
777
                when "010" =>   -- write transmission clock scaler
778
                    v.txdivcnt      := apbi.pwdata(7 downto 0);
779
                when "011" =>   -- write timecode register
780
                    v.time_in       := apbi.pwdata(13 downto 8);
781
                    if apbi.pwdata(16) = '1' then v.tick_in := '1'; end if;
782
                when "100" =>   -- write rx descriptor pointer
783
                    v.rxdesc_ptr    := apbi.pwdata(31 downto 3);
784
                when "101" =>   -- write tx descriptor pointer
785
                    v.txdesc_ptr    := apbi.pwdata(31 downto 3);
786
                when others =>
787
                    null;
788
            end case;
789
        end if;
790
 
791
        -- Drive control signals to RX fifo.
792
        s_rxfifo_raddr  <= v.rxfifo_raddr;      -- new value of rxfifo_raddr
793
        s_rxfifo_wen    <= r.rxfifo_write;
794
        s_rxfifo_waddr  <= r.rxfifo_waddr;
795
        s_rxfifo_wdata  <= r.rxfifo_wdata;
796
 
797
        -- Drive control signals to TX fifo.
798
        s_txfifo_raddr  <= v.txfifo_raddr;      -- new value of txfifo_raddr
799
        s_txfifo_wen    <= msto.txfifo_write;
800
        s_txfifo_waddr  <= r.txfifo_waddr;
801
        s_txfifo_wdata  <= msto.txfifo_wdata;
802
 
803
        -- Drive inputs to spwlink.
804
        linki.autostart <= r.ctl_autostart;
805
        linki.linkstart <= r.ctl_linkstart;
806
        linki.linkdis   <= r.ctl_linkdis;
807
        linki.rxroom    <= r.rxroom;
808
        linki.tick_in   <= r.tick_in;
809
        linki.ctrl_in   <= "00";
810
        linki.time_in   <= r.time_in;
811
        linki.txwrite   <= (not r.txfifo_empty) and (not r.txdiscard);
812
        linki.txflag    <= s_txfifo_rdata(35-v_txfifo_bytepos);
813
        linki.txdata    <= s_txfifo_rdata(31-8*v_txfifo_bytepos downto 24-8*v_txfifo_bytepos);
814
 
815
        -- Drive divcnt input to spwxmit.
816
        if linko.running = '1' then
817
            xmit_divcnt <= r.txdivcnt;
818
        else
819
            xmit_divcnt <= default_divcnt;
820
        end if;
821
 
822
        -- Drive inputs to AHB master.
823
        msti.rxdma_start    <= r.ctl_rxstart;
824
        msti.txdma_start    <= r.ctl_txstart;
825
        msti.txdma_cancel   <= r.ctl_txcancel;
826
        msti.rxdesc_ptr     <= r.rxdesc_ptr;
827
        msti.txdesc_ptr     <= r.txdesc_ptr;
828
        msti.rxfifo_rdata   <= s_rxfifo_rdata;
829
        msti.rxfifo_empty   <= r.rxfifo_empty;
830
        msti.rxfifo_nxempty <= v.rxfifo_empty;  -- new value of rxfifo_empty
831
        msti.txfifo_nxfull  <= r.txfifo_nxfull;
832
        msti.txfifo_highw   <= r.txfifo_highw;
833
 
834
        -- Drive APB output signals.
835
        apbo.prdata     <= v_prdata;
836
        apbo.pirq       <= (others => '0');
837
        apbo.pirq(pirq) <= r.irq;
838
        apbo.pconfig    <= pconfig;
839
        apbo.pindex     <= pindex;
840
 
841
        -- Reset components.
842
        ahbmst_rstn     <= rstn and (not r.ctl_reset) and (not r.ctl_resetdma);
843 6 jorisvr
        link_rst        <= (not rstn) or r.ctl_reset;
844
        xmit_rst        <= not rstn;
845 5 jorisvr
 
846
        -- Clear TX fifo on cancel request.
847
        if r.ctl_txcancel = '1' then
848
            v.txfifo_raddr  := (others => '0');
849
            v.txfifo_waddr  := (others => '0');
850
            v.txfifo_empty  := '1';
851
            v.txfifo_nxfull := '0';
852
            v.txfifo_highw  := '0';
853
            v.txfifo_bytepos := "00";
854
            v.txpacket      := '0';
855
            v.txdiscard     := '0';
856
        end if;
857
 
858
        -- Reset registers.
859
        if rstn = '0' or r.ctl_reset = '1' then
860
            v   := regs_reset;
861
        end if;
862
 
863
        -- Update registers.
864
        rin <= v;
865
    end process;
866
 
867
 
868
    --
869
    -- Update registers.
870
    --
871
    process (clk) is
872
    begin
873
        if rising_edge(clk) then
874
            r <= rin;
875
        end if;
876
    end process;
877
 
878
end architecture spwamba_arch;

powered by: WebSVN 2.1.0

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