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

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 805 to Rev 806
    Reverse comparison

Rev 805 → Rev 806

/trunk/or1ksim/peripheral/16450.c
48,7 → 48,7
static unsigned long char_clks(int dll, int dlh, int lcr)
{
float bauds_per_char = 1.;
unsigned long char_clks = ((dlh << 8) + dll) * UART_CLOCK_DIVIDER;
unsigned long char_clks = ((dlh << 8) + dll);
if (lcr & UART_LCR_PARITY)
bauds_per_char = bauds_per_char + 1.;
332,6 → 332,221
uarts[uart].istat.timeout_count = 0;
}
 
/* Simulation hook. Must be called every clock cycle to simulate all UART
devices. It does internal functional UART simulation. */
void uart_clock16(int i)
{
int retval;
/* If VAPI is not selected, UART communicates with two file streams;
if VAPI is selected, we use VAPI streams. */
 
/* if txfs is corrupted, skip this uart. */
if (!config.uarts[i].vapi_id && !uarts[i].txfs) return;
if (uarts[i].vapi.next_break_cnt >= 0)
if (--uarts[i].vapi.next_break_cnt < 0) {
if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break))
uarts[i].istat.break_set = 0;
}
/***************** Transmit *****************/
if (!uarts[i].istat.txser_full) {
// uarts[i].regs.lsr |= UART_LSR_TXBUFE;
if (uarts[i].istat.txbuf_full) {
uarts[i].iregs.txser = uarts[i].regs.txbuf[uarts[i].istat.txbuf_tail];
uarts[i].istat.txbuf_tail = (uarts[i].istat.txbuf_tail + 1) % uarts[i].fifo_len;
uarts[i].istat.txser_full = 1;
uarts[i].istat.txbuf_full--;
uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
uarts[i].istat.thre_int = 1;
} else {
uarts[i].regs.lsr |= UART_LSR_TXSERE;
uarts[i].regs.lsr |= UART_LSR_TXBUFE;
}
} else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
} else {
/* We are still sending char here*/
/* Check if we set the break bit */
if (uarts[i].regs.lcr & UART_LCR_SBC) {
if (!uarts[i].vapi.break_sent) {
#if 0
/* Send broken frame */
int nbits_sent = ((uarts[i].regs.lcr & UART_LCR_WLEN8) + 5) * (uarts[i].istat.txser_clks - 1) / uarts[i].char_clks;
send_char(i, nbits_sent);
#endif
/* Send one break signal */
vapi_send (config.uarts[i].vapi_id, UART_LCR_SBC << 8);
uarts[i].vapi.break_sent = 1;
}
/* mark as character was sent */
uarts[i].istat.txser_full = 0;
uarts[i].istat.txser_clks = 0;
} else
uarts[i].vapi.break_sent = 0;
}
 
/***************** Receive *****************/
/* Is there a break? */
if (uarts[i].vapi.cur_break) {
uarts[i].vapi.cur_break_cnt++;
if (uarts[i].vapi.cur_break_cnt > UART_BREAK_COUNT * uarts[i].vapi.char_clks) {
if (!uarts[i].istat.break_set) {
unsigned lsr;
uarts[i].istat.break_set = 1;
lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
printf ("[%x]\n", uarts[i].regs.lsr);
uarts[i].istat.rxser_full = 0;
uarts[i].istat.rxser_clks = 0;
uart_add_char (i, lsr << 8);
} else
uarts[i].vapi.cur_break_cnt = 0;
}
if (uarts[i].istat.rxser_full) {
uarts[i].istat.rxser_full = 0;
uarts[i].istat.rxser_clks = 0;
}
} else {
if (uarts[i].istat.rxser_full) {
if (uarts[i].char_clks <= uarts[i].istat.rxser_clks++) {
/* Set unused character bits to zero and allow lsr register in fifo */
uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1) | 0xff00;
debug(4, "Receiving 0x%02x'%c' via UART%d...\n", uarts[i].iregs.rxser, uarts[i].iregs.rxser, i);
uarts[i].istat.rxser_full = 0;
uarts[i].istat.rxser_clks = 0;
uart_add_char (i, uarts[i].iregs.rxser);
}
}
}
 
