blob: 45674039a1ae4f3ba8f235e66e9723890a3310ba [file] [log] [blame]
module GPIODevice #(
parameter ID = 4'h0,
parameter IO_COUNT = 16
)(
input wire clk,
input wire rst,
// Peripheral bus
input wire peripheralEnable,
input wire peripheralBus_we,
input wire peripheralBus_oe,
output wire peripheralBus_busy,
input wire[15:0] peripheralBus_address,
input wire[3:0] peripheralBus_byteSelect,
output wire[31:0] peripheralBus_dataRead,
input wire[31:0] peripheralBus_dataWrite,
output wire requestOutput,
// 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 reg gpio_irq
);
reg[IO_COUNT-1:0] inputBuffered;
always @(posedge clk) begin
if (rst) inputBuffered <= {IO_COUNT{1'b0}};
else inputBuffered <= gpio_input;
end
// Device select
wire[11:0] localAddress;
wire deviceEnable;
DeviceSelect #(.ID(ID)) select(
.peripheralEnable(peripheralEnable),
.peripheralBus_address(peripheralBus_address),
.localAddress(localAddress),
.deviceEnable(deviceEnable));
// Registers
// OE register: Default 0x0
wire[31:0] oeRegisterOutputData;
wire oeRegisterOutputRequest;
OutputRegister #(.WIDTH(IO_COUNT), .ADDRESS(8'h00), .DEFAULT(~{IO_COUNT{1'b0}})) oeRegister(
.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(oeRegisterOutputData),
.requestOutput(oeRegisterOutputRequest),
.currentValue(gpio_oe));
// Output data register: Default 0x0
wire[31:0] outputRegisterOutputData;
wire outputRegisterOutputRequest;
OutputRegister #(.WIDTH(IO_COUNT), .ADDRESS(8'h01), .DEFAULT({IO_COUNT{1'b0}})) outputRegister(
.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(outputRegisterOutputData),
.requestOutput(outputRegisterOutputRequest),
.currentValue(gpio_output));
// Input data register
wire[31:0] inputRegisterOutputData;
wire inputRegisterOutputRequest;
wire inputRegisterBusBusy_nc;
wire[IO_COUNT-1:0] inputRegisterWriteData_nc;
wire inputRegisterWriteDataEnable_nc;
wire inputRegisterReadDataEnable_nc;
DataRegister #(.WIDTH(IO_COUNT), .ADDRESS(12'h020)) inputRegister(
.clk(clk),
.rst(rst),
.enable(deviceEnable),
.peripheralBus_we(peripheralBus_we),
.peripheralBus_oe(peripheralBus_oe),
.peripheralBus_busy(inputRegisterBusBusy_nc),
.peripheralBus_address(localAddress),
.peripheralBus_byteSelect(peripheralBus_byteSelect),
.peripheralBus_dataWrite(peripheralBus_dataWrite),
.peripheralBus_dataRead(inputRegisterOutputData),
.requestOutput(inputRegisterOutputRequest),
.writeData(inputRegisterWriteData_nc),
.writeData_en(inputRegisterWriteDataEnable_nc),
.writeData_busy(1'b0),
.readData(inputBuffered),
.readData_en(inputRegisterReadDataEnable_nc),
.readData_busy(1'b0));
// IRQ register: Default 0x0
wire[31:0] irqEnableRegisterOutputData;
wire irqEnableRegisterOutputRequest;
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 & inputBuffered;
always @(posedge clk) begin
if (rst) gpio_irq <= 1'b0;
else gpio_irq <= |pinIRQ;
end
endmodule