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

Subversion Repositories pcie_ds_dma

[/] [pcie_ds_dma/] [trunk/] [soft/] [linux/] [application/] [adm_test/] [src/] [work/] [tf_teststrmout.cpp] - Blame information for rev 54

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dsmv
 
2
 
3
#define _USE_MATH_DEFINES
4
 
5
#include <math.h>
6
#include <stdio.h>
7
#include <fcntl.h>
8
#include <pthread.h>
9
#include <sys/types.h>
10
#include <sys/stat.h>
11
 
12
#include "utypes.h"
13
//#include "useful.h"
14
#include "tf_teststrmout.h"
15
#include "cl_ambpex.h"
16
 
17
 
18
 
19
#define BUFSIZEPKG 62
20
 
21
#define TRDIND_MODE0                                    0x0
22
#define TRDIND_MODE1                                    0x9
23
#define TRDIND_MODE2                                    0xA
24
#define TRDIND_SPD_CTRL                                 0x204
25
#define TRDIND_SPD_ADDR                                 0x205
26
#define TRDIND_SPD_DATA                                 0x206
27
 
28 27 dsmv
int GetTickCount(void);
29 2 dsmv
 
30
TF_TestStrmOut::TF_TestStrmOut( BRDCHAR* fname, CL_AMBPEX *fotr )
31
{
32
    lc_status=0;
33
 
34
    Terminate=0;
35
    BlockRd=0;
36
    BlockOk=0;
37
    BlockError=0;
38
    TotalError=0;
39
 
40
    pBrd=fotr;
41
 
42
    SetDefault();
43
    GetParamFromFile( fname );
44
    CalculateParams();
45
 
46
    isFirstCallStep=true;
47
 
48
    SetSignalInit();
49
}
50
 
51
TF_TestStrmOut::~TF_TestStrmOut()
52
{
53
    pBrd->StreamDestroy( tr0.Strm );
54
 
55
}
56
 
57
void TF_TestStrmOut::Prepare( void )
58
{
59
    PrepareAdm();
60
 
61
    tr0.trd=trdNo;
62
    tr0.Strm=strmNo;
63
    pBrd->StreamInit( tr0.Strm, CntBuffer, SizeBuferOfBytes, tr0.trd, 2, isCycle, isSystem, isAgreeMode );
64
 
65
}
66
 
67
void TF_TestStrmOut::Start( void )
68
{
69
    int res = pthread_attr_init(&attrThread_);
70
    if(res != 0) {
71
        fprintf(stderr, "%s\n", "Stream not started");
72
        return;
73
    }
74
 
75
    res = pthread_attr_setdetachstate(&attrThread_, PTHREAD_CREATE_JOINABLE);
76
    if(res != 0) {
77
        fprintf(stderr, "%s\n", "Stream not started");
78
        return;
79
    }
80
 
81
    res = pthread_create(&hThread, &attrThread_, ThreadFunc, this);
82
    if(res != 0) {
83
        fprintf(stderr, "%s\n", "Stream not started");
84
        return;
85
    }
86
}
87
 
88
void TF_TestStrmOut::Stop( void )
89
{
90
    if( isTest )
91
        TestCtrlStop( &tr0 );
92
 
93
    Terminate=1;
94
    lc_status=3;
95
}
96
 
97
void TF_TestStrmOut::Step( void )
98
{
99
    if( isTest )
100
        TestCtrlReadStatus( &tr0 );
101
 
102 27 dsmv
    long currentTime = GetTickCount();
103
    int min, sec_all, sec;
104
    sec_all= currentTime-tr0.time_start;
105
    sec_all/=1000;
106
    sec=sec_all%60;
107
    min=sec_all/60;
108
 
109
 
110 2 dsmv
    U32 status = pBrd->RegPeekDir( tr0.trd, 0 ) & 0xFFFF;
111 27 dsmv
    BRDC_fprintf( stderr, "%6s %3d %10d %10d %10d %10d  %9.1f %10.1f     0x%.4X       %u:%.2u  \r", "TRD :", tr0.trd, tr0.BlockWr, tr0.BlockRd, tr0.BlockOk, tr0.BlockError, tr0.VelocityCurrent, tr0.VelocityAvarage, status, min, sec );
112 2 dsmv
}
113
 
