//
// File: vga_textgrid22x.v
// Date: 03-Dec-05
// Author: I. Chuang <ichuang@mit.edu>
//
// VGA display of characters in a grid.
//
// Display both 12x24 and 2x pixel 12x24 characters on 640x480 display
// using one shared global font rom.
//
// The display is assumed to be 640x480, such that for 12x24
// characters, we get a 53x20 display.
`include "font1224_rom.v"
module vga_textgrid22x (
input wire vclock, // system synchronous clock
input wire pix_clk, // video pixel clock
input wire [9:0] hcount, // current hpos (0..639)
input wire [9:0] vcount, // current vpos (0..479)
output wire [2:0] pixel, // pixel output
output wire [5:0] cx, // next char pos
output wire [5:0] cy, // next char pos
output wire adv_cclk, // early character clock
input wire [10:0] charrgb, // char+rgb to display at pos
output wire [5:0] cx2, // next 2x char pos
output wire [5:0] cy2, // next 2x char pos
output wire adv_cclk2, // early 2x char clock
input wire [10:0] charrgb2 // 2x char+rgb
);
// global font rom
wire [11:0] font_byte; // each word has 12 bits
wire [12:0] font_addr;
font1224_rom fr(font_addr, vclock, font_byte); // font rom
// normal size (1x) character display
wire [2:0] pix1;
wire [12:0] font_addr1;
vga_textgrid2x vtg1(vclock, pix_clk, hcount, vcount, pix1, cx, cy,
adv_cclk, charrgb[7:0], charrgb[10:8],
font_addr1, font_byte);
// big (2x) character display
wire [2:0] pix2;
wire [12:0] font_addr2;
vga_textgrid2x vtg2(vclock, pix_clk, hcount, vcount, pix2, cx2, cy2,
adv_cclk2, charrgb2[7:0], charrgb2[10:8],
font_addr2, font_byte);
defparam vtg2.MAG = 1;
// share font rom by or'ing addresses together
assign font_addr = font_addr1 | font_addr2;
// generate combined pixel by OR'ing
assign pixel = pix1 | pix2;
endmodule // vga_textgrid22x
/////////////////////////////////////////////////////////////////////////////
module vga_textgrid2x (
input wire vclock, // system synchronous clock
input wire pix_clk, // video pixel clock
input wire [9:0] hcount, // current hpos (0..639)
input wire [9:0] vcount, // current vpos (0..479)
output reg [2:0] pixel, // pixel output
output reg [5:0] cx, // next char pos
output reg [5:0] cy, // next char pos
output reg adv_cclk, // early character clock
input wire [7:0] char, // char to display at pos
input wire [2:0] rgb, // RGB to output for char
output wire [12:0] font_addr, // font rom address
input wire [11:0] font_byte // font rom read data
);
parameter MAG = 0; // 1 for 2X chars
parameter HMAX = 12*(MAG+1); // # x-pixels in char (24 for 2x chars)
parameter VMAX = 24*(MAG+1); // # y-pixels in char (48 for 2x chars)
parameter CXMAX = 26*(2-MAG); // # of chars in row (26 for 2X chars)
// compute character clock (cclk) and h,v position within character
reg [4:0] h; // 0 .. 23 or 0 .. 11
reg [5:0] v; // 0 .. 47 or 0 .. 23
reg [5:0] vnext; // in-char v position for _next_ char
// wire hzero = (hcount>=679 | h==0);
wire hzero = (hcount==0 | h==0);
wire vzero = (vcount==0 | v==(VMAX-1));
wire hhalf = (h==3); // early char clk (external world)
reg old_hzero, old_hhalf;
reg cclk; // actual character clk (when vid char changes)
wire indisp = (hcount<624) & (vcount<480);
always @(posedge vclock)
begin
cclk <= hzero & ~old_hzero & indisp; // one pulse each time h==0
old_hzero <= hzero;
adv_cclk <= hhalf & ~old_hhalf & indisp; // get char index in advance
old_hhalf <= hhalf;
if (~pix_clk)
begin
h <= hzero ? (HMAX-1) : h-1;
v <= (~(hcount==0)) ? v : (vzero ? 0 : v+1);
vnext <= (hcount==679) ? (vzero ? 0 : vnext+1) : vnext;
end
end
// compute next character position based on current hpos, vpos
wire eol = (hcount>=((CXMAX-1)*HMAX));
always @(posedge vclock)
if (cclk)
begin
cx <= eol ? 0 : cx+1;
cy <= (cx==(CXMAX-1) & v==(VMAX-1)) ?
( (vcount>=456) ? 0 : cy+1 ) : cy;
end
// look up raster row from font rom: 24 words per character
// if char=0 then font_addr = 0 (so we can share the rom)
wire reverse = char[7];
assign font_addr = (|{char}) ? char[6:0]*24
+ vnext[4+MAG:0+MAG]-24 : 13'b0;
// assign [11:0] font_byte; // each word has 12 bits
// font1224_rom fr(font_addr, vclock, font_byte); // font rom
// latch output of font rom when character clock (cclk) is high
// and generate character pixel
reg [11:0] fb_latched;
reg nochar;
reg rev_latched;
reg [2:0] rgb_latched;
always @(posedge vclock)
if (cclk)
begin
fb_latched <= font_byte;
nochar <= (char==0);
rev_latched <= reverse;
rgb_latched <= rgb;
end
// wire [2:0] cpixel = ( (nochar|~indisp) ? 3'b0
// : (fb_latched[h[3+MAG:0+MAG]] ^ reverse) ? rgb
// : 3'b0 );
reg [2:0] cpixel;
always @(posedge vclock)
if (pix_clk)
cpixel <= ( (nochar|~indisp) ? 3'b0
: (fb_latched[h[3+MAG:0+MAG]] ^ rev_latched) ? rgb_latched
: 3'b0 );
// latch in pixel, and don't change except on pix_clk
always @(posedge vclock)
pixel <= (pix_clk & indisp) ? cpixel : pixel;
endmodule
////////////////////////////////////////
// vga_dispstr: Display a single text string, given as a parameter
// to the module.
module vga_dispstr(
input wire clk,
input wire cclk,
input wire [5:0] x,
input wire [5:0] y,
input wire [5:0] cx,
input wire [5:0] cy,
output reg [10:0] charrgb
);
parameter TEXT = "TEST";
parameter LEN = 4;
parameter RGB = 3'b111;
reg [LEN*8-1:0] sr;
wire dispflag = (cy==y) & (cx>=x) & (cx<(x+LEN));
// reg [7:0] q;
always @(posedge clk)
if (cclk)
begin
// char <= dispflag ? "T" : 8'b0;
charrgb <= dispflag ? {RGB,sr[LEN*8-1:LEN*8-8]} : 8'b0;
sr <= dispflag ? {sr[LEN*8-9:0],8'b0} : TEXT;
// char <= dispflag ? q : 8'b0;
// q <= dispflag ? q+1 : "0";
end
endmodule // vga_dispstr
////////////////////////////////////////
// hex2ascii
module hex2ascii(input wire [3:0] hex, output wire [7:0] ascii);
assign ascii = (hex<4'd10) ? (8'd48 + {4'b0,hex})
: (8'd65 + {4'b0,hex} - 4'd10);
endmodule // hex2ascii
////////////////////////////////////////
// vga_disphex: Display a string of hex digits
module vga_disphex
#(
parameter ND = 4,
parameter RGB = 3'b111
)(
input wire clk,
input wire cclk,
input wire [5:0] x,
input wire [5:0] y,
input wire [5:0] cx,
input wire [5:0] cy,
input wire [ND*4-1:0] data,
input wire [ND-1:0] rev,
output reg [10:0] charrgb
);
reg [ND*4-1+4:0] sr; // extra 4 bits on left handles when ND=1
reg [ND:0] rev_sr;
wire dispflag = (cy==y) & (cx>=x) & (cx<(x+ND));
wire [7:0] ascii;
hex2ascii h2a(sr[ND*4-1+4:ND*4],ascii);
always @(posedge clk)
if (cclk)
begin
charrgb <= dispflag ? {RGB,rev_sr[ND],ascii[6:0]} : 8'b0;
sr <= (dispflag & (ND>1)) ? {sr[ND*4-1:0],4'b0} : {data,4'b0};
rev_sr <= (dispflag & (ND>1)) ? {rev_sr[ND-1:0],1'b0} : {rev,1'b0};
end
endmodule // vga_disphex
This page: |
Created: | Sun Dec 11 09:59:58 2005 |
|
From: |
./vga_textgrid22x.v |