// Apple-1 for MiST // // Forked from Gehstock's implementation https://github.com/Gehstock/Mist_FPGA // // // TODO load binary files into memory // TODO make it work with SDRAM // TODO use 7 MHz clock in display // TODO isolate ps2 keyboard from apple1 // TODO check ps2 clock // TODO ram refresh lost cycles // TODO check display parameters vs real apple1 // TODO reset and cls key from keyboard // TODO power on-off key ? (init ram) // TODO reset if pll not locked // TODO reorganize file structure // TODO integrate with mist-modules // TODO support ACI interface for load and save // TODO special expansion boards: TMS9918, SID // TODO ascii keyboard module apple1_mist( input CLOCK_27, // SPI interface to arm io controller input SPI_SCK, output SPI_DO, input SPI_DI, //input SPI_SS2, input SPI_SS3, //input SPI_SS4, input CONF_DATA0, // SDRAM interface inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits output SDRAM_DQML, // SDRAM Low-byte Data Mask output SDRAM_DQMH, // SDRAM High-byte Data Mask output SDRAM_nWE, // SDRAM Write Enable output SDRAM_nCAS, // SDRAM Column Address Strobe output SDRAM_nRAS, // SDRAM Row Address Strobe output SDRAM_nCS, // SDRAM Chip Select output [1:0] SDRAM_BA, // SDRAM Bank Address output SDRAM_CLK, // SDRAM Clock output SDRAM_CKE, // SDRAM Clock Enable // VGA interface output [5:0] VGA_R, output [5:0] VGA_G, output [5:0] VGA_B, output VGA_HS, output VGA_VS, // other output LED, input UART_RX, output AUDIO_L, output AUDIO_R ); `include "rtl\build_id.v" /******************************************************************************************/ /******************************************************************************************/ /***************************************** @user_io ***************************************/ /******************************************************************************************/ /******************************************************************************************/ localparam CONF_STR = { "APPLE 1;;", "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", "T6,Reset;", "V,v1.01.",`BUILD_DATE }; localparam conf_str_len = $size(CONF_STR)>>3; wire st_reset_switch = buttons[1]; wire st_menu_reset = status[6]; wire clk14; // the 14.31818 MHz clock wire clk_osd; // x2 clock for the OSD menu wire r, g, b; wire hs, vs; wire [31:0] status; wire [1:0] buttons; wire [1:0] switches; wire scandoubler_disable; wire ypbpr; wire no_csync; wire ps2_kbd_clk; wire ps2_kbd_data; assign LED = 1; wire reset_button = status[0] | st_menu_reset | st_reset_switch | !pll_locked; /******************************************************************************************/ /******************************************************************************************/ /***************************************** @pll *******************************************/ /******************************************************************************************/ /******************************************************************************************/ wire pll_locked; pll pll ( .inclk0(CLOCK_27), .locked(pll_locked), .c0(clk_osd), // x2 clock for OSD menu .c1(clk14) // 14.31818 MHz system clock /* .c2 ( sys_clock ), // cpu x 8 .c3 ( SDRAM_CLK ) // cpu x 8 phase shifted -2.5 ns */ ); /******************************************************************************************/ /******************************************************************************************/ /***************************************** @apple1 ****************************************/ /******************************************************************************************/ /******************************************************************************************/ // RAM wire [7:0] ram_dout; ram ram( .clk(clk14), .address(cpu_addr[12:0]), .w_en(cpu_wr), .din(cpu_dout), .dout(ram_dout) ); // WozMon ROM wire [7:0] rom_dout; rom_wozmon rom_wozmon( .clk(clk14), .address(cpu_addr[7:0]), .dout(rom_dout) ); // Basic ROM wire [7:0] basic_dout; rom_basic rom_basic( .clk(clk14), .address(cpu_addr[11:0]), .dout(basic_dout) ); // ram interface wire [15:0] cpu_addr; wire [7:0] cpu_dout; wire cpu_rd; wire cpu_wr; wire ram_cs = (cpu_addr[15:13] == 3'b000); // 0x0000 -> 0x1FFF wire basic_cs = (cpu_addr[15:12] == 4'b1110); // 0xE000 -> 0xEFFF wire rom_cs = (cpu_addr[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF wire [7:0] bus_dout = basic_cs ? basic_dout : rom_cs ? rom_dout : ram_cs ? ram_dout : 8'b0; apple1 apple1 ( .clk14(clk14), .rst_n(~reset_button), // RAM interface .ram_addr (cpu_addr), .ram_din (cpu_dout), .ram_dout (bus_dout), .ram_rd (cpu_rd), .ram_wr (cpu_wr), .ps2_clk(ps2_kbd_clk), .ps2_din(ps2_kbd_data), .vga_h_sync(hs), .vga_v_sync(vs), .vga_red(r), .vga_grn(g), .vga_blu(b), .vga_cls() // clear screen button (not connected yet) ); mist_video #( .COLOR_DEPTH(1), // 1 bit color depth .OSD_AUTO_CE(1) // OSD autodetects clock enable ) mist_video ( .clk_sys(clk_osd), // OSD needs 2x the VDP clock for the scandoubler // OSD SPI interface .SPI_DI(SPI_DI), .SPI_SCK(SPI_SCK), .SPI_SS3(SPI_SS3), .scanlines(2'b00), // scanline emulation disabled for now .ce_divider(1), // non-scandoubled pixel clock divider 0 - clk_sys/4, 1 - clk_sys/2 .scandoubler_disable(scandoubler_disable), // disable scandoubler option from mist.ini .no_csync(no_csync), // csync option from mist.ini .ypbpr(ypbpr), // YPbPr option from mist.ini .rotate(2'b00), // no ODS rotation .blend(0), // composite-like blending // video input signals to mist_video .R(r), .G(g), .B(b), .HSync(hs), .VSync(vs), // video output signals that go into MiST hardware .VGA_R(VGA_R), .VGA_G(VGA_G), .VGA_B(VGA_B), .VGA_VS(VGA_VS), .VGA_HS(VGA_HS), ); user_io #( .STRLEN(conf_str_len) //.PS2DIV(14) // ps2 clock divider: CLOCK / 14 must be approx = 15 Khz ) user_io ( .conf_str (CONF_STR ), .clk_sys (clk14 ), .SPI_CLK (SPI_SCK ), .SPI_SS_IO (CONF_DATA0 ), .SPI_MISO (SPI_DO ), .SPI_MOSI (SPI_DI ), .status (status ), .buttons (buttons ), .switches (switches ), .scandoubler_disable ( scandoubler_disable ), // get this option from mist.ini .ypbpr ( ypbpr ), // get this option from mist.ini .no_csync ( no_csync ), // get this option from mist.ini .ps2_kbd_clk (ps2_kbd_clk ), // ps2 keyboard from mist firmware .ps2_kbd_data (ps2_kbd_data ) // ps2 keyboard from mist firmware ); /******************************************************************************************/ /******************************************************************************************/ /***************************************** @sdram *****************************************/ /******************************************************************************************/ /******************************************************************************************/ /* // SDRAM control signals assign SDRAM_CKE = 1'b1; wire [24:0] sdram_addr; wire [7:0] sdram_din; wire sdram_wr; wire sdram_rd; wire [7:0] sdram_dout; always @(*) begin if(is_downloading && download_wr) begin sdram_addr <= download_addr; sdram_din <= download_data; sdram_wr <= download_wr; sdram_rd <= 1'b1; end else if(eraser_busy) begin sdram_addr <= eraser_addr; sdram_din <= eraser_data; sdram_wr <= eraser_wr; sdram_rd <= 1'b1; end else begin sdram_addr <= { 9'd0, cpu_addr[15:0] }; sdram_din <= cpu_dout; sdram_wr <= cpu_wr; sdram_rd <= cpu_rd; end end sdram sdram ( // interface to the MT48LC16M16 chip .sd_data ( SDRAM_DQ ), .sd_addr ( SDRAM_A ), .sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ), .sd_cs ( SDRAM_nCS ), .sd_ba ( SDRAM_BA ), .sd_we ( SDRAM_nWE ), .sd_ras ( SDRAM_nRAS ), .sd_cas ( SDRAM_nCAS ), // system interface .clk ( sys_clock ), .clkref ( cpu_clock ), .init ( !pll_locked ), // cpu interface .din ( sdram_din ), .addr ( sdram_addr ), .we ( sdram_wr ), .oe ( sdram_rd ), .dout ( sdram_dout ) ); */ endmodule