	localparam IODEV_ADDR_BITS         = 'h00000004; // 4
	localparam IODEV_ADDR_SHIFT        = 'h00000007; // 7
	localparam SDRAM_ADDR              = 'h40000000; // 1073741824
	localparam SDRAM_BITS              = 'h00000019; // 25
	localparam SRAM_ADDR               = 'h00000000; // 0
	localparam SRAM_BITS               = 'h0000000f; // 15
	localparam SYS_MAGIC_MAX80         = 'h3858414d; // 945307981
	localparam TIMER_SHIFT             = 'h00000005; // 5
	localparam TTY_CHANNELS            = 'h00000004; // 4
	localparam XDEV_ADDR_BITS          = 'h00000002; // 2
	localparam XDEV_ADDR_SHIFT         = 'h0000001c; // 28
	localparam _PC_IRQ                 = 'h00000020; // 32
	localparam _PC_RESET               = 'h00000010; // 16

	reg  [31:0] nxdev_rdata;
	reg  [31:0] iodev_rdata;
	wire [ 3:0] xdev_valid  = iodev_mem_valid << cpu_mem_addr[29:28];
	wire [15:0] iodev_valid = xdev_valid[3] << cpu_mem_addr[10:7];

	wire [31:0] iodev_rdata_sys;
	wire [ 0:0] iodev_valid_sys = iodev_valid[0:0];
	tri1 [ 0:0] iodev_wait_n_sys;

	wire [31:0] iodev_rdata_abc;
	wire [ 0:0] iodev_irq_abc;
	wire [ 0:0] iodev_valid_abc = iodev_valid[1:1];
	tri1 [ 0:0] iodev_wait_n_abc;

	wire [31:0] iodev_rdata_abcmemmap;
	wire [ 0:0] iodev_valid_abcmemmap = xdev_valid[0:0];
	tri1 [ 0:0] iodev_wait_n_abcmemmap;

	wire [31:0] iodev_rdata_sysclock;
	wire [ 0:0] iodev_irq_sysclock;
	wire [ 0:0] iodev_valid_sysclock = iodev_valid[2:2];
	tri1 [ 0:0] iodev_wait_n_sysclock;

	wire [31:0] iodev_rdata_tty;
	wire [ 3:0] iodev_irq_tty;
	wire [ 0:0] iodev_valid_tty = iodev_valid[3:3];
	tri1 [ 0:0] iodev_wait_n_tty;

	wire [31:0] iodev_rdata_usbdesc;
	wire [ 0:0] iodev_valid_usbdesc = xdev_valid[1:1];
	tri1 [ 0:0] iodev_wait_n_usbdesc;

	wire [31:0] iodev_rdata_romcopy;
	wire [ 0:0] iodev_irq_romcopy;
	wire [ 0:0] iodev_valid_romcopy = iodev_valid[4:4];
	tri1 [ 0:0] iodev_wait_n_romcopy;

	wire [31:0] iodev_rdata_sdcard;
	wire [ 0:0] iodev_irq_sdcard;
	wire [ 0:0] iodev_valid_sdcard = iodev_valid[5:5];
	tri1 [ 0:0] iodev_wait_n_sdcard;

	wire [31:0] iodev_rdata_i2c;
	wire [ 0:0] iodev_irq_i2c;
	wire [ 0:0] iodev_valid_i2c = iodev_valid[6:6];
	tri1 [ 0:0] iodev_wait_n_i2c;

	wire [31:0] iodev_rdata_esp;
	wire [ 0:0] iodev_irq_esp;
	wire [ 0:0] iodev_valid_esp = iodev_valid[7:7];
	tri1 [ 0:0] iodev_wait_n_esp;

	wire [31:0] iodev_rdata_random;
	wire [ 0:0] iodev_irq_random;
	wire [ 0:0] iodev_valid_random = iodev_valid[8:8];
	tri1 [ 0:0] iodev_wait_n_random;

	wire [31:0] iodev_rdata_vjtag;
	wire [ 0:0] iodev_irq_vjtag;
	wire [ 0:0] iodev_valid_vjtag = iodev_valid[9:9];
	tri1 [ 0:0] iodev_wait_n_vjtag;

	// I/O input MUX
	always_comb
		case (cpu_mem_addr[29:28])
			2'd0:	 iodev_rdata = iodev_rdata_abcmemmap;
			2'd1:	 iodev_rdata = iodev_rdata_usbdesc;
			2'd3:
			case (cpu_mem_addr[10:7])
				4'd0:	 iodev_rdata = iodev_rdata_sys;
				4'd1:	 iodev_rdata = iodev_rdata_abc;
				4'd2:	 iodev_rdata = iodev_rdata_sysclock;
				4'd3:	 iodev_rdata = iodev_rdata_tty;
				4'd4:	 iodev_rdata = iodev_rdata_romcopy;
				4'd5:	 iodev_rdata = iodev_rdata_sdcard;
				4'd6:	 iodev_rdata = iodev_rdata_i2c;
				4'd7:	 iodev_rdata = iodev_rdata_esp;
				4'd8:	 iodev_rdata = iodev_rdata_random;
				4'd9:	 iodev_rdata = iodev_rdata_vjtag;
				default: iodev_rdata = 32'hxxxxxxxx;
			endcase
			default: iodev_rdata = 32'hxxxxxxxx;
		endcase

	tri0 [31:0] sys_irq;
	assign sys_irq[ 3] = iodev_irq_abc[0];
	assign sys_irq[ 4] = iodev_irq_sysclock[0];
	assign sys_irq[ 5] = iodev_irq_tty[0];
	assign sys_irq[ 6] = iodev_irq_tty[1];
	assign sys_irq[ 7] = iodev_irq_tty[2];
	assign sys_irq[ 8] = iodev_irq_tty[3];
	assign sys_irq[ 9] = iodev_irq_romcopy[0];
	assign sys_irq[10] = iodev_irq_sdcard[0];
	assign sys_irq[11] = iodev_irq_i2c[0];
	assign sys_irq[12] = iodev_irq_esp[0];
	assign sys_irq[13] = iodev_irq_random[0];
	assign sys_irq[14] = iodev_irq_vjtag[0];

	localparam [31:0] irq_edge_mask =  32'h00004010;
	localparam [31:0] irq_masked    = ~32'h00007fff;

	wire iodev_wait_n = (&iodev_wait_n_sys) & 
		(&iodev_wait_n_abc) & 
		(&iodev_wait_n_abcmemmap) & 
		(&iodev_wait_n_sysclock) & 
		(&iodev_wait_n_tty) & 
		(&iodev_wait_n_usbdesc) & 
		(&iodev_wait_n_romcopy) & 
		(&iodev_wait_n_sdcard) & 
		(&iodev_wait_n_i2c) & 
		(&iodev_wait_n_esp) & 
		(&iodev_wait_n_random) & 
		(&iodev_wait_n_vjtag);
