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

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [bench/] [vhdl/] [spwlink_tb.vhd] - Blame information for rev 7

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

Line No. Rev Author Line
1 2 jorisvr
--
2
-- Test Bench for Link interface.
3
--
4
-- Unfortunately rather incomplete.
5
-- The following items are verified:
6
--  * reset;
7
--  * link start, NULL exchange, FCT exchange;
8
--  * link autostart on first NULL;
9
--  * send/receive time codes, data characters, EOP/EEP;
10
--  * detection of timeout, disconnection, parity error, escape error.
11
--
12
 
13
library ieee;
14
use ieee.std_logic_1164.all, ieee.numeric_std.all;
15
use std.textio.all;
16
use work.spwpkg.all;
17
 
18
entity spwlink_tb is
19
 
20
    -- Tests should be done with several different combinations
21
    -- of values for the generics.
22
    generic (
23
 
24
        -- System clock frequency
25
        sys_clock_freq: real        := 20.0e6 ;
26
 
27
        -- Receiver sample clock frequency
28
        rx_clock_freq:  real        := 20.0e6 ;
29
 
30
        -- Transmitter clock frequency
31
        tx_clock_freq:  real        := 20.0e6 ;
32
 
33
        -- Input bit rate
34
        input_rate:     real        := 10.0e6 ;
35
 
36
        -- TX clock division factor (actual factor is one tx_clock_div+1)
37
        tx_clock_div:   integer     := 1 ;
38
 
39
        -- Receiver implementation
40
        rximpl: spw_implementation_type := impl_generic ;
41
 
42
        -- Bits per sysclk for fast receiver
43
        rxchunk:        integer     := 1 ;
44
 
45
        -- Transmitter implementation
46
        tximpl: spw_implementation_type := impl_generic ;
47
 
48
        -- Wait before starting test bench
49
        startwait:      time        := 0 sec
50
    );
51
 
52
end spwlink_tb;
53
 
54
architecture tb_arch of spwlink_tb is
55
 
56
    -- Bit periods for incoming / outgoing signal
57
    constant inbit_period:      time    := (1 sec) / input_rate ;
58
    constant outbit_period:     time    := (1 sec) * real(tx_clock_div + 1) / tx_clock_freq ;
59
    constant txclk_period:      time    := (1 sec) / tx_clock_freq ;
60
 
61
    -- clock generation
62
    signal sys_clock_enable: std_logic := '0';
63
    signal sysclk:           std_logic;
64
    signal rxclk:            std_logic;
65
    signal txclk:            std_logic;
66
 
67
    -- output monitoring
68
    type t_output_chars is array(natural range <>) of std_logic_vector(9 downto 0);
69
    signal output_collect:   std_logic;
70
    signal output_ptr:       integer;
71
    signal output_bits:      std_logic_vector(0 to 4095);
72
    signal output_nchars:    integer;
73
    signal output_chars:     t_output_chars(0 to 4095);
74
 
75
    -- input generation
76
    signal input_par:        std_logic;
77
    signal input_idle:       std_logic;
78
    signal input_pattern:    integer := 0;
79
 
80
    -- interconnect signals
81
    signal s_linki:     spw_link_in_type;
82
    signal s_linko:     spw_link_out_type;
83
    signal s_rxen:      std_logic;
84
    signal s_recvo:     spw_recv_out_type;
85
    signal s_xmiti:     spw_xmit_in_type;
86
    signal s_xmito:     spw_xmit_out_type;
87
    signal s_inact:     std_logic;
88
    signal s_inbvalid:  std_logic;
89
    signal s_inbits:    std_logic_vector(rxchunk-1 downto 0);
90
 
91
    -- interface signals
92
    signal rst:       std_logic := '1';
93
    signal autostart: std_logic;
94
    signal linkstart: std_logic;
95
    signal linkdis:   std_logic;
96
    signal divcnt:    std_logic_vector(7 downto 0) := (others => '0');
97
    signal tick_in:   std_logic;
98
    signal ctrl_in:   std_logic_vector(1 downto 0);
99
    signal time_in:   std_logic_vector(5 downto 0);
100
    signal rxroom:    std_logic_vector(5 downto 0);
101
    signal txwrite:   std_logic;
102
    signal txflag:    std_logic;
103
    signal txdata:    std_logic_vector(7 downto 0);
104
    signal txrdy:     std_logic;
105
    signal tick_out:  std_logic;
106
    signal ctrl_out:  std_logic_vector(1 downto 0);
107
    signal time_out:  std_logic_vector(5 downto 0);
108
    signal rxchar:    std_logic;
109
    signal rxflag:    std_logic;
110
    signal rxdata:    std_logic_vector(7 downto 0);
111
    signal started:   std_logic;
112
    signal connecting:std_logic;
113
    signal running:   std_logic;
114
    signal errdisc:   std_logic;
115
    signal errpar:    std_logic;
116
    signal erresc:    std_logic;
117
    signal errcred:   std_logic;
118
    signal spw_di:    std_logic;
119
    signal spw_si:    std_logic;
120
    signal spw_do:    std_logic;
121
    signal spw_so:    std_logic;
122
 
123
    -- misc
124
    signal errany:    std_logic;
125
 
126
    procedure print(i: integer) is
127
        variable v: LINE;
128
    begin
129
        write(v, i);