/* Check if there is something waiting, and put it into rxser */
if (uarts[i].regs.mcr & UART_MCR_LOOP) {
uarts[i].iregs.rxser = uarts[i].iregs.loopback;
uarts[i].istat.rxser_full = 1;
} else {
if (!config.uarts[i].vapi_id) {
if(uarts[i].istat.rxser_full == 0) {
if (uarts[i].slowdown)
uarts[i].slowdown--;
else if((retval = fgetc(uarts[i].rxfs)) != EOF) {
uarts[i].iregs.rxser = (char)retval;
uarts[i].istat.rxser_full = 1;
} else uarts[i].slowdown = UART_FGETC_SLOWDOWN;
}
} else { /* VAPI */
int received = 0;
/* do not handle commands while receiving */
if (uarts[i].istat.rxser_full) return;
while (!received) {
if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
debug(4, "Handling: %08x (%i,%i)\n", data, uarts[i].vapi_buf_head_ptr, uarts[i].vapi_buf_tail_ptr);
uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
switch (data >> 24) {
case 0x00:
uarts[i].vapi.lcr = (data >> 8) & 0xff;
/* Put data into rx fifo */
uarts[i].iregs.rxser = data & 0xff;
uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC)
|| uarts[i].vapi.char_clks != uarts[i].char_clks
|| uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC);
/* Set error bits */
uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8;
}
uarts[i].istat.rxser_full = 1;
received = 1;
break;
case 0x01:
uarts[i].vapi.dll = (data >> 0) & 0xff;
uarts[i].vapi.dlh = (data >> 8) & 0xff;
break;
case 0x02:
uarts[i].vapi.lcr = (data >> 8) & 0xff;
break;
case 0x03:
uarts[i].vapi.skew = (signed short)(data & 0xffff);
break;
case 0x04:
uarts[i].vapi.next_break_cnt = data & 0xffff;
uarts[i].vapi.next_break = (data >> 16) & 1;
break;
default:
debug (0, "WARNING: Invalid vapi command %02x\n", data >> 24);
break;
}
} else break;
}
}
}
/***************** Loopback *****************/
if (uarts[i].regs.mcr & UART_MCR_LOOP) {
debug(5, "uart_clock: Loopback\n");
if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
uarts[i].regs.msr |= UART_MSR_DDCD;
if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
((uarts[i].regs.msr & UART_MSR_RI) >> 4))
uarts[i].regs.msr |= UART_MSR_TERI;
if ((uarts[i].regs.mcr & UART_MCR_RTS) !=
((uarts[i].regs.msr & UART_MSR_CTS) >> 3))
uarts[i].regs.msr |= UART_MSR_DCTS;
if ((uarts[i].regs.mcr & UART_MCR_DTR) !=
((uarts[i].regs.msr & UART_MSR_DSR) >> 5))
uarts[i].regs.msr |= UART_MSR_DDSR;
uarts[i].regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
| UART_MSR_DSR | UART_MSR_CTS);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX2) << 4);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX1) << 4);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_RTS) << 3);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_DTR) << 5);
}
if (uarts[i].regs.lsr & UART_LSR_RDRDY)
uarts[i].istat.timeout_count++;
/* Update LSR error bits from the ones from rx FIFO */
if (uarts[i].istat.rxbuf_full) {
uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8;
/* we must delete the lsr status, so that we can clear it from lsr */
uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff;
}
/* Interrupt detection in proper priority order. */
uarts[i].regs.iir = UART_IIR_NO_INT;
if (uarts[i].regs.ier & UART_IER_RLSI && /* Receiver LS */
uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
| UART_LSR_FRAME | UART_LSR_BREAK)) {
uarts[i].regs.iir = UART_IIR_RLSI;
} else if ((uarts[i].regs.ier & UART_IER_RDI) /* RD available */
&& (uarts[i].istat.rxbuf_full >= UART_FIFO_TRIGGER(uarts[i].regs.fcr >> 6))
&& (uarts[i].regs.lsr & UART_LSR_RDRDY)) {
uarts[i].regs.iir = UART_IIR_RDI;
} else if ((uarts[i].regs.ier & UART_IER_RDI) /* timeout */
&& (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
uarts[i].regs.iir = UART_IIR_CTI;
} else if (uarts[i].regs.ier & UART_IER_THRI && /* Transm. empty */
uarts[i].regs.lsr & UART_LSR_TXBUFE &&
uarts[i].istat.thre_int == 1) {
uarts[i].regs.iir = UART_IIR_THRI;
} else if (uarts[i].regs.ier & UART_IER_MSI && /* Modem status */
uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
| UART_MSR_TERI | UART_MSR_DDCD)) {
uarts[i].regs.iir = UART_IIR_MSI;
}
if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
report_interrupt(config.uarts[i].irq);
}
SCHED_ADD (uart_clock16, i, cycles + UART_CLOCK_DIVIDER);
}
 