114
int TF_TestStrmOut::isComplete( void )
115
{
116
    if( (lc_status==4)  )
117
        return 1;
118
    return 0;
119
}
120
 
121
void TF_TestStrmOut::GetResult( void )
122
{
123
    //if(pkg_in.BlockRd!=0 && pkg_in.BlockError!=0)
124
    //  printf("%s\n", pkg_in.testBuf.report_word_error());
125
 
126
    if( isTest )
127
    {
128 27 dsmv
        BRDC_fprintf( stderr, "\n\nResult of transmitted data via trd %d \n", trdNo );
129 2 dsmv
        TestCtrlResult( &tr0 );
130
    }
131
    BRDC_fprintf( stderr, "\n\n" );
132
}
133
 
134
void* TF_TestStrmOut::ThreadFunc( void*   lpvThreadParm )
135
{
136
    TF_TestStrmOut *test=(TF_TestStrmOut*)lpvThreadParm;
137
    UINT ret;
138
    if( !test )
139
        return 0;
140
    ret=test->Execute();
141 54 v.karak
    return (void*)(size_t)ret;
142 2 dsmv
}
143
 
144
 
145
 
146
//! Установка параметров по умолчанию
147
void TF_TestStrmOut::SetDefault( void )
148
{
149
    int ii=0;
150
 
151
    array_cfg[ii++]=STR_CFG(  0, "CntBuffer",                    "16", (U32*)&CntBuffer, "число буферов стрима" );
152
    array_cfg[ii++]=STR_CFG(  0, "CntBlockInBuffer",     "512",  (U32*)&CntBlockInBuffer, "Число блоков в буфере" );
153
    array_cfg[ii++]=STR_CFG(  0, "SizeBlockOfWords",     "2048",  (U32*)&SizeBlockOfWords, "Размер блока в словах" );
154
    array_cfg[ii++]=STR_CFG(  0, "isCycle",                              "1",  (U32*)&isCycle, "1 - Циклический режим работы стрима" );
155
    array_cfg[ii++]=STR_CFG(  0, "isSystem",                     "0",  (U32*)&isSystem, "1 - выделение системной памяти" );
156
    array_cfg[ii++]=STR_CFG(  0, "isAgreeMode",                  "0",  (U32*)&isAgreeMode, "1 - согласованный режим" );
157
 
158
    array_cfg[ii++]=STR_CFG(  0, "trdNo",        "4",  (U32*)&trdNo, "Номер тетрады" );
159
    array_cfg[ii++]=STR_CFG(  0, "strmNo",       "0",  (U32*)&strmNo, "Номер стрма" );
160
    array_cfg[ii++]=STR_CFG(  0, "isSdram",      "0",  (U32*)&isSdram, "1 - тетрада SDRAM" );
161
    array_cfg[ii++]=STR_CFG(  0, "isTest",       "0",  (U32*)&isTest, "0 - нет, 1 - проверка псевдослучайной последовательности" );
162
 
163
    array_cfg[ii++]=STR_CFG(  0, "DataType",     "0",  (U32*)&tr0.DataType, "Тип данных при фиксированном типе блока, 6 - счётчик, 8 - псевдослучайная последовательность" );
164
 
165
    array_cfg[ii++]=STR_CFG(  0, "DataFix",      "0",  (U32*)&tr0.DataFix, "1 - фиксированный тип блока, 0 - данные в блоке записят от номера блока" );
166
 
167
 
168
 
169
    max_item=ii;
170
 
171
    {
172
        char str[1024];
173
        for( unsigned ii=0; ii<max_item; ii++ )
174
        {
175
            sprintf( str, "%s  %s", array_cfg[ii].name, array_cfg[ii].def );
176
            GetParamFromStr( str );
177
        }
178
 
179
 
180
    }
181
 
182
}
183
 
184
//! Расчёт параметров
185
void TF_TestStrmOut::CalculateParams( void )
186
{
187
    SizeBlockOfBytes = SizeBlockOfWords * 4;                                            // Размер блока в байтах
188
    SizeBuferOfBytes    = CntBlockInBuffer * SizeBlockOfBytes  ;        // Размер буфера в байтах
189
    SizeStreamOfBytes   = CntBuffer * SizeBuferOfBytes;                         // Общий размер буфера стрима
190
 
191
    ShowParam();
192
}
193
 