130
        writeline(output, v);
131
    end procedure;
132
 
133
    procedure print(x: std_logic_vector) is
134
        variable v: LINE;
135
    begin
136
        write(v, to_bitvector(x));
137
        writeline(output, v);
138
    end procedure;
139
 
140
    procedure prints(s: string) is
141
        variable v: LINE;
142
    begin
143
        write(v, s);
144
        writeline(output, v);
145
    end procedure;
146
 
147
    procedure print(lbl: string; x: integer) is
148
        variable v: LINE;
149
    begin
150
        write(v, lbl & " = ");
151
        write(v, x);
152
        writeline(output, v);
153
    end procedure;
154
 
155
    procedure print(lbl: string; x: real) is
156
        variable v: LINE;
157
    begin
158
        write(v, lbl & " = ");
159
        write(v, x);
160
        writeline(output, v);
161
    end procedure;
162
 
163
begin
164
 
165
    -- Instantiate components.
166
 
167
    spwlink_inst: spwlink
168
        generic map (
169
            reset_time =>      integer(sys_clock_freq * 0.0000064) )  -- 6.4 us
170
        port map (
171
            clk     => sysclk,
172
            rst     => rst,
173
            linki   => s_linki,
174
            linko   => s_linko,
175
            rxen    => s_rxen,
176
            recvo   => s_recvo,
177
            xmiti   => s_xmiti,
178
            xmito   => s_xmito );
179
 
180
    spwrecv_inst: spwrecv
181
        generic map (
182
            disconnect_time => integer(sys_clock_freq * 0.00000085),   -- 850 ns
183
            rxchunk => rxchunk )
184
        port map (
185
            clk     => sysclk,
186
            rxen    => s_rxen,
187
            recvo   => s_recvo,
188
            inact   => s_inact,
189
            inbvalid => s_inbvalid,
190
            inbits  => s_inbits );
191
 
192
    spwxmit_if: if tximpl = impl_generic generate
193
        spwxmit_inst: spwxmit
194
            port map (
195
                clk     => sysclk,
196
                rst     => rst,
197
                divcnt  => divcnt,
198
                xmiti   => s_xmiti,
199
                xmito   => s_xmito,
200
                spw_so  => spw_so,
201
                spw_do  => spw_do );
202
    end generate;
203
    spwxmit_fast_if: if tximpl = impl_fast generate
204
        spwxmit_fast_inst: spwxmit_fast
205
            port map (
206
                clk     => sysclk,
207
                txclk   => txclk,
208
                rst     => rst,
209
                divcnt  => divcnt,
210
                xmiti   => s_xmiti,
211
                xmito   => s_xmito,
212
                spw_so  => spw_so,
213
                spw_do  => spw_do );
214
    end generate;
215
 
216
    spwrecvfront_generic_if: if rximpl = impl_generic generate
217
        spwrecvfront_generic_inst: spwrecvfront_generic
218
            port map (
219
                clk     => sysclk,
220
                rxen    => s_rxen,
221
                inact   => s_inact,
222
                inbvalid => s_inbvalid,
223
                inbits  => s_inbits,
224
                spw_di  => spw_di,
225
                spw_si  => spw_si );
226
    end generate;
227
    spwrecvfront_fast_if: if rximpl = impl_fast generate
228
        spwrecvfront_fast_inst: spwrecvfront_fast
229
            generic map (
230
                rxchunk => rxchunk )
231
            port map (
232
                clk     => sysclk,
233
                rxclk   => rxclk,
234
                rxen    => s_rxen,
235
                inact   => s_inact,
236
                inbvalid => s_inbvalid,
237
                inbits  => s_inbits,
238
                spw_di  => spw_di,
239
                spw_si  => spw_si );
240
    end generate;
241
 
242
    s_linki <= ( autostart  => autostart,
243
                 linkstart  => linkstart,
244
                 linkdis    => linkdis,
245
                 rxroom     => rxroom,
246
                 tick_in    => tick_in,
247
                 ctrl_in    => ctrl_in,
248
                 time_in    => time_in,
249
                 txwrite    => txwrite,
250
                 txflag     => txflag,
251
                 txdata     => txdata );
252
    started     <= s_linko.started;
253
    connecting  <= s_linko.connecting;
254
    running     <= s_linko.running;
255
    errdisc     <= s_linko.errdisc;
256
    errpar      <= s_linko.errpar;
257
    erresc      <= s_linko.erresc;
258
    errcred     <= s_linko.errcred;
259
    txrdy       <= s_linko.txack;
260
    tick_out    <= s_linko.tick_out;
261
    ctrl_out    <= s_linko.ctrl_out;
262
    time_out    <= s_linko.time_out;
263
    rxchar      <= s_linko.rxchar;
264
    rxflag      <= s_linko.rxflag;
265
    rxdata      <= s_linko.rxdata;
266
 
267
    -- Logic OR of all error signals.
268
    errany <= errdisc or errpar or erresc or errcred;
269
 
270
    -- Generate system clock.
271
    process is
272
    begin
273
        if sys_clock_enable /= '1' then
274
            wait until sys_clock_enable = '1';
275
        end if;
276
        sysclk <= '1';
277
        wait for (0.5 sec) / sys_clock_freq;
278
        sysclk <= '0';
279
        wait for (0.5 sec) / sys_clock_freq;
