fpga-disk-controller/lattice/top.v

113 lines
3.6 KiB
Verilog

`timescale 1 ns / 1 ps
module top(
// bus interface
input [11:0] addr,
input fclk, // Clock for serial communication, either 7 or 8 MHz (7 MHz on Apple II)
input q3, // 2 MHz non-symmetric timing signal
inout [7:0] data,
input rw, // 1 means read, 0 means write
input _iostrobe, // goes low during read or write to any address $C800-$CFFF
input _iosel, // goes low during read or write to $CX00-$CXFF, where X is slot number
input _devsel, // goes low during read or write to $C0(X+8)0-$C0(X+8)F, where X is slot number. IWM: Falling edge latches A3-A0. Rising edge of (Q3 or _devsel) qualifies write register data
input _reset,
// disk interface
output wrdata,
output [3:0] phase,
output _wrreq,
output _enbl1,
inout _enbl2, // output that may be hardwired to ground when connected to a drive
inout select, // output that may be hardwired to ground when connected to a drive
inout _en35, // output that may be hardwired to ground when connected to a drive
input sense,
input rddata,
// SPI
output spi_clk,
output spi_mosi,
input spi_miso,
output spi_cs,
// level-shifting buffers
output _en245, // bidirectional connection of data bus to FPGA
// debugging: LEDs or switches or misc stuff
output [7:0] debugInfo
);
wire isOutputting;
wire romExpansionActive; // 1 if the Yellowstone card's ROM is the currently selected slot ROM
assign debugInfo = { romExpansionActive, rw, q3, isOutputting/*_devsel*/, _iosel, _iostrobe, _reset, spi_miso }; //{ romActive, 6'b000000, spi_miso };
wire _romoe;
//reg [1:0] en245Delay;
//always @(posedge fclk) begin
// en245Delay <= { en245Delay[0], (~_devsel || ~_romoe) };
//end
assign _en245 = ~(/*~q3 &&*//*(en245Delay == 2'b11) &&*/ (~_devsel || ~_romoe)); // IWM selected or ROM outputting
// IMPORTANT! TO-DO
// for select, _enbl2, _en35, these outputs may be driven externally to ground!
// never drive these actively high. configure as inout, enable the internal pull-up, and set output value to 0 or hi-Z
// may need to pause a few microseconds after setting these to hi-Z to let the pull-up work. It's around 50Kohm equivalent.
// RC time constant assuming 10 pF trace capacitance is 0.5 microseconds
wire _enbl2_from_iwm;
assign _enbl2 = 1'bZ;
assign select = 1'bZ;
assign _en35 = 1'bZ;
addrDecoder myAddrDecoder(
.addr(addr),
.fclk(fclk),
._iostrobe(_iostrobe),
._iosel(_iosel),
._reset(_reset),
._romoe(_romoe),
.romExpansionActive(romExpansionActive)
);
wire [7:0] iwmDataOut;
iwm myIwm(
.addr(addr[3:0]),
._devsel(_devsel),
.fclk(fclk),
.q3(q3),
._reset(_reset),
.dataIn(data),
.dataOut(iwmDataOut),
.wrdata(wrdata),
.phase(phase),
._wrreq(_wrreq),
._enbl1(_enbl1),
._enbl2(_enbl2_from_iwm),
.sense(sense),
.rddata(rddata)
);
wire [7:0] romOutput;
codeROM myROM(
.Address(addr[11:0]),
.OutClock(fclk), // use internal clock?
.OutClockEn(1'b1),
.Reset(1'b0),
.Q(romOutput)
);
//reg [1:0] lastDataEnable;
//always @(posedge fclk) begin
// lastDataEnable <= { lastDataEnable[0], (rw == 1 && _romoe == 0) || (rw == 1 && _devsel == 0 && addr[0] == 0) };
//end
// provide data from the card's ROM, or the IWM?
// IWM registers are read during any operation in which A0 is 0
assign isOutputting = (rw && ~_romoe) /*|| (rw == 1 && _devsel == 0 && addr[0] == 0)*/;
assign data = (/*lastDataEnable == 2'b11 &&*/ rw == 1 && _romoe == 0) ? romOutput :
(/*lastDataEnable == 2'b11 &&*/ rw == 1 && _devsel == 0 && addr[0] == 0) ? iwmDataOut :
8'bZZZZZZZZ;
endmodule