194
//! Отображение параметров
195
void TF_TestStrmOut::ShowParam( void )
196
{
197
    TF_WorkParam::ShowParam();
198
 
199
    BRDC_fprintf( stderr, "Total stream buffer size: %d МБ\n\n", SizeStreamOfBytes/(1024*1024) );
200
 
201
}
202
 
203
 
204
U32 TF_TestStrmOut::Execute( void )
205
{
206
    tr0.testBuf.buf_check_start( 32, 64 );
207
 
208
    { // Начальное заполнение кольцевого буфера
209
        U32 ii, kk, mode;
210
        U32 *ptr, *ptrBlock;
211
        mode = (tr0.DataFix << 7) | (tr0.DataType<<8);
212
        for( kk=0; kk<CntBuffer; kk++ )
213
        {
214
            ptr=pBrd->StreamGetBufByNum( tr0.Strm, kk );
215
            for( ii=0; ii<CntBlockInBuffer; ii++ )
216
            {
217
 
218
                ptrBlock=ptr+ii*SizeBlockOfWords;
219
 
220
                if( isTest )
221
                    tr0.testBuf.buf_set( ptrBlock, tr0.BlockWr, SizeBlockOfWords, mode );
222
                else
223
                    SetSignal( ptrBlock );
224
 
225
                tr0.BlockWr++;
226
 
227
            }
228
        }
229
 
230
        TestCtrlStart( &tr0 );
231
    }
232
 
233
 
234
 
235
 
236 27 dsmv
    pBrd->RegPokeInd( tr0.trd, 0, 0x2000 );
237 2 dsmv
 
238
 
239
    pBrd->StreamStart( tr0.Strm );
240
 
241 27 dsmv
    Sleep( 100 );
242 2 dsmv
 
243
 
244
    tr0.BlockLast=tr0.BlockStart=tr0.BlockWr;
245
 
246
    pBrd->RegPokeInd( tr0.trd, 0, 0x2038 );
247
 
248 27 dsmv
    isDmaStart=1;
249 2 dsmv
 
250
 
251
 
252 27 dsmv
    tr0.time_last=tr0.time_start=GetTickCount();
253 2 dsmv
 
254
 
255
    for( ; ; )
256
    {
257
        if( Terminate )
258
        {
259
            break;
260
        }
261
 
262
        SendData( &tr0 );
263
 
264
    }
265
    pBrd->RegPokeInd( tr0.trd, 0, 2 );
266
    Sleep( 200 );
267
 
268
    pBrd->StreamStop( tr0.Strm );
269
    Sleep( 10 );
270
 
271
 
272
    lc_status=4;
273
    return 1;
274
}
275
 
276
 
277
 
278
 
279
void TF_TestStrmOut::SendData(  ParamExchange *pr )
280
{
281
    U32 *ptr;
282
    U32 *ptrBlock;
283
    U32 mode=0;
284
    mode |= pr->DataType<<8;
285
    mode |= pr->DataFix<<7;
286
 
287
    int ret;
288
    int kk;
289
 
290
    //pr->BlockRd++;
291
    //Sleep( 10 );
292
    //return;
293
 
294
 
295
    for( kk=0; kk<16; kk++ )
296
    {
297
        ret=pBrd->StreamGetBuf( pr->Strm, &ptr );
298
        if( ret )
299
        { // Заполнение буфера стрима
300
            for( unsigned ii=0; ii<CntBlockInBuffer; ii++ )
301
            {
302
                ptrBlock=ptr+ii*SizeBlockOfWords;
303
 
304
                if( isTest )
305
                    pr->testBuf.buf_set( ptrBlock, pr->BlockWr, SizeBlockOfWords, mode );
306
                /*
307
                                else
308
                                        SetSignal( ptrBlock );
309
                                */
310
                pr->BlockWr++;
311
                if( isAgreeMode )
312
                {
313
                    pBrd->StreamGetBufDone( pr->Strm );
314
                }
315
 
316
            }
317
        } else
318
        {
319
            //Sleep( 0 );
320
            pr->freeCycle++;
321
            //break;
322
        }
323
    }
324
    //Sleep( 0 );
325
 
326 27 dsmv
 
327 2 dsmv
    U32 currentTime = GetTickCount();
328
    if( (currentTime - pr->time_last)>4000 )
329
    {
330
        float t1 = currentTime - pr->time_last;
331
        float t2 = currentTime - pr->time_start;
332
        float v = 1000.0*(pr->BlockWr-pr->BlockLast)*SizeBlockOfBytes/t1;
333
        v/=1024*1024;
334
        pr->VelocityCurrent=v;
335
 
336
        v = 1000.0*(pr->BlockWr-pr->BlockStart)*SizeBlockOfBytes/t2;
337
        v/=1024*1024;
338
        pr->VelocityAvarage=v;
339
        pr->time_last = currentTime;
340
        pr->BlockLast = pr->BlockWr;
341
        pr->freeCycleZ=pr->freeCycle;
342
        pr->freeCycle=0;
343
 
344
    }
345
    //Sleep(1);
346
 
347 27 dsmv
 
348 2 dsmv
}
349
 
