module IOBM(
	/* PDS interface */
	input C16M, input C8M, input E,
	output reg nASout, output reg nLDS, output reg nUDS, output reg nVMA,
	input nDTACK, input nVPA, input nBERR, input nRES,
	/* PDS address and data latch control */
	input AoutOE, output nDoutOE, output reg ALE0, output reg nDinLE,
	/* IO bus slave port interface */
	input IORDREQ, input IOWRREQ, input IOLDS, input IOUDS,
	output reg IOACT, output reg IODONE, output reg IOBERR);

	/* C8M clock registration */
	reg C8Mr; always @(posedge C16M) C8Mr <= C8M;

	/* I/O request input synchronization */
	reg IORDREQr; always @(posedge C16M) IORDREQr <= IORDREQ;
	reg IOWRREQr; always @(posedge C16M) IOWRREQr <= IOWRREQ;
	wire IOREQr = IORDREQr || IOWRREQr;

	/* VPA synchronization */
	reg VPAr; always @(negedge C8M) VPAr <= !nVPA;
	
	/* E clock synchronization */
	reg Er; always @(negedge C8M) begin Er <= E; end
	
	/* E clock state */
	reg [3:0] ES;
	always @(negedge C8M) begin
		if (!E && Er) ES <= 1;
		else if (ES==0 || ES==9) ES <= 0;
		else ES <= ES+1;
	end

	/* ETACK and VMA generation */
	wire ETACK = (ES==8) && !nVMA;
	always @(posedge C8M) begin
		if ((ES==5) && IOACT && VPAr) nVMA <= 0;
		else if(ES==0) nVMA <= 1;
	end
	
	/* DTACK and BERR synchronization */
	always @(negedge C8M, posedge nASout) begin
		if (nASout) begin
			IODONE <= 0;
			IOBERR <= 0;
		end else begin
			IODONE <= (!nDTACK || ETACK || !nRES);
			IOBERR <= !nBERR;
		end
	end

	/* I/O bus state */
	reg [2:0] IOS = 0;
	reg IOS0;
	always @(posedge C16M) begin
		if (IOS==0) begin
			if (IOREQr && !C8Mr && AoutOE) begin // "IOS1"
				IOS <= 2;
				IOS0 <= 0;
			end else begin // "regular" IOS0
				IOS <= 0;
				IOS0 <= 1;
			end
			IOACT <= IOREQr && AoutOE;
			ALE0 <= IOREQr && AoutOE;
		end else if (IOS==2) begin
			IOS <= 3;
			IOS0 <= 0;
			IOACT <= 1;
			ALE0 <= 1;
		end else if (IOS==3) begin
			IOS <= 4;
			IOS0 <= 0;
			IOACT <= 1;
			ALE0 <= 1;
		end else if (IOS==4) begin
			IOS <= 5;
			IOS0 <= 0;
			IOACT <= 1;
			ALE0 <= 1;
		end else if (IOS==5) begin
			if (!C8Mr && (IODONE || IOBERR)) begin
				IOS <= 6;
				IOACT <= 0;
			end else begin
				IOS <= 5;
				IOACT <= 1;
			end
			IOS0 <= 0;
			ALE0 <= 1;
		end else if (IOS==6) begin
			IOS <= 7;
			IOS0 <= 0;
			IOACT <= 0;
			ALE0 <= 0;
		end else if (IOS==7) begin
			IOS <= 0;
			IOS0 <= 1;
			IOACT <= 0;
			ALE0 <= 0;
		end
	end

	/* PDS address and data latch control */
	always @(negedge C16M) begin nDinLE = IOS==4 || IOS==5; end
	reg DoutOE = 0;
	always @(posedge C16M) begin
		DoutOE <= (IOS==0 && IOWRREQr && !C8Mr) ||
				  (DoutOE && (IOS==2 || IOS==3 || IOS==4 || IOS==5));
	end
	assign nDoutOE = !(AoutOE && (DoutOE || (IOS0 && !IOREQr)));

	/* AS, DS control */
	always @(negedge C16M) begin
		nASout <= !((IOS==0 && IOREQr && !C8Mr) || IOS==2 || IOS==3 || IOS==4 || IOS==5);
		nLDS <= !(IOLDS && ((IOS==0 && IORDREQr && !C8Mr) || (IOS==2 && !nLDS) || IOS==3 || IOS==4 || IOS==5));
		nUDS <= !(IOUDS && ((IOS==0 && IORDREQr && !C8Mr) || (IOS==2 && !nUDS) || IOS==3 || IOS==4 || IOS==5));
	end

endmodule
