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