Added peripheral interrupts
diff --git a/verilog/rtl/CaravelHost/CaravelHost_top.v b/verilog/rtl/CaravelHost/CaravelHost_top.v
index 791f4b6..88d699a 100644
--- a/verilog/rtl/CaravelHost/CaravelHost_top.v
+++ b/verilog/rtl/CaravelHost/CaravelHost_top.v
@@ -32,6 +32,9 @@
 		input wire caravel_uart_rx,
 		output wire caravel_uart_tx,
 
+		// Caravel IRQ
+		output wire[2:0] caravel_irq,
+
 		// Configuration constants
 		output wire[7:0] core0Index,
 		output wire[7:0] core1Index,
@@ -167,4 +170,6 @@
 		.uart_rx(caravel_uart_rx),
 		.uart_tx(caravel_uart_tx));
 	
+	assign caravel_irq = 3'b0;
+	
 endmodule
\ No newline at end of file
diff --git a/verilog/rtl/ExperiarCore/CoreManagement.v b/verilog/rtl/ExperiarCore/CoreManagement.v
index 6b1748b..efcf3c0 100644
--- a/verilog/rtl/ExperiarCore/CoreManagement.v
+++ b/verilog/rtl/ExperiarCore/CoreManagement.v
@@ -5,6 +5,7 @@
 		// Interface to core
 		output wire management_run,
 		output wire management_trapEnable,
+		output wire management_interruptEnable,
 		output wire management_writeEnable,
 		output wire[3:0] management_byteSelect,
 		output wire[15:0] management_address,
@@ -67,10 +68,11 @@
 	// Control register: Default 0x0
 	// b00: run
 	// b01: trapEnable
-	wire[1:0] control;
+	// b02: interruptEnable
+	wire[2:0] control;
 	wire[31:0] controlOutputData;
 	wire controlOutputRequest;
-	ConfigurationRegister #(.WIDTH(2), .ADDRESS(12'h000), .DEFAULT(2'b0)) controlRegister(
+	ConfigurationRegister #(.WIDTH(3), .ADDRESS(12'h000), .DEFAULT(3'b0)) controlRegister(
 		.clk(clk),
 		.rst(rst),
 		.enable(registerEnable),
@@ -114,6 +116,7 @@
 	// Core
 	assign management_run = control[0];
 	assign management_trapEnable = control[1];
+	assign management_interruptEnable = control[2];
 	assign management_writeEnable = coreEnable && peripheralBus_we;
 	assign management_byteSelect = peripheralBus_byteSelect;
 	assign management_address = peripheralBus_address[15:0];
diff --git a/verilog/rtl/ExperiarCore/ExperiarCore_top.v b/verilog/rtl/ExperiarCore/ExperiarCore_top.v
index aaa6519..6723dc8 100644
--- a/verilog/rtl/ExperiarCore/ExperiarCore_top.v
+++ b/verilog/rtl/ExperiarCore/ExperiarCore_top.v
@@ -19,7 +19,7 @@
 		output wire jtag_tdo,
 
 		// Interrupts
-		//input wire[15:0] userInterrupts,
+		input wire[15:0] irq,
 
 		// Wishbone master interface from core
 		output wire core_wb_cyc_o,
@@ -140,6 +140,7 @@
 	// Core management
 	wire management_run;
 	wire management_trapEnable;
+	wire management_interruptEnable;
 	wire management_writeEnable;
 	wire[3:0] management_byteSelect;
 	wire[15:0] management_address;
@@ -186,6 +187,7 @@
 		.rst(wb_rst_i),
 		.management_run(management_run),
 		.management_trapEnable(management_trapEnable),
+		.management_interruptEnable(management_interruptEnable),
 		.management_writeEnable(management_writeEnable),
 		.management_byteSelect(management_byteSelect),
 		.management_address(management_address),
@@ -210,7 +212,6 @@
 		.wb_management_busy(wb_management_busy));
 
 	// Core
