module apple_vid1(sysclk, CLOCK_50,clk32, reset_in, kbd_clk, kbd_dat, v_ad, ram_dat, mem_ce, mem_rw, vga_h_sync, vga_v_sync, vga_R, vga_G, vga_B, serioclk, ces, BusCycle, kbd_is_available, SW, card_status ); input CLOCK_50, clk32, sysclk, reset_in, kbd_clk, kbd_dat; output vga_h_sync, vga_v_sync; output [3:0] vga_R; output [3:0] vga_G; output [3:0] vga_B; output mem_ce,mem_rw,serioclk; output [3:0] ces; output [2:0] card_status; // LEDs for ramcard inout [7:0] ram_dat; input [9:0] SW; output [16:0] v_ad; output kbd_is_available; wire [16:0] v_ad; wire inDisplayArea, rw; reg [6:0] CounterX = 0; reg [9:0] CounterY = 0; reg vga_HS, vga_VS; reg R,G,B; reg ram_we = 1'b1; reg [6:0] shiftreg; reg [1:0] colorbits; reg high_bit; reg BLANK,BLANK1; output [4:0] BusCycle; reg [4:0] BusCycle = 0; //wire [7:0] ram_dat; reg [7:0] char_code; wire [3:0] addr_sum; reg PAGE2; wire [15:0] final_ram_addr; wire [7:0] kbd_data; wire [7:0] di, do; wire [15:0] cpu_addr; wire cpu_access_time; wire memory_access_time; wire kbd_access; reg cpu_write_cycle; reg [4:0] flash_count; wire cpu_drives_address; // assign memory_access_time = ShiftCounter[0] ^ ShiftCounter[1] ; assign memory_access_time = (BusCycle == 1) || (BusCycle == 2) || (BusCycle == 15) || (BusCycle == 16) || (BusCycle == 7); assign cpu_access_time = (BusCycle == 7) || (BusCycle == 8); assign cpu_drives_address = (BusCycle == 7) || (BusCycle == 8) ||(BusCycle == 6) || (BusCycle == 5); assign mem_ce = ~memory_access_time; assign mem_rw = ~((BusCycle == 7) && cpu_write_cycle); assign kbd_is_available = kbd_available; wire LDPS; assign LDPS = (BusCycle == 3) || (BusCycle == 17); // // ShiftCounter[2] & ShiftCounter[1]; assign addr_sum = {~CounterX[5],~CounterX[5],CounterX[4],CounterX[3]} + {CounterY[8],CounterY[7],CounterY[8],CounterY[7]} + 1; assign vga_R = BLANK1 ? 4'h0 : (GR && ~HIRES) ? lowres_color_val[11:8] : {R,R,R,R}; assign vga_G = BLANK1 ? 4'h0 : (GR && ~HIRES) ? lowres_color_val[7:4] : {G,G,G,G}; assign vga_B = BLANK1 ? 4'h0 : (GR && ~HIRES) ? lowres_color_val[3:0] : {B,B,B,B}; assign vga_h_sync = SW[3]? ~resampled_vsync : ~vga_HS; assign vga_v_sync = ~vga_VS; // assign char_code = {addr_sum ,CounterX[2:0]}; assign ram_dat = (cpu_access_time && ~rw) ? do : 8'hz; reg inverse; reg flash; wire [6:0] high_vid_addr; assign high_vid_addr = (HIRES & GR) ? {2'b00, PAGE2, ~PAGE2, CounterY[3:1]} : {5'b00000, PAGE2, ~PAGE2} ; assign v_ad = //~cpu_access_time ? // // ShiftCounter[2] ? ~cpu_drives_address ? {high_vid_addr, CounterY[6:4], addr_sum ,CounterX[2:0]} : // ShiftCounter[2] high during the last 3 states out of 7 final_ram_addr; // cpu_addr; // final_ram_addr; // fist 4 states of shifter //assign ram_dat[4:0] = BusCycle; wire HBL, VBL; wire odd; assign odd = BusCycle[0]; reg [2:0] ShiftCounter; wire [7:0] video_data; reg [7:0] video_shift_data; //wire AltCharSet = SW[4]; reg AltCharSet; always @(posedge clk32) begin if(GR) // no need to check HIRES: we don't shift lowres at all video_shift_data <= ram_dat; else video_shift_data <= video_data; if(LDPS) begin low_color_nibble <= CounterY[3]? ram_dat[7:4] : ram_dat[3:0]; char_code <= ram_dat; flash <= AltCharSet ? 0 : (char_code[6] & ~char_code[7]); BLANK1 <= BLANK; inverse <= ~char_code[7]; // : ~(char_code[7] | (char_code[6] & char_code[7])); end end wire [6:0] final_char_code = AltCharSet ? char_code : { (char_code[6] & char_code[7]), char_code[5:0]} ; reg [3:0] low_color_nibble; wire [11:0] lowres_color_val; wire GR; assign GR = ~(TEXT || ( MIXED && CounterY[6] && CounterY[8])); lores_color_map lores_color_map ( .nibble(low_color_nibble), .RGB_val(lowres_color_val) ); `ifdef ROM2K CharROM2k CharROM2k_inst ( .address ( {1'b0, char_code, CounterY[3:1] }), .clock ( clk32), .q ( video_data ) ); `else charrom_2esmall charrom_2esmall ( .address( { final_char_code, CounterY[3:1] }), .clock( clk32), .q( video_data) ); `endif always @(posedge clk32) begin // if(reset_in) // BusCycle <= 5'b0; //else if (BusCycle == 27) BusCycle <= 0; else BusCycle <= BusCycle + 1; end always @(posedge clk32) if(BusCycle == 8) cpu_write_cycle <= (rw == 0); // 7 shift states divide 32 MHz always @(posedge clk32) if( odd ) begin if((ShiftCounter[2] & ShiftCounter[1]) | reset_in | (BusCycle == 3)) begin ShiftCounter <= 3'b000; end else ShiftCounter <= ShiftCounter+1; end /* always @(posedge clk32) if( odd ) begin if(BusCycle == 3) begin ShiftCounter <= 3'b000; end else ShiftCounter <= ShiftCounter+1; end */ always @(posedge clk32) // if(odd & (ShiftCounter == 0)) begin if(LDPS) begin BLANK <= (HBL | VBL); if(!CounterX[6]) begin CounterX <= 7'b1000000; VBL_delayed <= VBL; if(CounterY == 10'b1111111111) begin CounterY <= 10'b0111110100; flash_count = flash_count +1; end else CounterY <= CounterY+1; end else CounterX <= CounterX + 1; end assign HBL = ~CounterX[5] & (~CounterX[4] | ~CounterX[3]); // up to 011000 assign VBL = (CounterY[8] & CounterY[7]); // as in real Apple reg VBL_delayed; wire apple_pixel_out = shiftreg[0] ^ ((inverse ^ flashing) && ~GR); wire flashing = flash ? flash_count[4] : 1'b0; always @(posedge clk32) begin vga_HS <= (CounterX[6:2]==5'b10010); // change this value to move the display horizontally vga_VS <= (CounterY==10'b1111000000); // change this value to move the display vertically if(SW[2]) begin //debugging if(VBL_delayed) begin R <= 0; G <= 0; B <= 0; end else begin R <= pixel_out; G <= pixel_out; B <= pixel_out; end end else begin if(BLANK1) begin R <= 0; G <= 0; B <= 0; end else begin R <= apple_pixel_out; G <= apple_pixel_out; B <= apple_pixel_out; end end end always @(posedge clk32) if( odd ) begin if (LDPS) begin // if((BusCycle == 1) || (BusCycle == 15)) begin shiftreg <= video_shift_data[6:0]; high_bit <= video_shift_data[7]; end else begin //if( odd ) begin shiftreg <= {1'b0,shiftreg[6:1]}; end end ///// VGA compatibility wire pixel_out; reg resampled_vsync; reg VGA_clk; linebuff linebuff ( .data(apple_pixel_out), .rdaddress({~CounterY[0], VGA_pixel_count}), .rdclock(CLOCK_50), .wraddress({CounterY[0],Apple_pixel_count}), .wrclock(clk32), .wren(~BLANK1), .q(pixel_out)); reg [9:0] VGA_pixel_count; reg [9:0] Apple_pixel_count; wire AppleLineStart = (CounterX[6:0] == 7'b1011000); wire VGALineStart = (CounterX[6:0] == 7'b1010100); always @ (posedge CLOCK_50) begin resampled_vsync <= vga_HS; if(VGALineStart ) begin VGA_pixel_count <= 0; VGA_clk <= 0; end else begin if( VGA_clk ) VGA_pixel_count <= VGA_pixel_count +1; VGA_clk = ~VGA_clk; end end always @(posedge clk32) if(AppleLineStart) Apple_pixel_count <= 0; else Apple_pixel_count <= Apple_pixel_count + 1; /////////////////////////////////////////////////// end of video part ************************************ assign card_status = {card_ram_we, card_ram_rd, bank1}; ramcard ramcard ( .mclk28(clk32), .reset_in(reset_in), .strobe(BusCycle == 7), .addr(cpu_addr), .ram_addr(final_ram_addr), .we(~rw), .card_ram_we(card_ram_we), .card_ram_rd(card_ram_rd), .bank1(bank1) ); wire io_access = (cpu_addr[15:8] == 8'b11000000); reg TEXT,MIXED,HIRES, mode_80COL,mode_80STORE; reg RAMRD, RAMWRT, ALTZP; always @(posedge clk32) if(reset_in) begin PAGE2 <= 0; HIRES <= 0; AltCharSet <= 0; mode_80COL <= 0; end else begin if((BusCycle == 7) && io_access)begin if(cpu_write_cycle) 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 //***************************** keyboard intface ******************** wire [6:0] ascii; wire kbd_available; wire read_kbd; assign kbd_data = {kbd_available, ascii}; assign kbd_access = (cpu_addr[15:4] == 12'hC00); assign read_kbd = (cpu_addr == 16'hC010); assign di = kbd_access ? kbd_data : ram_dat; kbd_intf kbd_intf ( .mclk25(clk32), .reset_in(reset_in), .PS2_Clk(kbd_clk), .PS2_Data(kbd_dat), // .shift(shift), .ascii(ascii), .kbd_available(kbd_available), .read_kb(read_kbd) ); wire cpuclk = ( BusCycle == 8); reg nmi = 0; reg irq = 0; wire rdy = 1; bc6502 cpu0(.reset(reset_in), .clk(cpuclk), .nmi(nmi), .irq(irq), .rdy(rdy), .di(di), .do(do), .rw(rw), .ma(cpu_addr), .sync(sync) ); endmodule