/* Reset. It initializes all registers of all UART devices to zero values,
(re)opens all RX/TX file streams and places devices in memory address
space. */
338,10 → 553,7
void uart_reset()
{
int i;
 
if (config.sim.verbose && config.nuarts)
printf("Resetting %u UART(s).\n", config.nuarts);
 
if (config.sim.verbose && config.nuarts) printf("Resetting %u UART(s).\n", config.nuarts);
memset(uarts, 0, sizeof(uarts));
 
for(i = 0; i < config.nuarts; i++) {
385,227 → 597,10
uarts[i].regs.lcr = UART_LCR_RESET;
uarts[i].vapi.cur_break = uarts[i].vapi.cur_break_cnt = uarts[i].vapi.next_break = 0;
uarts[i].vapi.next_break_cnt = -1;
SCHED_ADD (uart_clock16, i, cycles + UART_CLOCK_DIVIDER);
}
}
 
/* Simulation hook. Must be called every clock cycle to simulate all UART
devices. It does internal functional UART simulation. */
void uart_clock()
{
int i, retval;
 
for(i = 0; i < config.nuarts; i++) {
/* If VAPI is not selected, UART communicates with two file streams;
if VAPI is selected, we use VAPI streams. */
 
/* if txfs is corrupted, skip this uart. */
if (!config.uarts[i].vapi_id && !uarts[i].txfs) continue;
if (uarts[i].vapi.next_break_cnt >= 0)
if (--uarts[i].vapi.next_break_cnt < 0) {
if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break))
uarts[i].istat.break_set = 0;
}
/***************** Transmit *****************/
if (!uarts[i].istat.txser_full) {
// uarts[i].regs.lsr |= UART_LSR_TXBUFE;
if (uarts[i].istat.txbuf_full) {
uarts[i].iregs.txser = uarts[i].regs.txbuf[uarts[i].istat.txbuf_tail];
uarts[i].istat.txbuf_tail = (uarts[i].istat.txbuf_tail + 1) % uarts[i].fifo_len;
uarts[i].istat.txser_full = 1;
uarts[i].istat.txbuf_full--;
uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
uarts[i].istat.thre_int = 1;
} else {
uarts[i].regs.lsr |= UART_LSR_TXSERE;
uarts[i].regs.lsr |= UART_LSR_TXBUFE;
}
} else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
} else {
/* We are still sending char here*/
/* Check if we set the break bit */
if (uarts[i].regs.lcr & UART_LCR_SBC) {
if (!uarts[i].vapi.break_sent) {
#if 0
/* Send broken frame */
int nbits_sent = ((uarts[i].regs.lcr & UART_LCR_WLEN8) + 5) * (uarts[i].istat.txser_clks - 1) / uarts[i].char_clks;
send_char(i, nbits_sent);
#endif
/* Send one break signal */
vapi_send (config.uarts[i].vapi_id, UART_LCR_SBC << 8);
uarts[i].vapi.break_sent = 1;
}
/* mark as character was sent */
uarts[i].istat.txser_full = 0;
uarts[i].istat.txser_clks = 0;
} else
uarts[i].vapi.break_sent = 0;
}
 
