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

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [rtl/] [vhdl/] [streamtest.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 jorisvr
--
2
--  Test application for spwstream.
3
--
4
--  This entity implements one spwstream instance with SpaceWire signals
5
--  routed to external ports. The SpaceWire port is assumed to be looped back
6
--  to itself externally, either directly (tx pins wired to rx pins) or
7
--  through a foreigh SpaceWire device which is programmed to echo anything
8
--  it receives.
9
--
10
--  This entity submits a series of test patterns to the transmit side of
11
--  spwstream. At the same time it monitors the receive side of spwstream
12
--  and verifies that received data matches the transmitted data pattern.
13
--
14
--  Link mode and tx bit rate may be programmed through digital inputs
15
--  (presumably connected to switches or buttons). Link state and progress of
16
--  the test are reported through digital outputs (presumably connected to
17
--  LEDs).
18
--
19
--  Note: there is no check on the integrity of the first packet received
20
--  after the link goes up.
21
--
22
 
23
library ieee;
24
use ieee.std_logic_1164.all;
25
use ieee.numeric_std.all;
26
use work.spwpkg.all;
27
 
28
entity streamtest is
29
 
30
    generic (
31
        -- System clock frequency in Hz.
32
        sysfreq:    real;
33
 
34
        -- 2-log of division factor from system clock freq to timecode freq.
35
        tickdiv:    integer range 12 to 24 := 20;
36
 
37
        -- Receiver front-end implementation.
38
        rximpl:     spw_implementation_type := impl_generic;
39
 
40
        -- Maximum number of bits received per system clock (impl_fast only).
41
        rxchunk:    integer range 1 to 4 := 1;
42
 
43
        -- Transmitter implementation.
44
        tximpl:     spw_implementation_type := impl_generic;
45
 
46
        -- Size of receive FIFO.
47
        rxfifosize_bits: integer range 6 to 14 := 11;
48
 
49
        -- Size of transmit FIFO.
50
        txfifosize_bits: integer range 2 to 14 := 11 );
51
 
52
    port (
53
        -- System clock.
54
        clk:        in  std_logic;
55
 
56
        -- Receiver sample clock (only for impl_fast).
57
        rxclk:      in  std_logic;
58
 
59
        -- Transmit clock (only for impl_fast).
60
        txclk:      in  std_logic;
61
 
62
        -- Synchronous reset (active-high).
63
        rst:        in  std_logic;
64
 
65
        -- Enables spontaneous link start.
66
        linkstart:  in  std_logic;
67
 
68
        -- Enables automatic link start on receipt of a NULL token.
69
        autostart:  in  std_logic;
70
 
71
        -- Do not start link and/or disconnect current link.
72
        linkdisable: in std_logic;
73
 
74
        -- Enable sending test patterns to spwstream.
75
        senddata:   in  std_logic;
76
 
77
        -- Enable sending time codes to spwstream.
78
        sendtick:   in  std_logic;
79
 
80
        -- Scaling factor minus 1 for TX bitrate.
81
        txdivcnt:   in  std_logic_vector(7 downto 0);
82
 
83
        -- Link in state Started.
84
        linkstarted: out std_logic;
85
 
86
        -- Link in state Connecting.
87
        linkconnecting: out std_logic;
88
 
89
        -- Link in state Run.
90
        linkrun:    out std_logic;
91
 
92
        -- Link error (one cycle pulse, not directly suitable for LED)
93
        linkerror:  out std_logic;
94
 
95
        -- High when taking a byte from the receive FIFO.
96
        gotdata:    out std_logic;
97
 
98
        -- Incorrect or unexpected data received (sticky).
99
        dataerror:  out std_logic;
100
 
101
        -- Incorrect or unexpected time code received (sticky).
102
        tickerror:  out std_logic;
103
 
104
        -- SpaceWire signals.
105
        spw_di:     in  std_logic;
106
        spw_si:     in  std_logic;
107
        spw_do:     out std_logic;
108
        spw_so:     out std_logic );
109
 
110
end entity streamtest;
111
 
112
architecture streamtest_arch of streamtest is
113
 
114
    -- Update 16-bit maximum length LFSR by 8 steps
115
    function lfsr16(x: in std_logic_vector) return std_logic_vector is
116
        variable y: std_logic_vector(15 downto 0);
117
    begin
118
        -- poly = x^16 + x^14 + x^13 + x^11 + 1
119
        -- tap positions = x(0), x(2), x(3), x(5)
120
        y(7 downto 0)  := x(15 downto 8);
121
        y(15 downto 8) := x(7 downto 0) xor x(9 downto 2) xor x(10 downto 3) xor x(12 downto 5);
122
        return y;
123
    end function;
124
 
125
    -- Sending side state.
126
    type tx_state_type is ( txst_idle, txst_prepare, txst_data );
127
 
128
    -- Receiving side state.
129
    type rx_state_type is ( rxst_idle, rxst_data );
130
 
131
    -- Registers.
132
    type regs_type is record
133
        tx_state:       tx_state_type;
134
        tx_timecnt:     std_logic_vector((tickdiv-1) downto 0);
135
        tx_quietcnt:    std_logic_vector(15 downto 0);
136
        tx_pktlen:      std_logic_vector(15 downto 0);
137
        tx_lfsr:        std_logic_vector(15 downto 0);
138
        tx_enabledata:  std_ulogic;
139
        rx_state:       rx_state_type;
140
        rx_quietcnt:    std_logic_vector(15 downto 0);
141
        rx_enabledata:  std_ulogic;
142
        rx_gottick:     std_ulogic;
143
        rx_expecttick:  std_ulogic;
144
        rx_expectglitch: unsigned(5 downto 0);
145
        rx_badpacket:   std_ulogic;
146
        rx_pktlen:      std_logic_vector(15 downto 0);
147
        rx_prev:        std_logic_vector(15 downto 0);
148
        rx_lfsr:        std_logic_vector(15 downto 0);
149
        running:        std_ulogic;
150
        tick_in:        std_ulogic;
151
        time_in:        std_logic_vector(5 downto 0);
152
        txwrite:        std_ulogic;
153
        txflag:         std_ulogic;
154
        txdata:         std_logic_vector(7 downto 0);
155
        rxread:         std_ulogic;
156
        gotdata:        std_ulogic;
157
        dataerror:      std_ulogic;
158
        tickerror:      std_ulogic;
159
    end record;
160
 
161
    -- Reset state.
162
    constant regs_reset: regs_type := (
163
        tx_state        => txst_idle,
164
        tx_timecnt      => (others => '0'),
165
        tx_quietcnt     => (others => '0'),
166
        tx_pktlen       => (others => '0'),
167
        tx_lfsr         => (1 => '1', others => '0'),
168
        tx_enabledata   => '0',
169
        rx_state        => rxst_idle,
170
        rx_quietcnt     => (others => '0'),
171
        rx_enabledata   => '0',
172
        rx_gottick      => '0',
173
        rx_expecttick   => '0',
174
        rx_expectglitch => "000001",
175
        rx_badpacket    => '0',
176
        rx_pktlen       => (others => '0'),
177
        rx_prev         => (others => '0'),
178
        rx_lfsr         => (others => '0'),
179
        running         => '0',
180
        tick_in         => '0',
181
        time_in         => (others => '0'),
182
        txwrite         => '0',
183
        txflag          => '0',
184
        txdata          => (others => '0'),
185
        rxread          => '0',
186
        gotdata         => '0',
187
        dataerror       => '0',
188
        tickerror       => '0' );
189
 
190
    signal r:   regs_type := regs_reset;
191
    signal rin: regs_type;
192
 
193
    -- Interface signals.
194
    signal s_txrdy:     std_logic;
195
    signal s_tickout:   std_logic;
196
    signal s_timeout:   std_logic_vector(5 downto 0);
197
    signal s_rxvalid:   std_logic;
198
    signal s_rxflag:    std_logic;
199
    signal s_rxdata:    std_logic_vector(7 downto 0);
200
    signal s_running:   std_logic;
201
    signal s_errdisc:   std_logic;
202
    signal s_errpar:    std_logic;
203
    signal s_erresc:    std_logic;
204
    signal s_errcred:   std_logic;
205
 
206
begin
207
 
208
    -- spwstream instance
209
    spwstream_inst: spwstream
210
        generic map (
211
            sysfreq         => sysfreq,
212
            rximpl          => rximpl,
213
            rxchunk         => rxchunk,
214
            tximpl          => tximpl,
215
            rxfifosize_bits => rxfifosize_bits,
216
            txfifosize_bits => txfifosize_bits )
217
        port map (
218
            clk         => clk,
219
            rxclk       => rxclk,
220
            txclk       => txclk,
221
            rst         => rst,
222
            autostart   => autostart,
223
            linkstart   => linkstart,
224
            linkdis     => linkdisable,
225
            txdivcnt    => txdivcnt,
226
            tick_in     => r.tick_in,
227
            ctrl_in     => (others => '0'),
228
            time_in     => r.time_in,
229
            txwrite     => r.txwrite,
230
            txflag      => r.txflag,
231
            txdata      => r.txdata,
232
            txrdy       => s_txrdy,
233
            txhalff     => open,
234
            tick_out    => s_tickout,
235
            ctrl_out    => open,
236
            time_out    => s_timeout,
237
            rxvalid     => s_rxvalid,
238
            rxhalff     => open,
239
            rxflag      => s_rxflag,
240
            rxdata      => s_rxdata,
241
            rxread      => r.rxread,
242
            started     => linkstarted,
243
            connecting  => linkconnecting,
244
            running     => s_running,
245
            errdisc     => s_errdisc,
246
            errpar      => s_errpar,
247
            erresc      => s_erresc,
248
            errcred     => s_errcred,
249
            spw_di      => spw_di,
250
            spw_si      => spw_si,
251
            spw_do      => spw_do,
252
            spw_so      => spw_so );
253
 
254
    -- Drive status indications.
255
    linkrun     <= s_running;
256
    linkerror   <= s_errdisc or s_errpar or s_erresc or s_errcred;
257
    gotdata     <= r.gotdata;
258
    dataerror   <= r.dataerror;
259
    tickerror   <= r.tickerror;
260
 
261
    process (r, rst, senddata, sendtick, s_txrdy, s_tickout, s_timeout, s_rxvalid, s_rxflag, s_rxdata, s_running) is
262
        variable v: regs_type;
263
    begin
264
        v           := r;
265
 
266
        -- Initiate timecode transmissions.
267
        v.tx_timecnt := std_logic_vector(unsigned(r.tx_timecnt) + 1);
268
        if unsigned(v.tx_timecnt) = 0 then
269
            v.tick_in   := sendtick;
270
        else
271
            v.tick_in   := '0';
272
        end if;
273
        if r.tick_in = '1' then
274
            v.time_in   := std_logic_vector(unsigned(r.time_in) + 1);
275
            v.rx_expecttick := '1';
276
            v.rx_gottick    := '0';
277
        end if;
278
 
279
        -- Turn data generator on/off at regular intervals.
280
        v.tx_quietcnt := std_logic_vector(unsigned(r.tx_quietcnt) + 1);
281
        if unsigned(r.tx_quietcnt) = 61000 then
282
            v.tx_quietcnt := (others => '0');
283
        end if;
284
        v.tx_enabledata := senddata and (not r.tx_quietcnt(15));
285
 
286
        -- Generate data packets.
287
        case r.tx_state is
288
            when txst_idle =>
289
                -- generate packet length
290
                v.tx_state  := txst_prepare;
291
                v.tx_pktlen := r.tx_lfsr;
292
                v.txwrite   := '0';
293
                v.tx_lfsr   := lfsr16(r.tx_lfsr);
294
            when txst_prepare =>
295
                -- generate first byte of packet
296
                v.tx_state  := txst_data;
297
                v.txwrite   := r.tx_enabledata;
298
                v.txflag    := '0';
299
                v.txdata    := r.tx_lfsr(15 downto 8);
300
                v.tx_lfsr   := lfsr16(r.tx_lfsr);
301
            when txst_data =>
302
                -- generate data bytes and EOP
303
                v.txwrite   := r.tx_enabledata;
304
                if r.txwrite = '1' and s_txrdy = '1' then
305
                    -- just sent one byte
306
                    v.tx_pktlen := std_logic_vector(unsigned(r.tx_pktlen) - 1);
307
                    if unsigned(r.tx_pktlen) = 0 then
308
                        -- done with packet
309
                        v.tx_state  := txst_idle;
310
                        v.txwrite   := '0';
311
                    elsif unsigned(r.tx_pktlen) = 1 then
312
                        -- generate EOP
313
                        v.txwrite   := r.tx_enabledata;
314
                        v.txflag    := '1';
315
                        v.txdata    := (others => '0');
316
                        v.tx_lfsr   := lfsr16(r.tx_lfsr);
317
                    else
318
                        -- generate next data byte
319
                        v.txwrite   := r.tx_enabledata;
320
                        v.txflag    := '0';
321
                        v.txdata    := r.tx_lfsr(15 downto 8);
322
                        v.tx_lfsr   := lfsr16(r.tx_lfsr);
323
                    end if;
324
                end if;
325
        end case;
326
 
327
        -- Blink light when receiving data.
328
        v.gotdata   := s_rxvalid and r.rxread;
329
 
330
        -- Detect missing timecodes.
331
        if r.tick_in = '1' and r.rx_expecttick = '1' then
332
            -- This is bad; a new timecode is being generated while
333
            -- we have not even received the previous one yet.
334
            v.tickerror := '1';
335
        end if;
336
 
337
        -- Receive and check incoming timecodes.
338
        if s_tickout = '1' then
339
            if unsigned(s_timeout) + 1 /= unsigned(r.time_in) then
340
                -- Received time code does not match last transmitted code.
341
                v.tickerror := '1';
342
            end if;
343
            if r.rx_gottick = '1' then
344
                -- Already received the last transmitted time code.
345
                v.tickerror := '1';
346
            end if;
347
            v.rx_expecttick := '0';
348
            v.rx_gottick    := '1';
349
        end if;
350
 
351
        -- Turn data receiving on/off at regular intervals
352
        v.rx_quietcnt := std_logic_vector(unsigned(r.rx_quietcnt) + 1);
353
        if unsigned(r.rx_quietcnt) = 55000 then
354
            v.rx_quietcnt := (others => '0');
355
        end if;
356
        v.rx_enabledata := not r.rx_quietcnt(15);
357
 
358
        case r.rx_state is
359
            when rxst_idle =>
360
                -- get expected packet length
361
                v.rx_state  := rxst_data;
362
                v.rx_pktlen := r.rx_lfsr;
363
                v.rx_lfsr   := lfsr16(r.rx_lfsr);
364
                v.rx_prev   := (others => '0');
365
            when rxst_data =>
366
                v.rxread    := r.rx_enabledata;
367
                if r.rxread = '1' and s_rxvalid = '1' then
368
                    -- got next byte
369
                    v.rx_pktlen := std_logic_vector(unsigned(r.rx_pktlen) - 1);
370
                    v.rx_prev   := s_rxdata & r.rx_prev(15 downto 8);
371
                    if s_rxflag = '1' then
372
                        -- got EOP or EEP
373
                        v.rxread    := '0';
374
                        v.rx_state  := rxst_idle;
375
                        if s_rxdata = "00000000" then
376
                            -- got EOP
377
                            if unsigned(r.rx_pktlen) /= 0 then
378
                                -- unexpected EOP
379
                                v.rx_badpacket := '1';
380
                            end if;
381
                            -- count errors against expected glitches
382
                            if v.rx_badpacket = '1' then
383
                                -- got glitch
384
                                if r.rx_expectglitch = 0 then
385
                                    v.dataerror := '1';
386
                                else
387
                                    v.rx_expectglitch := r.rx_expectglitch - 1;
388
                                end if;
389
                            end if;
390
                            -- resynchronize LFSR
391
                            v.rx_lfsr   := lfsr16(lfsr16(r.rx_prev));
392
                        else
393
                            -- got EEP
394
                            v.rx_badpacket := '1';
395
                        end if;
396
                        v.rx_badpacket := '0';
397
                    else
398
                        -- got next byte
399
                        v.rx_lfsr   := lfsr16(r.rx_lfsr);
400
                        if unsigned(r.rx_pktlen) = 0 then
401
                            -- missing EOP
402
                            v.rx_badpacket := '1';
403
                        end if;
404
                        if s_rxdata /= r.rx_lfsr(15 downto 8) then
405
                            -- bad data
406
                            v.rx_badpacket := '1';
407
                        end if;
408
                    end if;
409
                end if;
410
        end case;
411
 
412
        -- If the link goes away, we should expect inconsistency on the receiving side.
413
        v.running := s_running;
414
        if r.running = '1' and s_running = '0' then
415
            if r.rx_expectglitch /= "111111" then
416
                v.rx_expectglitch := r.rx_expectglitch + 1;
417
            end if;
418
        end if;
419
 
420
        -- If there is no link, we should not expect to receive time codes.
421
        if s_running = '0' then
422
            v.rx_expecttick := '0';
423
        end if;
424
 
425
        -- Synchronous reset.
426
        if rst = '1' then
427
            v := regs_reset;
428
        end if;
429
 
430
        -- Update registers.
431
        rin <= v;
432
    end process;
433
 
434
    -- Update registers.
435
    process (clk) is
436
    begin
437
        if rising_edge(clk) then
438
            r <= rin;
439
        end if;
440
    end process;
441
 
442
end architecture streamtest_arch;

powered by: WebSVN 2.1.0

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