-	wire[15:0] userInterrupts = 16'b0;
 	RV32ICore core(
 `ifdef USE_POWER_PINS
 		.vccd1(vccd1),	// User area 1 1.8V power
@@ -227,6 +228,7 @@
 		.memoryBusy(coreMemoryBusy),
 		.management_run(management_run),
 		.management_trapEnable(management_trapEnable),
+		.management_interruptEnable(management_interruptEnable),
 		.management_writeEnable(management_writeEnable),
 		.management_byteSelect(management_byteSelect),
 		.management_address(management_address),
@@ -240,7 +242,7 @@
 		.eCall(eCall),
 		.eBreak(eBreak),
 		.isAddressBreakpoint(isAddressBreakpoint),
-		.userInterrupts(userInterrupts),
+		.userInterrupts(irq),
 		.probe_state(probe_state),
 		.probe_env(probe_env),
 		.probe_programCounter(probe_programCounter),
diff --git a/verilog/rtl/ExperiarCore/RV32ICore.v b/verilog/rtl/ExperiarCore/RV32ICore.v
index 0263807..babbaf4 100644
--- a/verilog/rtl/ExperiarCore/RV32ICore.v
+++ b/verilog/rtl/ExperiarCore/RV32ICore.v
@@ -19,6 +19,7 @@
 		// Management interface
 		input wire management_run,
 		input wire management_trapEnable,
+		input wire management_interruptEnable,
 		input wire management_writeEnable,
 		input wire[3:0] management_byteSelect,
 		input wire[15:0] management_address,
@@ -542,7 +543,7 @@
 		.isEBREAK(eBreak),
 		.isECALL(eCall),
 		.isAddressBreakpoint(isAddressBreakpoint),
-		.userInterrupts(userInterrupts),
+		.userInterrupts(management_interruptEnable ? userInterrupts : 16'b0),
 		.trapReturn(trapReturn),
 		.inTrap(inTrap),
 		.trapVector(trapVector),
diff --git a/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v b/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v
index ff06ba0..409a830 100644
--- a/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v
+++ b/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v
@@ -24,9 +24,10 @@
 		output wire[`MPRJ_IO_PADS-1:0] io_out,
 		output wire[`MPRJ_IO_PADS-1:0] io_oeb,
 		
-		// Caravel UART
+		// Caravel
 		input wire caravel_uart_rx,
 		output wire caravel_uart_tx,
+		input wire[2:0] caravel_irq,
 
 		// Logic Analyzer Signals
 		input wire[127:0] la_data_in,
@@ -62,6 +63,7 @@
 	// IRQ
 	// wire irq_en;
 	// wire irq_in;
+	wire[15:0] irq;
 
 	// Wishbone wires
 	// Master 0: Caravel
@@ -379,6 +381,7 @@
 		.jtag_tms(jtag_tms),
 		.jtag_tdi(core0_tdi),
 		.jtag_tdo(core0_tdo),
+		.irq(irq),
 		.core_wb_cyc_o(core0_wb_cyc_o),
 		.core_wb_stb_o(core0_wb_stb_o),
 		.core_wb_we_o(core0_wb_we_o),
@@ -528,6 +531,7 @@
 		.jtag_tms(jtag_tms),
 		.jtag_tdi(core1_tdi),
 		.jtag_tdo(core1_tdo),
+		.irq(irq),
 		.core_wb_cyc_o(core1_wb_cyc_o),
 		.core_wb_stb_o(core1_wb_stb_o),
 		.core_wb_we_o(core1_wb_we_o),
@@ -727,6 +731,7 @@
 	wire[SRAM_ADDRESS_SIZE-1:0] videoSRAMRight_addr1;
 	wire[63:0] videoSRAMRight_dout1;
 
+	wire[1:0] video_irq;
 	Video video(
 `ifdef USE_POWER_PINS
 		.vccd1(vccd1),	// User area 1 1.8V power
@@ -744,6 +749,7 @@
 		.wb_stall_o(videoMemory_wb_stall_o),
 		.wb_error_o(videoMemory_wb_error_o),
 		.wb_data_o(videoMemory_wb_data_o),
+		.video_irq(video_irq),
 		.sram0_clk0(videoSRAMLeft_clk0),
 		.sram0_csb0(videoSRAMLeft_csb0),
 		.sram0_web0(videoSRAMLeft_web0),
@@ -863,6 +869,7 @@
 	//-------------------Peripherals-------------------//
 	//-------------------------------------------------//
 	wire[1:0] probe_blink;
+	wire[9:0] peripheral_irq;
 	Peripherals peripherals(
 `ifdef USE_POWER_PINS
 		.vccd1(vccd1),	// User area 1 1.8V power
@@ -899,6 +906,7 @@
 		.flash_io1_read(flash_io1_read),
 		//.irq_en(irq_en),
 		//.irq_in(irq_in),
+		.peripheral_irq(peripheral_irq),
 		.vga_r(vga_r),
 		.vga_g(vga_g),
 		.vga_b(vga_b),
@@ -923,4 +931,10 @@
 		probe_blink					// 2
 	};
 
+	//-------------------------------------------------//
+	//-----------------------IRQ-----------------------//
+	//-------------------------------------------------//
+
+	assign irq = { caravel_irq, video_irq, peripheral_irq };
+
 endmodule
\ No newline at end of file
diff --git a/verilog/rtl/Peripherals/GPIO/GPIODevice.v b/verilog/rtl/Peripherals/GPIO/GPIODevice.v
index 6c0f41c..fdfca26 100644
--- a/verilog/rtl/Peripherals/GPIO/GPIODevice.v
+++ b/verilog/rtl/Peripherals/GPIO/GPIODevice.v
@@ -19,7 +19,8 @@
 		// GPIO
 		input wire[IO_COUNT-1:0] gpio_input,
 		output wire[IO_COUNT-1:0] gpio_output,
-		output wire[IO_COUNT-1:0] gpio_oe
+		output wire[IO_COUNT-1:0] gpio_oe,
+		output wire gpio_irq
 	);
 
 	// Device select
@@ -90,11 +91,33 @@
 		.readData_en(inputRegisterReadDataEnable_nc),
 		.readData_busy(1'b0));
 
-	assign requestOutput = oeRegisterOutputRequest || outputRegisterOutputRequest || inputRegisterOutputRequest;
-	assign peripheralBus_dataRead = oeRegisterOutputRequest 	? oeRegisterOutputData :
-								    outputRegisterOutputRequest ? outputRegisterOutputData :
-								    inputRegisterOutputRequest  ? inputRegisterOutputData :
-								   								  ~32'b0;
+	// IRQ register: Default 0x0
+	wire[31:0] irqEnableRegisterOutputData;
+	wire oirqEnableRegisterOutputRequest;
+	wire[IO_COUNT-1:0] irqEnable;
+	OutputRegister #(.WIDTH(IO_COUNT), .ADDRESS(8'h03), .DEFAULT({IO_COUNT{1'b0}})) irqEnableRegister(
+		.clk(clk),
+		.rst(rst),
+		.enable(deviceEnable),
+		.peripheralBus_we(peripheralBus_we),
+		.peripheralBus_oe(peripheralBus_oe),
+		.peripheralBus_address(localAddress),
+		.peripheralBus_byteSelect(peripheralBus_byteSelect),
+		.peripheralBus_dataWrite(peripheralBus_dataWrite),
+		.peripheralBus_dataRead(irqEnableRegisterOutputData),
+		.requestOutput(irqEnableRegisterOutputRequest),
+		.currentValue(irqEnable));
+
+	assign requestOutput = oeRegisterOutputRequest || outputRegisterOutputRequest || inputRegisterOutputRequest || irqEnableRegisterOutputRequest;
+	assign peripheralBus_dataRead = oeRegisterOutputRequest 	   ? oeRegisterOutputData :
+								    outputRegisterOutputRequest    ? outputRegisterOutputData :
+								    inputRegisterOutputRequest     ? inputRegisterOutputData :
+									irqEnableRegisterOutputRequest ? irqEnableRegisterOutputData :
+								   								     ~32'b0;
 	assign peripheralBus_busy = 1'b0;
 	
+
+	wire[IO_COUNT-1:0] pinIRQ = irqEnable & gpio_oe & gpio_input;
+	assign gpio_irq = |pinIRQ;
+
 endmodule
\ No newline at end of file
diff --git a/verilog/rtl/Peripherals/GPIO/GPIO_top.v b/verilog/rtl/Peripherals/GPIO/GPIO_top.v
index f0d8eef..7dd6618 100644
--- a/verilog/rtl/Peripherals/GPIO/GPIO_top.v
+++ b/verilog/rtl/Peripherals/GPIO/GPIO_top.v
@@ -21,7 +21,8 @@
 
 		input wire[`MPRJ_IO_PADS-1:0] gpio_input,
 		output wire[`MPRJ_IO_PADS-1:0] gpio_output,
-		output wire[`MPRJ_IO_PADS-1:0] gpio_oe
+		output wire[`MPRJ_IO_PADS-1:0] gpio_oe,
+		output wire[1:0] gpio_irq
 	);
 	
 	wire[`MPRJ_IO_PADS_1-1:0] gpio0_input;
@@ -56,7 +57,8 @@
 		.requestOutput(device0OutputRequest),
 		.gpio_input(gpio0_input),
 		.gpio_output(gpio0_output),
-		.gpio_oe(gpio0_oe));
+		.gpio_oe(gpio0_oe),
+		.gpio_irq(gpio_irq[0]));
 
 	wire[31:0] device1OutputData;
 	wire device1OutputRequest;
