MacPlus_MiSTer/rtl/videoTimer.v

82 lines
2.4 KiB
Verilog

// generates 1024x768 (actually 512x768) @ 60Hz, from a 32.5MHz input clock
module videoTimer(
input clk,
input clk_en,
input [1:0] busCycle,
input vid_alt,
output [21:0] videoAddr,
output reg hsync,
output reg vsync,
output _hblank,
output _vblank,
output loadPixels
);
// timing data from http://tinyvga.com/vga-timing/1024x768@60Hz
localparam kVisibleWidth = 128, // (1024/2)/4
kTotalWidth = 168, // (1344/2)/4
kVisibleHeightStart = 42,
kVisibleHeightEnd = 725,
kTotalHeight = 806,
kHsyncStart = 131, // (1048/2)/4
kHsyncEnd = 147, // (1184/2)/4-1
kVsyncStart = 771,
kVsyncEnd = 776,
kPixelLatency = 1; // number of clk8 cycles from xpos==0 to when pixel data actually exits the video shift register
// use screen buffer address for a 4MB RAM layout-- it will wrap
// around to the proper address for 1MB, 512K, and 128K layouts
localparam kScreenBufferBase = 22'h3FA700;
localparam startAddr = kVisibleHeightStart/2 * kVisibleWidth/2;
reg [7:0] xpos;
reg [9:0] ypos;
wire endline = (xpos == kTotalWidth-1);
always @(posedge clk) begin
if (clk_en) begin
if (endline)
xpos <= 0;
else if (xpos == 0 && busCycle != 0)
// hold xpos at 0, until xpos and busCycle are in phase
xpos <= 0;
else
xpos <= xpos + 1'b1;
end
end
always @(posedge clk) begin
if (clk_en) begin
if (endline) begin
if (ypos == kTotalHeight-1)
ypos <= 0;
else
ypos <= ypos + 1'b1;
end
end
end
always @(posedge clk) begin
if (clk_en) begin
hsync <= ~(xpos >= kHsyncStart+kPixelLatency && xpos <= kHsyncEnd+kPixelLatency);
vsync <= ~(ypos >= kVsyncStart && ypos <= kVsyncEnd);
end
end
assign _hblank = ~(xpos >= kVisibleWidth+kPixelLatency);
assign _vblank = ~(ypos < kVisibleHeightStart || ypos > kVisibleHeightEnd);
// The 0,0 address actually starts below kScreenBufferBase, because the Mac screen buffer is
// not displayed beginning at 0,0, but at 0,kVisibleHeightStart.
// kVisibleHeightStart divided by 2 to account for vertical pixel doubling.
// kVisibleWidth divided by 2 because it's the 8MHz visible width times 4 to get actual number of pixels,
// then divided by 8 bits per byte
assign videoAddr = kScreenBufferBase - (vid_alt ? 16'h0 : 16'h8000) -
startAddr[21:0] +
{ ypos[9:1], xpos[6:2], 1'b0 };
assign loadPixels = _vblank == 1'b1 && _hblank == 1'b1 && busCycle == 2'b00;
endmodule