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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [SuperH_SH7216_Renesas/] [RTOSDemo/] [main.c] - Blame information for rev 607

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

Line No. Rev Author Line
1 585 jeremybenn
/*
2
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
3
 
4
    ***************************************************************************
5
    *                                                                         *
6
    * If you are:                                                             *
7
    *                                                                         *
8
    *    + New to FreeRTOS,                                                   *
9
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
10
    *    + Looking for basic training,                                        *
11
    *    + Wanting to improve your FreeRTOS skills and productivity           *
12
    *                                                                         *
13
    * then take a look at the FreeRTOS books - available as PDF or paperback  *
14
    *                                                                         *
15
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
16
    *                  http://www.FreeRTOS.org/Documentation                  *
17
    *                                                                         *
18
    * A pdf reference manual is also available.  Both are usually delivered   *
19
    * to your inbox within 20 minutes to two hours when purchased between 8am *
20
    * and 8pm GMT (although please allow up to 24 hours in case of            *
21
    * exceptional circumstances).  Thank you for your support!                *
22
    *                                                                         *
23
    ***************************************************************************
24
 
25
    This file is part of the FreeRTOS distribution.
26
 
27
    FreeRTOS is free software; you can redistribute it and/or modify it under
28
    the terms of the GNU General Public License (version 2) as published by the
29
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
30
    ***NOTE*** The exception to the GPL is included to allow you to distribute
31
    a combined work that includes FreeRTOS without being obliged to provide the
32
    source code for proprietary components outside of the FreeRTOS kernel.
33
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
34
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
36
    more details. You should have received a copy of the GNU General Public
37
    License and the FreeRTOS license exception along with FreeRTOS; if not it
38
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
39
    by writing to Richard Barry, contact details for whom are available on the
40
    FreeRTOS WEB site.
41
 
42
    1 tab == 4 spaces!
43
 
44
    http://www.FreeRTOS.org - Documentation, latest information, license and
45
    contact details.
46
 
47
    http://www.SafeRTOS.com - A version that is certified for use in safety
48
    critical systems.
49
 
50
    http://www.OpenRTOS.com - Commercial support, development, porting,
51
    licensing and training services.
52
*/
53
 
54
 
55
 
56
/*
57
 * Creates all the demo application tasks, then starts the scheduler.  The WEB
58
 * documentation provides more details of the standard demo application tasks,
59
 * which provide no particular functionality but do provide a good example of
60
 * how to use the FreeRTOS API.  In addition to the standard demo tasks, the
61
 * following tasks and tests are defined and/or created within this file:
62
 *
63
 * Webserver ("uIP") task - This serves a number of dynamically generated WEB
64
 * pages to a standard WEB browser.  The IP and MAC addresses are configured by
65
 * constants defined at the bottom of FreeRTOSConfig.h.  Use either a standard
66
 * Ethernet cable to connect through a hug, or a cross over (point to point)
67
 * cable to connect directly.  Ensure the IP address used is compatible with the
68
 * IP address of the machine running the browser - the easiest way to achieve
69
 * this is to ensure the first three octets of the IP addresses are the same.
70
 *
71
 * "Reg test" tasks - These fill the registers with known values, then check
72
 * that each register still contains its expected value.  Each task uses
73
 * different values.  The tasks run with very low priority so get preempted very
74
 * frequently.  A register containing an unexpected value is indicative of an
75
 * error in the context switching mechanism.  Both standard and floating point
76
 * registers are checked.  The nature of the reg test tasks necessitates that
77
 * they are written in assembly code.  They are defined in regtest.src.
78
 *
79
 * "math" tasks - These are a set of 8 tasks that perform various double
80
 * precision floating point calculations in order to check that the tasks
81
 * floating point registers are being correctly saved and restored during
82
 * context switches.  The math tasks are defined in flop.c.
83
 *
84
 * "Check" task - This only executes every five seconds but has a high priority
85
 * to ensure it gets processor time.  Its main function is to check that all the
86
 * standard demo tasks are still operational.  While no errors have been
87
 * discovered the check task will toggle an LED every 5 seconds - the toggle
88
 * rate increasing to 200ms being a visual indication that at least one task has
89
 * reported unexpected behaviour.
90
 *
91
 * *NOTE 1* If LED5 is toggling every 5 seconds then all the demo application
92
 * tasks are executing as expected and no errors have been reported in any
93
 * tasks.  The toggle rate increasing to 200ms indicates that at least one task
94
 * has reported unexpected behaviour.
95
 *
96
 * *NOTE 2* This file and flop.c both demonstrate the use of
97
 * xPortUsesFloatingPoint() which informs the kernel that a task should maintain
98
 * a floating point context.
99
 *
100
 * *NOTE 3* vApplicationSetupTimerInterrupt() is called by the kernel to let
101
 * the application set up a timer to generate the tick interrupt.  In this
102
 * example a compare match timer is used for this purpose.
103
 * vApplicationTickHook() is used to clear the timer interrupt and relies on
104
 * configUSE_TICK_HOOK being set to 1 in FreeRTOSConfig.h.
105
 *
106
 * *NOTE 4* The traceTASK_SWITCHED_IN and traceTASK_SWITCHED_OUT trace hooks
107
 * are used to save and restore the floating point context respectively for
108
 * those tasks that require it (those for which xPortUsesFloatingPoint() has
109
 * been called).
110
 *
111
 * *NOTE 5* Any interrupt that can cause a context switch requires an asm
112
 * wrapper and must be assigned an interrupt priority of
113
 * portKERNEL_INTERRUPT_PRIORITY.
114
 *
115
 * *NOTE 6* vSetupClockForRunTimeStats() is called by the kernel (via the
116
 * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()) macro to configure an MTU channel
117
 * to produce a time base that is used to log how much processor time each task
118
 * is consuming.  The MTU is used to generate a high(ish) frequency interrupt,
119
 * and so also provides an example of how interrupts that don't make use of the
120
 * FreeRTOS kernel can be assigned a priority above any priority used by the
121
 * kernel itself.
122
 */
