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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [usb/] [serial/] [slave/] [current/] [src/] [usbs_serial.c] - Blame information for rev 867

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

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      usbs_serial.c
4
//
5
//      Support for slave-side USB serial devices.
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2008, 2010 Free Software Foundation, Inc.                        
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    Frank M. Pagliughi (fmp), SoRo Systems, Inc.
43
// Contributors: jld
44
// Date:         2008-06-02
45
//
46
//####DESCRIPTIONEND####
47
//
48
//==========================================================================
49
 
50
#include <cyg/infra/cyg_type.h>
51
#include <cyg/infra/cyg_ass.h>
52
#include <cyg/infra/cyg_trac.h>
53
#include <cyg/infra/diag.h>
54
#include <cyg/hal/hal_arch.h>
55
#include <cyg/hal/drv_api.h>
56
#include <cyg/kernel/kapi.h>
57
 
58
#include <pkgconf/io_usb_slave_serial.h>
59
#include <cyg/io/usb/usbs_serial.h>
60
#include <string.h>
61
 
62
#if defined(CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG)
63
#define DBG diag_printf
64
#else
65
#define DBG (1) ? (void)0 : diag_printf
66
#endif
67
 
68
#define EP0_MAX_PACKET_SIZE     CYGNUM_IO_USB_SLAVE_SERIAL_EP0_MAX_PACKET_SIZE
69
 
70
extern usbs_control_endpoint    CYGDAT_IO_USB_SLAVE_SERIAL_EP0;
71
 
72
#if defined(CYGPKG_IO_USB_SLAVE_SERIAL_STATIC_EP)
73
extern usbs_tx_endpoint         CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP;
74
extern usbs_rx_endpoint         CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP;
75
#define TX_EP                   (&CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP)
76
#define RX_EP                   (&CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP)
77
#define INTR_EP                 (&CYGDAT_IO_USB_SLAVE_SERIAL_INTR_EP)
78
#endif
79
 
80
#define TX_EP_NUM               CYGNUM_IO_USB_SLAVE_SERIAL_TX_EP_NUM
81
#define RX_EP_NUM               CYGNUM_IO_USB_SLAVE_SERIAL_RX_EP_NUM
82
#define INTR_EP_NUM             CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP_NUM
83
#define EP0                     (&CYGDAT_IO_USB_SLAVE_SERIAL_EP0)
84
 
85
 
86
#define VENDOR_ID               CYGNUM_IO_USB_SLAVE_SERIAL_VENDOR_ID
87
#define PRODUCT_ID              CYGNUM_IO_USB_SLAVE_SERIAL_PRODUCT_ID
88
 
89
#define USB_MAX_STR_LEN         256
90
 
91
#define LO_BYTE_16(word16)      ((cyg_uint8) ((word16) & 0xFF))
92
#define HI_BYTE_16(word16)      ((cyg_uint8) (((word16) >> 8) & 0xFF))
93
 
94
#define BYTE0_32(word32)        ((cyg_uint8) ((word32) & 0xFF))
95
#define BYTE1_32(word32)        ((cyg_uint8) (((word32) >>  8) & 0xFF))
96
#define BYTE2_32(word32)        ((cyg_uint8) (((word32) >> 16) & 0xFF))
97
#define BYTE3_32(word32)        ((cyg_uint8) (((word32) >> 24) & 0xFF))
98
 
99
 
100
#define MFG_STR_INDEX           '\x01'
101
#define PRODUCT_STR_INDEX       '\x02'
102
 
103
#define USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH(interfaces, endpoints) \
104
            (USB_CONFIGURATION_DESCRIPTOR_LENGTH +            \
105
            ((interfaces) * USB_INTERFACE_DESCRIPTOR_LENGTH) +  \
106
            ((endpoints)  * USB_ENDPOINT_DESCRIPTOR_LENGTH))
107
 
108
 
109
#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
110
    #define USBS_SERIAL_DEVICE_CLASS        2
111
    #define USBS_SERIAL_NUM_IFACE           2
112
    #define USBS_SERIAL_NUM_ENDP            3
113
    #define USBS_SERIAL_DATA_IFACE_CLASS    0x0A    // Data
114
#else
115
    #define USBS_SERIAL_DEVICE_CLASS        0
116
    #define USBS_SERIAL_NUM_IFACE           1
117
    #define USBS_SERIAL_NUM_ENDP            2