@@ -75,7 +77,8 @@
 		.requestOutput(device1OutputRequest),
 		.gpio_input(gpio1_input),
 		.gpio_output(gpio1_output),
-		.gpio_oe(gpio1_oe));
+		.gpio_oe(gpio1_oe),
+		.gpio_irq(gpio_irq[1]));
 
 	assign requestOutput = device0OutputRequest || device1OutputRequest;
 	assign peripheralBus_dataRead = device0OutputRequest ? device0OutputData :
diff --git a/verilog/rtl/Peripherals/PWM/PWMDevice.v b/verilog/rtl/Peripherals/PWM/PWMDevice.v
index b24a5a8..7e3402d 100644
--- a/verilog/rtl/Peripherals/PWM/PWMDevice.v
+++ b/verilog/rtl/Peripherals/PWM/PWMDevice.v
@@ -20,7 +20,8 @@
 		
 		// PWM output
 		output wire[OUTPUTS-1:0] pwm_en,
-		output wire[OUTPUTS-1:0] pwm_out
+		output wire[OUTPUTS-1:0] pwm_out,
+		output wire pwm_irq
 	);
 
 	localparam WIDTH_BITS = $clog2(WIDTH);
@@ -43,15 +44,27 @@
 		.deviceEnable(deviceEnable));
 
 	// Register