123
 
124
/* Kernel includes. */
125
#include "FreeRTOS.h"
126
#include "task.h"
127
 
128
/* Demo application includes. */
129
#include "BlockQ.h"
130
#include "death.h"
131
#include "integer.h"
132
#include "blocktim.h"
133
#include "flash.h"
134
#include "partest.h"
135
#include "semtest.h"
136
#include "PollQ.h"
137
#include "GenQTest.h"
138
#include "QPeek.h"
139
#include "recmutex.h"
140
#include "flop.h"
141
 
142
/* Constants required to configure the hardware. */
143
#define mainFRQCR_VALUE                                         ( 0x0303 )      /* Input = 12.5MHz, I Clock = 200MHz, B Clock = 50MHz, P Clock = 50MHz */
144
 
145
/* Task priorities. */
146
#define mainQUEUE_POLL_PRIORITY                         ( tskIDLE_PRIORITY + 1 )
147
#define mainCHECK_TASK_PRIORITY                         ( tskIDLE_PRIORITY + 3 )
148
#define mainSEM_TEST_PRIORITY                           ( tskIDLE_PRIORITY + 1 )
149
#define mainBLOCK_Q_PRIORITY                            ( tskIDLE_PRIORITY + 2 )
150
#define mainCREATOR_TASK_PRIORITY           ( tskIDLE_PRIORITY + 3 )
151
#define mainFLASH_TASK_PRIORITY                         ( tskIDLE_PRIORITY + 1 )
152
#define mainuIP_TASK_PRIORITY                           ( tskIDLE_PRIORITY + 2 )
153
#define mainINTEGER_TASK_PRIORITY           ( tskIDLE_PRIORITY )
154
#define mainGEN_QUEUE_TASK_PRIORITY                     ( tskIDLE_PRIORITY )
155
#define mainFLOP_TASK_PRIORITY                          ( tskIDLE_PRIORITY )
156
 
157
/* The WEB server uses string handling functions, which in turn use a bit more
158
stack than most of the other tasks. */
159
#define mainuIP_STACK_SIZE                                      ( configMINIMAL_STACK_SIZE * 3 )
160
 
161
/* The LED toggled by the check task. */
162
#define mainCHECK_LED                                           ( 5 )
163
 
164
/* The rate at which mainCHECK_LED will toggle when all the tasks are running
165
without error. */
166
#define mainNO_ERROR_CYCLE_TIME                         ( 5000 / portTICK_RATE_MS )
167
 
168
/* The rate at which mainCHECK_LED will toggle when an error has been reported
169
by at least one task. */
170
#define mainERROR_CYCLE_TIME                            ( 200 / portTICK_RATE_MS )
171
 
172
/*
173
 * vApplicationMallocFailedHook() will only be called if
174
 * configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
175
 * function that will execute if a call to pvPortMalloc() fails.
176
 * pvPortMalloc() is called internally by the kernel whenever a task, queue or
177
 * semaphore is created.  It is also called by various parts of the demo
178
 * application.
179
 */
180
void vApplicationMallocFailedHook( void );
181
 
