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

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [trunk/] [rtl/] [systemc/] [link_l2/] [link_frame_rx_l3.cpp] - Blame information for rev 19

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 acastong
//link_frame_rx_l3.cpp
2
 
3
/* ***** BEGIN LICENSE BLOCK *****
4
 * Version: MPL 1.1
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version
7
 * 1.1 (the "License"); you may not use this file except in compliance with
8
 * the License. You may obtain a copy of the License at
9
 * http://www.mozilla.org/MPL/
10
 *
11
 * Software distributed under the License is distributed on an "AS IS" basis,
12
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
 * for the specific language governing rights and limitations under the
14
 * License.
15
 *
16
 * The Original Code is HyperTransport Tunnel IP Core.
17
 *
18
 * The Initial Developer of the Original Code is
19
 * Ecole Polytechnique de Montreal.
20
 * Portions created by the Initial Developer are Copyright (C) 2005
21
 * the Initial Developer. All Rights Reserved.
22
 *
23
 * Contributor(s):
24
 *   Ami Castonguay <acastong@grm.polymtl.ca>
25
 *
26
 * Alternatively, the contents of this file may be used under the terms
27
 * of the Polytechnique HyperTransport Tunnel IP Core Source Code License
28
 * (the  "PHTICSCL License", see the file PHTICSCL.txt), in which case the
29
 * provisions of PHTICSCL License are applicable instead of those
30
 * above. If you wish to allow use of your version of this file only
31
 * under the terms of the PHTICSCL License and not to allow others to use
32
 * your version of this file under the MPL, indicate your decision by
33
 * deleting the provisions above and replace them with the notice and
34
 * other provisions required by the PHTICSCL License. If you do not delete
35
 * the provisions above, a recipient may use your version of this file
36
 * under either the MPL or the PHTICSCL License."
37
 *
38
 * ***** END LICENSE BLOCK ***** */
39
#include "link_frame_rx_l3.h"
40
 
41
 
42
///Constructor of module
43
link_frame_rx_l3::link_frame_rx_l3( sc_module_name name) : sc_module(name) {
44
 
45
        SC_METHOD(sample_link_width);
46
        sensitive_neg(pwrok);
47
        sensitive_pos(clk);
48
 
49
        SC_METHOD(clocked_process);
50
        sensitive_pos(clk);
51
 
52
        SC_METHOD(clocked_and_reset_process);
53
        sensitive_pos(clk);
54
        sensitive_neg(resetx);
55
 
56
        SC_METHOD(generate_ctl_and_timeout_errors);
57
        sensitive_pos(clk);
58
        sensitive_neg(resetx);
59
 
60
        SC_METHOD(encode);
61
        sensitive(reordered_cad);
62
 
63
        SC_METHOD(detect_ctl_transition_error);
64
        sensitive << state << reordered_data_ready << reordered_ctl
65
#ifdef INTERNAL_SHIFTER_ALIGNMENT
66
                << delayed_reordered_ctl << frame_shift_div_width
67
#endif
68
                ;
69
 
70
#ifndef INTERNAL_SHIFTER_ALIGNMENT
71
        SC_METHOD(output_reordered_cad_and_ctl);
72
        sensitive << reordered_cad << reordered_ctl;
73
#endif
74
 
75
 
76
}
77
 
78
 
79
 
