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 :