-	// Configuration register 	Default 0x3DC (for .WIDTH(16), .CLOCK_WIDTH(32))
-	// b00: counterEnable		Default 0x0
-	// b01-b05: clockScale		Default 0x0E
-	// b06-09: top 				Default 0xF
-	// b10: outputEnable0		Default 0x0
-	// b11: outputEnable1		Default 0x0
-	// b12: outputEnable2		Default 0x0
-	// b13: outputEnable3		Default 0x0
-	localparam CONFIG_WIDTH = 1 + CLOCK_BITS + WIDTH_BITS + OUTPUTS;
+	// Configuration register 	 Default 0x3DC (for .WIDTH(16), .CLOCK_WIDTH(32))
+	// b00: counterEnable		 Default 0x0
+	// b01-b05: clockScale		 Default 0x0E
+	// b06-09: top 				 Default 0xF
+	// b10: outputEnable0		 Default 0x0
+	// b11: outputEnable1		 Default 0x0
+	// b12: outputEnable2		 Default 0x0
+	// b13: outputEnable3		 Default 0x0
+	// b14: outputEnable0		 Default 0x0
+	// b15: outputEnable1		 Default 0x0
+	// b16: outputEnable2		 Default 0x0
+	// b17: outputEnable3		 Default 0x0
+	// b18: riseInterruptEnable0 Default 0x0
+	// b19: riseInterruptEnable1 Default 0x0
+	// b20: riseInterruptEnable2 Default 0x0
+	// b21: riseInterruptEnable3 Default 0x0
+	// b22: fallInterruptEnable0 Default 0x0
+	// b23: fallInterruptEnable1 Default 0x0
+	// b24: fallInterruptEnable2 Default 0x0
+	// b25: fallInterruptEnable3 Default 0x0
+	localparam CONFIG_WIDTH = 1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 4);
 	wire[CONFIG_WIDTH-1:0] configuration;
 	wire[31:0] configurationRegisterOutputData;
 	wire configurationRegisterOutputRequest;
@@ -71,7 +84,10 @@
 	wire counterEnable = configuration[0];
 	wire[CLOCK_BITS-1:0] clockScale = configuration[CLOCK_BITS:1];
 	wire[WIDTH_BITS-1:0] topBit = configuration[CLOCK_BITS + WIDTH_BITS:1 + CLOCK_BITS];
-	wire[OUTPUTS-1:0] outputEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + OUTPUTS)-1:1 + CLOCK_BITS + WIDTH_BITS];
+	wire[OUTPUTS-1:0] compareEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + OUTPUTS)-1:1 + CLOCK_BITS + WIDTH_BITS];
+	wire[OUTPUTS-1:0] outputEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 2))-1:1 + CLOCK_BITS + WIDTH_BITS + OUTPUTS];
+	wire[OUTPUTS-1:0] riseInterruptEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 3))-1:1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 2)];
+	wire[OUTPUTS-1:0] fallInterruptEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 4))-1:1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 3)];
 
 	// Current data register (for .WIDTH(16), .OUTPUTS(4))
 	// b00-b15: counterValue