118
    #define USBS_SERIAL_DATA_IFACE_CLASS    0xFF    // Vendor
119
#endif
120
 
121
// ----- Configuration Descriptor -----
122
 
123
static const usb_configuration_descriptor usb_configuration = {
124
    length:             sizeof(usb_configuration_descriptor),
125
    type:               USB_CONFIGURATION_DESCRIPTOR_TYPE,
126
    total_length_lo:
127
        USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_LO(USBS_SERIAL_NUM_IFACE,
128
                                                     USBS_SERIAL_NUM_ENDP),
129
    total_length_hi:
130
        USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_HI(USBS_SERIAL_NUM_IFACE,
131
                                                     USBS_SERIAL_NUM_ENDP),
132
    number_interfaces:  USBS_SERIAL_NUM_IFACE,
133
    configuration_id:   1,
134
    configuration_str:  0,
135
#ifdef CYGOPT_IO_USB_SLAVE_SERIAL_BUSPOWERED
136
    attributes:         (USB_CONFIGURATION_DESCRIPTOR_ATTR_REQUIRED),
137
#else
138
    attributes:         (USB_CONFIGURATION_DESCRIPTOR_ATTR_REQUIRED |
139
                         USB_CONFIGURATION_DESCRIPTOR_ATTR_SELF_POWERED),
140
#endif
141
    max_power:          (CYGNUM_IO_USB_SLAVE_SERIAL_CURRENTDRAW+1)/2
142
};
143
 
144
// ----- Interface Descriptor -----
145
 
146
static const usb_interface_descriptor usb_interface[] = {
147
 
148
#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
149
    {
150
        length:             sizeof(usb_interface_descriptor),
151
        type:               USB_INTERFACE_DESCRIPTOR_TYPE,
152
        interface_id:       0,
153
        alternate_setting:  0,
154
        number_endpoints:   1,
155
        interface_class:    0x02,   // Comm class
156
        interface_subclass: 0x02,
157
        interface_protocol: 0x01,
158
        interface_str:      0x00
159
    },
160
    {
161
        length:             sizeof(usb_interface_descriptor),
162
        type:               USB_INTERFACE_DESCRIPTOR_TYPE,
163
        interface_id:       1,
164
        alternate_setting:  0,
165
        number_endpoints:   2,
166
        interface_class:    USBS_SERIAL_DATA_IFACE_CLASS,
167
        interface_subclass: 0x00,
168
        interface_protocol: 0x00,
169
        interface_str:      0x00
170
    }
171
#else
172
    {
173
        length:             sizeof(usb_interface_descriptor),
174
        type:               USB_INTERFACE_DESCRIPTOR_TYPE,
175
        interface_id:       0,
176
        alternate_setting:  0,
177
        number_endpoints:   2,
178
        interface_class:    USBS_SERIAL_DATA_IFACE_CLASS,
179
        interface_subclass: 0x00,
180
        interface_protocol: 0x00,
181
        interface_str:      0x00
182
    }
183
#endif
184
};
185
 
186
// ----- Endpoint Descriptors -----
187
 
188
static const usb_endpoint_descriptor usb_endpoints[] =
189
{
190
#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
191
    // Interrupt in endpoint
192
    {
193
        sizeof(usb_endpoint_descriptor),
194
        USB_ENDPOINT_DESCRIPTOR_TYPE,
195
        USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | INTR_EP_NUM,
196
        USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT,
197
        0x40,
198
        0,
199
        255
200
    },
201
#endif
202
 
203
    // Tx (Bulk IN) Endpoint Descriptor
204
    {
205
        sizeof(usb_endpoint_descriptor),
206
        USB_ENDPOINT_DESCRIPTOR_TYPE,
207
        USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | TX_EP_NUM,
208
        USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
209
        0x40,
210
        0,
211
 
212
    },
213
 
214
    // Rx (Bulk OUT) Endpoint Descriptor
215
    {
216
        sizeof(usb_endpoint_descriptor),
217
        USB_ENDPOINT_DESCRIPTOR_TYPE,
218
        USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT | RX_EP_NUM,
219
        USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
220
        0x40,
221
        0,
222
 
223
    }
224
};
225
 
226
// ----- String Descriptors -----
227
 
228
static char mfg_str_descr[USB_MAX_STR_LEN],
229
            product_str_descr[USB_MAX_STR_LEN];
230
 
231
 