280
    end process;
281
 
282
    -- Generate rx sample clock.
283
    process is
284
    begin
285
        if sys_clock_enable /= '1' then
286
            wait until sys_clock_enable = '1';
287
        end if;
288
        rxclk <= '1';
289
        wait for (0.5 sec) / rx_clock_freq;
290
        rxclk <= '0';
291
        wait for (0.5 sec) / rx_clock_freq;
292
    end process;
293
 
294
    -- Generate tx clock.
295
    process is
296
    begin
297
        if sys_clock_enable /= '1' then
298
            wait until sys_clock_enable = '1';
299
        end if;
300
        txclk <= '1';
301
        wait for (0.5 sec) / tx_clock_freq;
302
        txclk <= '0';
303
        wait for (0.5 sec) / tx_clock_freq;
304
    end process;
305
 
306
    -- Collect output bits on SPW_DO and SPW_SO.
307
    process is
308
        variable t_last: time;
309
        variable output_last_do: std_logic;
310
        variable output_last_so: std_logic;
311
    begin
312
        if output_collect = '1' then
313
            -- wait for next bit
314
            if output_ptr <= output_bits'high then
315
                output_bits(output_ptr) <= spw_do;
316
                output_ptr <= output_ptr + 1;
317
            end if;
318
            output_last_do := spw_do;
319
            output_last_so := spw_so;
320
            t_last := now;
321
            wait until (output_collect = '0') or (output_last_do /= spw_do) or (output_last_so /= spw_so);
322
            if output_collect = '1' and output_ptr > 1 then
323
                assert now > t_last + outbit_period - 1 ns
324
                    report "output bit period too short";
325
                assert now < t_last + outbit_period + 1 ns
326
                    report "output bit period too long";
327
            end if;
328
        else
329
            -- reset
330
            output_ptr <= 0;
331
            output_last_do := '0';
332
            output_last_so := '0';
333
            wait until output_collect = '1';
334
        end if;
335
    end process;
336
 
337
    -- Collect received data on rxdata and tick_out.
338
    process is
339
    begin
340
        wait until ((output_collect = '1') and rising_edge(sysclk)) or
341
                   ((output_collect = '0') and (output_nchars /= 0));
342
        if output_collect = '0' then
343
            output_nchars <= 0;
