Hardware scrolling seems to be working!

This commit is contained in:
Alan Garfield 2018-02-08 00:40:43 +11:00
parent 1f4fe41a97
commit fdc93fb0d2
5 changed files with 1108 additions and 69 deletions

File diff suppressed because it is too large Load Diff

View File

@ -88,8 +88,8 @@ module apple1(
.we (we), .we (we),
.irq_n (1'b1), .irq_n (1'b1),
.nmi_n (1'b1), .nmi_n (1'b1),
.ready (cpu_clken), .ready (cpu_clken)
.pc_monitor (pc_monitor) //.pc_monitor (pc_monitor)
); );
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -112,6 +112,8 @@ module apple1(
wire basic_cs = (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF wire basic_cs = (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF
wire rom_cs = (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF wire rom_cs = (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
wire mode_cs = (ab[15:12] == 4'b1100); // 0xC000
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// RAM and ROM // RAM and ROM
@ -182,10 +184,12 @@ module apple1(
); );
// VGA Display interface // VGA Display interface
reg [1:0] vga_mode;
vga my_vga( vga my_vga(
.clk25(clk25), .clk25(clk25),
.enable(vga_cs & cpu_clken), .enable(vga_cs & cpu_clken),
.rst(rst), .rst(rst),
.vga_h_sync(vga_h_sync), .vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync), .vga_v_sync(vga_v_sync),
.vga_red(vga_red), .vga_red(vga_red),
@ -194,9 +198,20 @@ module apple1(
.address(ab[0]), .address(ab[0]),
.w_en(we & vga_cs), .w_en(we & vga_cs),
.din(dbo) .din(dbo),
.mode(vga_mode),
.debug(pc_monitor)
); );
always @(posedge clk25 or posedge rst)
begin
if (rst)
vga_mode <= 2'b0;
else
if (mode_cs & we & cpu_clken)
vga_mode <= dbo[1:0];
end
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// CPU Data In MUX // CPU Data In MUX
@ -206,5 +221,6 @@ module apple1(
basic_cs ? basic_dout : basic_cs ? basic_dout :
uart_cs ? uart_dout : uart_cs ? uart_dout :
ps2kb_cs ? ps2_dout : ps2kb_cs ? ps2_dout :
mode_cs ? vga_mode :
8'hFF; 8'hFF;
endmodule endmodule

View File

@ -26,6 +26,7 @@
module font_rom( module font_rom(
input clk, // clock signal input clk, // clock signal
input [1:0] mode, // character mode
input [5:0] character, // address bus input [5:0] character, // address bus
input [3:0] pixel, // address of the pixel to output input [3:0] pixel, // address of the pixel to output
input [4:0] line, // address of the line to output input [4:0] line, // address of the line to output
@ -38,10 +39,10 @@ module font_rom(
parameter ROM_FILENAME = "../../roms/vga_font.bin"; parameter ROM_FILENAME = "../../roms/vga_font.bin";
`endif `endif
reg [7:0] rom[0:639]; reg [7:0] rom[0:1023];
initial initial
$readmemb(ROM_FILENAME, rom, 0, 639); $readmemb(ROM_FILENAME, rom, 0, 1023);
// double width of pixel by ignoring bit 0 // double width of pixel by ignoring bit 0
wire [2:0] pixel_ptr; wire [2:0] pixel_ptr;
@ -52,15 +53,14 @@ module font_rom(
always @(posedge clk) always @(posedge clk)
begin begin
`ifdef DOTTY // mode
out <= (line[0] & pixel[0]) ? rom[(character * 10) + {2'd0, line_ptr}][pixel_ptr] : 1'b0; // 00 - normal
`endif // 01 - vertical scanlines
`ifdef SCANLINES // 10 - horizontal scanlines
out <= (line[0]) ? rom[(character * 10) + {2'd0, line_ptr}][pixel_ptr] : 1'b0; // 11 - dotty mode
`endif out <= (mode[1] & line[0]) ? 1'b0 :
`ifdef NORMAL (mode[0] & pixel[0]) ? 1'b0 :
out <= rom[(character * 10) + {2'd0, line_ptr}][pixel_ptr]; rom[(character * 10) + {2'd0, line_ptr}][pixel_ptr];
`endif
end end
endmodule endmodule

View File

@ -9,7 +9,9 @@ module vga(
output vga_blu, // blue VGA signal output vga_blu, // blue VGA signal
input address, // address bus input address, // address bus
input w_en, // active high write enable strobe input w_en, // active high write enable strobe
input [7:0] din // 8-bit data bas (input) input [7:0] din, // 8-bit data bus (input)
input [1:0] mode, // 2-bit mode setting for pixel doubling
output [15:0] debug
); );
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -32,18 +34,19 @@ module vga(
reg [4:0] v_dot; reg [4:0] v_dot;
// hardware cursor registers // hardware cursor registers
wire [9:0] cursor; wire [10:0] cursor;
reg [5:0] h_cursor; reg [5:0] h_cursor;
reg [9:0] v_cursor; reg [4:0] v_cursor;
// vram indexing registers // vram indexing registers
reg [9:0] vram_start_addr;
reg [5:0] vram_h_addr; reg [5:0] vram_h_addr;
reg [9:0] vram_v_addr; reg [4:0] vram_v_addr;
reg [4:0] vram_start_addr;
reg [4:0] vram_end_addr;
// vram registers // vram registers
wire [9:0] vram_r_addr; wire [10:0] vram_r_addr;
reg [9:0] vram_w_addr; reg [10:0] vram_w_addr;
reg vram_w_en; reg vram_w_en;
reg [5:0] vram_din; reg [5:0] vram_din;
wire [5:0] vram_dout; wire [5:0] vram_dout;
@ -115,6 +118,7 @@ module vga(
font_rom my_font_rom( font_rom my_font_rom(
.clk(clk25), .clk(clk25),
.mode(mode),
.character(font_char), .character(font_char),
.pixel(font_pixel), .pixel(font_pixel),
.line(font_line), .line(font_line),
@ -139,23 +143,23 @@ module vga(
always @(posedge clk25 or posedge rst) begin always @(posedge clk25 or posedge rst) begin
if (rst) begin if (rst) begin
vram_h_addr <= 0; vram_h_addr <= 'd0;
vram_v_addr <= 0; vram_v_addr <= 'd0;
end else begin end else begin
// start the pipeline for reading vram and font details // start the pipeline for reading vram and font details
// 3 pixel clock cycles early // 3 pixel clock cycles early
if (h_dot == 4'hC) if (h_dot == 4'hC)
vram_h_addr <= vram_h_addr + 1; vram_h_addr <= vram_h_addr + 'd1;
// advance to next row when last display line is reached for row // advance to next row when last display line is reached for row
if (v_dot == 5'd19 && h_cnt == 10'd0) if (v_dot == 5'd19 && h_cnt == 10'd0)
vram_v_addr <= vram_v_addr + 10'h28; vram_v_addr <= vram_v_addr + 'd1;
// clear the address registers if we're not in visible area // clear the address registers if we're not in visible area
if (~h_active) if (~h_active)
vram_h_addr <= 0; vram_h_addr <= 'd0;
if (~v_active) if (~v_active)
vram_v_addr <= 0; vram_v_addr <= vram_start_addr;
end end
end end
@ -181,8 +185,9 @@ module vga(
// Pipeline and VGA signals // Pipeline and VGA signals
// vram to font rom to display pipeline assignments // vram to font rom to display pipeline assignments
assign cursor = ({4'd0, h_cursor} + v_cursor); assign cursor = {v_cursor, h_cursor};
assign vram_r_addr = (vram_start_addr + {4'd0, vram_h_addr} + vram_v_addr); assign vram_r_addr = {vram_v_addr, vram_h_addr};
assign font_char = (vram_r_addr != cursor) ? vram_dout : (blink) ? 6'd0 : 6'd32; assign font_char = (vram_r_addr != cursor) ? vram_dout : (blink) ? 6'd0 : 6'd32;
assign font_pixel = h_dot + 1; // offset by one to get pixel into right cycle, assign font_pixel = h_dot + 1; // offset by one to get pixel into right cycle,
// font output one pixel clk behind // font output one pixel clk behind
@ -195,6 +200,8 @@ module vga(
assign vga_h_sync = (h_cnt < h_pulse) ? 0 : 1; assign vga_h_sync = (h_cnt < h_pulse) ? 0 : 1;
assign vga_v_sync = (v_cnt < v_pulse) ? 0 : 1; assign vga_v_sync = (v_cnt < v_pulse) ? 0 : 1;
assign debug = {v_cursor, 6'd0, vram_start_addr};
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// CPU control and hardware cursor // CPU control and hardware cursor
@ -203,14 +210,28 @@ module vga(
if (rst) if (rst)
begin begin
h_cursor <= 6'd0; h_cursor <= 6'd0;
v_cursor <= 10'd0; v_cursor <= 5'd0;
char_seen <= 0; char_seen <= 'b0;
vram_start_addr <= 0; vram_start_addr <= 5'd0;
vram_end_addr <= 5'd23;
end end
else else
begin begin
vram_w_en <= 0; vram_w_en <= 0;
// cursor overflow handling
if (h_cursor == 6'd40)
begin
h_cursor <= 6'd0;
v_cursor <= v_cursor + 'd1;
end
if (v_cursor == vram_end_addr)
begin
vram_start_addr <= vram_start_addr + 'd1;
vram_end_addr <= vram_end_addr + 'd1;
end
if (address == 1'b0) // address low == TX register if (address == 1'b0) // address low == TX register
begin begin
if (enable & w_en & ~char_seen) if (enable & w_en & ~char_seen)
@ -219,56 +240,34 @@ module vga(
char_seen <= 1; char_seen <= 1;
case(din) case(din)
8'h8D: 8'h8D: begin
begin
// handle carriage return // handle carriage return
h_cursor <= 0; h_cursor <= 0;
v_cursor <= v_cursor + 10'h28; v_cursor <= v_cursor + 'd1;
end end
8'h7F: 8'h7F: begin
// ignore the DDR call to the PIA // ignore the DDR call to the PIA
h_cursor <= 0; h_cursor <= 0;
end
default: default: begin
begin
vram_w_addr <= cursor; vram_w_addr <= cursor;
vram_din <= {~din[6], din[4:0]}; vram_din <= {~din[6], din[4:0]};
vram_w_en <= 1; vram_w_en <= 1;
h_cursor <= h_cursor + 1; h_cursor <= h_cursor + 1;
end end
endcase endcase
if (h_cursor == 39)
begin
h_cursor <= 0;
v_cursor <= v_cursor + 1;
end
if (v_cursor == 920)
begin
// force cursor to start at bottom of screen
// FIXME: now we need to scroll
v_cursor <= 920;
vram_start_addr <= vram_start_addr + 10'h28;
end
if (vram_start_addr >= 920)
vram_start_addr <= 0;
/*
if (v_cursor == 23)
begin
// here we need to add the scroll, probably by moving the
// HEAD of vram up one line
vram_start_addr <= vram_start_addr + 10'h28;
end
*/
end end
else if(~enable & ~w_en) else if(~enable & ~w_en)
char_seen <= 0; char_seen <= 0;
end end
else
begin
vram_w_addr <= {(vram_end_addr + 2), vram_h_addr};
vram_din <= 6'd32;
vram_w_en <= 1;
end
end end
end end

View File

@ -24,8 +24,8 @@
module vram( module vram(
input clk, // clock signal input clk, // clock signal
input [9:0] read_addr, // read address bus input [10:0] read_addr, // read address bus
input [9:0] write_addr, // write address bus input [10:0] write_addr, // write address bus
input r_en, // active high read enable strobe input r_en, // active high read enable strobe
input w_en, // active high write enable strobe input w_en, // active high write enable strobe
input [5:0] din, // 6-bit data bus (input) input [5:0] din, // 6-bit data bus (input)
@ -38,10 +38,10 @@ module vram(
parameter RAM_FILENAME = "../../roms/vga_vram.bin"; parameter RAM_FILENAME = "../../roms/vga_vram.bin";
`endif `endif
reg [5:0] ram_data[0:1023]; reg [5:0] ram_data[0:2047];
initial initial
$readmemb(RAM_FILENAME, ram_data, 0, 1023); $readmemb(RAM_FILENAME, ram_data, 0, 2047);
always @(posedge clk) always @(posedge clk)
begin begin