@@ -115,6 +131,9 @@
 		.out(peripheralBus_dataRead),
 		.outputEnable(requestOutput));
 
+	wire[OUTPUTS-1:0] compareRise;
+	wire[OUTPUTS-1:0] compareFall;
+
 	// Outputs
 	genvar i;
 	generate
@@ -137,15 +156,20 @@
 				.clk(clk),
 				.rst(rst),
 				.compareValue(compareValue),
-				.enable(outputEnable[i]),
+				.enable(compareEnable[i]),
 				.counterValue(counterValue),
-				.pwm_out(outputs[i]));
+				.pwm_out(outputs[i]),
+				.compareRise(compareRise[i]),
+				.compareFall(compareFall[i]));
 		end
 	endgenerate
 
 	assign peripheralBus_busy = 1'b0;
 
-	assign pwm_en = outputEnable;
+	assign pwm_en = compareEnable & outputEnable;
 	assign pwm_out = outputs;
 
+	wire[OUTPUTS-1:0] comparatorIRQ = (riseInterruptEnable & compareRise) || (fallInterruptEnable & compareFall);
+	assign pwm_irq = |comparatorIRQ;
+
 endmodule
diff --git a/verilog/rtl/Peripherals/PWM/PWMOutput.v b/verilog/rtl/Peripherals/PWM/PWMOutput.v
index ff9494b..c1ca2e4 100644
--- a/verilog/rtl/Peripherals/PWM/PWMOutput.v
+++ b/verilog/rtl/Peripherals/PWM/PWMOutput.v
@@ -8,7 +8,10 @@
 		input wire enable,
 
 		input wire[WIDTH-1:0] counterValue,
