1
0
mirror of synced 2026-01-11 23:53:00 +00:00
2007-01-02 16:24:48 +00:00

225 lines
5.2 KiB
Verilog

// vga.v
// simple b&w 640x480 terminal with VGA output
`include "vgacore.v"
`include "crt.v"
`include "video_ram.v"
`include "char_rom.v"
`include "ps2.v"
`include "scancode.v"
module vga (reset_n, clock,
pixel, blank_n,
hsync, vsync,
ps2_clk,
ps2_data,
led_data);
input reset_n;
input clock;
output [8:0] pixel;
output blank_n;
output hsync;
output vsync;
input ps2_clk, ps2_data;
output [7:0] led_data;
wire startVGA;
wire resetVGA;
wire done;
wire clearing;
wire [9:0] hloc; // horiz timing, including sync & blanking
wire [9:0] vloc;
wire hblank; // set when in non-visable part of frame
wire vblank;
wire [6:0] hpos; // horiz position 0..79, during visable frame
wire [8:0] vpos; // vert line 0..480, during visable frame
reg [8:0] pixelData;
wire [11:0] vpos_times_80;
wire pixelclk;
reg [2:0] pclk;
wire charclk;
reg charload;
reg [7:0] pixel_hold;
reg crtclk;
wire ram_wclk;
wire ram_wslot;
wire [11:0] ram_addr_write, ram_addr_video, ram_addr_mux;
wire [7:0] ram_data, ram_data_out, rom_data_out;
wire ram_we_n;
wire [9:0] rom_addr;
reg [7:0] rom_addr_char;
char_rom char_rom(.addr(rom_addr),
.data(rom_data_out));
video_ram video_ram(.addr(ram_addr_mux),
.data_out(ram_data_out), .clk_r(charload/*charclk*/),
.data_in(ram_data), .clk_w(ram_wclk), .we_n(ram_we_n));
vgacore vgacore(.reset_n(reset_n), .clock(clock),
.hsync(hsync),
.vsync(vsync),
.hblank(hblank),
.vblank(vblank),
.enable(blank_n),
.hloc(hloc),
.vloc(vloc));
wire kb_rdy;
wire kb_bsy;
wire kb_release;
wire [7:0] kb_scancode;
wire [7:0] kb_ascii;
wire kb_ascii_rdy;
reg [7:0] crt_data;
reg insert_crt_data;
ps2 ps2(.clk(clock),
.rst_n(reset_n),
.ps2_clk(ps2_clk),
.ps2_data(ps2_data),
.scancode(kb_scancode),
.parity(),
.busy(kb_bsy),
.rdy(kb_rdy),
.error()
);
scancode_convert scancode_convert(.clock(clock),
.reset_n(reset_n),
.scancode(kb_scancode),
.ascii(kb_ascii),
.key_up(kb_release),
.strobe_in(kb_rdy),
.strobe_out(kb_ascii_rdy));
// debug - led output
assign led_data = { kb_ascii[6], kb_rdy, kb_ascii[5:0] };
always @(posedge clock or negedge reset_n)
if (~reset_n)
begin
crt_data <= 0;
insert_crt_data <= 0;
end
else
begin
if (kb_ascii_rdy)
begin
crt_data <= kb_ascii;
if (~kb_release)
insert_crt_data <= 1;
end
else
insert_crt_data <= 0;
end
// assign insert_crt_data = kb_ascii_rdy && ~kb_release;
wire [6:0] cursorh;
wire [5:0] cursorv;
wire cursor_match;
crt crt(.reset_n(reset_n),
.clock(crtclk),
.insert(insert_crt_data),
.done(done),
.data(crt_data),
.clearing(clearing),
.ram_addr(ram_addr_write),
.ram_data(ram_data),
.ram_we_n(ram_we_n),
.ram_wclk(ram_wclk),
.ram_wslot(ram_wslot),
.cursorh(cursorh),
.cursorv(cursorv));
// generate video ram address from (vpos/8) * 80 + hpos
assign vpos_times_80 = {vpos[8:3], 6'b0} + {2'b00, vpos[8:3], 4'b0};
assign ram_addr_video = vpos_times_80 + {5'b00000, hpos};
assign ram_addr_mux = ram_we_n ? ram_addr_video : ram_addr_write;
assign rom_addr = {rom_addr_char[6:0], vpos[2:0]};
assign cursor_match = (cursorh == hpos && cursorv == vpos[8:3]) ? 1 : 0;
// clock divider by 8 - assume 8x8 font
always @(posedge pixelclk or negedge reset_n)
if (~reset_n)
pclk = 3'b111;
else
pclk = (hblank || clearing) ? 3'b111 : pclk + 1;
assign charclk = ~pclk[2];
// crtclk runs at half speed
always @(posedge pixelclk or negedge reset_n)
if (~reset_n)
crtclk = 1'b0;
else
crtclk = ~crtclk;
// ram "writ slot" sits at 2nd half of charclk cycle
assign ram_wslot = ~pclk[1] & pclk[2];
// generate hpos, vpos (from hloc, vloc of vgacore)
assign hpos = hloc[9:3];
assign vpos = vloc[8:0];
// latch ram output to form rom address
always @(posedge charclk)
rom_addr_char <= ram_data_out;
/*
//temp-debug
//always @(posedge charclk) rom_addr_char <= {1'b0, hpos};
wire [7:0] hack;
assign hack = {1'b0,hpos} + 8'h30;
//assign hack = {1'b0,hpos};
always @(posedge charclk) rom_addr_char <= hack;
*/
// inhibit shift and load instead during last slot
always @(negedge pixelclk or negedge reset_n)
if (~reset_n)
charload = 0;
else
charload = pclk == 3'b111 ? 1 : 0;
// shift pixel data, one bit at a time (or load when at last slot)
always @(posedge pixelclk)
pixel_hold <= charload ?
(cursor_match ? 8'hff : rom_data_out) :
{ pixel_hold[6:0], 1'b0 };
// clock pixel data on pixel clock
always @(posedge pixelclk)
pixelData <= pixel_hold[7] ? 9'h1ff : 9'h000;
assign pixel = (hblank || vblank) ? 9'h000 : pixelData;
// reset & start VGA
assign startVGA = 1;
assign resetVGA = reset_n & startVGA;
// Provide 25MHz pixel clock
assign pixelclk = clock;
endmodule