前言
上一篇文章实现的驱动LCD显示一个移动的方块。本文要实现LCD显示图片和字符(汉字),图片直接初始化到RAM中,字符由取模软件取出。
一、图片的初始化与显示
图片转换成需要的RGB888
用Windows自带的画图打开图片,点击重新调整大小,256*256像素。
另存为你需要的格式 我用的RGB888所以选择24位位图,bmp格式。
打开图片转换的软件,加载图片,选择格式和输出的文件类型,我选的.coe类型。软件直接搜BMP2Mif就行。
RAM IP核初始化数据
单端口RAM
因为RGB888是24位,所以数据深度24,256*256等于65536。
点击Browse选择.coe文件来加载初始化数据。
点击OK完成配置之后直接例化就行,地址的输入看后面的代码。
二、字符显示
取模
设置字符的分辨率。
字模配置,点阵4是因为32/8=4。32是横向分辨率,除8是因为是16进制。
生成字模
生成的字模是一个字一个字的我手动把四个字对齐写在一起。
数据
00000000000000000000000000000000;
00000000000000000000000000000000;
0000400000400000000C000000104100;
000E700000700000000F200000186180;
003E630000600000000C180018386180;
07E061C000600000000C0E0004706180;
086060E000600000000C070003606180;
0060606000600000000C030001C06188;
0060606000600030000C0110019FFFFC;
00606010007FFFF8000C003803C06180;
00606030006000003FFFFFFC06406180;
3FFFFFF800600000000C300008406180;
0060200000600000000C300010606180;
0060200000600000000C304020600000;
0060204000400020000C30E000E40010;
006030E000FFFFF0000C30C000E3FFF8;
006130C000C000600008318001A20C30;
006E3180000000600018330001220C30;
00703300000000600018360003220C30;
07E033000000006000183C0006220C30;
3E60160000000060003038000C220C30;
38601C0000001860003030080823FFF0;
106018003FFFFC600060700810220C30;
00603C04000000600060F00820620C30;
00606E040000006000C3300800620C30;
00618704000000C00184300800620C30;
0063038C000000C00318300C00620C30;
006C01CC000041C006003FFC00C20C30;
07F000FC00003F800C001FF807C3FFF0;
01C0003C00000F001000000003820030;
00800006000006002000000001020000;
00000000000000000000000000000000;
三、显示图像字符代码
lcd_display.v
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/05/16 19:54:26
// Design Name:
// Module Name: lcd_display
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module lcd_display(
input vpg_clk,
input rst ,
input wire [12:0] cnt_h, //行计数器
input wire [12:0] cnt_v, //场计数器
output reg[23:0] RGB
);
parameter MAX = 65536 - 1; //256*256 - 1
reg w_ram_en ;
reg [15:0] r_addr ;
reg [23:0] din ;
wire [23:0] dout ;
//--------------------------vga时序参数--------------------
//场同步信号
parameter H_TOTAL = 525 - 1;
parameter H_SYNC = 41 - 1;
parameter H_START = 43 - 1;//数据开始结束计算值
parameter H_END = 523 - 1;
//行同步信号
parameter V_TOTAL = 286 - 1;
parameter V_SYNC = 10 - 1;
parameter V_START = 12 - 1;//数据开始结束计算值
parameter V_END = 284 - 1;
//场图像数据
parameter IMG_X = 256;//方块x
parameter IMG_Y = 256;//方块y
parameter STRING_X = 128;//字符x
parameter STRING_Y = 32;//字符y
parameter SCREEN_X = 480;//屏幕水平长度
parameter SCREEN_Y = 272;//屏幕垂直长度
reg [127:0] char[31:0]; //字符数组
reg [11:0] x; //方块左上角横坐标
reg [11:0] y; //方块左上角纵坐标
//-----------------------------------字符赋值-----------------------
always @(posedge vpg_clk) begin
char[0 ] <= 128'h00000000000000000000000000000000;
char[1 ] <= 128'h00000000000000000000000000000000;
char[2 ] <= 128'h0000400000400000000C000000104100;
char[3 ] <= 128'h000E700000700000000F200000186180;
char[4 ] <= 128'h003E630000600000000C180018386180;
char[5 ] <= 128'h07E061C000600000000C0E0004706180;
char[6 ] <= 128'h086060E000600000000C070003606180;
char[7 ] <= 128'h0060606000600000000C030001C06188;
char[8 ] <= 128'h0060606000600030000C0110019FFFFC;
char[9 ] <= 128'h00606010007FFFF8000C003803C06180;
char[10] <= 128'h00606030006000003FFFFFFC06406180;
char[11] <= 128'h3FFFFFF800600000000C300008406180;
char[12] <= 128'h0060200000600000000C300010606180;
char[13] <= 128'h0060200000600000000C304020600000;
char[14] <= 128'h0060204000400020000C30E000E40010;
char[15] <= 128'h006030E000FFFFF0000C30C000E3FFF8;
char[16] <= 128'h006130C000C000600008318001A20C30;
char[17] <= 128'h006E3180000000600018330001220C30;
char[18] <= 128'h00703300000000600018360003220C30;
char[19] <= 128'h07E033000000006000183C0006220C30;
char[20] <= 128'h3E60160000000060003038000C220C30;
char[21] <= 128'h38601C0000001860003030080823FFF0;
char[22] <= 128'h106018003FFFFC600060700810220C30;
char[23] <= 128'h00603C04000000600060F00820620C30;
char[24] <= 128'h00606E040000006000C3300800620C30;
char[25] <= 128'h00618704000000C00184300800620C30;
char[26] <= 128'h0063038C000000C00318300C00620C30;
char[27] <= 128'h006C01CC000041C006003FFC00C20C30;
char[28] <= 128'h07F000FC00003F800C001FF807C3FFF0;
char[29] <= 128'h01C0003C00000F001000000003820030;
char[30] <= 128'h00800006000006002000000001020000;
char[31] <= 128'h00000000000000000000000000000000;
end
//RGB
always @(posedge vpg_clk ) begin
if (!rst) begin
RGB <='d0;
end
else if(cnt_h >= H_START + x && cnt_h < H_START + IMG_X + x && cnt_v >= V_START + y && cnt_v < V_START +IMG_Y + y)begin
// RGB <= 24'hFFB6C1;//输出方块
RGB <= dout;
end
else if(cnt_h >= H_START + x + IMG_X && cnt_h < H_START + STRING_X + x + IMG_X && cnt_v >= V_START + y && cnt_v < V_START + STRING_Y + y)begin
if(char[cnt_v - V_START - y - 1'b1][STRING_X - 1'b1 - (cnt_h - H_START - x - IMG_X)])
RGB <= 24'hFFFF00; //显示字符黄色
else if(cnt_h[4:0] >= 'd20)
RGB <= 24'h00FF00;
else if(cnt_h[4:0] >= 'd10)
RGB <= 24'h0000FF;
else if(cnt_h[4:0] <= 'd10)
RGB <= 24'hFF0000;
end
else if (cnt_h >= H_START && cnt_h < H_END && cnt_v >=V_START && cnt_v < V_END && cnt_h[4:0] >= 'd20) begin
RGB <=24'h00FF00;//green
end
else if (cnt_h >=H_START && cnt_h <H_END && cnt_v >=V_START && cnt_v <V_END && (cnt_h[4:0]>='d10 && cnt_h[2:0]<'d20)) begin
RGB <=24'h0000FF;//bulue
end
else if (cnt_h >=H_START && cnt_h <H_END && cnt_v >=V_START && cnt_v <V_END && cnt_h[4:0]<'d10) begin
RGB <=24'hFF0000;//red
end
else begin
RGB <= 24'h000000;
end
end
//RAM的例化
blk_mem_gen_0 init (
.clka(vpg_clk), // input wire clka
.wea(w_ram_en), // input wire [0 : 0] wea
.addra(r_addr), // input wire [15 : 0] addra
.dina(din), // input wire [23 : 0] dina
.douta(dout) // output wire [23 : 0] doutb
);
always @(posedge vpg_clk or negedge rst)
begin
if(!rst)
begin
w_ram_en <= 'd0;
r_addr <= 'd0;
din <= 'd0;
x <= 'd0; //x y位显示图片左上角坐标
y <= 'd0;
end
//因为RAM读数据有延时 把地址提前两个周期
//如果不延后图像可能会上下平移
else if(cnt_h >= H_START + x - 2&& cnt_h < H_START + IMG_X + x - 2&& cnt_v >= V_START + y && cnt_v < V_START +IMG_Y + y )
begin
if(r_addr == MAX)
r_addr <= 'd0;
else
r_addr <= r_addr + 1'b1;
end
else
r_addr <= r_addr;
end
endmodule
总结
图片和字符正常显示,下次实现串口发送数据到RAM里在显示出来。