182
/*
183
 * vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set to 1
184
 * in FreeRTOSConfig.h.  It is a hook function that is called on each iteration
185
 * of the idle task.  It is essential that code added to this hook function
186
 * never attempts to block in any way (for example, call xQueueReceive() with
187
 * a block time specified).  If the application makes use of the vTaskDelete()
188
 * API function (as this demo application does) then it is also important that
189
 * vApplicationIdleHook() is permitted to return to its calling function because
190
 * it is the responsibility of the idle task to clean up memory allocated by the
191
 * kernel to any task that has since been deleted.
192
 */
193
void vApplicationIdleHook( void );
194
 
195
/*
196
 * Just sets up clocks, ports, etc. used by the demo application.
197
 */
198
static void prvSetupHardware( void );
199
 
200
/*
201
 * The check task as described at the top of this file.
202
 */
203
static void prvCheckTask( void *pvParameters );
204
 
205
/*
206
 * The reg test tasks as described at the top of this file.
207
 */
208
extern void vRegTest1Task( void *pvParameters );
209
extern void vRegTest2Task( void *pvParameters );
210
 
211
/*
212
 * Contains the implementation of the WEB server.
213
 */
214
extern void vuIP_Task( void *pvParameters );
215
 
216
/*
217
 * The interrupt handler for the MTU - which is used to maintain the time base
218
 * used by the run time stats.
219
 */
220
#pragma interrupt MTU_Match
221
void MTU_Match( void );
222
 
223
/*-----------------------------------------------------------*/
224
 
225
/* Variables that are incremented on each iteration of the reg test tasks -
226
provided the tasks have not reported any errors.  The check task inspects these
227
variables to ensure they are still incrementing as expected. */
228
volatile unsigned long ulRegTest1CycleCount = 0UL, ulRegTest2CycleCount = 0UL;
229
 
230
/* The status message that is displayed at the bottom of the "task stats" WEB
231
page, which is served by the uIP task. */
232
const char *pcStatusMessage = "All tasks executing without error.";
233
 
234
/* The time use for the run time stats. */
235
unsigned long ulRunTime = 0UL;
236
 
237
/*-----------------------------------------------------------*/
238
 
239
/*
240
 * Creates the majority of the demo application tasks before starting the
241
 * scheduler.
242
 */