232
static const char* usb_strings[] = {
233
    "\x04\x03\x09\x04",
234
    mfg_str_descr,
235
    product_str_descr
236
};
237
 
238
// ----- Enumeration Data w/ Device Descriptor -----
239
 
240
static usbs_enumeration_data usb_enum_data = {
241
    {
242
        length:                 sizeof(usb_device_descriptor),
243
        type:                   USB_DEVICE_DESCRIPTOR_TYPE,
244
        usb_spec_lo:            0x00,
245
        usb_spec_hi:            0x02,
246
        device_class:           USBS_SERIAL_DEVICE_CLASS,
247
        device_subclass:        0,
248
        device_protocol:        0,
249
        max_packet_size:        EP0_MAX_PACKET_SIZE,
250
        vendor_lo:              LO_BYTE_16(VENDOR_ID),
251
        vendor_hi:              HI_BYTE_16(VENDOR_ID),
252
        product_lo:             LO_BYTE_16(PRODUCT_ID),
253
        product_hi:             HI_BYTE_16(PRODUCT_ID),
254
        device_lo:              0x00,
255
        device_hi:              0x00,
256
        manufacturer_str:       MFG_STR_INDEX,
257
        product_str:            PRODUCT_STR_INDEX,
258
        serial_number_str:      0,
259
        number_configurations:  1
260
    },
261
 
262
    total_number_interfaces:    USBS_SERIAL_NUM_IFACE,
263
    total_number_endpoints:     USBS_SERIAL_NUM_ENDP,
264
    total_number_strings:       3,
265
    configurations:             &usb_configuration,
266
    interfaces:                 usb_interface,
267
    endpoints:                  usb_endpoints,
268
    strings:                    (const unsigned char **) usb_strings
269
};
270
 
271
// --------------------------------------------------------------------------
272
// USBS Serial Data
273
// --------------------------------------------------------------------------
274
 
275
usbs_control_endpoint* usbs_serial_ep0 = EP0;
276
 
277
// Lock for the state.
278
cyg_mutex_t usbs_serial_lock;
279
 
280
// Condition variable for state changes
281
cyg_cond_t  usbs_serial_state_cond;
282
 
283
int usbs_serial_state;
284
 
285
usbs_serial usbs_ser0 = {
286
    tx_result:  0,
287
    rx_result:  0,
288
};
289
 
290
static void (*usbs_serial_app_state_change_fn)(struct usbs_control_endpoint*,
291
                                               void*, usbs_state_change, int)
292
= 0;
293
 
294
// --------------------------------------------------------------------------
295
// Create a USB String Descriptor from a C string.
296
 
297
void
298
usbs_serial_create_str_descriptor(char descr[], const char *str)
299
{
300
    int i, n = strlen(str);
301
 
302
    if (n > (USB_MAX_STR_LEN/2 - 2))
303
        n = USB_MAX_STR_LEN/2 - 2;
304
 
305
    descr[0] = (cyg_uint8) (2*n + 2);
306
    descr[1] = USB_DEVREQ_DESCRIPTOR_TYPE_STRING;
307
 
308
    for (i=0; i<n; i++) {
309
        descr[i*2+2] = str[i];
310
        descr[i*2+3] = '\x00';
311
    }
312
}
313
 
314
// --------------------------------------------------------------------------
315
// ACM Class Handler
316
//
317
// For a Windows host, the device must, at least, respond to a SetLineCoding
318
// request (0x20), otherwise Windows will report that it's unable to open the 
319
// port. This request normally sets the standard serial parameters:
320
//          baud rate, # stop bits, parity, and # data bits
321
// If we're just making believe that we're a serial port to communicate with
322
// the host via USB, then these values don't matter. So we ACK the request,
323
// but ignore the parameters.
324
// If we were actually creating a USB-serial converter, then we would need to
325
// read these values and configure the serial port accordingly.
326
// 
327
// Similarly, the host can request the current settings through a 
328
// GetLineCoding request (0x21). Since we're just faking it, we return some
329
// arbitrary values: 38400,1,N,8
330
 
331
#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
332
 