350
 
351
void TF_TestStrmOut::PrepareAdm( void )
352
{
353
    U32 trd=trdNo;
354
    U32 id, id_mod, ver;
355
    BRDC_fprintf( stderr, "\nPrepare tetrade\n" );
356
 
357
 
358
    id = pBrd->RegPeekInd( trd, 0x100 );
359
    id_mod = pBrd->RegPeekInd( trd, 0x101 );
360
    ver = pBrd->RegPeekInd( trd, 0x102 );
361
 
362
 
363
    BRDC_fprintf( stderr, "\nTetrade %d  ID: 0x%.2X MOD: %d  VER: %d.%d \n\n",
364
            trd, id, id_mod, (ver>>8) & 0xFF, ver&0xFF );
365
}
366
 
367
 
368
//! Запуск проверки в тетраде TestCtrl
369
void TF_TestStrmOut::TestCtrlStart( ParamExchange *pr )
370
{
371
    U32 trd=1;
372
 
373
    U32 check_size=SizeBlockOfBytes/4096;
374
    U32 check_ctrl= (pr->DataFix<<7) | (pr->DataType<<8);
375
 
376
    pBrd->RegPokeInd( trd, 0x0F, 1 );
377
 
378
    pBrd->RegPokeInd( trd, 0x1C, 1 ); // Reset
379
    Sleep( 10 );
380
    pBrd->RegPokeInd( trd, 0x1C, 0 );
381
    Sleep( 10 );
382
    pBrd->RegPokeInd( trd, 0x1D, check_size );
383
    pBrd->RegPokeInd( trd, 0x1C, check_ctrl | 0x20 );
384
 
385
}
386
 
387
 
388
 
389
//! Остановка проверки в тетраде TestCtrl
390
void TF_TestStrmOut::TestCtrlStop( ParamExchange *pr )
391
{
392
    U32 trd=1;
393
 
394
    U32 check_ctrl= (pr->DataFix<<7) | (pr->DataType<<8);
395
 
396
    pBrd->RegPokeInd( trd, 0x1C, check_ctrl ); // Останов
397
}
398
 
399
//! Чтение текущего состояния тетрады TestCtrl
400
void TF_TestStrmOut::TestCtrlReadStatus( ParamExchange *pr )
401
{
402
    U32 trd=1;
403
    U32 block_rd, block_ok, block_error, total_error;
404
 
405
    U32 reg_l, reg_h;
406
 
407
    reg_l = pBrd->RegPeekInd( trd, 0x210 );
408
    reg_h = pBrd->RegPeekInd( trd, 0x211 );
409
    block_rd = (reg_l&0xFFFF) | (reg_h<<16);
410
 
411
    reg_l = pBrd->RegPeekInd( trd, 0x212 );
412
    reg_h = pBrd->RegPeekInd( trd, 0x213 );
413
    block_ok = (reg_l&0xFFFF) | (reg_h<<16);
414
 
415
    reg_l = pBrd->RegPeekInd( trd, 0x214 );
416
    reg_h = pBrd->RegPeekInd( trd, 0x215 );
417
    block_error = (reg_l&0xFFFF) | (reg_h<<16);
418
 
419
    reg_l = pBrd->RegPeekInd( trd, 0x216 );
420
    reg_h = pBrd->RegPeekInd( trd, 0x217 );
421
    total_error = (reg_l&0xFFFF) | (reg_h<<16);
422
 
423
    pr->BlockRd=block_rd;
424
    pr->BlockOk=block_ok;
425
    pr->BlockError=block_error;
426
    pr->TotalError=total_error;
427
 
428
 
429
 
430
}
431
 