344
        elsif rising_edge(sysclk) and (output_nchars <= output_chars'high) then
345
            assert (rxchar = '0') or (tick_out = '0');
346
            if tick_out = '1' then
347
                output_chars(output_nchars) <= "10" & ctrl_out & time_out;
348
                output_nchars <= output_nchars + 1;
349
            elsif rxchar = '1' then
350
                output_chars(output_nchars) <= "0" & (rxflag) & rxdata;
351
                output_nchars <= output_nchars + 1;
352
            end if;
353
        end if;
354
    end process;
355
 
356
    -- Generate input data.
357
    process is
358
        procedure input_reset is
359
        begin
360
            spw_di <= '0';
361
            spw_si <= '0';
362
            input_par <= '0';
363
        end procedure;
364
        procedure genbit(b: std_logic) is
365
        begin
366
            spw_si <= not (spw_si xor spw_di xor b);
367
            spw_di <= b;
368
            wait for inbit_period;
369
        end procedure;
370
        procedure genfct is
371
        begin
372
            genbit(input_par);
373
            genbit('1');
374
            genbit('0');
375
            input_par <= '0';
376
            genbit('0');
377
        end procedure;
378
        procedure genesc is
379
        begin
380
            genbit(input_par);
381
            genbit('1');
382
            genbit('1');
383
            input_par <= '0';
384
            genbit('1');
385
        end procedure;
386
        procedure geneop(e: std_logic) is
387
        begin
388
            genbit(input_par);
389
            genbit('1');
390
            genbit(e);
391
            input_par <= '1';
392
            genbit(not e);
393
        end procedure;
394
        procedure gendat(dat: std_logic_vector(7 downto 0)) is
395
        begin
396
            genbit(not input_par);
397
            genbit('0');
398
            genbit(dat(0)); genbit(dat(1)); genbit(dat(2)); genbit(dat(3));
399
            genbit(dat(4)); genbit(dat(5)); genbit(dat(6));
400
            input_par <= dat(0) xor dat(1) xor dat(2) xor dat(3) xor
401
                         dat(4) xor dat(5) xor dat(6) xor dat(7);
402
            genbit(dat(7));
403
        end procedure;
404
    begin
405
        input_idle <= '1';
406
        input_reset;
407
        wait until input_pattern /= 0;
408
        input_idle <= '0';
409
        while input_pattern /= 0 loop
410
            if input_pattern = 1 then
411
                -- NULL tokens
412
                genesc; genfct;
413
            elsif input_pattern = 2 then
414
                -- FCT tokens
415
                genfct;
416
            elsif input_pattern = 3 then
417
                -- invalid bit pattern
418
                genbit('0');
419
                genbit('1');
420
            elsif input_pattern = 4 then
421
                -- EOP token
422
                geneop('0');
423
            elsif input_pattern = 5 then
424
                -- FCT, TIME, 8 chars, NULLs
425
                genfct;
426
                genesc; gendat("00111000");
427
                gendat("01010101");
428
                gendat("10101010");
429
                gendat("01010101");
430
                gendat("10101010");
431
                gendat("01010101");
432
                gendat("10101010");
433
                gendat("01010101");
434
                gendat("10101010");
435
                while input_pattern = 5 loop
436
                    genesc; genfct;
437
                end loop;
438
            elsif input_pattern = 6 then
439
                -- ESC tokens
440
                genesc;
441
            elsif input_pattern = 7 then
442
                -- FCT, NULL, NULL, EOP, EEP, NULLs
443
                genfct;
444
                genesc; genfct;
445
                genesc; genfct;
446
                geneop('0');
447
                geneop('1');
448
                while input_pattern = 7 loop
449
                    genesc; genfct;
450
                end loop;
451
            elsif input_pattern = 8 then
452
                -- FCT, NULL, NULL, NULL, NULL, NULL, char, parity error
453
                genfct;
454
                genesc; genfct;
455
                genesc; genfct;
456
                genesc; genfct;
457
                genesc; genfct;
458
                genesc; genfct;
459
                gendat("01010101");
460
                genbit(not input_par);
461
                genbit('0');
462
                genbit('1'); genbit('0'); genbit('1'); genbit('0');
463
                genbit('1'); genbit('0'); genbit('1');
464
                input_par <= '1'; -- wrong parity !!
465
                genbit('0');
466
                while input_pattern = 8 loop
467
                    genesc; genfct;
468
                end loop;
469 7 jorisvr
            elsif input_pattern = 9 then
470
                -- FCT, FCT, NULLs
471
                genfct;
472
                genfct;
473
                while input_pattern = 9 loop
474
                    genesc; genfct;
475
                end loop;
476 2 jorisvr
            else
477
                assert false;
478
            end if;
479
        end loop;
480
    end process;
481
 
482
    -- Main process.
483
    process is
484
 
485
        -- Skip NULL tokens and return position of first non-NULL.
486
        function skip_null(data: in std_logic_vector; start: in integer; len: in integer) return integer is
487
            variable i: integer;
488
        begin
489
            i := start;
490
            if (i + 7 < len) and (data((i+1) to (i+7)) = "1110100") then
491
                i := i + 8;
492
            end if;
493
            while (i + 7 < len) and (data(i to (i+7)) = "01110100") loop
494
                i := i + 8;
495
            end loop;
496
            return i;
497
        end function;
498
 
499
        function check_parity(data: in std_logic_vector; start: in integer; len: in integer) return boolean is
500
            variable i: integer;
501
            variable p: std_logic;
502
        begin
503
            i := start;
504
            p := data(start);
505
            while i + 3 < len loop
506
                if data(i+1) = '1' then
507
                    if data(0) /= p then return false; end if;
508
                    p := data(2) xor data(3);
509
                    i := i + 4;
510
                else
511
                    if i + 9 < len then return true; end if;
512
                    if data(0) /= not p then return false; end if;
513
                    p := not (data(2) xor data(3) xor data(4) xor data(5) xor
514
                              data(6) xor data(7) xor data(8) xor data(9));
515
                    i := i + 10;
516
                end if;
517
            end loop;
518
            return true;
519
        end function;
520
 
521
        variable i: integer;
522
 
523
    begin
524
 
525
        -- Wait for start of test.
526
        wait for startwait;
527
 
528
        -- Initialize.
529
        rst <= '1';
530
        input_pattern <= 0;
531
        sys_clock_enable <= '1';
532
        output_collect <= '0';
533
 
534
        -- Say hello
535
        report "Starting spwlink test bench";
536
        print("  sys_clock_freq", sys_clock_freq);
537
        print("  rx_clock_freq ", rx_clock_freq);
538
        print("  tx_clock_freq ", tx_clock_freq);
539
        print("  input_rate    ", input_rate);
540
        print("  tx_clock_div  ", tx_clock_div);
541
        case rximpl is
542
            when impl_generic => prints("  rximpl         = impl_generic");
543
            when impl_fast =>    prints("  rximpl         = impl_fast");
544
        end case;
545
        print("  rxchunk       ", rxchunk);
546
        case tximpl is
547
            when impl_generic => prints("  tximpl         = impl_generic");
548
            when impl_fast =>    prints("  tximpl         = impl_fast");
549
        end case;
550
 
551
        -- Test 1: Reset.
552
        autostart <= '0'; linkstart <= '0'; linkdis <= '0';
553
        divcnt <= std_logic_vector(to_unsigned(tx_clock_div, divcnt'length));
554
        tick_in <= '0'; ctrl_in <= "00"; time_in <= "000000"; rxroom <= "000000";
555
        txwrite <= '0'; txflag <= '0'; txdata <= "00000000";
556
        wait until rising_edge(sysclk);
557
        wait until rising_edge(sysclk);
558
        wait for 1 ns;
559
        rst <= '0';
560
        assert (txrdy = '0')        report " 1. reset (txrdy = 0)";
561
        assert (tick_out = '0')     report " 1. reset (tick_out = 0)";
562
        assert (rxchar = '0')       report " 1. reset (rxchar = 0)";
563
        assert (started = '0')      report " 1. reset (started = 0)";
564
        assert (connecting = '0')   report " 1. reset (connecting = 0)";
565
        assert (running = '0')      report " 1. reset (running = 0)";
566
        assert (errdisc = '0')      report " 1. reset (errdisc = 0)";
567
        assert (errpar = '0')       report " 1. reset (errpar = 0)";
568
        assert (erresc = '0')       report " 1. reset (erresc = 0)";
569
        assert (errcred = '0')      report " 1. reset (errcred = 0)";
570
        assert (spw_do = '0')       report " 1. reset (spw_do = 0)";
571
        assert (spw_so = '0')       report " 1. reset (spw_so = 0)";
572
 
573
        -- Test 2: Remain idle after one clock cycle.
574
        wait until rising_edge(sysclk);
575
        wait until falling_edge(sysclk);
576
        assert (started = '0') and (running = '0')
577
            report " 2. init (state)";
578
        assert (spw_do =  '0') and (spw_so = '0')
579
            report " 2. init (SPW idle)";
580
 
581
        -- Test 3: Move to Ready state.
582
        wait on started, running, spw_do, spw_so for 50 us;
583
        assert (started = '0') and (running = '0')
584
            report " 3. ready (state)";
585
        assert (spw_do = '0') and (spw_so = '0')
586
            report " 3. ready (SPW idle)";
587
 
588
        -- Test 4: Start link; wait for NULL patterns.
589
        linkstart <= '1';
590
        rxroom <= "001111";
591
        wait on started, connecting, running, spw_do, spw_so for 1 us;
592
        assert (started = '1') and (running = '0')
593
            report " 4. nullgen (started)";
594
        if spw_so = '0' then
595
            wait on started, connecting, running, spw_do, spw_so for 1.2 us;
596
        end if;
597
        assert (started = '1') and (connecting = '0') and (running = '0') and
598
               (spw_do = '0') and (spw_so = '1')
599
            report " 4. nullgen (SPW strobe)";
600
        output_collect <= '1';
601
        wait on started, connecting, running for (7.1 * outbit_period);
602
        assert (started = '1') and (running = '0')
603
            report " 4. nullgen (state 2)";
604
        assert (output_ptr = 8) and (output_bits(0 to 7) = "01110100")
605
            report " 4. nullgen (NULL 1)";
606
        -- got the first NULL, wait for the second one ...
607
        wait on started, connecting, running for (8.0 * outbit_period);
608
        assert (started = '1') and (running = '0')
609
            report " 4. nullgen (state 3)";
610
        assert (output_ptr = 16) and (output_bits(8 to 15) = "01110100")
611
            report " 4. nullgen (NULL 2)";
612
        output_collect <= '0';
613
 
614
        -- Test 5: Timeout in Started state.
615
        wait on started, connecting, running, errany for 9.5 us - (15.0 * outbit_period);
616
        assert (started = '1') and (running = '0') and (errany = '0')
617
            report " 5. started_timeout (wait)";
618
        wait on started, connecting, running, errany for 4 us;
619
        assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
620
            report " 5. started_timeout (trigger)";
621
        wait for (3.1 * outbit_period + 20 * txclk_period);
622
        assert (spw_do = '0') and (spw_so = '0')
623
            report " 5. started_timeout (SPW to zero)";
624
 
625
        -- Test 6: Start link; simulate NULL pattern; wait for FCT pattern.
626
        wait on started, connecting, running, spw_so for 18 us - (3.1 * outbit_period + 20 * txclk_period);
627
        assert (started = '0') and (connecting = '0') and (running = '0') and (spw_so = '0')
628
            report " 6. fctgen (SPW idle)";
629
        wait on started, connecting, running, spw_so for 2 us;
630
        assert (started = '1') and (connecting = '0') and (running = '0')
631
            report " 6. fctgen (started)";
632
        if spw_so = '0' then
633
            wait on started, connecting, running, spw_do, spw_so for 1.2 us;
634
        end if;
635
        assert (spw_do = '0') and (spw_so = '1')
636
            report " 6. fctgen (SPW strobe)";
637
        output_collect <= '1';
638
        input_pattern <= 1;
639
        wait on started, connecting, running for 8 us;
640
        assert (started = '0') and (connecting = '1') and (running = '0')
641
            report " 6. fctgen (detect NULL)";
642
        wait for (1.1 sec) / sys_clock_freq;
643
        wait on started, connecting, running, errany for 12 us;
644
        assert (started = '0') and (connecting = '1') and (running = '0') and (errany = '0')
645
            report " 6. fctgen (connecting failed early)";
646
        assert (output_ptr > 7) and (output_bits(0 to 7) = "01110100")
647
            report " 6. fctgen (gen NULL)";
648
        i := skip_null(output_bits, 0, output_ptr);
649
        assert (i > 0) and (i + 11 < output_ptr) and (output_bits(i to (i+11)) = "010001110100")
650
            report " 6. fctgen (gen FCT NULL)";
651
        output_collect <= '0';
652
 
653
        -- Test 7: Timeout in Connecting state.
654
        wait on started, connecting, running, errany for 4 us;
655
        assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
656
            report " 7. connecting_timeout";
657
        input_pattern <= 0;
658
        wait until rising_edge(sysclk);
659
 
660
        -- Test 8: Autostart link; simulate NULL and FCT; move to Run state; disconnect.
661
        linkstart <= '0';
662
        autostart <= '1';
663
        rxroom <= "010000";
664
        wait on started, connecting, running, errany for 50 us;
665
        assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
666
            report " 8. autostart (wait)";
667
        output_collect <= '1';
668
        input_pattern <= 1;
669 7 jorisvr
        wait on started, connecting, running for 200 ns + 24 * inbit_period;
670 2 jorisvr
        assert (started = '1') and (connecting = '0') and (running = '0')
671
            report " 8. autostart (Started)";
672 7 jorisvr
        input_pattern <= 9;
673 2 jorisvr
        wait on started, connecting, running for 1 us;
674
        assert (started = '0') and (connecting = '1') and (running = '0')
675
            report " 8. autostart (Connecting)";
676
        wait on started, connecting, running, errany for 200 ns + 24 * inbit_period;
677
        assert (started = '0') and (connecting = '0') and (running = '1') and (errany = '0')
678
            report " 8. autostart (Run)";
679
        input_pattern <= 1;
680
        txwrite <= '1';
681
        if txrdy = '0' then
682
            wait on running, errany, txrdy for (20 * outbit_period);
683
        end if;
684
        assert (running = '1') and (errany = '0') and (txrdy = '1')
685
            report " 8. running (txrdy = 1)";
686
        txwrite <= '0';
687
        wait on running, errany for 50 us;
688
        assert (running = '1') and (errany = '0')
689
            report " 8. running stable";
690
        assert output_bits(1 to 24) = "011101000100010001110100"
691
            report " 8. NULL FCT FCT NULL";
692
        output_collect <= '0';
693
        linkdis <= '1';
694
        wait on started, running, errany for (2.1 sec) / sys_clock_freq;
695
        assert (started = '0') and (running = '0') and (errany = '0')
696
            report " 8. link disable";
697
        autostart <= '0';
698
        linkdis <= '0';
699
        input_pattern <= 0;
700
        wait until rising_edge(sysclk);
701
 
702
        -- Test 9: Start link until Run state; disconnect.
703
        linkstart <= '1';
704
        rxroom <= "001000";
705
        input_pattern <= 1;
706
        wait on started, connecting, running for 20 us;
707
        assert (started = '1') and (connecting = '0') and (running = '0')
708
            report " 9. running_disconnect (Started)";
709
        linkstart <= '0';
710
        wait until rising_edge(sysclk);
711 7 jorisvr
        input_pattern <= 9;
712 2 jorisvr
        wait on started, connecting, running, errany for 20 * inbit_period;
713
        assert (started = '0') and (connecting = '1') and (running = '0') and (errany = '0')
714
            report " 9. running_disconnect (Connecting)";
715 7 jorisvr
        wait on started, connecting, running, errany for 200 ns + 24 * inbit_period;
716 2 jorisvr
        assert (started = '0') and (connecting = '0') and (running = '1') and (errany = '0')
717
            report " 9. running_disconnect (Run)";
718
        input_pattern <= 0;
719
        wait until input_idle = '1';
720
        wait on started, connecting, running, errany for 1500 ns;
721
        assert errdisc = '1'
722
            report " 9. running_disconnect (errdisc = 1)";
723
        if running = '1' then
724
            wait on started, connecting, running for (1.1 sec) / sys_clock_freq;
725
        end if;
726
        assert (started = '0') and (connecting = '0') and (running = '0')
727
            report " 9. running_disconnect (running = 0)";
728
        wait until rising_edge(sysclk);
729
        assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
730
            report " 9. running_disconnect (reset)";
731
        wait until rising_edge(sysclk);
732
 
733
        -- Test 10: Junk signal before starting link.
734
        autostart <= '1';
735
        input_pattern <= 3;
736
        wait on started, errany for 6 us;
737
        assert (started = '0') and (errany = '0')
738
            report "10. junk signal (ignore noise)";
739
        input_pattern <= 2;
740
        wait on started, errany for 4 us;
741
        assert (started = '0') and (errany = '0')
742
            report "10. junk signal (ignore FCT)";
743
        input_pattern <= 0;
744
        wait until input_idle = '1';
745
        input_pattern <= 1; -- send NULL
746
        wait until input_idle = '0';
747
        input_pattern <= 3; -- send invalid pattern; spw should now reset
748
        wait on started, errany for 8 us;
749
        assert (started = '0') and (errany = '0')
750
            report "10. junk signal (hidden reset)";
751
        input_pattern <= 1; -- send NULL
752
        wait on started, errany for 10 us;
753
        assert (started = '0') and (errany = '0')
754
            report "10. junk signal (waiting)";
755
        wait on started, errany for 10 us;
756
        assert (started = '1') and (errany = '0')
757
            report "10. junk signal (Started)";
758
        autostart <= '0';
759
        rst <= '1';
760
        wait until rising_edge(sysclk);
761
        rst <= '0';
762
        wait until rising_edge(sysclk);
763
        assert (started = '0') and (errany = '0')
764
            report "10. junk signal (rst)";
765
        wait until rising_edge(sysclk);
766
 
767
        -- Test 11: Incoming EOP before first FCT.
768
        linkstart <= '1';
769
        rxroom <= "001000";
770
        input_pattern <= 1;
771
        wait on connecting, running, errany for 21 us;
772
        assert (connecting = '1') and (errany = '0')
773
            report "11. unexpected EOP (Connecting)";
774
        input_pattern <= 4;
775
        linkstart <= '0';
776
        wait on connecting, running, errany for 200 ns + 24 * inbit_period;
777
        assert (connecting = '0') and (running = '0') and (errany = '0')
778
            report "11. unexpected EOP (reset on EOP)";
779
        input_pattern <= 0;
780
        wait for (10 * outbit_period);
781
 
782
        -- Test 12: Send and receive characters, time codes, abort on double ESC.
783
        wait until falling_edge(sysclk);
784
        linkstart <= '1';
785
        wait on started, errany for 21 us;
786
        assert (started = '1') and (errany = '0')
787
            report "12. characters (Started)";
788
        rxroom <= "001000";
789
        input_pattern <= 1;
790
        output_collect <= '1';
791
        tick_in <= '1';
792
        wait on connecting, running, errany for 21 us;
793
        assert (connecting = '1') and (errany = '0')
794
            report "12. characters (Connecting)";
795
        wait until output_ptr > 9 for 2 us;
796
        input_pattern <= 5; -- FCT, TIME, 8 chars, NULLs
797
        time_in <= "000111";
798
        txwrite <= '1';
799
        txflag <= '0';
800
        txdata <= "01101100";
801
        wait on connecting, running, errany for 200 ns + (24 * inbit_period);
802
        assert (running = '1') and (errany = '0')
803
            report "12. characters (Run)";
804
        wait until rising_edge(sysclk);
805
        assert (running = '1') and (errany = '0')
806
            report "12. characters (running = 1)";
807
        tick_in <= '0';
808
        wait for 4 * outbit_period;   -- wait until first FCT sent
809
        rxroom <= "000111";
810
        wait until txrdy = '1' for 200 ns + (20 * outbit_period);
811
        assert (running = '1') and (txrdy = '1')
812
            report "12. characters (txrdy = 1)";
813
        wait on running, errany for 50 us + (80 * outbit_period);
814
        assert (running = '1') and (errany = '0')
815
            report "12. characters (stable)";
816
        input_pattern <= 6; -- just ESC tokens
817
        wait on running, errany for 200 ns + (32 * inbit_period);
818
        assert erresc = '1'
819
            report "12. characters (erresc = 1)";
820
        wait until rising_edge(sysclk);
821
        wait for 1 ns;
822
        assert (started = '0') and (connecting = '0') and (running = '0')
823
            report "12. characters (reset)";
824
        assert (output_ptr > 8) and (output_bits(1 to 8) = "01110100")
825
            report "12. characters (gen NULL 1)";
826
        i := skip_null(output_bits, 1, output_ptr);
827
        assert (i > 0) and (output_bits(i to (i+3)) = "0100")
828
            report "12. characters (gen FCT)";
829
        i := skip_null(output_bits, i + 4, output_ptr);
830
        assert (i + 13 < output_ptr) and (output_bits(i to (i+13)) = "01111011100000")
831
            report "12. characters (gen TimeCode)";
832
        i := i + 14;
833
        assert (i + 79 < output_ptr) and (output_bits(i to (i+79)) = "00001101101000110110100011011010001101101000110110100011011010001101101000110110")
834
            report "12. characters (gen Data)";
835
        i := i + 80;
836
        assert (i + 7 < output_ptr) and (output_bits(i to (i+7)) = "01110100")
837
            report "12. characters (gen NULL 2)";
838
        assert (output_nchars > 0) and (output_chars(0) = "1000111000")
839
            report "12. characters (got TimeCode)";
840
        assert (output_nchars > 1) and (output_chars(1) = "0001010101")
841
            report "12. characters (got byte 1)";
842
        assert (output_nchars > 2) and (output_chars(2) = "0010101010")
843
            report "12. characters (got byte 2)";
844
        assert (output_nchars > 3) and (output_chars(3) = "0001010101")
845
            report "12. characters (got byte 3)";
846
        assert (output_nchars > 4) and (output_chars(4) = "0010101010")
847
            report "12. characters (got byte 4)";
848
        assert check_parity(output_bits, 1, output_ptr)
849
            report "12. parity of output bits";
850
        output_collect <= '0';
851
        input_pattern <= 0;
852
        txwrite <= '0';
853
        linkstart <= '0';
854
        wait for (20 * outbit_period);
855
 
856
        -- Test 13: Send and receive EOP, EEP, abort on credit error.
857
        linkstart <= '1';
858
        rxroom <= "001000";
859
        input_pattern <= 1;
860
        output_collect <= '1';
861
        wait on connecting, running, errany for 21 us;
862
        assert (connecting = '1') and (errany = '0')
863
            report "13. eop, eep (Connecting)";
864
        wait until output_ptr > 9 for 2 us;
865
        input_pattern <= 7; -- FCT, NULL, NULL, EOP, EEP, NULLs
866
        wait for (1.1 sec) / sys_clock_freq;
867
        wait on connecting, running, errany for 12 us;
868
        assert (running = '1') and (errany = '0')
869
            report "13. eop, eep (Run)";
870
        wait for 1 ns;
871
        txwrite <= '1';
872
        txflag <= '1';
873
        txdata <= "01101100";
874
        wait until rising_edge(sysclk) and txrdy = '1' for 1 us + (14 * outbit_period);
875
        assert (txrdy = '1') and (running = '1') and (errany = '0')
876
            report "13. eop, eep (txrdy 1)";
877
        rxroom <= "000111" after 1 ns;
878
        txdata <= "00000001" after 1 ns;
879
        wait until rising_edge(sysclk) and txrdy = '1' for 1 us + (14 * outbit_period);
880
        assert (txrdy = '1') and (running = '1') and (errany = '0')
881
            report "13. eop, eep (txrdy 2)";
882
        txdata <= "00000000" after 1 ns;
883
        wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
884
        assert (txrdy = '1') and (running = '1') and (errany = '0')
885
            report "13. eop, eep (txrdy 3)";
886
        txdata <= "11111111" after 1 ns;
887
        wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
888
        assert (txrdy = '1') and (running = '1') and (errany = '0')
889
            report "13. eop, eep (txrdy 4)";
890
        txdata <= "11111110" after 1 ns;
891
        wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
892
        assert (txrdy = '1') and (running = '1') and (errany = '0')
893
            report "13. eop, eep (txrdy 5)";
894
        txdata <= "01010101" after 1 ns;
895
        wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
896
        assert (txrdy = '1') and (running = '1') and (errany = '0')
897
            report "13. eop, eep (txrdy 6)";
898
        txdata <= "10101010" after 1 ns;
899
        wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
900
        assert (txrdy = '1') and (running = '1') and (errany = '0')
901
            report "13. eop, eep (txrdy 7)";
902
        txdata <= "01010101" after 1 ns;
903
        wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
904
        assert (txrdy = '1') and (running = '1') and (errany = '0')
905
            report "13. eop, eep (txrdy 8)";
906
        txdata <= "10101010" after 1 ns;
907
        wait until rising_edge(sysclk) and (txrdy = '1') for (14 * outbit_period);
908
        assert (txrdy = '0') and (running = '1') and (errany = '0')
909
            report "13. eop, eep (txrdy 9)";
910
        txwrite <= '0';
911
        txflag <= '0';
912
        wait on running, errany for (10 * outbit_period);
913
        assert (running = '1') and (errany = '0')
914
            report "13. eop, eep (flush out)";
915
        input_pattern <= 2; -- FCT tokens
916
        wait on running, errany for (80 * inbit_period);
917
        assert errcred = '1'
918
            report "13. eop, eep (errcred = 1)";
919
        wait until running = '0';
920
        assert (output_ptr > 8) and (output_bits(1 to 8) = "01110100")
921
            report "13. eop, eep (gen NULL 1)";
922
        i := skip_null(output_bits, 1, output_ptr);
923
        assert (i > 0) and (output_bits(i to (i+3)) = "0100")
924
            report "13. eop, eep (gen FCT)";
925
        i := i + 4;
926
        for j in 0 to 3 loop
927
            i := skip_null(output_bits, i, output_ptr);
928
            assert (i + 3 < output_ptr) and (output_bits(i+1 to (i+3)) = "101")
929
                report "13. eop, eep (eop)";
930
            i := skip_null(output_bits, i + 4, output_ptr);
931
            assert (i + 3 < output_ptr) and (output_bits(i+1 to (i+3)) = "110")
932
                report "13. eop, eep (eep)";
933
            i := i + 4;
934
        end loop;
935
        assert (i + 8 < output_ptr) and (output_bits(i to (i+8)) = "111101000")
936
            report "13. eop, eep (gen NULL 2)";
937
        assert check_parity(output_bits, 1, output_ptr)
938
            report "12. parity of output bits";
939
        assert (output_nchars > 0) and (output_chars(0) = "0100000000")
940
            report "13. eop, eep (got EOP)";
941
        assert (output_nchars = 2) and (output_chars(1) = "0100000001")
942
            report "13. eop, eep (got EEP)";
943
        output_collect <= '0';
944
        input_pattern <= 0;
945
        linkstart <= '0';
946
        wait until rising_edge(sysclk);
947
 
948
        -- Test 14: Abort on parity error.
949
        wait for 10 us;
950
        assert spw_do = '0' and spw_so = '0'
951
            report "14. output still babbling";
952
        linkstart <= '1';
953
        rxroom <= "001000";
954
        input_pattern <= 1;
955
        output_collect <= '1';
956
        wait for 1 ns; -- ghdl is totally fucked up
957
        wait on connecting, running, errany for 21 us;
958
        assert (connecting = '1') and (errany = '0')
959
            report "14. partity (Connecting)";
960
        input_pattern <= 8; -- FCT, NULL, NULL, NULL, NULL, NULL, char, error
961
        wait for (1.1 sec) / sys_clock_freq;
962
        wait on running, errany for 12 us;
963
        assert (running = '1') and (errany = '0')
964
            report "14. parity (Run)";
965
        wait on running, errany for 150 ns + (84 * inbit_period);
966
        assert errpar = '1'
967
            report "14. parity (errpar = 1)";
968
        wait until running = '0';
969
        assert (output_nchars = 1) and (output_chars(0) = "0001010101")
970
            report "14. parity (received char)";
971
        output_collect <= '0';
972
        input_pattern <= 0;
973
        linkstart <= '0';
974
        wait until rising_edge(sysclk);
975
 
976
        -- Stop simulation
977
        input_pattern <= 0;
978
        wait for 100 us;
979
        sys_clock_enable <= '0';
980
        report "Done.";
981
        wait;
982
 
983
    end process;
984
 
985
end tb_arch;

powered by: WebSVN 2.1.0

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