-		output wire pwm_out
+		output wire pwm_out,
+		
+		output wire compareRise,
+		output wire compareFall
 	);
 
 	reg [WIDTH-1:0] currentCompareValue = {WIDTH{1'b0}};
@@ -19,7 +22,7 @@
 	always @(posedge clk) begin
 		if (rst) begin
 			currentCompareValue <= {WIDTH{1'b0}};
-			state <= 1'b0; 
+			state <= 1'b0;
 		end else begin
 			if (enable) begin
 				if (counterValue == 0) begin
@@ -34,7 +37,15 @@
 			end
 		end
 	end
+
+	reg lastState = 1'b0;
+	always @(posedge clk) begin
+		if (rst) lastState <= 1'b0;
+		else lastState <= state;
+	end
 	
+	assign compareRise = (lastState != state) && state;
+	assign compareFall = (lastState != state) && !state;
 	assign pwm_out = state;
 
 endmodule
\ No newline at end of file
diff --git a/verilog/rtl/Peripherals/PWM/PWM_top.v b/verilog/rtl/Peripherals/PWM/PWM_top.v
index 3920335..850ce71 100644
--- a/verilog/rtl/Peripherals/PWM/PWM_top.v
+++ b/verilog/rtl/Peripherals/PWM/PWM_top.v
@@ -20,7 +20,8 @@
 		output wire requestOutput,
 
 		output wire[15:0] pwm_en,
-		output wire[15:0] pwm_out
+		output wire[15:0] pwm_out,
+		output wire[3:0] pwm_irq
 	);
 
 	localparam DEVICE_COUNT = 4;
@@ -60,7 +61,8 @@
 				.peripheralBus_dataRead(deviceOutputData[(i * 32) + 31:i * 32]),
 				.requestOutput(deviceOutputRequest[i]),
 				.pwm_en(pwm_en[(i * OUTPUTS_PER_DEVICE) + OUTPUTS_PER_DEVICE - 1:i * OUTPUTS_PER_DEVICE]),
-				.pwm_out(pwm_out[(i * OUTPUTS_PER_DEVICE) + OUTPUTS_PER_DEVICE - 1:i * OUTPUTS_PER_DEVICE]));
+				.pwm_out(pwm_out[(i * OUTPUTS_PER_DEVICE) + OUTPUTS_PER_DEVICE - 1:i * OUTPUTS_PER_DEVICE]),
+				.pwm_irq(pwm_irq[i]));
 		end
 	endgenerate
 
diff --git a/verilog/rtl/Peripherals/Peripherals_top.v b/verilog/rtl/Peripherals/Peripherals_top.v
index a97c72e..1a1bf34 100644
--- a/verilog/rtl/Peripherals/Peripherals_top.v
+++ b/verilog/rtl/Peripherals/Peripherals_top.v
@@ -46,6 +46,7 @@
 		// IRQ
 		// input wire irq_en,
 		// output wire irq_in,
+		output wire[9:0] peripheral_irq,
 
 		// VGA
 		input wire[1:0] vga_r,
@@ -99,6 +100,7 @@
 	wire[3:0] uart_en;	
 	wire[3:0] uart_rx;
 	wire[3:0] uart_tx;
+	wire[3:0] uart_irq;
 	UART #(.ID(8'h00)) uart(
 	`ifdef USE_POWER_PINS
 		.vccd1(vccd1),	// User area 1 1.8V power
@@ -116,7 +118,8 @@
 		.requestOutput(uart_requestOutput),
 		.uart_en(uart_en),
 		.uart_rx(uart_rx),
-		.uart_tx(uart_tx));
+		.uart_tx(uart_tx),
+		.uart_irq(uart_irq));
 
 	assign uart_rx[0] = internal_uart_rx;
 	assign internal_uart_tx = uart_tx[0];
@@ -153,6 +156,7 @@
 	wire pwm_requestOutput;
 	wire[15:0] pwm_en;
 	wire[15:0] pwm_out;
+	wire[3:0] pwm_irq;
 	PWM #(.ID(8'h02)) pwm(
 	`ifdef USE_POWER_PINS
 		.vccd1(vccd1),	// User area 1 1.8V power
@@ -169,13 +173,15 @@
 		.peripheralBus_dataWrite(peripheralBus_dataWrite),
 		.requestOutput(pwm_requestOutput),
 		.pwm_en(pwm_en),
-		.pwm_out(pwm_out));
+		.pwm_out(pwm_out),
+		.pwm_irq(pwm_irq));
 
 	wire[31:0] gpio_peripheralBus_dataRead;
 	wire gpio_requestOutput;
 	wire[`MPRJ_IO_PADS-1:0] gpio_input;
 	wire[`MPRJ_IO_PADS-1:0] gpio_output;
 	wire[`MPRJ_IO_PADS-1:0] gpio_oe;
+	wire[1:0] gpio_irq;
 	GPIO #(.ID(8'h03)) gpio(
 	`ifdef USE_POWER_PINS
 		.vccd1(vccd1),	// User area 1 1.8V power
@@ -193,7 +199,8 @@
 		.requestOutput(gpio_requestOutput),
 		.gpio_input(gpio_input),
 		.gpio_output(gpio_output),
-		.gpio_oe(gpio_oe));
+		.gpio_oe(gpio_oe),
+		.gpio_irq(gpio_irq));
 
 	IOMultiplexer ioMux(
 	`ifdef USE_POWER_PINS
@@ -249,4 +256,6 @@
 		endcase
 	end
 
+	assign peripheral_irq = { pwm_irq, uart_irq, gpio_irq };
+
 endmodule
\ No newline at end of file
diff --git a/verilog/rtl/Peripherals/UART/UARTDevice.v b/verilog/rtl/Peripherals/UART/UARTDevice.v
index 3941941..62a9d5a 100644
--- a/verilog/rtl/Peripherals/UART/UARTDevice.v
+++ b/verilog/rtl/Peripherals/UART/UARTDevice.v
@@ -18,7 +18,8 @@
 		// PWM output
 		output wire uart_en,
 		input wire uart_rx,
-		output wire uart_tx
+		output wire uart_tx,
+		output wire uart_irq
 	);
 
 	localparam RX_BUFFER_SIZE = 32;
@@ -34,14 +35,17 @@
 		.deviceEnable(deviceEnable));
 
 	// Register
-	// Configuration register Default 0x01047
-	// b00-b15: cyclesPerBit  Default 0x1047	((CLK_FREQ + BAUD) / BAUD) - 1 => Default uses CLK_FREQ=40MHz BAUD=9600(Actually 9599.2)
-	// b16: waitForTxSpace	  Default 0x0
-	// b17: enable 			  Default 0x0
+	// Configuration register 				Default 0x01047
+	// b00-b15: cyclesPerBit  				Default 0x1047	((CLK_FREQ + BAUD) / BAUD) - 1 => Default uses CLK_FREQ=40MHz BAUD=9600(Actually 9599.2)
+	// b16: waitForTxSpace	  				Default 0x0
+	// b17: enable 			  				Default 0x0
+	// b18: dataLostInterruptEnable			Default 0x0
+	// b19: rxDataAvaliableInterruptEnable	Default 0x0
+	// b20: txDataSentInterruptEnable		Default 0x0
 	wire[31:0] configurationRegisterOutputData;
 	wire configurationRegisterOutputRequest;
-	wire[17:0] configuration;
-	ConfigurationRegister #(.WIDTH(18), .ADDRESS(12'h000), .DEFAULT(18'h01047)) configurationRegister(
+	wire[20:0] configuration;
+	ConfigurationRegister #(.WIDTH(21), .ADDRESS(12'h000), .DEFAULT(21'h001047)) configurationRegister(
 		.clk(clk),
 		.rst(rst),
 		.enable(deviceEnable),
@@ -57,6 +61,9 @@
 	wire[15:0] cyclesPerBit = configuration[15:0];
 	wire waitForTxSpace = configuration[16];
 	assign uart_en = configuration[17];
+	wire dataLostInterruptEnable = configuration[18];
+	wire rxDataAvaliableInterruptEnable = configuration[19];
+	wire txDataSentInterruptEnable = configuration[20];
 
 	// Clear register
 	wire[3:0] clearWriteData;
@@ -88,12 +95,12 @@
 	// b00: rxDataAvailable
 	// b01: rxBufferFull
 	// b02: rxDataLost
-	// b03: txByteOutAvailable
+	// b03: txDataAvailable
 	// b04: txBufferFull
 	// b05: txDataLost
 	wire txDataLost;
 	wire txBufferFull;
-	wire txByteOutAvailable;
+	wire txDataAvailable;
 	wire rxDataLost;
 	wire rxBufferFull;
 	wire rxDataAvailable;
@@ -118,7 +125,7 @@
 		.writeData(statusRegisterWriteData_nc),
 		.writeData_en(statusRegisterWriteDataEnable_nc),
 		.writeData_busy(1'b0),
-		.readData({ txDataLost, txBufferFull, txByteOutAvailable, rxDataLost, rxBufferFull, rxDataAvailable }),
+		.readData({ txDataLost, txBufferFull, txDataAvailable, rxDataLost, rxBufferFull, rxDataAvailable }),
 		.readData_en(statusRegisterReadDataEnable_nc),
 		.readData_busy(1'b0));
 
@@ -195,7 +202,7 @@
 		.blockTransmition(!uart_en),
     	.busy(txSendBusy),
     	.dataIn(txByteOut),
-    	.dataAvailable(txByteOutAvailable));
+    	.dataAvailable(txDataAvailable));
 
 	FIFO #(.WORD_SIZE(8), .BUFFER_SIZE(RX_BUFFER_SIZE)) rxBuffer(
 		.clk(clk),
@@ -214,8 +221,8 @@
 		.dataIn(txWriteData),
 		.we(txWriteDataEnable && peripheralBus_byteSelect[0] && (!waitForTxSpace || !txBufferFull)),
 		.dataOut(txByteOut),
-		.oe(txByteOutAvailable && uart_en && !txSendBusy),		
-		.isData(txByteOutAvailable),
+		.oe(txDataAvailable && uart_en && !txSendBusy),		
+		.isData(txDataAvailable),
 		.bufferFull(txBufferFull),
 		.dataLost(txDataLost));
 
@@ -227,5 +234,14 @@
 													   					 ~32'b0;
 	assign peripheralBus_busy = txBusy;
 
+	reg sendingData = 1'b0;
+	always @(posedge clk) begin
+		if (rst) sendingData <= 1'b0;
+		else sendingData <= txDataAvailable;
+	end
+
+	assign uart_irq = (dataLostInterruptEnable && (rxDataLost || txDataLost))
+				   || (rxDataAvaliableInterruptEnable && rxOutAvailable)
+				   || (txDataSentInterruptEnable && sendingData && !txDataAvailable);
 
 endmodule
\ No newline at end of file
diff --git a/verilog/rtl/Peripherals/UART/UART_top.v b/verilog/rtl/Peripherals/UART/UART_top.v
index 542abe7..f289055 100644
--- a/verilog/rtl/Peripherals/UART/UART_top.v
+++ b/verilog/rtl/Peripherals/UART/UART_top.v
@@ -22,7 +22,8 @@
 		// UART
 		output wire[3:0] uart_en,	
 		input wire[3:0] uart_rx,
-		output wire[3:0] uart_tx
+		output wire[3:0] uart_tx,
+		output wire[3:0] uart_irq
 	);
 
 	localparam DEVICE_COUNT = 4;
@@ -61,7 +62,8 @@
 				.requestOutput(deviceOutputRequest[i]),
 				.uart_en(uart_en[i]),
 				.uart_rx(uart_rx[i]),
-				.uart_tx(uart_tx[i]));
+				.uart_tx(uart_tx[i]),
+				.uart_irq(uart_irq[i]));
 		end
 	endgenerate
 
diff --git a/verilog/rtl/Video/VGA_top.v b/verilog/rtl/Video/VGA_top.v
index 31cea36..0dd3a62 100644
--- a/verilog/rtl/Video/VGA_top.v
+++ b/verilog/rtl/Video/VGA_top.v
@@ -29,7 +29,10 @@
 		output wire[1:0] vga_g,
 		output wire[1:0] vga_b,
 		output wire vga_vsync,
-		output wire vga_hsync
+		output wire vga_hsync,
+
+		// IRQ
+		output wire[1:0] vga_irq
 	);
 	
 	// MAX_ROW_WIDTH = 2^ROW_BITS = 64;
@@ -55,10 +58,12 @@
 	// b04-b07: verticalPixelSize		Default 0xA
 	// b08-b09: drawMode 				Default 0b00
 	// b10: enableOutput				Default 0
-	wire[10:0] configuration;
+	// b11: hsyncInterruptEnable		Default 0
+	// b12: vsyncInterruptEnable		Default 0
+	wire[12:0] configuration;
 	wire[31:0] configurationRegisterOutputData;
 	wire configurationRegisterOutputRequest;
-	ConfigurationRegister #(.WIDTH(11), .ADDRESS(12'h000), .DEFAULT(11'h0AA)) configurationRegister(
+	ConfigurationRegister #(.WIDTH(13), .ADDRESS(12'h000), .DEFAULT(11'h0AA)) configurationRegister(
 		.clk(clk),
 		.rst(rst),
 		.enable(configEnable),
@@ -75,6 +80,8 @@
 	wire[3:0] verticalPixelSize   = configuration[7:4];
 	wire[1:0] drawMode 			  = configuration[9:8];
 	wire enableOutput 			  = configuration[10];
+	wire hsyncInterruptEnable 	  = configuration[11];
+	wire vsyncInterruptEnable 	  = configuration[12];
 
 	// Defaults are timing for 800 x 600 at 60Hz
 	// http://tinyvga.com/vga-timing/800x600@60Hz
@@ -521,4 +528,21 @@
 	assign vga_g = enableOutput && onScreen ? raw_currentPixel[3:2] : 2'b0;
 	assign vga_b = enableOutput && onScreen ? raw_currentPixel[5:4] : 2'b0;
 
+	// IRQ
+	reg lastVSync;
+	reg lastHSync;
+	always @(posedge clk) begin
+		if (rst) begin
+			lastVSync <= 1'b0;
+			lastHSync <= 1'b0;
+		end else begin
+			lastVSync <= vsync;
+			lastHSync <= hsync;
+		end
+	end
+
+	wire vsync_irq = (lastVSync != vsync) && !vsync;
+	wire hsync_irq = (lastHSync != hsync) && !hsync;
+	assign vga_irq = { vsync_irq && vsyncInterruptEnable, hsync_irq && hsyncInterruptEnable };
+
 endmodule
diff --git a/verilog/rtl/Video/Video_top.v b/verilog/rtl/Video/Video_top.v
index b2cdb4b..940776c 100644
--- a/verilog/rtl/Video/Video_top.v
+++ b/verilog/rtl/Video/Video_top.v
@@ -18,6 +18,9 @@
 		output wire wb_error_o,
 		output wire[31:0] wb_data_o,
 
+		// IRQ
+		output wire[1:0] video_irq,
+
 		// Left Video SRAM rw port
 		output wire sram0_clk0,
 		output wire[1:0] sram0_csb0,
@@ -169,7 +172,8 @@
 		.vga_g(vga_g),
 		.vga_b(vga_b),
 		.vga_vsync(vga_vsync),
-		.vga_hsync(vga_hsync));
+		.vga_hsync(vga_hsync),
+		.vga_irq(video_irq));
 
 	assign peripheralBus_busy = videoMemoryBusBusy || vgaBusBusy;
 	assign peripheralBus_dataRead = videoMemoryRequestOutput ? videoMemoryDataRead :