一.VGA
VGA的全称是Video Graphics Array,即视频图形阵列,是一个使用模拟信号进行视频传
输的标准。早期的CRT显示器由于设计制造上的原因,只能接收模拟信号输入,因此计算机内
部的显卡负责进行数模转换,而VGA接口就是显卡上输出模拟信号的接口。如今液晶显示器虽
然可以直接接收数字信号,但是为了兼容显卡上的VGA接口,也大都支持VGA标准。
二、VGA显示彩色条纹
1.IP核时钟分频
因为时钟频率 = 行帧长 × 列帧长 * 刷新率
所以640 ×480 60HZ对应时钟频率= 800 ×525 × 60 = 25.2M
用25MHZ时钟
2.顶层代码:
module vga_top(
input wire clk,
input wire rst_n,
output wire hsync,
output wire vsync,
output wire [7:0] vga_r,
output wire [7:0] vga_g,
output wire [7:0] vga_b,
output wire vga_blk,
output wire vga_clk
);
wire [23:0] data_dis;
wire [10:0] h_addr;
wire [10:0] v_addr;
data_gen data_gen(
.vga_clk (vga_clk),
.rst_n (rst_n),
.h_addr (h_addr),
.v_addr (v_addr),
.data_dis (data_dis)
);
vga_ctrl vga_ctrl(
.clk (clk),
.rst_n (rst_n),
.data_dis (data_dis),
.h_addr (h_addr),//数据有效显示区域行地址
.v_addr (v_addr),//数据有效显示区域场地址
.hsync (hsync),
.vsync (vsync),
.vga_r (vga_r),
.vga_g (vga_g),
.vga_b (vga_b),
.vga_blk (vga_blk),
.vga_clk (vga_clk)
);
endmodule
2.vga_ctrl
`define vga_640_480
`include "vga_param.v"
module vga_ctrl(
input wire clk ,
input wire rst_n ,
input wire [23:0] data_dis ,
output reg [10:0] h_addr ,//数据有效显示区域行地址
output reg [10:0] v_addr ,//数据有效显示区域场地址
output reg hsync ,
output reg vsync ,
output reg [7:0] vga_r ,
output reg [7:0] vga_g ,
output reg [7:0] vga_b ,
output reg vga_blk ,
output wire vga_clk
);
parameter H_SYNC_STA = 1,
H_SYNC_STO = `H_Sync_Time,
H_DATA_STA = `H_Sync_Time + `H_Back_Porch + `H_Left_Border,
H_DATA_STO = `H_Sync_Time + `H_Back_Porch + `H_Left_Border + `H_Data_Time;
parameter V_SYNC_STA = 1,
V_SYNC_STO = `V_Sync_Time,
V_DATA_STA = `V_Sync_Time + `V_Back_Porch + `V_Top_Border,
V_DATA_STO = `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time;
reg [11:0] cnt_h_addr;//行地址计数器
wire add_h_addr ;
wire end_h_addr ;
reg [11:0] cnt_v_addr;//列地址计数器
wire add_v_addr ;
wire end_v_addr ;
wire clk_25 ;
clk_25 clk_25_inst (
.areset ( ~rst_n ),
.inclk0 ( clk ),
.c0 ( clk_25 )
);
assign vga_clk = ~clk_25;
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
cnt_h_addr <= 12'd0;
end
else if(add_h_addr)begin
if(end_h_addr)begin
cnt_h_addr <= 12'd0;
end
else begin
cnt_h_addr <= cnt_h_addr + 12'd1;
end
end
else begin
cnt_h_addr <= 12'd0;
end
end
assign add_h_addr = 1'b1;
assign end_h_addr = add_h_addr && cnt_h_addr >= `H_Total_Time - 1;
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
cnt_v_addr <= 12'd0;
end
else if(add_v_addr)begin
if(end_v_addr)begin
cnt_v_addr <= 12'd0;
end
else begin
cnt_v_addr <= cnt_v_addr + 12'd1;
end
end
else begin
cnt_v_addr <= cnt_v_addr;
end
end
assign add_v_addr = end_h_addr;
assign end_v_addr = add_v_addr && cnt_v_addr >= `V_Total_Time - 1;
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
hsync <= 1'b1;
end
else if(cnt_h_addr == H_SYNC_STA- 1)begin
hsync <= 1'b0;
end
else if(cnt_h_addr == H_SYNC_STO - 1)begin
hsync <= 1'b1;
end
else begin
hsync <= hsync;
end
end
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
vsync <= 1'b1;
end
else if(cnt_v_addr == V_SYNC_STA - 1)begin
vsync <= 1'b0;
end
else if(cnt_v_addr == V_SYNC_STO - 1)begin
vsync <= 1'b1;
end
else begin
vsync <= vsync;
end
end
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
h_addr <= 11'd0;
end
else if((cnt_h_addr >= H_DATA_STA - 1) && (cnt_h_addr <= H_DATA_STO -1) )begin
h_addr <= cnt_h_addr - H_DATA_STA + 1;
end
else begin
h_addr <= 11'd0;
end
end
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
v_addr <= 11'd0;
end
else if((cnt_v_addr >= V_DATA_STA - 1) && (cnt_v_addr <= V_DATA_STO -1) )begin
v_addr <= cnt_v_addr - V_DATA_STA + 1;
end
else begin
v_addr <= 11'd0;
end
end
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
vga_r <= 8'b0;
vga_g <= 8'b0;
vga_b <= 8'b0;
vga_blk <= 1'b0;
end
else if((cnt_h_addr >= H_DATA_STA - 1) && (cnt_h_addr <= H_DATA_STO -1) &&
(cnt_v_addr >= V_DATA_STA - 1) && (cnt_v_addr <= V_DATA_STO -1) )begin
vga_r <= data_dis[23:16];
vga_g <= data_dis[15:8];
vga_b <= data_dis[7:0];
vga_blk <= 1'b1;
end
else begin
vga_r <= 8'b0;
vga_g <= 8'b0;
vga_b <= 8'b0;
vga_blk <= 1'b0;
end
end
endmodule
3.data_gen
module data_gen(
input wire vga_clk,
input wire rst_n,
input wire [10:0] h_addr,
input wire [10:0] v_addr,
output reg [23:0] data_dis
);
parameter BLACK = 24'h000000,
RED = 24'hFF0000,
GREEN = 24'h00FF00,
BLUE = 24'h0000FF,
YELLOW = 24'hFFFF00,
SKY_BULE = 24'h00FFFF,
PURPLE = 24'hFF00FF,
GRAY = 24'hC0C0C0,
WHITE = 24'hFFFFFF;
//色条
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n)begin
data_dis <= WHITE;
end
else begin
case(h_addr)
0 : data_dis <= BLACK ;
80 : data_dis <= RED ;
160: data_dis <= GREEN ;
240: data_dis <= BLUE ;
320: data_dis <= YELLOW ;
400: data_dis <= SKY_BULE ;
480: data_dis <= PURPLE ;
560: data_dis <= GRAY;
default: data_dis <= data_dis;
endcase
end
end
endmodule
结果:
三、VGA显示文字
1.
2.导出位图
3.打开刚才保存的
4.导出生成字模
5.只需要更改data_gen的代码
module data_gen(
input wire vga_clk,
input wire rst_n,
input wire [10:0] h_addr,
input wire [10:0] v_addr,
output reg [23:0] data_dis
);
parameter BLACK = 24'h000000,
RED = 24'hFF0000,
GREEN = 24'h00FF00,
BLUE = 24'h0000FF,
YELLOW = 24'hFFFF00,
SKY_BULE = 24'h00FFFF,
PURPLE = 24'hFF00FF,
GRAY = 24'hC0C0C0,
WHITE = 24'hFFFFFF;
//文字
parameter //点阵字模:每一行char_lineXX是显示的一行,共272列
char_line00= 302'h000000001C00000000000000000000000000000000000000000000000000000000000000, //第1行
char_line01=302'h0001FFF01F0077001C1FFFC0000000000000000000000000000000000000000000000000, //第2行
char_line02=302'h0001FFF0070077001C1FFFC0000000000000000000000000000000000000000000000000, //第3行
char_line03=302'h7FF1FFF0070077C01F1FFFC0000000000000000000000000000000000000000000000000, //第4行
char_line04=302'h7FF1C070000071C007000700000000000000000000000000000000000000000000000000, //第5行
char_line05=302'h7FF1C071FFF1F1F007001F0007C01FF001C01FC007C07FFC07C007C007C0007001C07FFC, //第6行
char_line06=302'h7071C071FFF1C07007001C0007C01FF001C01FC007C07FFC07C007C007C0007001C07FFC, //第7行
char_line07=302'h7071C071FFF7DC71C7707C701FF07FFC1FC07FF01FF07FFC1FF01FF01FF001F01FC07FFC, //第8行
char_line08=302'h7071C07001C71C71C07070701C70701C1FC070701C70701C1C701C701C7001F01FC0701C, //第9行
char_line09=302'h7071FFF007C71C71F07777707C70701C1FC0707C7C7C707C7C7C7C707C7C01F01FC0707C, //第10行
char_line0a=302'h7071FFF007001C00707777707000701C01C0701C701C0070701C7000701C01F001C00070, //第11行
char_line0b=302'h7FF1FFF007007F007077FF707000701C01C0701C701C0070701C7000701C07F001C00070, //第12行
char_line0c=302'h7FF1C070070077007071FC707000001C01C0701C701C0070701C7000701C077001C00070, //第13行
char_line0d=302'h7FF1C0701F71F7C07771FC7077F0007C01C0701C701C01F0701C77F0701C1F7001C001F0, //第14行
char_line0e=302'h7071C0701F71C1C00770707077F0007001C0701C701C01C0701C77F0701C1C7001C001C0, //第15行
char_line0f=302'h7071C0707FF7C1FC0771FC707FFC07F001C0707C701C01C0701C7FFC701C1C7001C001C0, //第16行
char_line10=302'h7071C07077C7007C0771FC707C1C07C001C0707C701C01C0701C7C1C701C1C7001C001C0, //第17行
char_line11=302'h7071FFF1F7F7FFFC1F77FF707C1C07F001C07FFC701C07C0701C7C1C701C7C7001C007C0, //第18行
char_line12=302'h7071FFF1C771FFC01C777770701C007001C01FDC701C0700701C701C701C707001C00700, //第19行
char_line13=302'h7FF1FFF1C771FFC1FC7F77F0701C007C01C01FDC701C0700701C701C701C7FFF01C00700, //第20行
char_line14=302'h7FF1C0700771C1C1FC7C71F0701C001C01C0001C701C0700701C701C701C7FFF01C00700, //第21行
char_line15=302'h7FF1C0700771C1C1FC7F71F0701C701C01C0001C701C0700701C701C701C7FFF01C00700, //第22行
char_line16=302'h7071C0700701C1C01C777070701C701C01C0001C701C0700701C701C701C007001C00700, //第23行
char_line17=302'h7077C0700701C1C01C77F0707C1C701C01C01C7C7C7C07007C7C7C1C7C7C007001C00700, //第24行
char_line18=302'h000700700701C1C01C71C0701C1C701C01C01C701C7007001C701C1C1C70007001C00700, //第25行
char_line19=302'h000700700701C1C01C71C0701FFC7FFC1FFC1FF01FF007001FF01FFC1FF007FF1FFC0700, //第26行
char_line1a=302'h000700700701C1C01C70007007F01FF01FFC07C007C0070007C007F007C007FF1FFC0700, //第27行
char_line1b=302'h001F07700701FFC01C7FFFF007F01FF01FFC07C007C0070007C007F007C007FF1FFC0700, //第28行
char_line1c=302'h001C07700701FFC01C7FFFF0000000000000000000000000000000000000000000000000, //第29行
char_line1d=302'h007C07F00701FFC01C7FFFF0000000000000000000000000000000000000000000000000, //第30行
char_line1e=302'h007001C00701C1C000000070000000000000000000000000000000000000000000000000, //第31行
char_line1f=302'h007001C00701C1C000000070000000000000000000000000000000000000000000000000; //第32行
reg[8:0] char_bit;
always@(posedge vga_clk)
if(h_addr==10'd144)
char_bit<=9'd302; //当显示到144像素时准备开始输出图像数据
else if(h_addr>10'd144&&h_addr<10'd446) //左边距屏幕144像素到416像素时 416=144+272(图像宽度)
char_bit<=char_bit-1'b1; //倒着输出图像信息
always@(posedge vga_clk)
if(h_addr>10'd144&&h_addr<10'd446) //X控制图像的横向显示边界:左边距屏幕左边144像素 右边界距屏幕左边界416像素
begin case(v_addr) //Y控制图像的纵向显示边界:从距离屏幕顶部160像素开始显示第一行数据
10'd160:
if(char_line00[char_bit])
data_dis<=RED; //如果该行有数据 则颜色为红色
else
data_dis<=BLACK; //否则为黑色
10'd162:
if(char_line01[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd163:
if(char_line02[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd164:
if(char_line03[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd165:
if(char_line04[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd166:
if(char_line05[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd167:
if(char_line06[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd168:
if(char_line07[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd169:
if(char_line08[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd170:
if(char_line09[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd171:
if(char_line0a[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd172:
if(char_line0b[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd173:
if(char_line0c[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd174:
if(char_line0d[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd175:
if(char_line0e[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd176:
if(char_line0f[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd177:
if(char_line10[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd178:
if(char_line11[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd179:
if(char_line12[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd180:
if(char_line13[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd181:
if(char_line14[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd182:
if(char_line15[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd183:
if(char_line16[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd184:
if(char_line17[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd185:
if(char_line18[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd186:
if(char_line19[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd187:
if(char_line1a[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd188:
if(char_line1b[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd189:
if(char_line1c[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd190:
if(char_line1d[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd191:
if(char_line1e[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
10'd192:
if(char_line1f[char_bit])
data_dis<=RED;
else
data_dis<=BLACK;
default:data_dis<=BLACK; //默认颜色黑色
endcase
end
else data_dis<=BLACK; //否则黑色
endmodule
结果:
四、VGA显示图片
1.转换图片为mif格式,因为用的EP4CE115F29C7的板子VGA_R、VGA_G、VGA_B用的[7:0]所以选择格式888
2.导入ROM核
设置位宽度为24位,大小为图片大小128×78 = 9984
3.导入刚才的mif文件
4.修改data_gen代码
module data_gen(
input wire vga_clk,
input wire rst_n,
input wire [10:0] h_addr,
input wire [10:0] v_addr,
output reg [23:0] data_dis
);
parameter BLACK = 24'h000000,
RED = 24'hFF0000,
GREEN = 24'h00FF00,
BLUE = 24'h0000FF,
YELLOW = 24'hFFFF00,
SKY_BULE = 24'h00FFFF,
PURPLE = 24'hFF00FF,
GRAY = 24'hC0C0C0,
WHITE = 24'hFFFFFF;
wire flag_begin_h ; // 图片显示行
wire flag_begin_v ; // 图片显示列
parameter height = 78; // 图片高度
parameter width = 128; // 图片宽度
reg [ 13:0 ] rom_address ; // ROM地址
wire [ 23:0 ] rom_data ;
//ROM地址计数器
always@(posedge vga_clk or negedge rst_n)begin
if(!rst_n )begin
data_dis = WHITE;
end
else if(flag_enable_out2)begin
data_dis = rom_data;
end
else begin
data_dis = WHITE;
end
end
always @( posedge vga_clk or negedge rst_n ) begin
if ( !rst_n ) begin
rom_address <= 0;
end
else if ( rom_address == 9983 ) begin //计数满清零
rom_address <= 0;
end
else if ( flag_enable_out2 ) begin //在有效区域内+1
rom_address <= rom_address + 1;
end
else begin //无效区域保持
rom_address <= rom_address;
end
end
assign flag_begin_h = h_addr > ( ( 640 - width ) / 2 ) && h_addr < ( ( 640 - width ) / 2 ) + width + 1;
assign flag_begin_v = v_addr > ( ( 480 - height )/2 ) && v_addr <( ( 480 - height )/2 ) + height + 1;
assign flag_enable_out2 = flag_begin_h && flag_begin_v;
rom3 rom3_inst (
.address ( rom_address ),
.clock ( vga_clk ),
.q ( rom_data )
);
endmodule
结果:
参考:
https://blog.csdn.net/qq_47281915/article/details/125134764?spm=1001.2014.3001.5502
文章评论