432
 
433
//! Получение результата в тетраде TestCtrl
434
void TF_TestStrmOut::TestCtrlResult( ParamExchange *pr )
435
{
436
    U32 trd=1;
437
    U32 block_rd, block_ok, block_error, total_error;
438
 
439
    U32 reg_l, reg_h;
440
 
441
    reg_l = pBrd->RegPeekInd( trd, 0x210 );
442
    reg_h = pBrd->RegPeekInd( trd, 0x211 );
443
    block_rd = (reg_l&0xFFFF) | (reg_h<<16);
444
 
445
    reg_l = pBrd->RegPeekInd( trd, 0x212 );
446
    reg_h = pBrd->RegPeekInd( trd, 0x213 );
447
    block_ok = (reg_l&0xFFFF) | (reg_h<<16);
448
 
449
    reg_l = pBrd->RegPeekInd( trd, 0x214 );
450
    reg_h = pBrd->RegPeekInd( trd, 0x215 );
451
    block_error = (reg_l&0xFFFF) | (reg_h<<16);
452
 
453
    reg_l = pBrd->RegPeekInd( trd, 0x216 );
454
    reg_h = pBrd->RegPeekInd( trd, 0x217 );
455
    total_error = (reg_l&0xFFFF) | (reg_h<<16);
456
 
457
    pr->BlockRd=block_rd;
458
    pr->BlockOk=block_ok;
459
    pr->BlockError=block_error;
460
    pr->TotalError=total_error;
461
 
462 27 dsmv
    BRDC_fprintf( stderr, "\n Recieved blocks :   %d \n",  block_rd );
463
    BRDC_fprintf( stderr,   " Correct blocks  :   %d \n", block_ok );
464
    BRDC_fprintf( stderr,   " Incorrect blocks:   %d \n", block_error );
465
    BRDC_fprintf( stderr,   " Total errors    :   %d \n\n", total_error );
466
    BRDC_fprintf( stderr,   " Speed           :   %.1f [Mbytes/s] \n", pr->VelocityAvarage );
467 2 dsmv
 
468 27 dsmv
    U32 currentTime = GetTickCount();
469
    int min, sec_all, sec;
470
    sec_all= currentTime-pr->time_start;
471
    sec_all/=1000;
472
    sec=sec_all%60;
473
    min=sec_all/60;
474
 
475
    BRDC_fprintf( stderr,   " Time of test    :   %d min %.2d sec\n\n", min, sec );
476
 
477
 
478 2 dsmv
    if( total_error>0 )
479
    {
480
        BRDC_fprintf( stderr, " Error list:\n" );
481
        int cnt=total_error;
482
        if( cnt>16 )
483
            cnt=16;
484
 
485
        int ii;
486
        U32 block, adr, _adr;
487
        __int64 data_ex, data_in;
488
        __int64 r0, r1, r2, r3;
489
 
490
        BRDC_fprintf( stderr, "%5s %10s %10s %20s %20s   \n", "N", "Блок", "Адрес", "Ожидается", "Принято" );
491
        for( ii=0; ii<cnt; ii++ )
492
        {
493
            adr=(ii<<4) + 0; pBrd->RegPokeInd( trd, 0x218, adr ); r0 = pBrd->RegPeekInd( trd, 0x219 );
494
            adr=(ii<<4) + 1; pBrd->RegPokeInd( trd, 0x218, adr ); r1 = pBrd->RegPeekInd( trd, 0x219 );
495
            adr=(ii<<4) + 2; pBrd->RegPokeInd( trd, 0x218, adr ); r2 = pBrd->RegPeekInd( trd, 0x219 );
496
            adr=(ii<<4) + 3; pBrd->RegPokeInd( trd, 0x218, adr ); r3 = pBrd->RegPeekInd( trd, 0x219 );
497
            data_in = ((r3&0xFFFF)<<48) | ((r2&0xFFFF)<<32) | ((r1&0xFFFF)<<16) | (r0&0xFFFF);
498
 
499
            adr=(ii<<4) + 4; pBrd->RegPokeInd( trd, 0x218, adr ); r0 = pBrd->RegPeekInd( trd, 0x219 );
500
            adr=(ii<<4) + 5; pBrd->RegPokeInd( trd, 0x218, adr ); r1 = pBrd->RegPeekInd( trd, 0x219 );
501
            adr=(ii<<4) + 6; pBrd->RegPokeInd( trd, 0x218, adr ); r2 = pBrd->RegPeekInd( trd, 0x219 );
502
            adr=(ii<<4) + 7; pBrd->RegPokeInd( trd, 0x218, adr ); r3 = pBrd->RegPeekInd( trd, 0x219 );
503
            data_ex = ((r3&0xFFFF)<<48) | ((r2&0xFFFF)<<32) | ((r1&0xFFFF)<<16) | (r0&0xFFFF);
504
 
505
            adr=(ii<<4) + 8; pBrd->RegPokeInd( trd, 0x218, adr ); r0 = pBrd->RegPeekInd( trd, 0x219 );
506
            adr=(ii<<4) + 9; pBrd->RegPokeInd( trd, 0x218, adr ); r1 = pBrd->RegPeekInd( trd, 0x219 );
507
            _adr = ((r1&0xFFFF)<<16) | (r0&0xFFFF);
508
 
509
            adr=(ii<<4) + 10; pBrd->RegPokeInd( trd, 0x218, adr ); r0 = pBrd->RegPeekInd( trd, 0x219 );
510
            adr=(ii<<4) + 11; pBrd->RegPokeInd( trd, 0x218, adr ); r1 = pBrd->RegPeekInd( trd, 0x219 );
511
            block = ((r1&0xFFFF)<<16) | (r0&0xFFFF);
512
 
513
            //BRDC_fprintf( stderr, "%5d %10d %10d     %.16ll64X     %.16ll64X \n", ii, block, _adr, data_ex, data_in );
514
            BRDC_fprintf( stderr, "%5d %10d %10d     %.llX     %.llX \n", ii, block, _adr, (long long)data_ex, (long long)data_in );
515
        }
516
 
517
        BRDC_fprintf( stderr, "\n" );
518
    }
519
 
520
 
521
 
522
}
523
 