80
/**
81
        Immediately following cold reset (when resetx becomes
82
        true and pwrok was false during the reset), the cad
83
        signals are sampled to determine link width.  At that
84
        time, both signals
85
        lk_update_link_failure_property_csr  and
86
        lk_update_link_width_csr  are activated to update the
87
        value in the CSR.
88
 
89
        This is a clocked process, but using the signal
90
        pwrok as a reset instead of the usual resetx.  This is done
91
        because the link only has to be sampled after a cold reset
92
        (after pwrok being low).
93
*/
94
void link_frame_rx_l3::sample_link_width(){
95
 
96
        if(!pwrok.read()){
97
                ready_to_sample_link_width = false;
98
                ready_to_sample_link_width2 = false;
99
                link_width_sampled = false;
100
                lk_sampled_link_width_csr = "000";
101
                lk_link_failure_csr = false;
102
                lk_update_link_failure_property_csr = false;
103
                lk_update_link_width_csr = false;
104
        }
105
        else{
106
                //Sychronisation because resetx is asynchronous
107
                ready_to_sample_link_width = resetx;
108
                ready_to_sample_link_width2 = ready_to_sample_link_width;
109
 
110
                lk_update_link_failure_property_csr = false;
111
                lk_update_link_width_csr = false;
112
 
113
                //When reset is done, sample link width
114
                if(ready_to_sample_link_width2.read() && !link_width_sampled.read()){
115
                        link_width_sampled = true;
116
                        lk_update_link_failure_property_csr = true;
117
                        lk_update_link_width_csr = true;
118
 
119
                        //If cad[0] is false at reset, it means that no link is connected
120
                        //We have a link failure
121
                        if( phy_cad_lk[0].read()[0] == false){
122
                                lk_link_failure_csr = true;
123
                        }
124
                        else{
125
                                lk_link_failure_csr = false;
126
                        }
127
 
128
                        /*
129
                        Link widths
130
 
131
                         000 8 bits
132
                         100 2 bits
133
                         101 4 bits
134
                         111  Link physically not connected
135
                        */
136
 
137
                                        //2 bits width
138
                        if((sc_bit)phy_cad_lk[0].read()[0] && (sc_bit)phy_cad_lk[1].read()[0]
139
#if CAD_IN_WIDTH > 2
140
                                && !(sc_bit)phy_cad_lk[2].read()[0] && !(sc_bit)phy_cad_lk[3].read()[0]
141
#endif
142
#if CAD_IN_WIDTH > 4
143
                                && !(sc_bit)phy_cad_lk[4].read()[0] && !(sc_bit)phy_cad_lk[5].read()[0]
144
                                && !(sc_bit)phy_cad_lk[6].read()[0] && !(sc_bit)phy_cad_lk[7].read()[0]
145
#endif
146
                                ){
147
                                lk_sampled_link_width_csr = "100";
148
                        }
149
#if CAD_IN_WIDTH > 2
150
                        //4 bits width
151
                        else if((sc_bit)phy_cad_lk[0].read()[0] && (sc_bit)phy_cad_lk[1].read()[0]
152
                                && (sc_bit)phy_cad_lk[2].read()[0] && (sc_bit)phy_cad_lk[3].read()[0]
153
#if CAD_IN_WIDTH > 4
154
                                && !(sc_bit)phy_cad_lk[4].read()[0] && !(sc_bit)phy_cad_lk[5].read()[0]
155
                                && !(sc_bit)phy_cad_lk[6].read()[0] && !(sc_bit)phy_cad_lk[7].read()[0]
156
#endif
157
                                ){
158
                                lk_sampled_link_width_csr = "101";
159
                        }
160
#endif
161
#if CAD_IN_WIDTH > 4
162
                        //8 bits width
163
                        else if((sc_bit)phy_cad_lk[0].read()[0] && (sc_bit)phy_cad_lk[1].read()[0]
164
                                && (sc_bit)phy_cad_lk[2].read()[0] && (sc_bit)phy_cad_lk[3].read()[0]
165
                                && (sc_bit)phy_cad_lk[4].read()[0] && (sc_bit)phy_cad_lk[5].read()[0]
166
                                && (sc_bit)phy_cad_lk[6].read()[0] && (sc_bit)phy_cad_lk[7].read()[0] ){
167
                                lk_sampled_link_width_csr = "000";
168
                        }
169
#endif
170
                        //invalid bits width
171
                        else{
172
                                lk_sampled_link_width_csr = "111";
173
                        }
174
                }
175
        }
176
 
177
}
178
 
179
 
180
/**
181
        Process for registered outputs without reset
182
*/
183
void link_frame_rx_l3::clocked_process(){
184
        encode_link_width();
185
#ifdef INTERNAL_SHIFTER_ALIGNMENT
186
        frame_cad();
187
        frame_ctl();
188
#endif
189
}
190
 
191
/**
192
        HT link width is encoded on 3 bits, but since we only support
193
        width of 2,4 and 8 bits, we can re-encode it on two bits
194
        to simplify code in the module.
195
*/
196
void link_frame_rx_l3::encode_link_width(){
197
 
198
        switch((sc_uint<3>)csr_rx_link_width_lk.read()){
199
        case 0 :
200
                rx_link_width_encoded = LINK_8_BIT;
201
                break;
202
        case 4 :
203
                rx_link_width_encoded = LINK_2_BIT;
204
                break;
205
        case 5 :
206
                rx_link_width_encoded = LINK_4_BIT;
207
                break;
208
        default:
209
                rx_link_width_encoded = INVALID_LINK_WIDTH;
210
        }
211
}
212
 
