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 6

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

powered by: WebSVN 2.1.0

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