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),
.irq_n (1'b1),
.nmi_n (1'b1),
.ready (cpu_clken),
.pc_monitor (pc_monitor)
.ready (cpu_clken)
//.pc_monitor (pc_monitor)
);
//////////////////////////////////////////////////////////////////////////
@ -112,6 +112,8 @@ module apple1(
wire basic_cs = (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF
wire rom_cs = (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
wire mode_cs = (ab[15:12] == 4'b1100); // 0xC000
//////////////////////////////////////////////////////////////////////////
// RAM and ROM
@ -182,10 +184,12 @@ module apple1(
);
// VGA Display interface
reg [1:0] vga_mode;
vga my_vga(
.clk25(clk25),
.enable(vga_cs & cpu_clken),
.rst(rst),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
@ -194,9 +198,20 @@ module apple1(
.address(ab[0]),
.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
@ -206,5 +221,6 @@ module apple1(
basic_cs ? basic_dout :
uart_cs ? uart_dout :
ps2kb_cs ? ps2_dout :
mode_cs ? vga_mode :
8'hFF;
endmodule

View File

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

View File

@ -9,7 +9,9 @@ module vga(
output vga_blu, // blue VGA signal
input address, // address bus
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;
// hardware cursor registers
wire [9:0] cursor;
wire [10:0] cursor;
reg [5:0] h_cursor;
reg [9:0] v_cursor;
reg [4:0] v_cursor;
// vram indexing registers
reg [9:0] vram_start_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
wire [9:0] vram_r_addr;
reg [9:0] vram_w_addr;
wire [10:0] vram_r_addr;
reg [10:0] vram_w_addr;
reg vram_w_en;
reg [5:0] vram_din;
wire [5:0] vram_dout;
@ -115,6 +118,7 @@ module vga(
font_rom my_font_rom(
.clk(clk25),
.mode(mode),
.character(font_char),
.pixel(font_pixel),
.line(font_line),
@ -139,23 +143,23 @@ module vga(
always @(posedge clk25 or posedge rst) begin
if (rst) begin
vram_h_addr <= 0;
vram_v_addr <= 0;
vram_h_addr <= 'd0;
vram_v_addr <= 'd0;
end else begin
// start the pipeline for reading vram and font details
// 3 pixel clock cycles early
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
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
if (~h_active)
vram_h_addr <= 0;
vram_h_addr <= 'd0;
if (~v_active)
vram_v_addr <= 0;
vram_v_addr <= vram_start_addr;
end
end
@ -181,8 +185,9 @@ module vga(
// Pipeline and VGA signals
// vram to font rom to display pipeline assignments
assign cursor = ({4'd0, h_cursor} + v_cursor);
assign vram_r_addr = (vram_start_addr + {4'd0, vram_h_addr} + vram_v_addr);
assign cursor = {v_cursor, h_cursor};
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_pixel = h_dot + 1; // offset by one to get pixel into right cycle,
// font output one pixel clk behind
@ -195,6 +200,8 @@ module vga(
assign vga_h_sync = (h_cnt < h_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
@ -203,14 +210,28 @@ module vga(
if (rst)
begin
h_cursor <= 6'd0;
v_cursor <= 10'd0;
char_seen <= 0;
vram_start_addr <= 0;
v_cursor <= 5'd0;
char_seen <= 'b0;
vram_start_addr <= 5'd0;
vram_end_addr <= 5'd23;
end
else
begin
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
begin
if (enable & w_en & ~char_seen)
@ -219,56 +240,34 @@ module vga(
char_seen <= 1;
case(din)
8'h8D:
begin
8'h8D: begin
// handle carriage return
h_cursor <= 0;
v_cursor <= v_cursor + 10'h28;
v_cursor <= v_cursor + 'd1;
end
8'h7F:
8'h7F: begin
// ignore the DDR call to the PIA
h_cursor <= 0;
end
default:
begin
default: begin
vram_w_addr <= cursor;
vram_din <= {~din[6], din[4:0]};
vram_w_en <= 1;
h_cursor <= h_cursor + 1;
end
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
else if(~enable & ~w_en)
char_seen <= 0;
end
else
begin
vram_w_addr <= {(vram_end_addr + 2), vram_h_addr};
vram_din <= 6'd32;
vram_w_en <= 1;
end
end
end

View File

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