333
static usbs_control_return
334
usbs_serial_acm_class_handler(usbs_control_endpoint* ep0, void* data)
335
{
336
  usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
337
  usb_devreq      *req = (usb_devreq *) ep0->control_buffer;
338
  static cyg_uint8 rsp_buf[32];
339
  cyg_uint32 baud = 38400;  // Arbitrary, fake value to return to the host.
340
 
341
  DBG("USB Serial ACM Class Handler: ");
342
 
343
  switch (req->request) {
344
 
345
    case USBS_SERIAL_SET_LINE_CODING :
346
      DBG("ACM Request: Set Line Coding\n");
347
      result = USBS_CONTROL_RETURN_HANDLED;
348
      break;
349
 
350
    case USBS_SERIAL_GET_LINE_CODING :
351
      DBG("ACM Request: Get Line Coding\n");
352
      rsp_buf[0] = BYTE0_32(baud);
353
      rsp_buf[1] = BYTE1_32(baud);
354
      rsp_buf[2] = BYTE2_32(baud);
355
      rsp_buf[3] = BYTE3_32(baud);
356
      rsp_buf[4] = 0; // One stop bit
357
      rsp_buf[5] = 0; // No parity
358
      rsp_buf[6] = 8; // 8 data bits
359
      ep0->buffer = rsp_buf;
360
      ep0->buffer_size = 7;
361
      result = USBS_CONTROL_RETURN_HANDLED;
362
      break;
363
 
364
    default :
365
      DBG("*** Unhandled ACM Request: 0x%02X ***\n",
366
          (unsigned) req->request);
367
  }
368
 
369
  return result;
370
}
371
#endif      // CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
372
 
373
// --------------------------------------------------------------------------
374
// Callback for a USB state change
375
 
376
void
377
usbs_serial_state_change_handler(usbs_control_endpoint* ep, void* data,
378
                                 usbs_state_change change, int prev_state)
379
{
380
#if defined(CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG)
381
  const char *STATE_CHG_STR[] = { "Detached", "Attached", "Powered", "Reset",
382
                                  "Addressed", "Configured", "Deconfigured",
383
                                  "Suspended", "Resumed" };
384
 
385
  if (change > 0) {
386
    DBG("### %d:%s ###\n", change, STATE_CHG_STR[(int) change-1]);
387
  }
388
#endif
389
 
390
  // Called from DSR, cond broadcast should be ok without mutex lock
391
  usbs_serial_state = usbs_serial_ep0->state;
392
  cyg_cond_broadcast(&usbs_serial_state_cond);
393
 
394
  if (usbs_serial_app_state_change_fn)
395
    (*usbs_serial_app_state_change_fn)(ep, data, change, prev_state);
396
}
397
 
398
// --------------------------------------------------------------------------
399
// Block the calling thread until the USB is configured.
400
 
401
void
402
usbs_serial_wait_until_configured(void)
403
{
404
  cyg_mutex_lock(&usbs_serial_lock);
405
  while (usbs_serial_state != USBS_STATE_CONFIGURED)
406
    cyg_cond_wait(&usbs_serial_state_cond);
407
 
408
#if !defined(CYGPKG_IO_USB_SLAVE_SERIAL_STATIC_EP)
409
  usbs_ser0.tx_ep = usbs_get_tx_endpoint(usbs_serial_ep0, TX_EP_NUM);
410
  usbs_ser0.rx_ep = usbs_get_rx_endpoint(usbs_serial_ep0, RX_EP_NUM);
411
#endif
412
 
413
  cyg_mutex_unlock(&usbs_serial_lock);
414
}
415
 
416
// --------------------------------------------------------------------------
417
// Determine if the device is currently configured.
418
 
419
cyg_bool
420
usbs_serial_is_configured(void)
421
{
422
  return usbs_serial_state == USBS_STATE_CONFIGURED;
423
}
424
 
425
// --------------------------------------------------------------------------
426
// Callback for when a transmit is complete
427
 
428
static void
429
usbs_serial_tx_complete(void *p, int result)
430
{
431
  usbs_serial* ser = (usbs_serial*) p;
432
  ser->tx_result = result;
433
  cyg_semaphore_post(&ser->tx_ready);
434
}
435
 
436
// --------------------------------------------------------------------------
437
// Callback for when a receive is complete
438
 
439
static void
440
usbs_serial_rx_complete(void *p, int result)
441
{
442
  usbs_serial* ser = (usbs_serial*) p;
443
  ser->rx_result = result;
444
  cyg_semaphore_post(&ser->rx_ready);
445
}
446
 
447
// --------------------------------------------------------------------------
448
// Start an asynchronous transmit of a buffer.
449
// 
450
 