243
void main(void)
244
{
245
xTaskHandle xCreatedTask;
246
 
247
        prvSetupHardware();
248
 
249
        /* Start the reg test tasks which test the context switching mechanism. */
250
        xTaskCreate( vRegTest1Task, "RegTst1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xCreatedTask );
251
        xPortUsesFloatingPoint( xCreatedTask );
252
 
253
        xTaskCreate( vRegTest2Task, "RegTst2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xCreatedTask );
254
        xPortUsesFloatingPoint( xCreatedTask );
255
 
256
        xTaskCreate( vuIP_Task, "uIP", mainuIP_STACK_SIZE, NULL, mainuIP_TASK_PRIORITY, NULL );
257
 
258
        /* Start the check task as described at the top of this file. */
259
        xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
260
 
261
        /* Start the standard demo tasks.  These don't perform any particular useful
262
        functionality, other than to demonstrate the FreeRTOS API being used. */
263
        vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
264
        vCreateBlockTimeTasks();
265
    vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
266
    vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
267
    vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
268
    vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
269
        vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );
270
    vStartQueuePeekTasks();
271
        vStartRecursiveMutexTasks();
272
 
273
        /* Start the math tasks as described at the top of this file. */
274
        vStartMathTasks( mainFLOP_TASK_PRIORITY );
275
 
276
        /* The suicide tasks must be created last as they need to know how many
277
        tasks were running prior to their creation in order to ascertain whether
278
        or not the correct/expected number of tasks are running at any given time. */
279
    vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
280
 
281
        /* Start the tasks running. */
282
        vTaskStartScheduler();
283
 
284
        /* Will only get here if there was insufficient heap memory to create the idle
285
    task.  Increase the configTOTAL_HEAP_SIZE setting in FreeRTOSConfig.h. */
286
        for( ;; );
287
}
288
/*-----------------------------------------------------------*/
289
 
290
static void prvCheckTask( void *pvParameter )
291
{
292
portTickType xNextWakeTime, xCycleFrequency = mainNO_ERROR_CYCLE_TIME;
293
unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL;
294
 
295
        /* Just to remove compiler warning. */
296
        ( void ) pvParameter;
297
 
298
        /* Initialise xNextWakeTime - this only needs to be done once. */
299
        xNextWakeTime = xTaskGetTickCount();
300
 
301
        for( ;; )
302
        {
303
                /* Place this task in the blocked state until it is time to run again. */
304
                vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );
305
 
306
                /* Inspect all the other tasks to ensure none have experienced any errors. */
307
                if( xAreGenericQueueTasksStillRunning() != pdTRUE )
308
                {
309
                        /* Increase the rate at which this task cycles, which will increase the
310
                        rate at which mainCHECK_LED flashes to give visual feedback that an error
311
                        has occurred. */
312
                        xCycleFrequency = mainERROR_CYCLE_TIME;
313
                        pcStatusMessage = "Error in GenQ test.";
314
                }
315
                else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
316
                {
317
                        xCycleFrequency = mainERROR_CYCLE_TIME;
318
                        pcStatusMessage = "Error in Queue Peek test.";
319
                }
320
                else if( xAreBlockingQueuesStillRunning() != pdTRUE )
321
                {
322
                        xCycleFrequency = mainERROR_CYCLE_TIME;
323
                        pcStatusMessage = "Error in Blocking Queue test.";
324
                }
325
                else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
326
                {
327
                        xCycleFrequency = mainERROR_CYCLE_TIME;
328
                        pcStatusMessage = "Error in BlockTim test.";
329
                }
330
            else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
331
            {
332
                xCycleFrequency = mainERROR_CYCLE_TIME;
333
                        pcStatusMessage = "Error in Semaphore test.";
334
            }
335
            else if( xArePollingQueuesStillRunning() != pdTRUE )
336
            {
337
                xCycleFrequency = mainERROR_CYCLE_TIME;
338
                        pcStatusMessage = "Error in Polling Queue test.";
339
            }
340
            else if( xIsCreateTaskStillRunning() != pdTRUE )
341
            {
342
                xCycleFrequency = mainERROR_CYCLE_TIME;
343
                        pcStatusMessage = "Error in Create test.";
344
            }
345
            else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
346
            {
347
                xCycleFrequency = mainERROR_CYCLE_TIME;
348
                        pcStatusMessage = "Error in integer Math test.";
349
            }
350
            else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
351
            {
352
                xCycleFrequency = mainERROR_CYCLE_TIME;
353
                        pcStatusMessage = "Error in recursive mutex test.";
354
            }
355
                else if( xAreMathsTaskStillRunning() != pdTRUE )
356
                {
357
                        xCycleFrequency = mainERROR_CYCLE_TIME;
358
                        pcStatusMessage = "Error in floating point Math test.";
359
                }
360
 
361
                /* Check the reg test tasks are still cycling.  They will stop incrementing
362
                their loop counters if they encounter an error. */
363
                if( ulRegTest1CycleCount == ulLastRegTest1CycleCount )
364
                {
365
                        xCycleFrequency = mainERROR_CYCLE_TIME;
366
                        pcStatusMessage = "Error in RegTest.";
367
                }
368
 
369
                if( ulRegTest2CycleCount == ulLastRegTest2CycleCount )
370
                {
371
                        xCycleFrequency = mainERROR_CYCLE_TIME;
372
                        pcStatusMessage = "Error in RegTest.";
373
                }
374
 
375
                ulLastRegTest1CycleCount = ulRegTest1CycleCount;
376
                ulLastRegTest2CycleCount = ulRegTest2CycleCount;
377
 
378
                /* Toggle the check LED to give an indication of the system status.  If the
379
                LED toggles every 5 seconds then everything is ok.  A faster toggle indicates
380
                an error. */
381
                vParTestToggleLED( mainCHECK_LED );
382
        }
383
}
384
/*-----------------------------------------------------------*/
385
 
386
void vApplicationMallocFailedHook( void )
387
{
388
        /* A call to vPortMalloc() failed, probably during the creation of a task,
389
        queue or semaphore.  Inspect pxCurrentTCB to find which task is currently
390
        executing. */
391
        for( ;; );
392
}
393
/*-----------------------------------------------------------*/
394
 
395
void vApplicationIdleHook( void )
396
{
397
        /* Code can be added to the idle task here.  This function must *NOT* attempt
398
        to block.  Also, if the application uses the vTaskDelete() API function then
399
        this function must return regularly to ensure the idle task gets a chance to
400
        clean up the memory used by deleted tasks. */
401
}
402
/*-----------------------------------------------------------*/
403
 
404
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName )
405
{
406
        /* Just to remove compiler warnings.  This function will only actually
407
        get called if configCHECK_FOR_STACK_OVERFLOW is set to a non zero value.
408
        By default this demo does not use the stack overflow checking functionality
409
        as the SuperH will normally execute an exception if the stack overflows. */
410
        ( void ) pxTask;
411
        ( void ) pcTaskName;
412
 
413
        taskDISABLE_INTERRUPTS();
414
        for( ;; );
415
}
416
/*-----------------------------------------------------------*/
417
 
