verilog-apple-one/rtl/vga/vga.v
2018-01-27 00:21:05 +11:00

145 lines
3.8 KiB
Verilog

module vga(
input clk,
input [6:0] in,
input in_stb,
output vga_h_sync,
output vga_v_sync,
output reg vga_red,
output reg vga_grn,
output reg vga_blu
);
reg [5:0] v_ram[0:959] /* synthesis syn_ramstyle = "block_ram" */;
reg [4:0] c_rom[0:447] /* synthesis syn_ramstyle = "block_ram" */;
initial begin
$readmemb("../roms/vga_vram.bin", v_ram, 0, 959);
$readmemb("../roms/vga_font.bin", c_rom, 0, 447);
end
// generate 25MHz pixel clock enable
reg vga_cnt;
wire vga_clk_en;
always @(posedge clk)
begin
vga_cnt <= vga_cnt + 1;
end
assign vga_clk_en = vga_cnt;
// video structure constants
parameter hpixels = 800; // horizontal pixels per line
parameter vlines = 521; // vertical lines per frame
parameter hpulse = 96; // hsync pulse length
parameter vpulse = 2; // vsync pulse length
parameter hbp = 144; // end of horizontal back porch
parameter hfp = 784; // beginning of horizontal front porch
parameter vbp = 31; // end of vertical back porch
parameter vfp = 511; // beginning of vertical front porch
// registers for storing the horizontal & vertical counters
reg [9:0] hc;
reg [9:0] vc;
reg [5:0] hpos;
reg [4:0] vpos;
reg [3:0] hdot;
reg [4:0] vdot;
always @(posedge clk)
begin
if (vga_clk_en)
begin
if (hc < hpixels - 1)
begin
hc <= hc + 1;
// count 16 pixels, so 640px / 16 = 40 characters
if (vga_h_act)
begin
hdot <= hdot + 1;
if (hdot == 4'hF)
begin
hdot <= 0;
hpos <= hpos + 1;
end
end
end
else
begin
// reset horizontal counters
hc <= 0;
hdot <= 0;
hpos <= 0;
if (vc < vlines - 1)
begin
vc <= vc + 1;
// count 20 rows, so 480px / 20 = 24 rows
if (vga_v_act)
begin
vdot <= vdot + 1;
if (vdot == 5'd19)
begin
vdot <= 0;
vpos <= vpos + 1;
end
end
end
else
begin
vc <= 0;
vdot <= 0;
vpos <= 0;
end
end
end
end
assign vga_h_act = (hc >= hbp && hc < hfp);
assign vga_v_act = (vc >= vbp && vc < vfp);
assign vga_h_sync = (hc < hpulse) ? 0 : 1;
assign vga_v_sync = (vc < vpulse) ? 0 : 1;
// assign vblank = (vc >= vbp && vc < vfp) ? 0:1;
always @(posedge clk)
begin
if (~(vga_h_act && vga_v_act))
begin
// outside display area
vga_red = 0;
end else begin
// inside display area
if (vdot[4:1] == 0 || vdot[4:1] == 1 || vdot[4:1] == 9 || hdot[3:1] == 0 || hdot[3:1] == 6 || hdot[3:1] == 7)
vga_red = 0;
else
vga_red = c_rom[(v_ram[hpos + (vpos * 40)] * 7) + (vdot[4:1] - 2)][5 - hdot[3:1]];
end
vga_grn = vga_red;
vga_blu = vga_red;
end
reg [5:0] cur_pos;
reg stb;
always @(posedge clk)
begin
if (in_stb & ~stb)
begin
v_ram[cur_pos] <= {~in[6], in[4:0]};
stb <= 1;
cur_pos <= cur_pos + 1;
end
if (~in_stb & stb)
begin
stb <= 0;
end
end
endmodule