module addrController_top( // clocks: input clk, output clk8, // 8.125 MHz CPU clock output clk8_en_p, output clk8_en_n, output clk16_en_p, output clk16_en_n, // system config: input turbo, // 0 = normal, 1 = faster input [1:0] configROMSize, // 0 = 64K ROM, 1 = 128K ROM, 2 = 256K ROM input [1:0] configRAMSize, // 0 = 128K, 1 = 512K, 2 = 1MB, 3 = 4MB RAM // 68000 CPU memory interface: input [23:0] cpuAddr, input _cpuUDS, input _cpuLDS, input _cpuRW, input _cpuAS, // RAM/ROM: output [21:0] memoryAddr, output _memoryUDS, output _memoryLDS, output _romOE, output _ramOE, output _ramWE, output videoBusControl, output dioBusControl, output cpuBusControl, output memoryLatch, // peripherals: output selectSCSI, output selectSCC, output selectIWM, output selectVIA, output selectRAM, output selectROM, output selectSEOverlay, // video: output hsync, output vsync, output _hblank, output _vblank, output loadPixels, input vid_alt, input snd_alt, output loadSound, // misc input memoryOverlayOn, // interface to read dsk image from ram input [21:0] dskReadAddrInt, output dskReadAckInt, input [21:0] dskReadAddrExt, output dskReadAckExt ); // -------------- audio engine (may be moved into seperate module) --------------- assign loadSound = sndReadAck; localparam SIZE = 20'd135408; // 168*806 clk8 events per frame localparam STEP = 20'd5920; // one step every 16*370 clk8 events reg [21:0] audioAddr; reg [19:0] snd_div; reg sndReadAckD; always @(posedge clk) if (clk8_en_n) sndReadAckD <= sndReadAck; reg vblankD, vblankD2; always @(posedge clk) begin if(clk8_en_p && sndReadAckD) begin vblankD <= _vblank; vblankD2 <= vblankD; // falling adge of _vblank = begin of vblank phase if(vblankD2 && !vblankD) begin audioAddr <= snd_alt?22'h3FA100:22'h3FFD00; snd_div <= 20'd0; end else begin if(snd_div >= SIZE-1) begin snd_div <= snd_div - SIZE + STEP; audioAddr <= audioAddr + 22'd2; end else snd_div <= snd_div + STEP; end end end assign dioBusControl = extraBusControl; // interleaved RAM access for CPU and video reg [1:0] busCycle; reg [1:0] busPhase; reg [1:0] extra_slot_count; always @(posedge clk) begin busPhase <= busPhase + 1'd1; if (busPhase == 2'b11) busCycle <= busCycle + 2'd1; end assign memoryLatch = busPhase == 2'd3; assign clk8 = !busPhase[1]; assign clk8_en_p = busPhase == 2'b11; assign clk8_en_n = busPhase == 2'b01; assign clk16_en_p = !busPhase[0]; assign clk16_en_n = busPhase[0]; reg extra_slot_advance; always @(posedge clk) if (clk8_en_n) extra_slot_advance <= (busCycle == 2'b11); // allocate memory slots in the extra cycle always @(posedge clk) begin if(clk8_en_p && extra_slot_advance) begin extra_slot_count <= extra_slot_count + 2'd1; end end // video controls memory bus during the first clock of the four-clock cycle assign videoBusControl = (busCycle == 2'b00); // cpu controls memory bus during the second and fourth clock of the four-clock cycle assign cpuBusControl = (busCycle == 2'b01) || (busCycle == 2'b11); // IWM/audio gets 3rd cycle wire extraBusControl = (busCycle == 2'b10); // interconnects wire [21:0] videoAddr; // RAM/ROM control signals wire videoControlActive = _hblank; assign _romOE = ~(cpuBusControl && selectROM && _cpuRW); wire extraRamRead = sndReadAck; assign _ramOE = ~((videoBusControl && videoControlActive) || (extraRamRead) || (cpuBusControl && selectRAM && _cpuRW)); assign _ramWE = ~(cpuBusControl && selectRAM && !_cpuRW); assign _memoryUDS = cpuBusControl ? _cpuUDS : 1'b0; assign _memoryLDS = cpuBusControl ? _cpuLDS : 1'b0; wire [21:0] addrMux = sndReadAck ? audioAddr : videoBusControl ? videoAddr : cpuAddr[21:0]; wire [21:0] macAddr; assign macAddr[15:0] = addrMux[15:0]; // video and sound always addresses ram wire ram_access = (cpuBusControl && selectRAM) || videoBusControl || sndReadAck; wire rom_access = (cpuBusControl && selectROM); // simulate smaller RAM/ROM sizes assign macAddr[16] = rom_access && configROMSize == 2'b00 ? 1'b0 : // force A16 to 0 for 64K ROM access addrMux[16]; assign macAddr[17] = ram_access && configRAMSize == 2'b00 ? 1'b0 : // force A17 to 0 for 128K RAM access rom_access && configROMSize == 2'b01 ? 1'b0 : // force A17 to 0 for 128K ROM access rom_access && configROMSize == 2'b00 ? 1'b1 : // force A17 to 1 for 64K ROM access (64K ROM image is at $20000) addrMux[17]; assign macAddr[18] = ram_access && configRAMSize == 2'b00 ? 1'b0 : // force A18 to 0 for 128K RAM access rom_access && configROMSize != 2'b11 ? 1'b0 : // force A18 to 0 for 64K/128K/256K ROM access addrMux[18]; assign macAddr[19] = ram_access && configRAMSize[1] == 1'b0 ? 1'b0 : // force A19 to 0 for 128K or 512K RAM access rom_access ? 1'b0 : // force A19 to 0 for ROM access addrMux[19]; assign macAddr[20] = ram_access && configRAMSize != 2'b11 ? 1'b0 : // force A20 to 0 for all but 4MB RAM access rom_access ? 1'b0 : // force A20 to 0 for ROM access addrMux[20]; assign macAddr[21] = ram_access && configRAMSize != 2'b11 ? 1'b0 : // force A21 to 0 for all but 4MB RAM access rom_access ? 1'b0 : // force A21 to 0 for ROM access addrMux[21]; // floppy emulation gets extra slots 0 and 1 assign dskReadAckInt = (extraBusControl == 1'b1) && (extra_slot_count == 0); assign dskReadAckExt = (extraBusControl == 1'b1) && (extra_slot_count == 1); // audio gets extra slot 2 wire sndReadAck = (extraBusControl == 1'b1) && (extra_slot_count == 2); assign memoryAddr = dskReadAckInt ? dskReadAddrInt + 22'h100000: // first dsk image at 1MB dskReadAckExt ? dskReadAddrExt + 22'h200000: // second dsk image at 2MB macAddr; // address decoding addrDecoder ad( .configROMSize(configROMSize), .address(cpuAddr), ._cpuAS(_cpuAS), .memoryOverlayOn(memoryOverlayOn), .selectRAM(selectRAM), .selectROM(selectROM), .selectSCSI(selectSCSI), .selectSCC(selectSCC), .selectIWM(selectIWM), .selectVIA(selectVIA), .selectSEOverlay(selectSEOverlay)); // video videoTimer vt( .clk(clk), .clk_en(clk8_en_p), .busCycle(busCycle), .vid_alt(vid_alt), .videoAddr(videoAddr), .hsync(hsync), .vsync(vsync), ._hblank(_hblank), ._vblank(_vblank), .loadPixels(loadPixels)); endmodule