/***************** Receive *****************/
/* Is there a break? */
if (uarts[i].vapi.cur_break) {
uarts[i].vapi.cur_break_cnt++;
if (uarts[i].vapi.cur_break_cnt > UART_BREAK_COUNT * uarts[i].vapi.char_clks) {
if (!uarts[i].istat.break_set) {
unsigned lsr;
uarts[i].istat.break_set = 1;
lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
printf ("[%x]\n", uarts[i].regs.lsr);
uarts[i].istat.rxser_full = 0;
uarts[i].istat.rxser_clks = 0;
uart_add_char (i, lsr << 8);
} else
uarts[i].vapi.cur_break_cnt = 0;
}
if (uarts[i].istat.rxser_full) {
uarts[i].istat.rxser_full = 0;
uarts[i].istat.rxser_clks = 0;
}
} else {
if (uarts[i].istat.rxser_full) {
if (uarts[i].char_clks <= uarts[i].istat.rxser_clks++) {
/* Set unused character bits to zero and allow lsr register in fifo */
uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1) | 0xff00;
debug(4, "Receiving 0x%02x'%c' via UART%d...\n", uarts[i].iregs.rxser, uarts[i].iregs.rxser, i);
uarts[i].istat.rxser_full = 0;
uarts[i].istat.rxser_clks = 0;
uart_add_char (i, uarts[i].iregs.rxser);
}
}
}
 