213
/**
214
        This arranges bits received from the physical layer back into
215
        order.  This needs to be done because when the phy receives
216
        bits, all he does it use a shift register for each lane.  Lets
217
        take a 4 lane example with the order of bits received
218
 
219
        Lane 0: ... 8  4 0
220
        Lane 1: ... 9  5 1
221
        Lane 2: ... 10 6 2
222
        Lane 3: ... 11 7 3
223
 
224
        What is received by this module is every Lane vectors.  Whe want to
225
        reorder the bits into a single ordered vector
226
*/
227
void link_frame_rx_l3::reorder_cad(){
228
 
229
        //Work on a temporary variable because we can't easily modify
230
        //bits of a sc_signal.  The modifications will only be accepted
231
        //what is read is new data from the link (see end of function)
232
        sc_bv<32> reordered_cad_tmp;
233
 
234
        //The reordering algorithm strongly depends on the physical link
235
        //width that changes the depths (number of bits received from
236
        //every lane.
237
#if CAD_IN_WIDTH == 2
238
        //Reorder bits 31 through 0.
239
        for(int n = 0; n < 16; n ++ ){
240
                reordered_cad_tmp[2*n] = (sc_bit)phy_cad_lk[0].read()[n];
241
                reordered_cad_tmp[2*n + 1] = (sc_bit)phy_cad_lk[1].read()[n];
242
        }
243
#elif CAD_IN_WIDTH == 4
244
        switch(rx_link_width_encoded.read()){
245
        case 2_BIT_LINK :
246
                //Reorder bits 31 through 16.
247
                for(int n = 0; n < 8; n ++ ){
248
                        reordered_cad_tmp[2*n + 16] = (sc_bit)phy_cad_lk[0].read()[n];
249
                        reordered_cad_tmp[2*n + 17] = (sc_bit)phy_cad_lk[1].read()[n];
250
                }
251
 
252
                //Reorder bits 15 through 0 : shift the last registered bits
253
                reordered_cad_tmp.range(15,0) = reordered_cad.read().range(31,16);
254
                break;
255
 
256
        default:
257
                //Reorder bits 31 through 0.
258
                for(int n = 0; n < 8; n ++ ){
259
                        for(int y = 0; y < 4; y ++ ){
260
                                reordered_cad_tmp[4*n + y] = (sc_bit)phy_cad_lk[y].read()[n];
261
                        }
262
                }
263
                break;
264
        }
265
 
266
 
267
#else
268
        //CAD_IN_WIDTH == 8
269
 
270
        switch(rx_link_width_encoded.read()){
271
        case LINK_2_BIT :
272
                //Reorder bits 31 through 24.
273
                for(int n = 0; n < 4; n ++ ){
274
                        reordered_cad_tmp[2*n + 24] = (sc_bit)phy_cad_lk[0].read()[n];
275
                        reordered_cad_tmp[2*n + 25] = (sc_bit)phy_cad_lk[1].read()[n];
276
                }
277
 
278
                //Reorder bits 23 through 0. : shift the last registered bits
279
                reordered_cad_tmp.range(23,0) = reordered_cad.read().range(31,8);
280
                break;
281
 
282
        case LINK_4_BIT :
283
                //Reorder bits 31 through 16.
284
                for(int n = 0; n < 4; n ++ ){
285
                        for(int y = 0; y < 4; y ++ ){
286
                                reordered_cad_tmp[4*n + y + 16] = (sc_bit)phy_cad_lk[y].read()[n];
287
                        }
288
                }
289
 
290
                //Reorder bits 15 through 0. : shift the last registered bits
291
                reordered_cad_tmp.range(15,0) = reordered_cad.read().range(31,16);
292
                break;
293
        default :
294
                for(int n = 0; n < 4; n ++ ){
295
                        for(int y = 0; y < 8; y ++ ){
296
                                reordered_cad_tmp[8*n + y] = (sc_bit)phy_cad_lk[y].read()[n];
297
                        }
298
                }
299
        }
300
#endif
301
 
302
        //Store the new value if it was calculated from new data
303
        if(phy_available_lk.read())
304
                reordered_cad = reordered_cad_tmp;
305
}
306
 
307
/**
308
        This is similar to the cad reordering in the way that we want
309
        an easy to analyze ordered vector of the ctl signal received
310
        from the physical layer.
311
 
312
        It is slightly different though because CTL is only one
313
        lane : there is no real reordering to do.  What is also different
314
        is that the number of CTL transitions may vary :
315
                an 8-bit link will have 4 CTL bits per dword
316
                a  2-bit link will have 16 CTL bits per dword
317
 
318
        To simplify the post treatment of CTL, the received result
319
        is always stored in a 16 bits vector in this way
320
 
321
        8-bit link :
322
                ... CTL2 CTL1 CTL1 CTL1 CTL1 CTL0 CTL0 CTL0 CTL0
323
        2-bit link
324
                ... CTL8 CTL7 CTL6 CTL5 CTL4 CTL3 CTL2 CTL1 CTL0
325
 
326
        So once the CTL is reordering, the framing does not need
327
        to consider the link width and only deals with a constant
328
        16 bits vector.
329
*/
330
void link_frame_rx_l3::reorder_ctl(){
331
        sc_bv<16> reordered_ctl_tmp;
332
 
333
#if CAD_IN_WIDTH == 2
334
        reordered_ctl_tmp = phy_ctl_lk;
335
#elif CAD_IN_WIDTH == 4
336
        switch(rx_link_width_encoded.read()){
337
        case 2_BIT_LINK :
338
                reordered_ctl_tmp.range(15,8) = phy_ctl_lk.read().range(7,0);
339
                reordered_ctl_tmp.range(7,0) = reordered_ctl.read().range(15,8);
340
                break;
341
 
342
        default:
343
                for(int n = 0; n < 8; n++){
344
                        reordered_ctl_tmp[2*n] = (sc_bit)phy_ctl_lk.read()[n];
345
                        reordered_ctl_tmp[2*n + 1] = (sc_bit)phy_ctl_lk.read()[n];
346
                }
347
                break;
348
        }
349
 
350
#else
351
        //CAD_IN_WIDTH == 8
352
        switch(rx_link_width_encoded.read()){
353
        case LINK_2_BIT :
354
                reordered_ctl_tmp.range(15,12) = phy_ctl_lk.read().range(3,0);
355
                reordered_ctl_tmp.range(11,0) = reordered_ctl.read().range(15,4);
356
                break;
357
 
358
        case LINK_4_BIT :
359
                for(int n = 0; n < 4; n++){
360
                        reordered_ctl_tmp[2*n + 8] = (sc_bit)phy_ctl_lk.read()[n];
361
                        reordered_ctl_tmp[2*n + 9] = (sc_bit)phy_ctl_lk.read()[n];
362
                }
363
                reordered_ctl_tmp.range(7,0) = reordered_ctl.read().range(15,8);
364
                break;
365
        default :
366
                for(int n = 0; n < 4; n++){
367
                        reordered_ctl_tmp[4*n] = (sc_bit)phy_ctl_lk.read()[n];
368
                        reordered_ctl_tmp[4*n + 1] = (sc_bit)phy_ctl_lk.read()[n];
369
                        reordered_ctl_tmp[4*n + 2] = (sc_bit)phy_ctl_lk.read()[n];
370
                        reordered_ctl_tmp[4*n + 3] = (sc_bit)phy_ctl_lk.read()[n];
371
                }
372
        }
373
#endif
374
 
375
        //Store the new value if it was calculated from new data
376
        if(phy_available_lk.read())
377
                reordered_ctl = reordered_ctl_tmp;
378
}
379
 
