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 12

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

powered by: WebSVN 2.1.0

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