Menu Close

FPGA图像处理之三:VGA文字显示Verilog实现

上一篇我们介绍了使用fpga驱动vga显示一个简单的彩色条纹。这一篇我们看看文字如何显示输出。

文字显示原理。文字的显示,其实也是把文字当做图片,一个像素点一个像素点的来输出。如下图:

 

如果对正方形内字符的每一个像素点进行标记,哪些点应该显示白色,哪些点应该显示黑色,那么就可以在vga输出的时候,输出对应像素点的颜色值,也就能输出这个文字。

如何得到这个字的像素点颜色值呢?这儿我们可以使用一些工具,比如“PCtoLCD2002”这个软件。比如上面这个“字”,软件的字模格式设置如下:

 

可以得到以下字模:

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x07,0x00,0x00
0x00,0x03,0x80,0x00,0x00,0x01,0xC0,0x00,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8
0x1C,0x00,0x00,0x18,0x1C,0x00,0x00,0x18,0x1C,0x00,0x00,0x18,0x01,0xFF,0xFF,0x80
0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x00,0x00,0x1E,0x00,0x00,0x00,0x3C,0x00
0x00,0x00,0xF0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xC0,0x00,0x3F,0xFF,0xFF,0xFC
0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00
0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00
0x00,0x1B,0xC0,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00/*”字”,0*/

这是32X32的大小,点阵显得有点多。只要把这些值存到rom之中,当vga扫描到需要输出的位置时,从rom中取出对应的值给RGB输出即可。(如果要输出的字不多且固定,也可以把字模直接写在代码里)

参考代码入下:

module VGA_character(
input       wire                sysclk,         //系统时钟,也就是板子的时钟
input       wire                rst,

output      reg     [3:0]       R,              //输出的颜色值
output      reg     [3:0]       G,              //输出的颜色值
output      reg     [3:0]       B,              //输出的颜色值
output      wire                HS,             //水平同步信号
output      wire                VS              //垂直同步信号

);

//显示分辨率 640*480@60Hz
//时钟25.175M
localparam      HPOLA           =       0;  //水平同步信号极性
localparam      VPOLA           =       0;  //垂直同步信号极性

localparam      HTOTAL          =       800;//水平总像素数
localparam      HSYNCP          =       96; //水平同步信号像素数
localparam      HBACKP          =       40; //扫描后沿像素数
localparam      LBorder         =       8;  //左边框
localparam      HDISP           =       640;//显示区域
localparam      RBorder         =       8;  //右边框
localparam      HFRONTP         =       8;  //扫描前沿像素数


localparam      VTOTAL          =       525;//垂直总像素数
localparam      VSYNCP          =       2;  //垂直同步信号
localparam      VBACKP          =       25; //扫描后沿像素数
localparam      TBorder         =       8;  //顶边框
localparam      VDISP           =       480;//显示区域
localparam      BBorder         =       8;  //底边框
localparam      VFRONTP         =       2;  //扫描前沿像素数


wire                vgaclk;
wire                locked;
wire                vgarst;

assign  vgarst = ~locked;                   //locked为高表示时钟正常,此时不复位

//使用锁相环来输出指定时钟
pll pll_inst (
    .areset ( rst ),
    .inclk0 ( sysclk ),
    .c0 ( vgaclk ),
    .locked ( locked )
    );

//*****************************************************
//“字”字模
reg         [31:0]  character[0:31];        //存储字模
reg         [9:0]   location_x = 432;       //显示位置
reg         [9:0]   location_y = 243;       //显示位置

initial begin
character[00] = 32'h00000000;
character[01] = 32'h00000000;
character[02] = 32'h00020000;
character[03] = 32'h00070000;
character[04] = 32'h00038000;
character[05] = 32'h0001C000;
character[06] = 32'h1FFFFFF8;
character[07] = 32'h1FFFFFF8;
character[08] = 32'h1C000018;
character[09] = 32'h1C000018;
character[10] = 32'h1C000018;
character[11] = 32'h01FFFF80;
character[12] = 32'h01FFFF80;
character[13] = 32'h01FFFF80;
character[14] = 32'h00001E00;
character[15] = 32'h00003C00;
character[16] = 32'h0000F000;
character[17] = 32'h0001E000;
character[18] = 32'h0001C000;
character[19] = 32'h3FFFFFFC;
character[20] = 32'h3FFFFFFC;
character[21] = 32'h3FFFFFFC;
character[22] = 32'h0001C000;
character[23] = 32'h0001C000;
character[24] = 32'h0001C000;
character[25] = 32'h0001C000;
character[26] = 32'h0001C000;
character[27] = 32'h0001C000;
character[28] = 32'h001BC000;
character[29] = 32'h001F8000;
character[30] = 32'h000F8000;
character[31] = 32'h00000000;
end
//*****************************************************
   
reg         [9:0]   hcnt;                           //行计数
reg         [9:0]   vcnt;                           //场计数
   
   
//行计数
always@(posedge vgaclk or posedge vgarst) begin
if(vgarst)
    hcnt <= 0;
else
    if(hcnt == HTOTAL - 1)
        hcnt <= 0;
    else
        hcnt <= hcnt + 1;
end
   

//场计数
always@(posedge vgaclk or posedge vgarst) begin
if(vgarst)
    vcnt <= 0;
else
    if((hcnt == HTOTAL - 1) && (vcnt == VTOTAL - 1))
        vcnt <= 0;
    else if(hcnt == HTOTAL - 1)
        vcnt <= vcnt + 1;
    else
        vcnt <= vcnt;
end


//行同步信号输出
assign HS = (hcnt <= HSYNCP - 1)  ?  HPOLA : ~HPOLA;

//场同步信号输出
assign VS = (vcnt <= VSYNCP - 1)  ?  VPOLA : ~VPOLA;


//显示区域的判断
wire    h_disp;
assign h_disp = (hcnt > (HSYNCP + HBACKP + LBorder - 1) &&
                hcnt < (HSYNCP + HBACKP + LBorder + HDISP - 1)) ? 1'b1 : 1'b0;
               
wire    v_disp;
assign v_disp = (vcnt > (VSYNCP + VBACKP + TBorder - 1) &&
                vcnt < (VSYNCP + VBACKP + TBorder + VDISP- 1))  ? 1'b1 : 1'b0;


wire disp;
assign disp = h_disp && v_disp;



always@(posedge vgaclk or posedge vgarst) begin
if(vgarst)
    begin
        R <= 4'b0000;
        G <= 4'b0000;
        B <= 4'b0000;
    end
else
    if(disp)
        begin
            if((hcnt>=location_x && hcnt<location_x+32) && (vcnt >= location_y && vcnt<location_y+32))
                if(character[vcnt-location_y][hcnt-location_x])
                    begin
                        R <= 4'b1111;
                        G <= 4'b1111;
                        B <= 4'b1111;
                    end
                else
                    begin
                        R <= 4'b0000;
                        G <= 4'b0000;
                        B <= 4'b0000;
                    end
            else
                begin
                    R <= 4'b0000;
                    G <= 4'b0000;
                    B <= 4'b0000;
                end
        end
    else
        begin
            R <= 4'b0000;
            G <= 4'b0000;
            B <= 4'b0000;
        end
end

endmodule

 

效果如下:

 

附件下载

Posted in FPGA 教材教案, 教材与教案

发表回复

相关链接