524
static U32 fa_data[4096];
525
 
526
//! Заполнение блока синусом
527
void TF_TestStrmOut::SetSignalInit( void )
528
{
529
    int ii;
530
    float v, arg;
531
    int   d;
532
    for( ii=0; ii<4096; ii++ )
533
    {
534
        arg=2*M_PI*ii/4096;
535
        v=10000*sin( arg );
536
        d=v;
537
        fa_data[ii]=d;
538
    }
539
 
540
    fa_cnt_re=0;
541
    fa_cnt_im=0x40000000;
542
    fa_inc_re=0x1000000;
543
    fa_inc_im=fa_inc_re;
544
 
545
}
546
 
547
 
548
//! Заполнение блока синусом
549
void TF_TestStrmOut::SetSignal( U32* ptr )
550
{
551
    int re, im;
552
    unsigned ii;
553
    int adr_re;
554
    int adr_im;
555
    U32 data;
556
    U32 *dst=ptr;
557
 
558
    fa_cnt_re=0;
559
    fa_cnt_im=0x40000000;
560
    fa_inc_re=0x4000000;
561
    fa_inc_im=fa_inc_re;
562
 
563
    U32 d=0x4000000/(SizeBlockOfWords/2);
564
 
565
    for( ii=0; ii<(SizeBlockOfWords); ii++ )
566
    {
567
        adr_re=(fa_cnt_re>>20) & 0x0FFF;
568
        adr_im=(fa_cnt_im>>20) & 0x0FFF;
569
        re=fa_data[adr_re];
570
        im=fa_data[adr_im];
571
        data = (im<<16) | (re&0xFFFF);
572
        *dst++=data;
573
 
574
        fa_cnt_re+=fa_inc_re;
575
        fa_cnt_im+=fa_inc_im;
576
 
577
        fa_inc_re-=d;
578
        fa_inc_im=fa_inc_re;
579
    }
580
 
581
 
582
}

powered by: WebSVN 2.1.0

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