From 53145bba06008a45e14b9afa12fdec5209f3436e Mon Sep 17 00:00:00 2001 From: Mathias Kreider <m.kreider@gsi.de> Date: Mon, 2 Sep 2013 15:22:44 +0200 Subject: [PATCH] added msi irq support for wishbone --- modules/wishbone/wb_irq/msidemo/Makefile | 13 ++ modules/wishbone/wb_irq/msidemo/crt0.S | 259 ++++++++++++++++++++++ modules/wishbone/wb_irq/msidemo/display.c | 99 +++++++++ modules/wishbone/wb_irq/msidemo/irq.c | 128 +++++++++++ modules/wishbone/wb_irq/msidemo/linker.ld | 149 +++++++++++++ modules/wishbone/wb_irq/msidemo/main.c | 155 +++++++++++++ modules/wishbone/wb_irq/wb_irq_lm32.vhd | 63 ++++++ modules/wishbone/wb_irq/wb_irq_master.vhd | 124 +++++++++++ modules/wishbone/wb_irq/wb_irq_pkg.vhd | 193 ++++++++++++++++ modules/wishbone/wb_irq/wb_irq_slave.vhd | 200 +++++++++++++++++ modules/wishbone/wishbone_pkg.vhd | 7 +- 11 files changed, 1387 insertions(+), 3 deletions(-) create mode 100644 modules/wishbone/wb_irq/msidemo/Makefile create mode 100644 modules/wishbone/wb_irq/msidemo/crt0.S create mode 100644 modules/wishbone/wb_irq/msidemo/display.c create mode 100644 modules/wishbone/wb_irq/msidemo/irq.c create mode 100644 modules/wishbone/wb_irq/msidemo/linker.ld create mode 100644 modules/wishbone/wb_irq/msidemo/main.c create mode 100644 modules/wishbone/wb_irq/wb_irq_lm32.vhd create mode 100644 modules/wishbone/wb_irq/wb_irq_master.vhd create mode 100644 modules/wishbone/wb_irq/wb_irq_pkg.vhd create mode 100644 modules/wishbone/wb_irq/wb_irq_slave.vhd diff --git a/modules/wishbone/wb_irq/msidemo/Makefile b/modules/wishbone/wb_irq/msidemo/Makefile new file mode 100644 index 00000000..3c7ebceb --- /dev/null +++ b/modules/wishbone/wb_irq/msidemo/Makefile @@ -0,0 +1,13 @@ +LD := lm32-elf-ld +CC := lm32-elf-gcc +CFLAGS := -Wall -mmultiply-enabled -mbarrel-shift-enabled -Os -ggdb -ffreestanding + +msidemo.bin: msidemo.elf + lm32-elf-objcopy -O binary $< $@ + +msidemo.elf: crt0.o display.o irq.o main.o + $(CC) $(CFLAGS) -o $@ -nostdlib -T linker.ld $^ + + +clean: + rm -f *.o *.elf *.bin diff --git a/modules/wishbone/wb_irq/msidemo/crt0.S b/modules/wishbone/wb_irq/msidemo/crt0.S new file mode 100644 index 00000000..de7de225 --- /dev/null +++ b/modules/wishbone/wb_irq/msidemo/crt0.S @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Name: crt0ram.S +** +** Description: +** Implements boot-code that calls LatticeDDInit (that calls main()) +** Implements exception handlers (actually, redirectors) +** +** $Revision: $ +** +** Disclaimer: +** +** This source code is intended as a design reference which +** illustrates how these types of functions can be implemented. It +** is the user's responsibility to verify their design for +** consistency and functionality through the use of formal +** verification methods. Lattice Semiconductor provides no warranty +** regarding the use or functionality of this code. +** +** -------------------------------------------------------------------- +** +** Lattice Semiconductor Corporation +** 5555 NE Moore Court +** Hillsboro, OR 97214 +** U.S.A +** +** TEL: 1-800-Lattice (USA and Canada) +** (503)268-8001 (other locations) +** +** web: http://www.latticesemi.com +** email: techsupport@latticesemi.com +** +** -------------------------------------------------------------------------- +** +** Change History (Latest changes on top) +** +** Ver Date Description +** -------------------------------------------------------------------------- +** 3.8 Apr-15-2011 Added __MICO_USER_<handler>_HANDLER__ preprocessor to +** allow customers to implement their own handlers for: +** DATA_ABORT, INST_ABORT +** +** 3.1 Jun-18-2008 Added __MICO_NO_INTERRUPTS__ preprocessor +** option to exclude invoking MicoISRHandler +** to reduce code-size in apps that don't use +** interrupts +** +** 3.0 Mar-25-2008 Added Header +** +**--------------------------------------------------------------------------- +*****************************************************************************/ + +/* + * LatticeMico32 C startup code. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* From include/sys/signal.h */ +#define SIGINT 2 /* interrupt */ +#define SIGTRAP 5 /* trace trap */ +#define SIGFPE 8 /* arithmetic exception */ +#define SIGSEGV 11 /* segmentation violation */ + +//#define MICO32_FULL_CONTEXT_SAVE_RESTORE + + +/* Exception handlers - Must be 32 bytes long. */ + .section .boot, "ax", @progbits + + .global _start +_start: + + .global _reset_handler + .type _reset_handler, @function +_reset_handler: + xor r0, r0, r0 + wcsr IE, r0 + wcsr IM, r0 + mvhi r1, hi(_reset_handler) + ori r1, r1, lo(_reset_handler) + wcsr EBA, r1 + calli _crt0 + nop + .size _reset_handler, .-_reset_handler + +.extern _irq_entry +.org 0xc0 + .global _interrupt_handler + .type _interrupt_handler, @function +_interrupt_handler: + sw (sp+0), ra + calli _save_all + mvi r1, SIGINT +#ifndef __MICO_NO_INTERRUPTS__ + calli _irq_entry +#else + wcsr IE, r0 +#endif + bi _restore_all_and_return + nop + nop + nop + +.org 0x100 + .global _crt0 + .type _crt0, @function +_crt0: + /* Clear r0 */ + xor r0, r0, r0 + /* Setup stack and global pointer */ + mvhi sp, hi(_fstack) + ori sp, sp, lo(_fstack) + mvhi gp, hi(_gp) + ori gp, gp, lo(_gp) + + mvhi r1, hi(_fbss) + ori r1, r1, lo(_fbss) + mvi r2, 0 + mvhi r3, hi(_ebss) + ori r3, r3, lo(_ebss) + sub r3, r3, r1 + calli memset + mvi r1, 0 + mvi r2, 0 + mvi r3, 0 + calli main + +loopf: + bi loopf + + .global _save_all + .type _save_all, @function +_save_all: +#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE + addi sp, sp, -128 +#else + addi sp, sp, -60 +#endif + sw (sp+4), r1 + sw (sp+8), r2 + sw (sp+12), r3 + sw (sp+16), r4 + sw (sp+20), r5 + sw (sp+24), r6 + sw (sp+28), r7 + sw (sp+32), r8 + sw (sp+36), r9 + sw (sp+40), r10 +#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE + sw (sp+44), r11 + sw (sp+48), r12 + sw (sp+52), r13 + sw (sp+56), r14 + sw (sp+60), r15 + sw (sp+64), r16 + sw (sp+68), r17 + sw (sp+72), r18 + sw (sp+76), r19 + sw (sp+80), r20 + sw (sp+84), r21 + sw (sp+88), r22 + sw (sp+92), r23 + sw (sp+96), r24 + sw (sp+100), r25 + sw (sp+104), r26 + sw (sp+108), r27 + sw (sp+120), ea + sw (sp+124), ba + /* ra and sp need special handling, as they have been modified */ + lw r1, (sp+128) + sw (sp+116), r1 + mv r1, sp + addi r1, r1, 128 + sw (sp+112), r1 +#else + sw (sp+52), ea + sw (sp+56), ba + /* ra and sp need special handling, as they have been modified */ + lw r1, (sp+60) + sw (sp+48), r1 + mv r1, sp + addi r1, r1, 60 + sw (sp+44), r1 +#endif +// xor r1, r1, r1 +// wcsr ie, r1 + ret + .size _save_all, .-_save_all + + .global _restore_all_and_return + .type _restore_all_and_return, @function + /* Restore all registers and return from exception */ +_restore_all_and_return: +// addi r1, r0, 2 +// wcsr ie, r1 + lw r1, (sp+4) + lw r2, (sp+8) + lw r3, (sp+12) + lw r4, (sp+16) + lw r5, (sp+20) + lw r6, (sp+24) + lw r7, (sp+28) + lw r8, (sp+32) + lw r9, (sp+36) + lw r10, (sp+40) +#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE + lw r11, (sp+44) + lw r12, (sp+48) + lw r13, (sp+52) + lw r14, (sp+56) + lw r15, (sp+60) + lw r16, (sp+64) + lw r17, (sp+68) + lw r18, (sp+72) + lw r19, (sp+76) + lw r20, (sp+80) + lw r21, (sp+84) + lw r22, (sp+88) + lw r23, (sp+92) + lw r24, (sp+96) + lw r25, (sp+100) + lw r26, (sp+104) + lw r27, (sp+108) + lw ra, (sp+116) + lw ea, (sp+120) + lw ba, (sp+124) + /* Stack pointer must be restored last, in case it has been updated */ + lw sp, (sp+112) +#else + lw ra, (sp+48) + lw ea, (sp+52) + lw ba, (sp+56) + /* Stack pointer must be restored last, in case it has been updated */ + lw sp, (sp+44) +#endif + nop + eret + .size _restore_all_and_return, .-_restore_all_and_return + diff --git a/modules/wishbone/wb_irq/msidemo/display.c b/modules/wishbone/wb_irq/msidemo/display.c new file mode 100644 index 00000000..3d728b7b --- /dev/null +++ b/modules/wishbone/wb_irq/msidemo/display.c @@ -0,0 +1,99 @@ +#include "display.h" + +const unsigned int REG_MODE = 0x00000000; +const unsigned int REG_RST = 0x00000004; +const unsigned int REG_UART = 0x00010000; +const unsigned int REG_CHAR = 0x00020000; +const unsigned int REG_RAW = 0x00030000; + +const char MODE_RAW = 0x03; +const char MODE_UART = 0x01; +const char MODE_CHAR = 0x02; +const char MODE_IDLE = 0x00; + +const char ROW_LEN = 11; + +void disp_reset() +{ + *(display + REG_RST) = 1; +} + + + + +void disp_put_c(char ascii) +{ + + *(display + (REG_MODE>>2)) = (unsigned int)MODE_UART; + *(display + (REG_UART>>2)) = (unsigned int)ascii; +} + + +void disp_put_str(const char *sPtr) +{ + *(display + (REG_MODE>>2)) = (unsigned int)MODE_UART; + while(*sPtr != '\0') *(display + (REG_UART>>2)) = (unsigned int)*sPtr++; +} + +void disp_put_line(const char *sPtr, unsigned char row) +{ + unsigned char col, outp, pad; + pad = 0; + + for(col=0; col<ROW_LEN; col++) + { + if(*(sPtr+col) == '\0') pad = 1; + + if(pad) outp = ' '; + else outp = (unsigned int)*(sPtr+col); + + disp_loc_c(outp, row, col); + } +} + +void disp_loc_c(char ascii, unsigned char row, unsigned char col) +{ + unsigned int rowcol; + + *(display + (REG_MODE>>2)) = (unsigned int)MODE_CHAR; + rowcol = ((0x07 & (unsigned int)row)<<6) + ((0x0f & (unsigned int)col)<<2); + *(display + ((REG_CHAR + rowcol)>>2)) = (unsigned int)ascii; + +} + +void disp_put_raw(char pixcol, unsigned int address, char color) +{ + char oldpixcol; + + + *(display + (REG_MODE>>2)) = (unsigned int)MODE_RAW; + oldpixcol = *(display + (REG_RAW>>2) + ((address & 0x3FFF))); //read out old memcontent + + if(color) // 1 -> White + *(display + (REG_RAW>>2) + ((address & 0x3FFF))) = (unsigned int)(pixcol | oldpixcol); + else + *(display + (REG_RAW>>2) + ((address & 0x3FFF))) = (unsigned int)(~pixcol & oldpixcol); + + *(display + (REG_MODE>>2)) = (unsigned int)MODE_IDLE; + +} + +unsigned int get_pixcol_addr(unsigned char x_in, unsigned char y_in) +{ + unsigned int addr_base = 0x230; + unsigned int x, y; + + x = x_in & 0x3F; + if(y_in < 48) y = ((y_in>>3)<<8); //determine row. Shift by 8bit + else y = (5<<8); //outside visible area, take start of bottom row instead + + return addr_base + y + x; + +} + +unsigned int get_pixcol_val(unsigned char y_in) +{ + + return 1<<(y_in & 0x07); + +} diff --git a/modules/wishbone/wb_irq/msidemo/irq.c b/modules/wishbone/wb_irq/msidemo/irq.c new file mode 100644 index 00000000..f83a2fd1 --- /dev/null +++ b/modules/wishbone/wb_irq/msidemo/irq.c @@ -0,0 +1,128 @@ +/** @file irq.c + * @brief MSI capable IRQ handler for the LM32 + * + * Copyright (C) 2011-2012 GSI Helmholtz Centre for Heavy Ion Research GmbH + * + * @author Mathias Kreider <m.kreider@gsi.de> + * + * @bug None! + * + ******************************************************************************* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + ******************************************************************************* + */ + +#include "irq.h" + +//#include "display.h" DEBUG + +extern unsigned int* irq_slave; + +const unsigned int IRQ_REG_RST = 0x00000000; +const unsigned int IRQ_REG_STAT = 0x00000004; +const unsigned int IRQ_REG_POP = 0x00000008; +const unsigned int IRQ_OFFS_MSG = 0x00000000; +const unsigned int IRQ_OFFS_SRC = 0x00000004; +const unsigned int IRQ_OFFS_SEL = 0x00000008; + +inline void irq_pop_msi( unsigned int irq_no) +{ + unsigned int* msg_queue = (unsigned int*)(irq_slave + ((irq_no +1)<<2)); + + global_msi.msg = *(msg_queue+(IRQ_OFFS_MSG>>2)); + global_msi.src = *(msg_queue+(IRQ_OFFS_SRC>>2)); + global_msi.sel = *(msg_queue+(IRQ_OFFS_SEL>>2)); + *(irq_slave + (IRQ_REG_POP>>2)) = 1<<irq_no; + + return; +} + +inline void isr_table_clr(void) +{ + //set all ISR table entries to Null + unsigned int i; + for(i=0;i<32;i++) isr_ptr_table[i] = 0; +} + +inline unsigned int irq_get_mask(void) +{ + //read IRQ mask + unsigned int im; + asm volatile ( "rcsr %0, im": "=&r" (im)); + return im; +} + +inline void irq_set_mask( unsigned int im) +{ + //write IRQ mask + asm volatile ( "wcsr im, %0": "=&r" (im)); + return; +} + +inline void irq_disable(void) +{ + //globally disable interrupts + unsigned int ie; + asm volatile ( "rcsr %0, IE\n" \ + "andi %0, %0, 0xFFFE\n" \ + "wcsr IE, %0" : "=&r" (ie)); + return; +} + +inline void irq_enable(void) +{ + //globally enable interrupts + unsigned int ie; + asm volatile ( "rcsr %0, IE\n" \ + "ori %0, %0, 1\n" \ + "wcsr IE, %0" : "=&r" (ie)); + return; +} + +inline void irq_clear( unsigned int mask) +{ + //clear pending interrupt flag(s) + unsigned int ip; + asm volatile ( "rcsr %0, ip\n" \ + "and %0, %0, %1\n" \ + "wcsr ip, %0" : "=&r" (ip): "r" (mask) ); + return; +} + + + +inline void irq_process(void) +{ + char buffer[12]; + + unsigned int ip; + unsigned char irq_no = 0; + + //get pending flags + asm volatile ("rcsr %0, ip": "=r"(ip)); + + while(ip) //irqs pending ? + { + if(ip & 0x01) //check if irq with lowest number is pending + { + irq_pop_msi(irq_no); //pop msg from msi queue into global_msi variable + irq_clear(1<<irq_no); //clear pending bit + if((unsigned int)isr_ptr_table[irq_no]) isr_ptr_table[irq_no](); //execute isr + //else disp_put_str("No ISR\nptr found!\n"); DEBUG + } + irq_no++; + ip = ip >> 1; //process next irq + } + return; +} diff --git a/modules/wishbone/wb_irq/msidemo/linker.ld b/modules/wishbone/wb_irq/msidemo/linker.ld new file mode 100644 index 00000000..98a7c0ed --- /dev/null +++ b/modules/wishbone/wb_irq/msidemo/linker.ld @@ -0,0 +1,149 @@ +/* + * Simulator Link script for Lattice Mico32. + * Contributed by Jon Beniston <jon@beniston.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +OUTPUT_FORMAT("elf32-lm32") +ENTRY(_start) +/*INPUT() */ +GROUP(-lgcc -lc) + +MEMORY +{ + ram : ORIGIN = 0x00000000, LENGTH = 0x10000 /* 64K */ +} + +SECTIONS +{ + + .boot : { *(.boot) } > ram + + /* Code */ + .text : + { + . = ALIGN(4); + _ftext = .; + _ftext_rom = LOADADDR(.text); + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + KEEP (*(.init)) + KEEP (*(.fini)) + /* Constructors and destructors */ + KEEP (*crtbegin*.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + KEEP (*(.jcr)) + _etext = .; + } > ram =0 + + /* Exception handlers */ + .eh_frame_hdr : { *(.eh_frame_hdr) } > ram + .eh_frame : { KEEP (*(.eh_frame)) } > ram + .gcc_except_table : { *(.gcc_except_table) *(.gcc_except_table.*) } > ram + + /* Read-only data */ + .rodata : + { + . = ALIGN(4); + _frodata = .; + _frodata_rom = LOADADDR(.rodata); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + _erodata = .; + } > ram + + /* Data */ + .data : + { + . = ALIGN(4); + _fdata = .; + _fdata_rom = LOADADDR(.data); + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + SORT(CONSTRUCTORS) + _gp = ALIGN(16) + 0x7ff0; + *(.sdata .sdata.* .gnu.linkonce.s.*) + _edata = .; + } > ram + + /* BSS */ + .bss : + { + . = ALIGN(4); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + _end = .; + PROVIDE (end = .); + } > ram + + /* First location in stack is highest address in RAM */ + PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4); + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/modules/wishbone/wb_irq/msidemo/main.c b/modules/wishbone/wb_irq/msidemo/main.c new file mode 100644 index 00000000..0d06b389 --- /dev/null +++ b/modules/wishbone/wb_irq/msidemo/main.c @@ -0,0 +1,155 @@ +#include <stdio.h> +#include "display.h" +#include "irq.h" + +volatile unsigned int* display = (unsigned int*)0x02900000; +volatile unsigned int* irq_slave = (unsigned int*)0x02000d00; + + + +char* mat_sprinthex(char* buffer, unsigned long val) +{ + unsigned char i,ascii; + const unsigned long mask = 0x0000000F; + + for(i=0; i<8;i++) + { + ascii= (val>>(i<<2)) & mask; + if(ascii > 9) ascii = ascii - 10 + 'A'; + else ascii = ascii + '0'; + buffer[7-i] = ascii; + } + + buffer[8] = 0x00; + return buffer; +} + +void show_msi() +{ + char buffer[12]; + + mat_sprinthex(buffer, global_msi.msg); + disp_put_str("D "); + disp_put_str(buffer); + disp_put_c('\n'); + + + mat_sprinthex(buffer, global_msi.src); + disp_put_str("A "); + disp_put_str(buffer); + disp_put_c('\n'); + + + mat_sprinthex(buffer, (unsigned long)global_msi.sel); + disp_put_str("S "); + disp_put_str(buffer); + disp_put_c('\n'); +} + + +void isr0() +{ + unsigned int j; + + disp_put_str("ISR0\n"); + show_msi(); + + for (j = 0; j < 125000000; ++j) { + asm("# noop"); /* no-op the compiler can't optimize away */ + } + disp_put_c('\f'); +} + +void isr1() +{ + unsigned int j; + + disp_put_str("ISR1\n"); + show_msi(); + + for (j = 0; j < 125000000; ++j) { + asm("# noop"); /* no-op the compiler can't optimize away */ + } + disp_put_c('\f'); +} + +void _irq_entry(void) { + + disp_put_c('\f'); + disp_put_str("IRQ_ENTRY\n"); + irq_process(); + + +} + +const char mytext[] = "Hallo Welt!...\n\n"; + +void main(void) { + + isr_table_clr(); + isr_ptr_table[0]= isr0; + isr_ptr_table[1]= isr1; + irq_set_mask(0x03); + irq_enable(); + + + int j, xinc, yinc, x, y; + +unsigned int time = 0; + + + unsigned int addr_raw_off; + + char color = 0xFF; + + + + disp_reset(); + disp_put_c('\f'); + disp_put_str(mytext); + + + + + + + x = 0; + y = 9; + yinc = -1; + xinc = 1; + addr_raw_off = 0; + + while (1) { + /* Rotate the LEDs */ + + + + disp_put_raw( get_pixcol_val((unsigned char)y), get_pixcol_addr((unsigned char)x, (unsigned char)y), color); + + + if(x == 63) xinc = -1; + if(x == 0) xinc = 1; + + if(y == 47) yinc = -1; + if(y == 0) yinc = 1; + + x += xinc; + y += yinc; + + + + + + /* Each loop iteration takes 4 cycles. + * It runs at 125MHz. + * Sleep 0.2 second. + */ + for (j = 0; j < 125000000/160; ++j) { + asm("# noop"); /* no-op the compiler can't optimize away */ + } + + if(time++ > 500) {time = 0; color = ~color; } + + + } +} diff --git a/modules/wishbone/wb_irq/wb_irq_lm32.vhd b/modules/wishbone/wb_irq/wb_irq_lm32.vhd new file mode 100644 index 00000000..969edf33 --- /dev/null +++ b/modules/wishbone/wb_irq/wb_irq_lm32.vhd @@ -0,0 +1,63 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wishbone_pkg.all; +use work.wb_irq_pkg.all; + +entity wb_irq_lm32 is +generic(g_msi_queues: natural := 3; + g_profile: string); +port( +clk_sys_i : in std_logic; +rst_n_i : in std_logic; + +dwb_o : out t_wishbone_master_out; +dwb_i : in t_wishbone_master_in; +iwb_o : out t_wishbone_master_out; +iwb_i : in t_wishbone_master_in; + +irq_slave_o : out t_wishbone_slave_out_array(g_msi_queues-1 downto 0); -- wb msi interface +irq_slave_i : in t_wishbone_slave_in_array(g_msi_queues-1 downto 0); + +ctrl_slave_o : out t_wishbone_slave_out; -- ctrl interface for LM32 irq processing +ctrl_slave_i : in t_wishbone_slave_in +); +end wb_irq_lm32; + +architecture rtl of wb_irq_lm32 is + +signal s_irq : std_logic_vector(31 downto 0); + +begin + +s_irq(31 downto g_msi_queues) <= (others => '0'); + + msi_irq: wb_irq_slave + GENERIC MAP( g_queues => g_msi_queues, + g_depth => 8) + PORT MAP ( + clk_i => clk_sys_i, + rst_n_i => rst_n_i, + + irq_slave_o => irq_slave_o, + irq_slave_i => irq_slave_i, + irq_o => s_irq(g_msi_queues-1 downto 0), + + ctrl_slave_o => ctrl_slave_o, + ctrl_slave_i => ctrl_slave_i + ); + + LM32_CORE : xwb_lm32 + generic map(g_profile => g_profile) + port map( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + irq_i => s_irq, + + dwb_o => dwb_o, + dwb_i => dwb_i, + iwb_o => iwb_o, + iwb_i => iwb_i + ); + +end rtl; diff --git a/modules/wishbone/wb_irq/wb_irq_master.vhd b/modules/wishbone/wb_irq/wb_irq_master.vhd new file mode 100644 index 00000000..168240b7 --- /dev/null +++ b/modules/wishbone/wb_irq/wb_irq_master.vhd @@ -0,0 +1,124 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_pkg.all; +use work.genram_pkg.all; +use work.wb_irq_pkg.all; + +entity wb_irq_master is + port (clk_i : std_logic; + rst_n_i : std_logic; + + master_o : out t_wishbone_master_out; + master_i : in t_wishbone_master_in; + + irq_i : std_logic; + adr_i : t_wishbone_address; + msg_i : t_wishbone_data + ); +end entity; + +architecture behavioral of wb_irq_master is + +signal r_ffs_q : std_logic; +signal r_ffs_r : std_logic; +signal s_ffs_s : std_logic; + +type t_state is (s_IDLE, s_LOOKUP, s_SEND, s_DONE); +signal r_state : t_state; +signal s_master_o : t_wishbone_master_out; + +begin + + +------------------------------------------------------------------------- +--input rs flipflops +------------------------------------------------------------------------- +process(clk_i) + begin + if rising_edge(clk_i) then + if(rst_n_i = '0') then + r_ffs_q <= '0'; + else + if(s_ffs_s = '0' and r_ffs_r = '1') then + r_ffs_q <= '0'; + elsif(s_ffs_s = '1' and r_ffs_r = '0') then + r_ffs_q <= '1'; + else + r_ffs_q <= r_ffs_q; + end if; + end if; + end if; + end process; + + + +s_ffs_s <= irq_i; +s_master_o.sel <= (others => '1'); +s_master_o.we <= '1'; + +master_o <= s_master_o; +------------------------------------------------------------------------- + +------------------------------------------------------------------------- +-- WB master generating IRQ msgs +------------------------------------------------------------------------- +wb_irq_master : process(clk_i, rst_n_i) + + variable v_state : t_state; + variable v_irq : natural; + + begin + if(rst_n_i = '0') then + + s_master_o.cyc <= '0'; + s_master_o.stb <= '0'; + s_master_o.adr <= (others => '0'); + s_master_o.dat <= (others => '0'); + r_state <= s_IDLE; + + elsif rising_edge(clk_i) then + + v_state := r_state; + + case r_state is + when s_IDLE => if(r_ffs_q = '1') then + s_master_o.adr <= adr_i; + s_master_o.dat <= msg_i; + v_state := s_SEND; + end if; + + when s_SEND => if(master_i.stall = '0') then + v_state := s_DONE; + end if; + + when s_DONE => v_state := s_IDLE; + when others => v_state := s_IDLE; + end case; + + -- flags on state transition + if(v_state = s_DONE) then + r_ffs_r <= '1'; + else + r_ffs_r <= '0'; + end if; + + if(v_state = s_SEND) then + s_master_o.cyc <= '1'; + s_master_o.stb <= '1'; + else + s_master_o.cyc <= '0'; + s_master_o.stb <= '0'; + end if; + + r_state <= v_state; + + end if; + + end process; + + + +end architecture; diff --git a/modules/wishbone/wb_irq/wb_irq_pkg.vhd b/modules/wishbone/wb_irq/wb_irq_pkg.vhd new file mode 100644 index 00000000..38d41d91 --- /dev/null +++ b/modules/wishbone/wb_irq/wb_irq_pkg.vhd @@ -0,0 +1,193 @@ +--! @file wb_irq_pkg.vhd +--! @brief Wishbone IRQ Master +--! +--! Copyright (C) 2011-2012 GSI Helmholtz Centre for Heavy Ion Research GmbH +--! +--! Important details about its implementation +--! should go in these comments. +--! +--! @author Mathias Kreider <m.kreider@gsi.de> +--! +-------------------------------------------------------------------------------- +--! This library is free software; you can redistribute it and/or +--! modify it under the terms of the GNU Lesser General Public +--! License as published by the Free Software Foundation; either +--! version 3 of the License, or (at your option) any later version. +--! +--! This library is distributed in the hope that it will be useful, +--! but WITHOUT ANY WARRANTY; without even the implied warranty of +--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +--! Lesser General Public License for more details. +--! +--! You should have received a copy of the GNU Lesser General Public +--! License along with this library. If not, see <http://www.gnu.org/licenses/>. +--------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library work; +use work.wishbone_pkg.all; + +package wb_irq_pkg is + + type t_ivec_array_d is array(natural range <>) of t_wishbone_data; + + type t_ivec_ad is record + address : t_wishbone_address; + value : t_wishbone_data; + end record t_ivec_ad; + + type t_ivec_array_ad is array(natural range <>) of t_ivec_ad; + + function f_hot_to_bin(x : std_logic_vector) return integer; + function f_bin_to_hot(x : natural; len : natural) return std_logic_vector; + function or_all(slv_in : std_logic_vector) return std_logic; + + constant c_irq_hostbridge_ep_sdb : t_sdb_device := ( + abi_class => x"0000", -- undocumented device + abi_ver_major => x"01", + abi_ver_minor => x"01", + wbd_endian => c_sdb_endian_big, + wbd_width => x"7", -- 8/16/32-bit port granularity + sdb_component => ( + addr_first => x"0000000000000000", + addr_last => x"00000000000000ff", + product => ( + vendor_id => x"0000000000000651", -- GSI + device_id => x"10050081", + version => x"00000001", + date => x"20120308", + name => "IRQ_HOSTBRIDGE_EP "))); + + constant c_irq_ep_sdb : t_sdb_device := ( + abi_class => x"0000", -- undocumented device + abi_ver_major => x"01", + abi_ver_minor => x"01", + wbd_endian => c_sdb_endian_big, + wbd_width => x"7", -- 8/16/32-bit port granularity + sdb_component => ( + addr_first => x"0000000000000000", + addr_last => x"00000000000000ff", + product => ( + vendor_id => x"0000000000000651", -- GSI + device_id => x"10050081", + version => x"00000001", + date => x"20120308", + name => "IRQ_ENDPOINT "))); + + constant c_irq_ctrl_sdb : t_sdb_device := ( + abi_class => x"0000", -- undocumented device + abi_ver_major => x"01", + abi_ver_minor => x"01", + wbd_endian => c_sdb_endian_big, + wbd_width => x"7", -- 8/16/32-bit port granularity + sdb_component => ( + addr_first => x"0000000000000000", + addr_last => x"00000000000000ff", + product => ( + vendor_id => x"0000000000000651", -- GSI + device_id => x"10040081", + version => x"00000001", + date => x"20120308", + name => "IRQ_CTRL "))); + + component wb_irq_master is + port (clk_i : std_logic; + rst_n_i : std_logic; + + master_o : out t_wishbone_master_out; + master_i : in t_wishbone_master_in; + + irq_i : std_logic; + adr_i : t_wishbone_address; + msg_i : t_wishbone_data + ); + end component; + + component wb_irq_slave is + generic ( g_queues : natural := 4; + g_depth : natural := 8; + g_datbits : natural := 32; + g_adrbits : natural := 32; + g_selbits : natural := 4 + ); + port (clk_i : std_logic; + rst_n_i : std_logic; + + irq_slave_o : out t_wishbone_slave_out_array(g_queues-1 downto 0); + irq_slave_i : in t_wishbone_slave_in_array(g_queues-1 downto 0); + irq_o : out std_logic_vector(g_queues-1 downto 0); + + ctrl_slave_o : out t_wishbone_slave_out; + ctrl_slave_i : in t_wishbone_slave_in + ); + end component; + + component wb_irq_lm32 is + generic(g_msi_queues: natural := 3; + g_profile: string); + port( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + dwb_o : out t_wishbone_master_out; + dwb_i : in t_wishbone_master_in; + iwb_o : out t_wishbone_master_out; + iwb_i : in t_wishbone_master_in; + + irq_slave_o : out t_wishbone_slave_out_array(g_msi_queues-1 downto 0); -- wb msi interface + irq_slave_i : in t_wishbone_slave_in_array(g_msi_queues-1 downto 0); + + ctrl_slave_o : out t_wishbone_slave_out; -- ctrl interface for LM32 irq processing + ctrl_slave_i : in t_wishbone_slave_in + ); + end component; + +end package; + +package body wb_irq_pkg is + + + + function f_hot_to_bin(x : std_logic_vector) + return integer is + variable rv : integer; + begin + rv := 0; + -- if there are few ones set in _x_ then the most significant will be + -- translated to bin + for i in 0 to x'left loop + if x(i) = '1' then + rv := i+1; + end if; + end loop; + return rv; + end function; + +function f_bin_to_hot(x : natural; len : natural + ) return std_logic_vector is + + variable ret : std_logic_vector(len-1 downto 0); + + begin + + ret := (others => '0'); + ret(x) := '1'; + return ret; + end function; + +function or_all(slv_in : std_logic_vector) +return std_logic is +variable I : natural; +variable ret : std_logic; +begin + ret := '0'; + for I in 0 to slv_in'left loop + ret := ret or slv_in(I); + end loop; + return ret; +end function or_all; + +end package body; diff --git a/modules/wishbone/wb_irq/wb_irq_slave.vhd b/modules/wishbone/wb_irq/wb_irq_slave.vhd new file mode 100644 index 00000000..ec00fc39 --- /dev/null +++ b/modules/wishbone/wb_irq/wb_irq_slave.vhd @@ -0,0 +1,200 @@ +------------------------------------------------------------------------------ +-- Title : WB MSI Core +-- Project : Wishbone +------------------------------------------------------------------------------ +-- File : wb_irq_slave.vhd +-- Author : Mathias Kreider +-- Company : GSI +-- Created : 2013-08-10 +-- Last update: 2013-08-10 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: Provide prioritized Message Signaled Interrupt queues for an LM32 +------------------------------------------------------------------------------- +-- Copyright (c) 2013 GSI +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-08-10 1.0 mkreider Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_pkg.all; +use work.genram_pkg.all; +use work.eb_internals_pkg.all; +use work.wb_irq_pkg.all; + + +entity wb_irq_slave is + generic ( g_queues : natural := 4; -- number of int lines & queues + g_depth : natural := 8; -- queues depth + g_datbits : natural := 32; -- data bits from irq wb to store + g_adrbits : natural := 32; -- addr bits from irq wb to store + g_selbits : natural := 4 -- sel bits from irq wb to store + ); + port (clk_i : std_logic; + rst_n_i : std_logic; + + irq_slave_o : out t_wishbone_slave_out_array(g_queues-1 downto 0); -- wb msi interface + irq_slave_i : in t_wishbone_slave_in_array(g_queues-1 downto 0); + irq_o : out std_logic_vector(g_queues-1 downto 0); -- pending irq flags of queues + + ctrl_slave_o : out t_wishbone_slave_out; -- ctrl interface for LM32 irq processing + ctrl_slave_i : in t_wishbone_slave_in + ); +end entity; + +architecture behavioral of wb_irq_slave is +------------------------------------------------------------------------- +--memory map for ctrl wb +------------------------------------------------------------------------- +constant c_RST : natural := 0; --wo +constant c_STATUS : natural := c_RST+4; --ro, 1 bit per queue +constant c_POP : natural := c_STATUS+4; --wo, 1 bit per queue pop + +--pages for queues +--queue I is found at: c_QUEUES + I * c_N_QUEUE +constant c_QUEUES : natural := 16; +constant c_N_QUEUE : natural := 16; +constant c_OFFS_DATA : natural := 0; --ro wb data, msi message +constant c_OFFS_ADDR : natural := c_OFFS_DATA+4; --ro wb addr, msi adr low bits ID caller device +constant c_OFFS_SEL : natural := c_OFFS_ADDR+4; --ro wb sel, +------------------------------------------------------------------------- + +--ctrl wb signals +signal r_rst_n, s_rst_n : std_logic; +signal r_status, r_pop : std_logic_vector(31 downto 0); +signal queue_offs : natural; +signal word_offs : natural; +signal adr : unsigned(7 downto 0); + +--queue signals +type t_queue_dat is array(natural range <>) of std_logic_vector(g_datbits+g_adrbits+g_selbits-1 downto 0); +signal irq_push, irq_pop, irq_full, irq_empty : std_logic_vector(g_queues-1 downto 0); +signal irq_d, irq_q : t_queue_dat(g_queues-1 downto 0); +signal ctrl_en : std_logic; + +begin + + + ------------------------------------------------------------------------- + --irq wb and queues + ------------------------------------------------------------------------- + irq_o <= r_status(g_queues-1 downto 0); -- LM32 IRQs are active low! + s_rst_n <= rst_n_i and r_rst_n; + + G1: for I in 0 to g_queues-1 generate + + irq_d(I) <= irq_slave_i(I).sel & irq_slave_i(I).adr & irq_slave_i(I).dat; + irq_push(I) <= irq_slave_i(I).cyc and irq_slave_i(I).stb and not irq_full(I); + irq_slave_o(I).stall <= irq_full(I); + irq_pop(I) <= r_pop(I) and r_status(I); + r_status(I) <= not irq_empty(I); + + irq_slave_o(I).int <= '0'; --will be obsolete soon + irq_slave_o(I).rty <= '0'; + irq_slave_o(I).err <= '0'; + irq_slave_o(I).dat <= (others => '0'); + + p_ack : process(clk_i) -- ack all + begin + if rising_edge(clk_i) then + irq_slave_o(I).ack <= irq_push(I); + end if; + end process; + + irqfifo : eb_fifo -- TODO: change this to some other component fifo + generic map( + g_width => g_datbits + g_adrbits + g_selbits, + g_size => g_depth) + port map ( + clk_i => clk_i, + rstn_i => s_rst_n, + w_full_o => irq_full(I), + w_push_i => irq_push(I), + w_dat_i => irq_d(I), + r_empty_o => irq_empty(I), + r_pop_i => irq_pop(I), + r_dat_o => irq_q(I)); + + end generate; + ------------------------------------------------------------------------- + + + ------------------------------------------------------------------------- + -- ctrl wb and output + ------------------------------------------------------------------------- + r_status(31 downto g_queues) <= (others => '0'); + ctrl_en <= ctrL_slave_i.cyc and ctrl_slave_i.stb; + adr <= unsigned(ctrl_slave_i.adr(7 downto 2)) & "00"; + queue_offs <= to_integer(adr(adr'left downto 4)-1); + word_offs <= to_integer(adr(3 downto 0)); + + ctrl_slave_o.int <= '0'; + ctrl_slave_o.rty <= '0'; + ctrl_slave_o.stall <= '0'; + + process(clk_i) + + variable v_dat : std_logic_vector(g_datbits-1 downto 0); + variable v_adr : std_logic_vector(g_adrbits-1 downto 0); + variable v_sel : std_logic_vector(g_selbits-1 downto 0); + + begin + if rising_edge(clk_i) then + if(rst_n_i = '0' or r_rst_n = '0') then + r_rst_n <= '1'; + r_pop <= (others => '0'); + else + + ctrl_slave_o.ack <= '0'; + ctrl_slave_o.err <= '0'; + r_pop <= (others => '0'); + ctrl_slave_o.dat <= (others => '0'); + + if(ctrl_en = '1') then + + if(to_integer(adr) < c_QUEUES) then + case to_integer(adr) is -- control registers + when c_RST => if(ctrl_slave_i.we = '1') then + r_rst_n <= '0'; + end if; + ctrl_slave_o.dat <= (others => '0'); ctrl_slave_o.ack <= '1'; + + when c_STATUS => ctrl_slave_o.dat <= r_status; ctrl_slave_o.ack <= '1'; + + when c_POP => if(ctrl_slave_i.we = '1') then + r_pop <= ctrl_slave_i.dat; + end if; + ctrl_slave_o.dat <= (others => '0'); ctrl_slave_o.ack <= '1'; + + when others => null; ctrl_slave_o.err <= '1'; + end case; + else -- queues, one mem page per queue + if(adr < c_QUEUES + c_N_QUEUE * g_queues and ctrl_slave_i.we = '0') then + v_dat := irq_q(queue_offs)(g_datbits-1 downto 0); + v_adr := irq_q(queue_offs)(g_adrbits+g_datbits-1 downto g_datbits); + v_sel := irq_q(queue_offs)(g_selbits + g_adrbits + g_datbits-1 downto g_adrbits+g_datbits); + + case word_offs is + when c_OFFS_DATA => ctrl_slave_o.dat <= std_logic_vector(to_unsigned(0, 32-g_datbits)) & v_dat; ctrl_slave_o.ack <= '1'; + when c_OFFS_ADDR => ctrl_slave_o.dat <= std_logic_vector(to_unsigned(0, 32-g_adrbits)) & v_adr; ctrl_slave_o.ack <= '1'; + when c_OFFS_SEL => ctrl_slave_o.dat <= std_logic_vector(to_unsigned(0, 32-g_selbits)) & v_sel; ctrl_slave_o.ack <= '1'; + when others => ctrl_slave_o.err <= '1'; + end case; + else + ctrl_slave_o.err <= '1'; + end if; + end if; + + end if; + end if; -- rst + end if; -- clk edge + end process; + ------------------------------------------------------------------------- +end architecture; diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd index 591b245e..4ad504a2 100644 --- a/modules/wishbone/wishbone_pkg.vhd +++ b/modules/wishbone/wishbone_pkg.vhd @@ -52,10 +52,11 @@ package wishbone_pkg is type t_wishbone_address_array is array(natural range <>) of t_wishbone_address; type t_wishbone_master_out_array is array (natural range <>) of t_wishbone_master_out; + --type t_wishbone_slave_in_array is array (natural range <>) of t_wishbone_slave_in; + subtype t_wishbone_slave_in_array is t_wishbone_master_out_array; type t_wishbone_slave_out_array is array (natural range <>) of t_wishbone_slave_out; - type t_wishbone_master_in_array is array (natural range <>) of t_wishbone_master_in; - type t_wishbone_slave_in_array is array (natural range <>) of t_wishbone_slave_in; - + --type t_wishbone_master_in_array is array (natural range <>) of t_wishbone_master_in; + subtype t_wishbone_master_in_array is t_wishbone_slave_out_array; constant cc_dummy_address : std_logic_vector(c_wishbone_address_width-1 downto 0) := (others => 'X'); -- GitLab