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 5

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

powered by: WebSVN 2.1.0

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