module MMC_start_DE1_TOP ( //////////////////// Clock Input //////////////////// CLOCK_24, // 24 MHz CLOCK_27, // 27 MHz CLOCK_50, // 50 MHz EXT_CLOCK, // External Clock //////////////////// Push Button //////////////////// KEY, // Pushbutton[3:0] //////////////////// DPDT Switch //////////////////// SW, // Toggle Switch[9:0] //////////////////// 7-SEG Dispaly //////////////////// HEX0, // Seven Segment Digit 0 HEX1, // Seven Segment Digit 1 HEX2, // Seven Segment Digit 2 HEX3, // Seven Segment Digit 3 //////////////////////// LED /////////////////////// LEDG, // LED Green[7:0] LEDR, // LED Red[9:0] //////////////////////// UART //////////////////////// UART_TXD, // UART Transmitter UART_RXD, // UART Receiver ///////////////////// SDRAM Interface //////////////// DRAM_DQ, // SDRAM Data bus 16 Bits DRAM_ADDR, // SDRAM Address bus 12 Bits DRAM_LDQM, // SDRAM Low-byte Data Mask DRAM_UDQM, // SDRAM High-byte Data Mask DRAM_WE_N, // SDRAM Write Enable DRAM_CAS_N, // SDRAM Column Address Strobe DRAM_RAS_N, // SDRAM Row Address Strobe DRAM_CS_N, // SDRAM Chip Select DRAM_BA_0, // SDRAM Bank Address 0 DRAM_BA_1, // SDRAM Bank Address 0 DRAM_CLK, // SDRAM Clock DRAM_CKE, // SDRAM Clock Enable //////////////////// Flash Interface //////////////// FL_DQ, // FLASH Data bus 8 Bits FL_ADDR, // FLASH Address bus 22 Bits FL_WE_N, // FLASH Write Enable FL_RST_N, // FLASH Reset FL_OE_N, // FLASH Output Enable FL_CE_N, // FLASH Chip Enable //////////////////// SRAM Interface //////////////// SRAM_DQ, // SRAM Data bus 16 Bits SRAM_ADDR, // SRAM Address bus 18 Bits SRAM_UB_N, // SRAM High-byte Data Mask SRAM_LB_N, // SRAM Low-byte Data Mask SRAM_WE_N, // SRAM Write Enable SRAM_CE_N, // SRAM Chip Enable SRAM_OE_N, // SRAM Output Enable //////////////////// SD_Card Interface //////////////// SD_DAT, // SD Card Data SD_DAT3, // SD Card Data 3 SD_CMD, // SD Card Command Signal SD_CLK, // SD Card Clock //////////////////// USB JTAG link //////////////////// TDI, // CPLD -> FPGA (data in) TCK, // CPLD -> FPGA (clk) TCS, // CPLD -> FPGA (CS) TDO, // FPGA -> CPLD (data out) //////////////////// I2C //////////////////////////// I2C_SDAT, // I2C Data I2C_SCLK, // I2C Clock //////////////////// PS2 //////////////////////////// PS2_DAT, // PS2 Data PS2_CLK, // PS2 Clock //////////////////// VGA //////////////////////////// VGA_HS, // VGA H_SYNC VGA_VS, // VGA V_SYNC VGA_R, // VGA Red[3:0] VGA_G, // VGA Green[3:0] VGA_B, // VGA Blue[3:0] //////////////// Audio CODEC //////////////////////// AUD_ADCLRCK, // Audio CODEC ADC LR Clock AUD_ADCDAT, // Audio CODEC ADC Data AUD_DACLRCK, // Audio CODEC DAC LR Clock AUD_DACDAT, // Audio CODEC DAC Data AUD_BCLK, // Audio CODEC Bit-Stream Clock AUD_XCK, // Audio CODEC Chip Clock //////////////////// GPIO //////////////////////////// GPIO_0, // GPIO Connection 0 GPIO_1 // GPIO Connection 1 ); //////////////////////// Clock Input //////////////////////// input [1:0] CLOCK_24; // 24 MHz input [1:0] CLOCK_27; // 27 MHz input CLOCK_50; // 50 MHz input EXT_CLOCK; // External Clock //////////////////////// Push Button //////////////////////// input [3:0] KEY; // Pushbutton[3:0] //////////////////////// DPDT Switch //////////////////////// input [9:0] SW; // Toggle Switch[9:0] //////////////////////// 7-SEG Dispaly //////////////////////// output [6:0] HEX0; // Seven Segment Digit 0 output [6:0] HEX1; // Seven Segment Digit 1 output [6:0] HEX2; // Seven Segment Digit 2 output [6:0] HEX3; // Seven Segment Digit 3 //////////////////////////// LED //////////////////////////// output [7:0] LEDG; // LED Green[7:0] output [9:0] LEDR; // LED Red[9:0] //////////////////////////// UART //////////////////////////// output UART_TXD; // UART Transmitter input UART_RXD; // UART Receiver /////////////////////// SDRAM Interface //////////////////////// inout [15:0] DRAM_DQ; // SDRAM Data bus 16 Bits output [11:0] DRAM_ADDR; // SDRAM Address bus 12 Bits output DRAM_LDQM; // SDRAM Low-byte Data Mask output DRAM_UDQM; // SDRAM High-byte Data Mask output DRAM_WE_N; // SDRAM Write Enable output DRAM_CAS_N; // SDRAM Column Address Strobe output DRAM_RAS_N; // SDRAM Row Address Strobe output DRAM_CS_N; // SDRAM Chip Select output DRAM_BA_0; // SDRAM Bank Address 0 output DRAM_BA_1; // SDRAM Bank Address 0 output DRAM_CLK; // SDRAM Clock output DRAM_CKE; // SDRAM Clock Enable //////////////////////// Flash Interface //////////////////////// inout [7:0] FL_DQ; // FLASH Data bus 8 Bits output [21:0] FL_ADDR; // FLASH Address bus 22 Bits output FL_WE_N; // FLASH Write Enable output FL_RST_N; // FLASH Reset output FL_OE_N; // FLASH Output Enable output FL_CE_N; // FLASH Chip Enable //////////////////////// SRAM Interface //////////////////////// inout [15:0] SRAM_DQ; // SRAM Data bus 16 Bits output [17:0] SRAM_ADDR; // SRAM Address bus 18 Bits output SRAM_UB_N; // SRAM High-byte Data Mask output SRAM_LB_N; // SRAM Low-byte Data Mask output SRAM_WE_N; // SRAM Write Enable output SRAM_CE_N; // SRAM Chip Enable output SRAM_OE_N; // SRAM Output Enable //////////////////// SD Card Interface //////////////////////// inout SD_DAT; // SD Card Data inout SD_DAT3; // SD Card Data 3 inout SD_CMD; // SD Card Command Signal output SD_CLK; // SD Card Clock //////////////////////// I2C //////////////////////////////// inout I2C_SDAT; // I2C Data output I2C_SCLK; // I2C Clock //////////////////////// PS2 //////////////////////////////// input PS2_DAT; // PS2 Data input PS2_CLK; // PS2 Clock //////////////////// USB JTAG link //////////////////////////// input TDI; // CPLD -> FPGA (data in) input TCK; // CPLD -> FPGA (clk) input TCS; // CPLD -> FPGA (CS) output TDO; // FPGA -> CPLD (data out) //////////////////////// VGA //////////////////////////// output VGA_HS; // VGA H_SYNC output VGA_VS; // VGA V_SYNC output [3:0] VGA_R; // VGA Red[3:0] output [3:0] VGA_G; // VGA Green[3:0] output [3:0] VGA_B; // VGA Blue[3:0] //////////////////// Audio CODEC //////////////////////////// inout AUD_ADCLRCK; // Audio CODEC ADC LR Clock input AUD_ADCDAT; // Audio CODEC ADC Data inout AUD_DACLRCK; // Audio CODEC DAC LR Clock output AUD_DACDAT; // Audio CODEC DAC Data inout AUD_BCLK; // Audio CODEC Bit-Stream Clock output AUD_XCK; // Audio CODEC Chip Clock //////////////////////// GPIO //////////////////////////////// inout [35:0] GPIO_0; // GPIO Connection 0 inout [35:0] GPIO_1; // GPIO Connection 1 assign LEDR = {kbd_available, 1'h0, MMC_data}; // All inout port turn to tri-state assign DRAM_DQ = 16'hzzzz; assign SRAM_DQ = 16'hzzzz; assign SD_DAT = 1'bz; assign I2C_SDAT = 1'bz; assign AUD_ADCLRCK = 1'bz; assign AUD_DACLRCK = 1'bz; assign AUD_BCLK = 1'bz; assign GPIO_0 = {track, disk_phase}; // 36'hzzzzzzzzz; //{28'hzzzzzzz, sample_high8}; assign GPIO_1 = {8'hzz, SW[8]? {4'b0, MMC_addr } : mmc_mode_mem_addr, // 18 bits 1'bz, // first 10 z80_cen, cpu_oe, z80_cpu_we_n, 1'b0, 1'b0, SD_DAT, SD_DAT3, SD_CMD, SD_CLK, }; // Audio //assign AUD_ADCLRCK = AUD_DACLRCK; //assign AUD_XCK = AUD_CTRL_CLK; assign FL_WE_N = 1; assign FL_RST_N = 1; assign FL_OE_N = mem_ce_n_6502; assign FL_CE_N = ~reading_flash; assign FL_WE_N = 1'b1; assign FL_DQ = 8'hzz; assign FL_ADDR = address_is_rom ? {5'b0, 16'h1000 + cpu_addr[13:0]} : {5'b0, 16'h0000 + cpu_addr[13:0]}; //slot rom //assign LEDG = {1'b0, A16ram, DL}; assign LEDG = {1'b0, disk_phase, card_status}; //mJTAG_DATA_FROM_HOST[7:0]; wire reading_flash = (address_is_rom && ~card_ram_rd) || address_is_slot_rom; wire mclk28; wire [7:0] mem_data; wire [7:0] io_data; wire m1_n; wire [15:0] mSEG7_DIG; wire reset_in = ~CPU_reset_n; wire CPU_reset_n = locked_sig && KEY[0]; wire [12:0] video_addr; wire ROM_address_space; wire [15:0] cpu_addr; //6502 wire [7:0] cpu_di; wire [7:0] cpu_do; wire cpu_rom_access; wire cpu_ram_access; wire video_has_bus; wire [17:0] ram_addr; wire turbo; assign turbo = 0; wire [5:0] DL; wire vga_oe, cpu_oe; wire cpu_clock_en; wire [4:0] scan_res; //from keyboard assign vga_oe = ~video_has_bus; `define HAS_z80CPU //`define HAS_SOUND assign SRAM_DQ[15:8] = 8'bz; // clock is 28.56 mHz - close enough to double the Apple master clock pll pll_50_to_28 (.inclk0(CLOCK_50), .c0(mclk28),.locked(locked_sig)); SEG7_LUT_4 u0 ( HEX0,HEX1,HEX2,HEX3,mSEG7_DIG ); assign mSEG7_DIG = SW[2] ? cpu_addr : {2'b0, track, SRAM_DQ[7:0]}; wire int_n, nmi_n, busrq_n; assign int_n = 1;//~interrupt; assign nmi_n = 1; assign busrq_n = 1; wire [4:0] BusCycle; wire [6:0] CounterX; // 0x40 to 0x7f wire [9:0] CounterY; // reg [7:0] video_mem_data; wire LDPS = (BusCycle == 3) || (BusCycle == 17); // wire memory_access_time = (BusCycle == 3) || (BusCycle == 2) || (BusCycle == 17) || (BusCycle == 16) || (BusCycle == 7) || (BusCycle == 8); wire [3:0] addr_sum = {~CounterX[5],~CounterX[5],CounterX[4],CounterX[3]} + {CounterY[8],CounterY[7],CounterY[8],CounterY[7]} + 1; // wire GR = ~(TEXT || ( MIXED && CounterY[6] && CounterY[8])); reg TEXT,MIXED,HIRES, mode_80COL,mode_80STORE; reg RAMRD, RAMWRT, ALTZP; reg AltCharSet, PAGE2; wire [6:0] high_vid_addr; assign high_vid_addr = (HIRES & GR) ? {2'b00, PAGE2, ~PAGE2, CounterY[3:1]} : {5'b00000, PAGE2, ~PAGE2} ; wire [15:0] apple_video_addr = {high_vid_addr, CounterY[6:4], addr_sum ,CounterX[2:0]}; wire [15:0] final_ram_addr; wire io_access = (cpu_addr[15:8] == 8'b11000000); reg cpu_write_cycle; always @(posedge mclk28) if(reset_in) begin PAGE2 <= 0; HIRES <= 0; AltCharSet <= 0; mode_80COL <= 0; TEXT <= 1; end else begin if((BusCycle == 7) && io_access)begin if(~rw_6502) begin // writes that switch case(cpu_addr[7:0]) 8'h00: mode_80STORE <= 0; 8'h01: mode_80STORE <= 1; 8'h02: RAMRD <= 0; 8'h03: RAMRD <= 1; 8'h04: RAMWRT <= 0; 8'h05: RAMWRT <= 1; 8'h08: ALTZP <= 0; 8'h09: ALTZP <= 1; 8'h0C: mode_80COL <= 0; 8'h0D: mode_80COL <= 1; 8'h0E: AltCharSet <= 0; 8'h0F: AltCharSet <= 1; endcase end else begin // reads that switch case(cpu_addr[7:0]) 8'h50: TEXT <= 0; 8'h51: TEXT <= 1; 8'h52: MIXED <= 0; 8'h53: MIXED <= 1; 8'h54: PAGE2 <= 0; 8'h55: PAGE2 <= 1; 8'h56: HIRES <= 0; 8'h57: HIRES <= 1; endcase end end end // the 6502 side of the floppy disk interface reg odd_access = 0; // RWTS likes the disk data to change so it knows the disk is turning // so we'll feed it 0 every other byte always @ (posedge mclk28) if(read_disk_data) odd_access <= ~odd_access; wire c6_io = (cpu_addr[15:4] == 12'hc0e) && (BusCycle == 8); // c0ex wire read_disk_data = (cpu_addr == 'hC0EC) & (BusCycle == 8); wire [12:0] disk_ram_addr; wire [5:0] track; wire [3:0] disk_phase; wire [7:0] disk_buff_do; disk disk_intf ( .mclk28(mclk28), .read_disk_data(read_disk_data & odd_access), .c6_io(c6_io), .reset(reset_in), .addr(cpu_addr[7:0]), .wr(rw_6502), .ram_addr(disk_ram_addr), .track(track), .disk_phase(disk_phase) ); // 6502 CPU clock_ctrl clock_ctrl_inst ( .ena ( ( BusCycle == 8) && ~mmc_mode ), .inclk ( mclk28 ), .outclk ( cpuclk_6502 ) ); // wire cpuclk_6502 = ( BusCycle == 8) && ~mmc_mode; reg nmi_6502 = 0; reg irq_6502 = 0; wire rdy_6502 = 1; wire [7:0] ram_dat = reading_flash ? FL_DQ : SRAM_DQ ; wire [7:0] floppy_data = odd_access ? disk_buff_do : 8'h0; wire [7:0] di_6502 = apple_kbd_access ? {kbd_available, kbd_ascii} : (cpu_addr == 'hC0EC) ? floppy_data : ram_dat; wire [7:0] do_6502; //wire mem_rw_6502 = ~((BusCycle == 7) && cpu_write_cycle); wire mem_rw_6502 = ~((BusCycle == 7) && ~rw_6502); wire cpu_access_time = (BusCycle == 7) || (BusCycle == 8); wire mem_ce_n_6502 = ~memory_access_time; bc6502 cpu0(.reset(reset_in || ~KEY[3]), .clk(cpuclk_6502), .nmi(nmi_6502), .irq(irq_6502), .rdy(rdy_6502), .di(di_6502), .do(do_6502), .rw(rw_6502), .ma(cpu_addr), .sync(sync) ); // RAM card logic assign card_status = {card_ram_we, card_ram_rd, bank1}; ramcard ramcard ( .mclk28(mclk28), .reset_in(reset_in || ~KEY[3]), .strobe(BusCycle == 7), .addr(cpu_addr), .ram_addr(final_ram_addr), .we(~rw_6502), .card_ram_we(card_ram_we), .card_ram_rd(card_ram_rd), .bank1(bank1) ); // VIDEO section wire [3:0] R; wire [3:0] G; wire [3:0] B; assign VGA_R = (HBL2 || VBL1) ? 0: R; assign VGA_G = (HBL2 || VBL1) ? 0: G; assign VGA_B = (HBL2 || VBL1) ? 0: B; reg HBL1,HBL2, VBL1; wire [5:0] hor_addr = (CounterX - 7'h58); wire [7:0] video_mem_data = {( mmc_mode ? 1'b1: video_high_bit), SRAM_DQ[6:0]}; wire video_high_bit = SRAM_DQ[7]; always @(posedge mclk28) begin if(BusCycle == 8) begin cpu_write_cycle <= (rw_6502 == 0); end if(LDPS) begin HBL1 <= HBL; HBL2 <= HBL1; VBL1 <= VBL; // video_mem_data <= SRAM_DQ[7:0]; end end AppleShifter shifter ( .clk28(mclk28), .CounterY(CounterY), .do_shift(BusCycle[0]), .odd_dot(BusCycle[1]), .LDPS(LDPS), .ram_data(video_mem_data), .pixelout(pixelout), .GR(GR), .vga_R(R), .vga_G(G), .vga_B(B), .TEXT(TEXT), .MIXED(MIXED), .HIRES(HIRES), .AltCharSet(AltCharSet), .flash_count4(flash_count4) ); AppleVideoTiming AppleVideoTiming ( .clk28(mclk28), .reset_in(~CPU_reset_n), .vga_HS(VGA_HS), .vga_VS(VGA_VS), .BusCycle(BusCycle), .CounterX(CounterX), .CounterY(CounterY), .HBL(HBL), .VBL(VBL), .flash_count4(flash_count4) ); wire mmc_mode = SW[1] & mmc_load_mode; wire [17:0] mmc_mode_mem_addr; wire [15:0] z80_cpu_addr; wire [7:0] z80_cpu_di; wire [7:0] z80_cpu_do; wire z80_cen = ( BusCycle == 8) && mmc_mode; // (BusCycle[2:0] == 3'b111); // (BusCycle[2:0] == 3'b010); wire z80_write_time = (BusCycle[2:1] == 2'b11); // D000 and up wire address_is_rom = cpu_addr[15] && cpu_addr[14] && (cpu_addr[13] || cpu_addr[12]); wire address_is_slot_rom = (cpu_addr[15:8] == 8'hC6); //only disk ROM present wire address_is_ram = (cpu_addr[15:14] == 2'b00); wire ram_card_read = address_is_rom & card_status[1]; wire ram_card_write = address_is_rom & card_status[2]; wire [2:0] card_status; assign SRAM_UB_N = 1'b1; assign SRAM_LB_N = 1'b0; wire cpu_ram_oe = mmc_mode ? ~cpu_oe : // ( cpu_access_time && ~cpu_write_cycle); ( cpu_access_time && rw_6502); assign SRAM_OE_N = ~(LDPS || (cpu_ram_oe && ~reading_flash)); assign SRAM_CE_N = mmc_mode ? 0 : //always on mem_ce_n_6502; //Apple mode assign ram_addr = LDPS ? {2'b00, apple_video_addr} : {2'b00, final_ram_addr}; assign SRAM_ADDR = mmc_mode ? mmc_mode_mem_addr : ram_addr; // video memory mapped to 0x4000 in z80 space assign mmc_mode_mem_addr = z80_cen ? {2'b01,z80_cpu_addr} : //z80_write_time ? {2'b01,z80_cpu_addr} : LDPS ? {2'b01,4'b0100, apple_video_addr[11:0]} : 18'h0; `ifdef HAS_z80CPU wire mreq_n, iorq_n; wire cpu_wt; wire wait_n = 1; assign cpu_oe = mreq_n | cpu_rd | ~rfsh_n | ~z80_cen; // all low -> low assign io_data = z80_cpu_addr[7:0] == 8'hab ? {7'h0, SPI_active} : z80_cpu_addr[7:0] == 8'h00 ? {kbd_available, kbd_ascii} : 8'h00; assign SRAM_DQ[7:0] = (mmc_mode && ((mreq_n | cpu_wt) == 0) && z80_cen) ? z80_cpu_do : (~mem_rw_6502 && (~address_is_rom || ram_card_write)) ? do_6502 : 8'hzz; // (~(address_is_rom | address_is_slot_rom) && mem_rw_6502) ? do_6502 : 8'hzz; // we need to latch the di signal for this core reg [7:0] di_r1; always @(posedge mclk28) begin if(z80_cen) begin if(mreq_n == 0) di_r1 <= mem_data; if(iorq_n == 0) di_r1 <= io_data; end end assign z80_cpu_di = di_r1 ; assign ROM_address_space = ~(z80_cpu_addr[15] | z80_cpu_addr[14]); wire RAM_address_space = (z80_cpu_addr[15] | z80_cpu_addr[14]); assign mem_data = RAM_address_space ? SRAM_DQ[7:0] : low16k_data; wire z80_cpu_we_n = mreq_n | cpu_wt | ~z80_cen ; // all low -> low assign SRAM_WE_N = mmc_mode ? z80_cpu_we_n | ROM_address_space : ~(~mem_rw_6502 && (~address_is_rom || ram_card_write)); tv80s z80cpu ( .m1_n(m1_n), .mreq_n(mreq_n), .iorq_n(iorq_n), .rd_n(cpu_rd), .wr_n(cpu_wt), .rfsh_n(rfsh_n), .halt_n(halt_n), .busak_n(busak_n), .A(z80_cpu_addr), .do(z80_cpu_do), .reset_n(CPU_reset_n), .clk(mclk28), .wait_n(wait_n), .int_n(int_n), .nmi_n(nmi_n), .busrq_n(busrq_n), .di(z80_cpu_di), .cen(z80_cen) ); `else assign cpu_oe = 1'b1; `endif reg mmc_load_mode; // z80 in control running mmc_fat_rom code wire [7:0] disk_data; wire [7:0] mmc_cpu_di; always @(posedge mclk28) begin if(reset_in || (KEY[1] == 0) ) mmc_load_mode <= 1'b1; else begin if(~iorq_n && (z80_cpu_addr[7:0] == 8'had) && ~cpu_wt) mmc_load_mode <= 1'b0; end end wire [15:0] disk_buff_addr = mmc_mode ? z80_cpu_addr : {3'b000, disk_ram_addr}; mmc_disk mmc_disk (/*AUTOINST*/ // Outputs .SD_DAT3 (SD_DAT3), .SD_CMD (SD_CMD), .SD_CLK (SD_CLK), .mmc_read_kbd (mmc_read_kbd), .SPI_active (SPI_active), .disk_data (disk_data[7:0]), .MMC_addr (MMC_addr[12:0]), .MMC_data (MMC_data[7:0]), .z80_cpu_di (mmc_cpu_di[7:0]), // Inputs .SD_DAT (SD_DAT), .z80_cen (z80_cen), .mreq_n (mreq_n), .track (track[5:0]), .mclk28 (mclk28), .reset_in (reset_in), .iorq_n (iorq_n), .cpu_wt (cpu_wt), .z80_cpu_addr (disk_buff_addr), .z80_cpu_do (z80_cpu_do[7:0]), .mmc_init_mode(mmc_mode), .disk_buff_do(disk_buff_do) ); wire [7:0] MMC_data; wire [12:0] MMC_addr; //assign SD_DAT3 = ~SPI_control; wire [7:0] low16k_data = mmc_mode ? mmc_cpu_di : 8'h00; //VGA_Audio_PLL u3 ( .inclk0(CLOCK_27[0]),.c0(VGA_CTRL_CLK),.c1(AUD_CTRL_CLK) ); //***************************** keyboard intface ******************** assign read_kbd = mmc_mode ? mmc_read_kbd : (cpu_addr == 16'hC010); wire apple_kbd_access = (cpu_addr[15:4] == 12'hC00); wire [6:0] kbd_ascii; kbd_intf kbd_intf ( .mclk25(mclk28), .reset_in(reset_in), .PS2_Clk(PS2_CLK), .PS2_Data(PS2_DAT), // .shift(shift), .ascii(kbd_ascii), .kbd_available(kbd_available), .read_kb(read_kbd) ); endmodule