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 :