418
static void prvSetupHardware( void )
419
{
420
volatile unsigned long ul;
421
 
422
        /* Set the CPU and peripheral clocks. */
423
        CPG.FRQCR.WORD = mainFRQCR_VALUE;
424
 
425
        /* Wait for the clock to settle. */
426
        for( ul = 0; ul < 99; ul++ )
427
        {
428
                nop();
429
        }
430
 
431
        /* Initialise the ports used to toggle LEDs. */
432
        vParTestInitialise();
433
}
434
/*-----------------------------------------------------------*/
435
 
436
void vApplicationSetupTimerInterrupt( void )
437
{
438
/* The peripheral clock is divided by 32 before feeding the compare match
439
peripheral (CMT). */
440
const unsigned long ulCompareMatch = ( configPERIPHERAL_CLOCK_HZ / ( configTICK_RATE_HZ * 32 ) ) + 1;
441
 
442
        /* Configure a timer to create the RTOS tick interrupt.  This example uses
443
        the compare match timer, but the multi function timer or possible even the
444
        watchdog timer could also be used.  Ensure vPortTickInterrupt() is installed
445
        as the interrupt handler for whichever peripheral is used. */
446
 
447
        /* Turn the CMT on. */
448
        STB.CR4.BIT._CMT = 0;
449
 
450
        /* Set the compare match value for the required tick frequency. */
451
        CMT0.CMCOR = ( unsigned short ) ulCompareMatch;
452
 
453
        /* Divide the peripheral clock by 32. */
454
        CMT0.CMCSR.BIT.CKS = 0x01;
455
 
456
        /* Set the CMT interrupt priority - the interrupt priority must be
457
        configKERNEL_INTERRUPT_PRIORITY no matter which peripheral is used to generate
458
        the tick interrupt. */
459
        INTC.IPR08.BIT._CMT0 = portKERNEL_INTERRUPT_PRIORITY;
460
 
461
        /* Clear the interrupt flag. */
462
        CMT0.CMCSR.BIT.CMF = 0;
463
 
464
        /* Enable the compare match interrupt. */
465
        CMT0.CMCSR.BIT.CMIE = 0x01;
466
 
467
        /* Start the timer. */
468
        CMT.CMSTR.BIT.STR0 = 0x01;
469
}
470
/*-----------------------------------------------------------*/
471
 
472
void vApplicationTickHook( void )
473
{
474
        /* Clear the tick inerrupt.  This is called from an interrupt context. */
475
        CMT0.CMCSR.BIT.CMF = 0;
476
}
477
/*-----------------------------------------------------------*/
478
 
479
void vSetupClockForRunTimeStats( void )
480
{
481
        /* Configure an MTU channel to generate a periodic interrupt that is used
482
        as the run time stats time base.  The run time stats keep a track of how
483
        much processing time each task is using. */
484
 
485
        /* Turn the MTU2 on. */
486
        STB.CR3.BIT._MTU2 = 0;
487
 
488
        /* Clear counter on compare match A. */
489
        MTU20.TCR.BIT.CCLR = 0x01;
490
 
491
        /* Compare match value to give very approximately 10 interrupts per
492
        millisecond. */
493
        MTU20.TGRA = 5000;
494
 
495
        /* Ensure the interrupt is clear. */
496
        MTU20.TSR.BIT.TGFA = 0;
497
 
498
        /* Enable the compare match interrupt. */
499
        MTU20.TIER.BIT.TGIEA = 0x01;
500
 
501
        /* Set the interrupt priority. */
502
        INTC.IPR09.BIT._MTU20G = portKERNEL_INTERRUPT_PRIORITY + 1;
503
 
504
        /* Start the count. */
505
        MTU2.TSTR.BIT.CST0 = 1;
506
}
507
/*-----------------------------------------------------------*/
508
 
509
void MTU_Match( void )
510
{
511
volatile unsigned char ucStatus;
512
 
513
        /* Increment the run time stats time base. */
514
        ulRunTime++;
515
 
516
        /* Clear the interrupt. */
517
        ucStatus = MTU20.TSR.BYTE;
518
        MTU20.TSR.BIT.TGFA = 0;
519
}
520
/*-----------------------------------------------------------*/
521
 
522
char *pcGetTaskStatusMessage( void )
523
{
524
        /* Not bothered about a critical section here.  This just returns a string
525
        that is displaed on the "Task Stats" WEB page served by this demo. */
526
        return pcStatusMessage;
527
}
528
/*-----------------------------------------------------------*/

powered by: WebSVN 2.1.0

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