451
void
452
usbs_serial_start_tx(usbs_serial* ser, const void* buf, int n)
453
{
454
  usbs_start_tx_buffer(ser->tx_ep, (unsigned char*) buf, n,
455
                       usbs_serial_tx_complete, ser);
456
}
457
 
458
// --------------------------------------------------------------------------
459
// Block the caller until the transmit is complete
460
 
461
int
462
usbs_serial_wait_for_tx(usbs_serial* ser)
463
{
464
  cyg_semaphore_wait(&ser->tx_ready);
465
  return ser->tx_result;
466
}
467
 
468
// --------------------------------------------------------------------------
469
// Perform a synchronous transmit and wait for it to complete.
470
 
471
int
472
usbs_serial_tx(usbs_serial* ser, const void* buf, int n)
473
{
474
  usbs_serial_start_tx(ser, buf, n);
475
  return usbs_serial_wait_for_tx(ser);
476
}
477
 
478
// --------------------------------------------------------------------------
479
// Start an asynchronous receive of a buffer.
480
 
481
void
482
usbs_serial_start_rx(usbs_serial* ser, void* buf, int n)
483
{
484
  usbs_start_rx_buffer(ser->rx_ep, (unsigned char*) buf, n,
485
                       usbs_serial_rx_complete, ser);
486
}
487
 
488
// --------------------------------------------------------------------------
489
// Block the caller until the receive is complete
490
 
491
int
492
usbs_serial_wait_for_rx(usbs_serial* ser)
493
{
494
  cyg_semaphore_wait(&ser->rx_ready);
495
  return ser->rx_result;
496
}
497
 
498
// --------------------------------------------------------------------------
499
// Perform a synchronous receive and wait for it to complete.
500
 
501
int
502
usbs_serial_rx(usbs_serial* ser, void* buf, int n)
503
{
504
  usbs_serial_start_rx(ser, buf, n);
505
  return usbs_serial_wait_for_rx(ser);
506
}
507
 
508
// --------------------------------------------------------------------------
509
// Initialize a serial port structure.
510
 
511
void
512
usbs_serial_init(usbs_serial* ser, usbs_tx_endpoint* tx_ep,
513
                 usbs_rx_endpoint* rx_ep)
514
{
515
  ser->tx_ep = tx_ep;
516
  ser->rx_ep = rx_ep;
517
 
518
  cyg_semaphore_init(&ser->tx_ready, 0);
519
  cyg_semaphore_init(&ser->rx_ready, 0);
520
}
521
 
522
// --------------------------------------------------------------------------
523
// Start the USB subsystem
524
 
525
void
526
usbs_serial_start(void)
527
{
528
#if defined(CYGPKG_IO_USB_SLAVE_SERIAL_STATIC_EP)
529
  usbs_serial_init(&usbs_ser0, TX_EP, RX_EP);
530
#else  
531
  usbs_serial_init(&usbs_ser0, NULL, NULL);
532
#endif
533
 
534
  cyg_mutex_init(&usbs_serial_lock);
535
  cyg_cond_init(&usbs_serial_state_cond, &usbs_serial_lock);
536
 
537
  // Make the mfg & product names into USB string descriptors
538
 
539
  usbs_serial_create_str_descriptor(mfg_str_descr,
540
                                    CYGDAT_IO_USB_SLAVE_SERIAL_MFG_STR);
541
  usbs_serial_create_str_descriptor(product_str_descr,
542
                                    CYGDAT_IO_USB_SLAVE_SERIAL_PRODUCT_STR);
543
 
544
  // ----- Set up enumeration & USB callbacks -----
545
 
546
  usbs_serial_state = usbs_serial_ep0->state;
547
 
548
  usbs_serial_ep0->enumeration_data   = &usb_enum_data;
549
 
550
  if (usbs_serial_ep0->state_change_fn)
551
    usbs_serial_app_state_change_fn = usbs_serial_ep0->state_change_fn;
552
 
553
  usbs_serial_ep0->state_change_fn = usbs_serial_state_change_handler;
554
 
555
#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM
556
  if (!usbs_serial_ep0->class_control_fn)
557
    usbs_serial_ep0->class_control_fn = usbs_serial_acm_class_handler;
558
#endif
559
 
560
  // ----- Start USB subsystem -----
561
 
562
  usbs_start(usbs_serial_ep0);
563
}

powered by: WebSVN 2.1.0

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