/* Check if there is something waiting, and put it into rxser */
if (uarts[i].regs.mcr & UART_MCR_LOOP) {
uarts[i].iregs.rxser = uarts[i].iregs.loopback;
uarts[i].istat.rxser_full = 1;
} else {
if (!config.uarts[i].vapi_id) {
if(uarts[i].istat.rxser_full == 0) {
if (uarts[i].slowdown)
uarts[i].slowdown--;
else if((retval = fgetc(uarts[i].rxfs)) != EOF) {
uarts[i].iregs.rxser = (char)retval;
uarts[i].istat.rxser_full = 1;
} else uarts[i].slowdown = UART_FGETC_SLOWDOWN;
}
} else { /* VAPI */
int received = 0;
/* do not handle commands while receiving */
if (uarts[i].istat.rxser_full)
break;
while (!received) {
if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
debug(4, "Handling: %08x (%i,%i)\n", data, uarts[i].vapi_buf_head_ptr, uarts[i].vapi_buf_tail_ptr);
uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
switch (data >> 24) {
case 0x00:
uarts[i].vapi.lcr = (data >> 8) & 0xff;
/* Put data into rx fifo */
uarts[i].iregs.rxser = data & 0xff;
uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC)
|| uarts[i].vapi.char_clks != uarts[i].char_clks
|| uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC);
/* Set error bits */
uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8;
}
uarts[i].istat.rxser_full = 1;
received = 1;
break;
case 0x01:
uarts[i].vapi.dll = (data >> 0) & 0xff;
uarts[i].vapi.dlh = (data >> 8) & 0xff;
break;
case 0x02:
uarts[i].vapi.lcr = (data >> 8) & 0xff;
break;
case 0x03:
uarts[i].vapi.skew = (signed short)(data & 0xffff);
break;
case 0x04:
uarts[i].vapi.next_break_cnt = data & 0xffff;
uarts[i].vapi.next_break = (data >> 16) & 1;
break;
default:
debug (0, "WARNING: Invalid vapi command %02x\n", data >> 24);
break;
}
} else break;
}
}
}
/***************** Loopback *****************/
if (uarts[i].regs.mcr & UART_MCR_LOOP) {
debug(5, "uart_clock: Loopback\n");
if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
uarts[i].regs.msr |= UART_MSR_DDCD;
if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
((uarts[i].regs.msr & UART_MSR_RI) >> 4))
uarts[i].regs.msr |= UART_MSR_TERI;
if ((uarts[i].regs.mcr & UART_MCR_RTS) !=
((uarts[i].regs.msr & UART_MSR_CTS) >> 3))
uarts[i].regs.msr |= UART_MSR_DCTS;
if ((uarts[i].regs.mcr & UART_MCR_DTR) !=
((uarts[i].regs.msr & UART_MSR_DSR) >> 5))
uarts[i].regs.msr |= UART_MSR_DDSR;
uarts[i].regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
| UART_MSR_DSR | UART_MSR_CTS);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX2) << 4);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX1) << 4);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_RTS) << 3);
uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_DTR) << 5);
}
if (uarts[i].regs.lsr & UART_LSR_RDRDY)
uarts[i].istat.timeout_count++;
/* Update LSR error bits from the ones from rx FIFO */
if (uarts[i].istat.rxbuf_full) {
uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8;
/* we must delete the lsr status, so that we can clear it from lsr */
uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff;
}
/* Interrupt detection in proper priority order. */
uarts[i].regs.iir = UART_IIR_NO_INT;
if (uarts[i].regs.ier & UART_IER_RLSI && /* Receiver LS */
uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
| UART_LSR_FRAME | UART_LSR_BREAK)) {
uarts[i].regs.iir = UART_IIR_RLSI;
} else if ((uarts[i].regs.ier & UART_IER_RDI) /* RD available */
&& (uarts[i].istat.rxbuf_full >= UART_FIFO_TRIGGER(uarts[i].regs.fcr >> 6))
&& (uarts[i].regs.lsr & UART_LSR_RDRDY)) {
uarts[i].regs.iir = UART_IIR_RDI;
} else if ((uarts[i].regs.ier & UART_IER_RDI) /* timeout */
&& (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
uarts[i].regs.iir = UART_IIR_CTI;
} else if (uarts[i].regs.ier & UART_IER_THRI && /* Transm. empty */
uarts[i].regs.lsr & UART_LSR_TXBUFE &&
uarts[i].istat.thre_int == 1) {
uarts[i].regs.iir = UART_IIR_THRI;
} else if (uarts[i].regs.ier & UART_IER_MSI && /* Modem status */
uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
| UART_MSR_TERI | UART_MSR_DDCD)) {
uarts[i].regs.iir = UART_IIR_MSI;
}
if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
report_interrupt(config.uarts[i].irq);
}
}
}
 
/* Print register values on stdout. */
void uart_status()
{
/trunk/or1ksim/peripheral/16450.h
19,7 → 19,6
 
/* Prototypes */
void uart_reset();
void uart_clock();
 
/* Definitions */
#define UART_ADDR_SPACE (8) /* UART memory address space size in bytes */
/trunk/or1ksim/toplevel.c
59,7 → 59,7
#include "mc.h"
 
/* CVS revision number. */
const char rcsrev[] = "$Revision: 1.81 $";
const char rcsrev[] = "$Revision: 1.82 $";
 
/* Continuos run versus single step tracing switch. */
int cont_run;
722,7 → 722,6
if (config.ic.enabled) ic_clock();
}
 
if (config.uarts) uart_clock();
if (config.dmas) dma_clock();
if (config.ethernets) eth_clock();
if (config.ngpios) gpio_clock();

powered by: WebSVN 2.1.0

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