pcsx-redux/hardware/PIO-Dev/verilog/piodev3.v
2019-12-31 10:55:20 -08:00

324 lines
8.5 KiB
Verilog

module piodev3(
// The address lines we have connected.
input A0,
input A1,
input A2,
input A3,
input A4,
input A16,
input A17,
input A18,
input A19,
input A20,
input A21,
input A22,
// The internal data bus, that connects to all of our parts on the board.
inout [0:7] D,
// The PIO's !WR and !RD pins.
input nWR,
input nRD,
// The CS pin of the SRAM.
output nCS_SRAM,
// The !OE pin of the switch's latch.
output nCS_SWITCH,
// Our 12Mhz clock.
input CLK,
// A20 and CS pins for the onboard flash, and zif socket.
output A20_FLASH,
output nCS_FLASH,
output A20_SOCKET,
output nCS_SOCKET,
// Two hardware jumpers, pulled up. Grounded on version 3.0 of the board.
// Version 3.1 has the actual jumpers traces.
input JP1,
input JP2,
// The CH375's CS pin.
output nCS_CH,
// The CH375's interrupt line.
input nIN_CH,
// The LE pin of the LED's latch.
output CS_LEDS,
// Our momentary soft button, pulled up.
input SOFT,
// The FT2232H's !CS, A0, and !RESET lines. The !RESET line is
// pulled down by default, and goes up when a usb cable is
// connected to the computer, providing 5v.
output nCS_PORTB,
output A0_PORTA,
output nCS_PORTA,
inout nRESET_FT,
// The 10 optional GPIO pins on top of the CPLD.
inout [1:10] GPIO,
// The additional pins from the PIO.
inout DACK,
input nWR2,
inout DREQ,
// The two small dip switches near the CPLD.
input SW1,
input SW2,
// The A20 pin of the SRAM.
output A20_SRAM,
// The interrupt line of the PIO port.
output nIN10,
// The Switch Board enable pin, to redirect the CS2 line.
// If the line 5 of the PIO port hasn't been cut, this will
// make the CPLD burn 3.3v through ground. There is a 200ohm
// resistor to prevent damage.
output SBEN,
// !CS0 and !CS2 from the PIO. The !CS2 line will only work if
// the Switch Board has been installed, SBEN is high, and the
// line 39 of the PIO port has been cut and redirected to the
// Switch Board properly.
//
// By default, !CS0 will be active when reading from the
// 0x1f000000 memory range, and !CS2 will be active when reading
// from the 0xbfc00000 memory range.
input nCS0,
input nCS2,
// The PIO's data line. It isn't connected on any other device on
// the PCB, leaving it up to the CPLD to latch it.
inout [0:7] PD,
// The PSX's !RESET line. Will go high after ~300ms after power up,
// as long as the reset controller chips are still there on the PSU.
// Can be used to cause the PSX to reset, by asserting this line low.
inout nRESET
);
// --------------------------------
// Some helpers. Should be easily optimized away by the compiler.
wire [23:0] A = {
1'b0, A22, A21, A20,
A19, A18, A17, A16,
1'b0, 1'b0, 1'b0, 1'b0,
1'b0, 1'b0, 1'b0, 1'b0,
1'b0, 1'b0, 1'b0, 1'b0,
1'b0, 1'b0, 1'b0, A4,
A3, A2, A1, A0
};
wire WR = ~nWR;
wire RD = ~nRD;
wire IN_CH = ~nIN_CH;
wire CS0 = ~nCS0;
wire CS2 = ~nCS2;
// Defaults for all of the outputs.
//assign nCS_SRAM = 1'b1;
//assign nCS_SWITCH = 1'b1;
//assign CS_LEDS = 1'b0;
//assign A20_FLASH = 1'b0;
//assign nCS_FLASH = 1'b1;
//assign A20_SOCKET = 1'b0;
//assign nCS_SOCKET = 1'b1;
//assign nCS_CH = 1'b1;
//assign nCS_PORTB = 1'b1;
//assign A0_PORTA = 1'b0;
//assign nCS_PORTA = 1'b1;
assign nRESET_FT = 1'bz;
assign GPIO = 10'bzzzzzzzzzz;
assign DACK = 1'bz;
assign DREQ = 1'bz;
//assign A20_SRAM = 1'b0;
assign nIN_10 = 1'b1;
//assign SBEN = 1'b0;
//assign PD = 8'bzzzzzzzz;
//assign D = 8'bzzzzzzzz;
assign nRESET = 1'bz;
// --------------------------------
// Quick diagnostics code. Will make LEDs blink,
// according to the clock by default, and according to
// the dip switches when the soft button is pressed.
//
// Tests if the dip switches, the LEDs, the latches and the clock
// are properly wired and working correctly.
/*
assign CS_LEDS = 1'b1;
assign nCS_SWITCH = SOFT;
reg [31:0] cnt = 0;
always @(posedge CLK) cnt <= cnt + 1;
assign D = SOFT ? ~cnt[27:20] : 8'bzzzzzzzz;
*/
// --------------------------------
// Passthrough from CS0 to the FT2232H's port A (recovery)
/*
assign nCS_PORTA = nCS0;
assign A0_PORTA = 1'b0;
assign PD = RD && CS0 ? D : 8'bzzzzzzzz;
*/
// --------------------------------
// Passthrough from CS0 to the socket flash (caetla)
/*
assign nCS_SOCKET = nCS0;
assign A20_SOCKET = 1'b0;
assign PD = RD && CS0 ? D : 8'bzzzzzzzz;
*/
// --------------------------------
// Passthrough from CS2 to the socket flash (bios)
/*
assign nCS_SOCKET = nCS2;
assign A20_SOCKET = 1'b0;
assign PD = RD && CS2 ? D : 8'bzzzzzzzz;
assign SBEN = 1'b1;
*/
// --------------------------------
// Main behavior description of the PIO board
reg [7:0] bufferOut = 8'b00000000;
reg [7:0] bufferIn = 8'b00000000;
reg activateOutput = 0;
reg [7:0] bits = 8'b00000000;
// Helper for making sure CS isn't strobing.
wire strobe = WR || RD;
// Our mappings.
// Flash1 runs from 0x000000 to 0x1fffff, so check address bits A21 and A22,
// and ignore everything else.
assign nCS_FLASH = !(strobe && CS0 && !A22 && !A21);
// Flash2 runs from 0x200000 to 0x3fffff, so check address bits A21 and A22,
// and ignore everything else. It's also used to mirror the BIOS, so toggle
// it for any CS2 read.
assign nCS_SOCKET = !(strobe && CS2 || CS0 && !A22 && A21);
// SRAM runs from 0x400000 to 0x5fffff, so check address bits A21 and A22,
// and ignore everything else.
assign nCS_SRAM = !(strobe && CS0 && A22 && !A21);
// While all of the above are full-length mappings, the next ones are one
// or two bytes larges, therefore we need to check more address bits.
// We technically have more address bits than that tied to the CPLD, but
// for now, that's all we need to distinguish. If we need to add more
// addresses to watch for, then we'll have to add more address bits to
// these checks.
// FT2232H's port A runs from 0x600000 to 0x600001.
assign nCS_PORTA = !(strobe && CS0 && A22 && A21 && !A2 && !A1);
// FT2232H's port B runs from 0x600002 to 0x600003.
assign nCS_PORTB = !(strobe && CS0 && A22 && A21 && !A2 && A1);
// CH375B's runs from 0x600004 to 0x600005.
assign nCS_CH = !(strobe && CS0 && A22 && A21 && A2 && !A1);
// Switches and leds are at 0x600006. Writing to this address means
// assigning some value to the LEDs. Reading this address means
// reading the dip switch values.
assign nCS_SWITCH = !(strobe && CS0 && A22 && A21 && A2 && A1 && !A0 && RD);
assign CS_LEDS = (strobe && CS0 && A22 && A21 && A2 && A1 && !A0 && WR);
// Configuration bits are at 0x600007.
wire internalData = strobe && A22 && A21 && A2 && A1 && A0;
// We need to pay attention for CS0 and CS2.
// Note that CS2 is on a grounded line of the PIO by default.
// If not cut, this will always be active.
wire CS = CS0 || CS2;
// When the CPU is writing, the PIO's data port needs to be an input.
assign PD = WR ? 8'bzzzzzzzz :
// Otherwise, if we're currently being read, pass through the data bus
// to the PIO data bus.
(CS && RD ? (internalData ? bits : D) :
// RD goes up before CS usually. When that's the case, try to sustain
// the sampled value of the data bus.
(CS && activateOutput ? bufferOut :
// By default, in any other case, present a high-Z bus to the PIO.
8'bzzzzzzzz));
// When the CPU is writing, just be a pass through from the CPU to
// our data bus.
assign D = WR ? PD :
// Othewise, when the CPU is reading from us, we need to be an input
// for the devices on our data bus.
(CS && RD ? 8'bzzzzzzzz :
// In all other cases, mirror on the data bus the last sampled value
// from the CPU. This last case covers the moment when WR goes up before
// CS, giving time to the devices on our data bus to sample it properly.
bufferIn);
// For now, no special paging.
assign A20_FLASH = A20;
assign A20_SOCKET = A20;
assign A20_SRAM = A20;
// Disable real BIOS chip.
assign SBEN = 1'b1;
// For now, no special meaning for port A's A0.
// Might be useful for recovery mode later on.
assign A0_PORTA = A0;
// When RD goes up, sample the devices on our data bus.
always @(posedge nRD) begin
bufferOut <= internalData ? bits : D;
end
// When WR goes up, sample the PIO's data bus.
always @(posedge nWR) begin
bufferIn <= PD;
end
// Our internal configuration bits' special needs.
always @(posedge nWR or posedge nRESET) begin
if (nRESET) begin
bits <= 8'b00000000;
end else if (internalData) begin
bits <= PD;
end
end
// Sample our boolean telling us if we need to emit data on the
// PIO port when RD goes low.
always @(negedge nRD) begin
activateOutput <= CS;
end
assign GPIO[1] = nCS_PORTB;
assign GPIO[2] = nCS_CH;
assign GPIO[3] = nCS_SRAM;
assign GPIO[4] = nCS_FLASH;
assign GPIO[5] = nCS_PORTA;
endmodule