380
 
381
/**
382
        Regroups all registers that require a asynchronous reset
383
        Contains the state machine
384
*/
385
void link_frame_rx_l3::clocked_and_reset_process(){
386
        if(!resetx.read()){
387
                disconnect_counter = 0;
388
                state = RX_FRAME_INACTIVE_ST;
389
                rx_waiting_for_ctl_tx = true;
390
                reordered_data_ready = false;
391
 
392
                lk_rx_connected = false;
393
 
394
                lk_disable_receivers_phy = false;
395
                framed_data_available = false;
396
 
397
#ifdef INTERNAL_SHIFTER_ALIGNMENT
398
                frame_shift_div_width = 0;
399
                delayed_reordered_cad = "11111111111111111111111111111111";
400
                delayed_reordered_ctl = 0;
401
#else
402
                lk_deser_stall_phy = false;
403
                lk_deser_stall_cycles_phy = 0;
404
#endif
405
                delayed_calculated_frame_shift_div_width = 0;
406
                reordered_ctl = 0;
407
                reordered_cad = "11111111111111111111111111111111";
408
 
409
 
410
#if CAD_IN_WIDTH > 2
411
                phy_cad_lk_count = 0;
412
#endif
413
 
414
        }
415
        else{
416
 
417
#ifdef RETRY_MODE_ENABLED
418
                bool retry_disconnect = cd_initiate_retry_disconnect.read() ||
419
                        lk_initiate_retry_disconnect.read();
420
#endif
421
                //Reorder the bits
422
                reorder_cad();
423
                reorder_ctl();
424
 
425
                //By default we are not connected
426
                lk_rx_connected = false;
427
 
428
 
429
#ifdef INTERNAL_SHIFTER_ALIGNMENT
430
                //Register reordered_cad & reordered_ctl
431
                if(reordered_data_ready.read()){
432
                        delayed_reordered_cad = reordered_cad;
433
                        delayed_reordered_ctl = reordered_ctl;
434
                }
435
#else
436
                delayed_calculated_frame_shift_div_width = calculated_frame_shift_div_width;
437
 
438
                //By default, do not stall phy
439
                lk_deser_stall_phy = false;
440
                lk_deser_stall_cycles_phy = delayed_calculated_frame_shift_div_width.read();
441
#endif
442
                bool reordered_data_ready_tmp;
443
 
444
                /** The count of how many receptions are made is only needed for links
445
                with more than two bits because of the depth : An 8-bit link has a depth
446
                of 4, a 2-bit link has a depth of 16.  So every cycle with a 2-bit link,
447
                we received a full dword (2x16), so we don't need to count how much data
448
                is received before a dword is received.
449
 
450
                In the case of an 8-bit link that's only running at a 2-bit width, only
451
                8 bits are received per cycle (2x4) so it will take 4 cycles to receive
452
                a full dword.
453
                */
454
#if CAD_IN_WIDTH > 2
455
                if(RX_FRAME_INACTIVE_ST)
456
                        phy_cad_lk_count = 0;
457
                if(phy_available_lk.read())
458
                        phy_cad_lk_count = phy_cad_lk_count.read() + 1;
459
#endif
460
 
461
#if CAD_IN_WIDTH == 8
462
                switch(rx_link_width_encoded.read()){
463
                case LINK_8_BIT:
464
                        reordered_data_ready_tmp = phy_available_lk.read();
465
                        break;
466
 
467
                case LINK_4_BIT:
468
                        reordered_data_ready_tmp = phy_cad_lk_count.read()[0] == false && phy_available_lk.read();
469
                        break;
470
 
471
                case LINK_2_BIT:
472
                        reordered_data_ready_tmp = phy_cad_lk_count.read() == 2 && phy_available_lk.read();
473
                        break;
474
 
475
                default:
476
                        reordered_data_ready_tmp = false;
477
 
478
                }
479
#elif CAD_IN_WIDTH == 4
480
                switch(rx_link_width_encoded.read()){
481
                case LINK_4_BIT:
482
                        reordered_data_ready_tmp = phy_available_lk.read();
483
                        break;
484
 
485
                case LINK_2_BIT:
486
                        reordered_data_ready_tmp = phy_cad_lk_count.read()[0] == false && phy_available_lk.read();
487
                        break;
488
 
489
                default:
490
                        reordered_data_ready_tmp = false;
491
 
492
                }
493
#else
494
                switch(rx_link_width_encoded.read()){
495
                case LINK_2_BIT:
496
                        reordered_data_ready_tmp = phy_available_lk.read();
497
                        break;
498
 
499
                default:
500
                        reordered_data_ready_tmp = false;
501
 
502
                }
503
#endif
504
                reordered_data_ready = reordered_data_ready_tmp;
505
 
506
                disconnect_counter = 1;
507
 
508
                rx_waiting_for_ctl_tx = false;
509
                lk_disable_receivers_phy = false;
510
                framed_data_available = false;
511
 
512
                /**
513
                        State machine to detect the init sequence
514
                */
515
                switch(state){
516
 
517
                case RX_FRAME_ACTIVE_ST:
518
                        lk_rx_connected = true;
519
 
520
                        if(ldtstop_disconnect_rx.read() || csr_end_of_chain.read()){
521
                                state = RX_FRAME_LDTSTOP_DISCONNECT_ST;
522
                        }
523
#ifdef RETRY_MODE_ENABLED
524
                        else if(retry_disconnect){
525
                                state = RX_FRAME_RETRY_DISCONNECT_ST;
526
                        }
527
#endif
528
 
529
 
530
#ifdef INTERNAL_SHIFTER_ALIGNMENT
531
                        //With internal shifter alignment, there is a register after alignment,
532
                        //so we send framed_data_available one cycle after reordered data is ready
533
                        if(     reordered_data_ready.read() &&
534
#else
535
                        //Without internal shifter, there is not a register after alignment (there is no
536
                        //alignment), so the data ready signal can be sent right away
537
                        if(     reordered_data_ready_tmp && //reordered_data_ready_tmp means data ready NEXT cycle!
538
#endif
539
#ifdef RETRY_MODE_ENABLED
540
                                !retry_disconnect && !new_detected_ctl_transition_error.read() &&
541
#endif
542
                        !ldtstop_disconnect_rx.read()){
543
                                framed_data_available = true;
544
                        }
545
                        break;
546
 
547
                case RX_FRAME_WAIT_FRAME_ST:
548
                        if(ldtstop_disconnect_rx.read() || csr_end_of_chain.read()){
549
                                state = RX_FRAME_LDTSTOP_DISCONNECT_ST;
550
                        }
551
#ifdef INTERNAL_SHIFTER_ALIGNMENT
552
                        else if(reordered_data_ready.read() && (sc_bit)(reordered_cad.read()[0])){
553
#else
554
                        else if(reordered_data_ready_tmp && (sc_bit)(reordered_cad.read()[0])){
555
                                framed_data_available = true;
556
#endif
557
                                state = RX_FRAME_ACTIVE_ST;
558
                        }
559
                        break;
560
 
561
#ifdef RETRY_MODE_ENABLED
562
                case RX_FRAME_RETRY_DISCONNECT_ST:
563
                        disconnect_counter = disconnect_counter.read() + 1;
564
                        if(ldtstop_disconnect_rx.read() || csr_end_of_chain.read()){
565
                                state = RX_FRAME_LDTSTOP_DISCONNECT_ST;
566
                        }
567
                        else if(disconnect_counter.read() == 0){
568
                                state = RX_FRAME_INACTIVE_ST;
569
                        };
570
 
571
                        break;
572
#endif
573
                case RX_FRAME_LDTSTOP_DISCONNECT_ST:
574
                        lk_disable_receivers_phy = true;
575
 
576
                        if(ldtstopx.read()){
577
                                disconnect_counter = disconnect_counter.read() + 1;
578
                        }
579
 
580
                        if(disconnect_counter.read() == 0){
581
                                state = RX_FRAME_INACTIVE_ST;
582
                        };
583
 
584
                        break;
585
                default: // RX_FRAME_INACTIVE_ST:
586
 
587
                        //Warn TX side that CTL is not active
588
                        rx_waiting_for_ctl_tx = !phy_ctl_lk[0];
589
 
590
                        if(ldtstop_disconnect_rx.read() || csr_end_of_chain.read()){
591
                                state = RX_FRAME_LDTSTOP_DISCONNECT_ST;
592
                        }
593
                        /**
594
                                Originally, the end of inactive state was checked with bit
595
                                !(sc_bit)reordered_cad.read()[31], but this can be problematic
596
                                after cold reset if the link width is smaller than 8 bits since
597
                                the width update takes multiple cycles to propagate to the
598
                                cad reordering logic.  What can happen is that the reordering logic
599
                                at the beginning will reorder all inputs as if it was 8-bit width
600
                                event if it is 2-bit width for example, reordering the 0's at inputs
601
                                7..2.  Those 0's could be mistaken for 0's sent by the next node.
602
 
603
                                To go around this problem, bit 0 is used instead, but with a
604
                                delayed "calculated_frame_shift_div_width" instead.
605
 
606
                                If bit 31 = 0 and bit 0 = 0, it means the shift is 0 and since last
607
                                frame contained all 1's, delayed_calculated_frame_shift_div_width will still have
608
                                the correct value of 0.
609
                        */
610
                        else if(!(sc_bit)reordered_cad.read()[0]){
611
                                state = RX_FRAME_WAIT_FRAME_ST;
612
#ifdef INTERNAL_SHIFTER_ALIGNMENT
613
                                frame_shift_div_width = delayed_calculated_frame_shift_div_width.read();
614
#else
615
                                //Always has this value (set in top of process)
616
                                //lk_deser_stall_cycles_phy = delayed_calculated_frame_shift_div_width.read();
617
                                lk_deser_stall_phy = delayed_calculated_frame_shift_div_width.read() != 0;
618
#endif
619
                        }
620
                }
621
 
622
                if(csr_sync.read()){
623
                        state = RX_FRAME_INACTIVE_ST;
624
                }
625
        }
626
}
627
 
628
/**
629
        During the link initialization, the data allignement must be determined.  This function
630
        encodes the stored cad data to determine the shift necessary to properly align the data.
631
        Of course, this is combinatory, so it always outputs something, but it is only valid
632
        at a precise moment during the initialization sequence, at which time the value
633
        is stored.
634
*/
635
void link_frame_rx_l3::encode(){
636
 
637
        sc_bv<LOG2_CAD_IN_DEPTH> encoded_reordered_cad;
638
 
639
        //When we received the first int cad sequence, it's going to be all zeroes
640
        //in the higher bits and all ones in the bottom.  We want to encode the position
641
        //of this change so we start with some edge detection
642
        sc_bv<32/CAD_IN_WIDTH> edge_x;
643
        for(int n = 1; n < 32/CAD_IN_WIDTH; n++){
644
                edge_x[n] = !(!(sc_bit)reordered_cad.read()[32-CAD_IN_WIDTH*n] && (sc_bit)reordered_cad.read()[30-CAD_IN_WIDTH]);
645
        }
646
 
647
        //Only one edge is detected (if we are indeed in the init sequence), encode it
648
        //The larger the link is, the smaller the depth is (to have a constant 32 bits input).  The alignment
649
        //can only be related to the depth of the input : an 8 bits input has depth of 4 (4x8), so the alignment
650
        //offset can be 0, 8, 16 or 24.  The alignment offset can be represented on 2 bits (0,1,2 or 3).
651
        //A link with a smaller width (higher depth) needs more bits to represent the offset.
652
#if CAD_IN_WIDTH == 2
653
        encoded_reordered_cad[3] =
654
                !((((sc_bit)edge_x[15] && (sc_bit)edge_x[14] )
655
                && ((sc_bit)edge_x[13] && (sc_bit)edge_x[12]))
656
                                &&
657
                (((sc_bit)edge_x[11] && (sc_bit)edge_x[10]) &&
658
                ((sc_bit)edge_x[9] && (sc_bit)edge_x[8])));
659
 
660
        encoded_reordered_cad[2] =
661
                !((((sc_bit)edge_x[15] && (sc_bit)edge_x[14]) &&
662
                ((sc_bit)edge_x[13] &&  (sc_bit)edge_x[12])) &&
663
                (((sc_bit)edge_x[7] && (sc_bit)edge_x[6]) &&
664
                ((sc_bit)edge_x[5] && (sc_bit)edge_x[4])));
665
 
666
        encoded_reordered_cad[1] =
667
                !((((sc_bit)edge_x[15] && (sc_bit)edge_x[14]) &&
668
                ((sc_bit)edge_x[11] && (sc_bit)edge_x[10])) &&
669
                (((sc_bit)edge_x[7] && (sc_bit)edge_x[6]) &&
670
                ((sc_bit)edge_x[3] && (sc_bit)edge_x[2])));
671
 
672
        encoded_reordered_cad[0] =
673
                !((((sc_bit)edge_x[15] && (sc_bit)edge_x[13]) &&
674
                ((sc_bit)edge_x[11] && (sc_bit)edge_x[9])) &&
675
                (((sc_bit)edge_x[7] && (sc_bit)edge_x[5]) &&
676
                ((sc_bit)edge_x[3] && (sc_bit)edge_x[1])));
677
#elif CAD_IN_WIDTH == 4
678
        encoded_reordered_cad[2] =
679
                !(((sc_bit)edge_x[7] && (sc_bit)edge_x[6]) &&
680
                ((sc_bit)edge_x[5] && (sc_bit)edge_x[4]));
681
 
682
        encoded_reordered_cad[1] =
683
                !(((sc_bit)edge_x[7] && (sc_bit)edge_x[6]) &&
684
                ((sc_bit)edge_x[3] && (sc_bit)edge_x[2]));
685
 
686
        encoded_reordered_cad[0] =
687
                !(((sc_bit)edge_x[7] && (sc_bit)edge_x[5]) &&
688
                ((sc_bit)edge_x[3] && (sc_bit)edge_x[1]));
689
#else
690
        encoded_reordered_cad[1] =
691
                !((sc_bit)edge_x[3] && (sc_bit)edge_x[2]);
692
 
693
        encoded_reordered_cad[0] =
694
                !((sc_bit)edge_x[3] && (sc_bit)edge_x[1]);
695
#endif
696
 
697
        calculated_frame_shift_div_width = encoded_reordered_cad;
698
}
699
 
700
#ifndef INTERNAL_SHIFTER_ALIGNMENT
701
void link_frame_rx_l3::output_reordered_cad_and_ctl(){
702
        framed_cad = reordered_cad;
703
        framed_lctl = (sc_bit)reordered_ctl.read()[0];
704
        framed_hctl = (sc_bit)reordered_ctl.read()[8];
705
}
706
#else
707
 
708
/**
709
        Once bits are reordered, they are in a correct sequence of order. BUT,
710
        there is no guarantee that the beginning of the reordered vector is
711
        the actual beginning of a transmitted dword : there might be an
712
        offset.
713
 
714
        That offset is calculated during the init sequence and the amount
715
        of shift that needs to be done to correct that offset is stored
716
        in the frame_shift_div_width register.
717
 
718
        In other words, this is simply a shifter to correctly frame the
719
        received data, also using the previous received data.
720
*/
721
void link_frame_rx_l3::frame_cad(){
722
        //Here, there are multiple shifters : one for every bit of the input
723
        //It saves on resources compared to using one big shifter
724
 
725
        sc_bv<32> framed_cad_tmp;
726
 
727
        for(int n = 0; n < CAD_IN_WIDTH;n++){
728
 
729
                sc_bv<64/CAD_IN_WIDTH> shift_cad;
730
 
731
                for(int i = 0; i < 32/CAD_IN_WIDTH; i++){
732
                        shift_cad[ i + 32/CAD_IN_WIDTH] = (sc_bit)reordered_cad.read()[CAD_IN_WIDTH*i+n];
733
                }
734
                for(int i = 0; i < 32/CAD_IN_WIDTH; i++){
735
                        shift_cad[ i ] = (sc_bit)delayed_reordered_cad.read()[CAD_IN_WIDTH*i+n];
736
                }
737
 
738
                sc_bv<64/CAD_IN_WIDTH> shifted_cad = shift_cad << frame_shift_div_width.read();
739
 
740
                for(int i = 0; i < 32/CAD_IN_WIDTH; i++){
741
                        framed_cad_tmp[CAD_IN_WIDTH*i+n] = (sc_bit)shifted_cad[i+32/CAD_IN_WIDTH];
742
                }
743
        }
744
 
745
        framed_cad = framed_cad_tmp;
746
}
747
 
748
/**
749
        Same principle as the frame_cad function, except since we are only
750
        interested in two CTL values (LCTL and HCTL), there is no need to
751
        shift the bits.  We simplyread the correct bit.
752
*/
753
void link_frame_rx_l3::frame_ctl(){
754
        sc_bv<32> shift_ctl_bits;
755
        shift_ctl_bits.range(31,16) = reordered_ctl.read();
756
        shift_ctl_bits.range(15,0) = delayed_reordered_ctl.read();
757
 
758
        framed_lctl = (sc_bit)shift_ctl_bits[16-frame_shift_div_width.read()];
759
        framed_hctl = (sc_bit)shift_ctl_bits[24-frame_shift_div_width.read()];
760
}
761
 
762
 
763
#endif
764
 
765
/**
766
        This process handles various errors of the CTL bit.  CTL transition
767
        errors are detected by another process, but this process will
768
        log the error after the correct amount of time.  If in retry
769
        mode, it will even initiate the retry sequence when an error\
770
        is detected.
771
 
772
        Also, if CTL stays low for too long, an error is also logged.
773
*/
774
void link_frame_rx_l3::generate_ctl_and_timeout_errors(){
775
 
776
        if(!resetx.read()){
777
                detected_ctl_transition_error = false;
778
                lk_protocol_error_csr = false;
779
                ctl_watchdog_timer = 0;
780
#ifdef RETRY_MODE_ENABLED
781
                lk_initiate_retry_disconnect = false;
782
#endif
783
        }
784
        else{
785
                lk_protocol_error_csr = false;
786
 
787
                bool active_ctl =
788
                ((((sc_bit)reordered_ctl.read()[0] || (sc_bit)reordered_ctl.read()[1]) ||
789
                ((sc_bit)reordered_ctl.read()[2] || (sc_bit)reordered_ctl.read()[3])) ||
790
                (((sc_bit)reordered_ctl.read()[4] || (sc_bit)reordered_ctl.read()[5]) ||
791
                ((sc_bit)reordered_ctl.read()[6] || (sc_bit)reordered_ctl.read()[7]))) ||
792
                ((((sc_bit)reordered_ctl.read()[8] || (sc_bit)reordered_ctl.read()[9]) ||
793
                ((sc_bit)reordered_ctl.read()[10] || (sc_bit)reordered_ctl.read()[11])) ||
794
                (((sc_bit)reordered_ctl.read()[12] || (sc_bit)reordered_ctl.read()[13]) ||
795
                ((sc_bit)reordered_ctl.read()[14] || (sc_bit)reordered_ctl.read()[15])));
796
 
797
 
798
                if(! (state == RX_FRAME_ACTIVE_ST || state == RX_FRAME_WAIT_FRAME_ST)){
799
                        detected_ctl_transition_error = false;
800
#ifdef RETRY_MODE_ENABLED
801
                        lk_initiate_retry_disconnect = false;
802
#endif
803
                }
804
                else if(reordered_data_ready.read()){
805
                        detected_ctl_transition_error = new_detected_ctl_transition_error.read() ||
806
                                detected_ctl_transition_error.read();
807
 
808
                        //Only activate the transition error when we receive another CTL
809
                        //so that a reset sequence is not loged as an error
810
                        bool ctl_transition_error_tmp = detected_ctl_transition_error.read() && active_ctl;
811
                        lk_protocol_error_csr = ctl_transition_error_tmp;
812
 
813
#ifdef RETRY_MODE_ENABLED
814
                        lk_initiate_retry_disconnect = csr_retry.read() && ctl_transition_error_tmp;
815
#endif
816
                }
817
 
818
                /**
819
                        This is a watchdog timer that checks if the link has not received a positive
820
                        CTL value for more than a certain amount of time, which would mean that
821
                        some kind of error has occured.
822
                */
823
                if(! (state == RX_FRAME_ACTIVE_ST || state == RX_FRAME_WAIT_FRAME_ST) || active_ctl){
824
                        ctl_watchdog_timer = 0;
825
                }
826
                else{
827
                        ctl_watchdog_timer = ctl_watchdog_timer.read() + 1;
828
                }
829
 
830
                if( !csr_extended_ctl_timeout_lk.read() &&
831
                        (ctl_watchdog_timer.read() == NUMBER_CYCLES_1_MS) ||
832
                        csr_extended_ctl_timeout_lk.read() &&
833
                        (ctl_watchdog_timer.read() == NUMBER_CYCLES_1_S) )
834
                {
835
                        lk_protocol_error_csr = true;
836
                }
837
        }
838
}
839
 
840
/**
841
        This process detects transitions errors of the CTL bit.  The CTL
842
        bit is normally only allowed to make a transition half way
843
        through the transmission of a dword : for LCTL and HCTL.  If
844
        a transition is detected at another moment, it means that
845
        an error has occured.
846
*/
847
void link_frame_rx_l3::detect_ctl_transition_error(){
848
        if(reordered_data_ready.read() &&
849
                (state == RX_FRAME_ACTIVE_ST || state == RX_FRAME_WAIT_FRAME_ST)){
850
 
851
#ifdef INTERNAL_SHIFTER_ALIGNMENT
852
                sc_bv<32> shift_ctl_bits;
853
                shift_ctl_bits.range(31,16) = reordered_ctl.read();
854
                shift_ctl_bits.range(15,0) = delayed_reordered_ctl.read();
855
 
856
                sc_bv<16> shifted_ctl_bits;
857
                for(int n = 0; n < 16; n++){
858
                        shifted_ctl_bits[n] = shift_ctl_bits[16+n-frame_shift_div_width.read()*CAD_IN_WIDTH/2];
859
                }
860
#else
861
                sc_bv<16> shifted_ctl_bits = reordered_ctl.read();
862
#endif
863
 
864
                //First, detect transition errors : if not all values of LCTL or HCTL
865
                //are the same, it's an error
866
                new_detected_ctl_transition_error = !(
867
                        (((((sc_bit)shifted_ctl_bits[0] && (sc_bit)shifted_ctl_bits[1]) &&
868
                          ((sc_bit)shifted_ctl_bits[2] && (sc_bit)shifted_ctl_bits[3])) &&
869
                          (((sc_bit)shifted_ctl_bits[4] && (sc_bit)shifted_ctl_bits[5]) &&
870
                          ((sc_bit)shifted_ctl_bits[6] && (sc_bit)shifted_ctl_bits[7])) )
871
                        ||
872
                        (((!(sc_bit)shifted_ctl_bits[0] && !(sc_bit)shifted_ctl_bits[1]) &&
873
                        (!(sc_bit)shifted_ctl_bits[2] && !(sc_bit)shifted_ctl_bits[3])) &&
874
                        ((!(sc_bit)shifted_ctl_bits[4] && !(sc_bit)shifted_ctl_bits[5]) &&
875
                        (!(sc_bit)shifted_ctl_bits[6] && !(sc_bit)shifted_ctl_bits[7])) ))
876
                                        &&
877
                        (((((sc_bit)shifted_ctl_bits[8] && (sc_bit)shifted_ctl_bits[9]) &&
878
                        ((sc_bit)shifted_ctl_bits[10] && (sc_bit)shifted_ctl_bits[11])) &&
879
                        (((sc_bit)shifted_ctl_bits[12] && (sc_bit)shifted_ctl_bits[13]) &&
880
                        ((sc_bit)shifted_ctl_bits[14] && (sc_bit)shifted_ctl_bits[15])))
881
                        ||
882
                        (((!(sc_bit)shifted_ctl_bits[8] && !(sc_bit)shifted_ctl_bits[9]) &&
883
                        (!(sc_bit)shifted_ctl_bits[10] && !(sc_bit)shifted_ctl_bits[11])) &&
884
                        (((!(sc_bit)shifted_ctl_bits[12] && !(sc_bit)shifted_ctl_bits[13]) &&
885
                        (!(sc_bit)shifted_ctl_bits[14] && !(sc_bit)shifted_ctl_bits[15]))))));
886
        }
887
        else
888
                new_detected_ctl_transition_error = false;
889
 
890
}
891
 

powered by: WebSVN 2.1.0

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