VGA 显示器显示图像,并不是直接让图像在显示器上显示出来,而是采用扫描的方式,将构成图像的像素点,在行同步信号和场同步信号的同步下,按照从上到下、由左到右的顺序扫描到显示屏上,行扫描周期 * 场扫描周期 * 刷新频率 = 时钟频率。
工程任务:用matlab生成串口图像传输文件,然后用pc通过串口将图像数据传入fpga设备,并在设备中间被七彩条包围的图像信息。
实现原理:先将传入信息写入ram存储,然后利用vga图像显示协议完成图像显示。
总体框图
vga_pic的verilog代码:
module vga_pic(
input wire clk_vga ,
input wire rst_n_sys ,
input wire [9:0]pix_x ,
input wire [9:0]pix_y ,
input wire clk_sys ,
input wire [7:0]po_data,
input wire po_flag ,
output reg [7:0]pix_data
);
reg [11:0]wr_addr,rd_addr ;
wire [7:0]q_pic ;
parameter lift =10'd270 ,
right =10'd319 ,
top =10'd190 ,
bottom=10'd239 ;
parameter a=8'd0 ,
b=8'd28 ,
c=8'd56 ,
aa=8'd84 ,
bb=8'd112 ,
cc=8'd140 ,
aaa=8'd168 ,
bbb=8'd196 ,
ccc=8'd224 ;
always@(posedge clk_vga or negedge rst_n_sys)
if (~rst_n_sys)
rd_addr<=12'h0 ;
else if(rd_addr==12'd2499)
rd_addr<=12'h0 ;
else if(pix_x<=10'd317 && pix_x>=10'd268 && pix_y>=10'd188 && pix_y<=10'd237 )
rd_addr<=rd_addr+1'b1 ;
else
rd_addr<=rd_addr ;
always@(posedge clk_sys or negedge rst_n_sys)
if(~rst_n_sys)
wr_addr<=1'b0 ;
else if(po_flag==1'b1 && wr_addr==12'd2499)
wr_addr<=1'b0 ;
else if(po_flag==1'b1)
wr_addr<=wr_addr+1'b1 ;
else
wr_addr<=wr_addr ;
always@(posedge clk_vga or negedge rst_n_sys)
if(~rst_n_sys)
pix_data<=8'hff;
else if (pix_y==10'h3ff || pix_x==10'h3ff)
pix_data<=8'hff ;
else if(pix_x<=10'd319 && pix_x>=10'd270 && pix_y>=10'd190 && pix_y<=10'd239)
pix_data<=q_pic ;
else if (pix_x<=10'd63)
pix_data<=a ;
else if (pix_x<=10'd127)
pix_data<=b ;
else if (pix_x<=10'd191)
pix_data<=c ;
else if (pix_x<=10'd255)
pix_data<=aa ;
else if (pix_x<=10'd319)
pix_data<=bb ;
else if (pix_x<=10'd447)
pix_data<=cc ;
else if (pix_x<=10'd511)
pix_data<=aaa ;
else if (pix_x<=10'd511)
pix_data<=bbb ;
else if (pix_x<=10'd639)
pix_data<=ccc ;
else
pix_data<=8'hff ;
vga_ram vga_ram_inst (
.data ( po_data ),
.inclock ( clk_sys ),
.outclock ( clk_vga ),
.rdaddress ( rd_addr ),
.wraddress ( wr_addr ),
.wren ( po_flag ),
.q ( q_pic )
);
endmodule
vga_pic的verilog代码:
module vga_ctrl(
input wire clk_vga ,
input wire rst_n_sys ,
input wire [7:0]pix_data ,
output reg [7:0]rgb ,
output wire [9:0]pix_x ,
output wire [9:0]pix_y ,
output reg hsync ,
output reg vsync
);
reg [9:0]cnt_hsync ;
reg [9:0]cnt_vsync ;
reg rgb_vaild ;
always@(posedge clk_vga or negedge rst_n_sys )
if(~rst_n_sys)
cnt_hsync<=10'd0 ;
else if(cnt_hsync==10'd799)
cnt_hsync<=10'd0 ;
else
cnt_hsync<=1'b1+cnt_hsync ;
always@(posedge clk_vga or negedge rst_n_sys )
if(~rst_n_sys)
cnt_vsync<=10'd0 ;
else if(cnt_vsync==10'd524 && cnt_hsync==10'd799)
cnt_vsync<=10'd0 ;
else if(cnt_hsync==10'd799)
cnt_vsync<=cnt_vsync+1'b1 ;
else
cnt_vsync<=cnt_vsync ;
always@(posedge clk_vga or negedge rst_n_sys )
if(~rst_n_sys)
rgb_vaild<=1'b0;
else if(cnt_hsync>=10'd143 && cnt_hsync<10'd783 && cnt_vsync>=10'd35 && cnt_vsync<=10'd514)
rgb_vaild<=1'b1 ;
else
rgb_vaild<=1'b0;
assign pix_x=(cnt_hsync>=10'd143 && cnt_hsync<10'd783 && cnt_vsync>=10'd35 && cnt_vsync<=10'd514)?cnt_hsync-10'd143:10'hff ;
assign pix_y=(cnt_hsync>=10'd143 && cnt_hsync<10'd783 && cnt_vsync>=10'd35 && cnt_vsync<=10'd514)?cnt_vsync-10'd35 :10'hff ;
always@(posedge clk_vga or negedge rst_n_sys )
if(~rst_n_sys)
hsync<=1'b0 ;
else if (cnt_hsync<=10'd95 )
hsync<=1'b1 ;
else
hsync<=1'b0 ;
always@(posedge clk_vga or negedge rst_n_sys )
if(~rst_n_sys)
vsync<=1'b0 ;
else if (cnt_hsync<=10'd783 && cnt_vsync <=10'd1 )
vsync<=1'b1 ;
else
vsync<=1'b0 ;
always@(posedge clk_vga or negedge rst_n_sys )
if(~rst_n_sys)
rgb<=8'H0 ;
else if(rgb_vaild==1'b1)
rgb<=pix_data ;
else
rgb<=8'Hff ;
endmodule
配置ram如下:
用matlab生成RS232传输的图像数据,matlab代码:
clc;
clear all;
RGB=imread('LOGO_2.jpg');%图像文件名
[ROW,COL,D]=size(RGB);
R=RGB(:,:,1);
G=RGB(:,:,2);
B=RGB(:,:,3);
imgdata=zeros(1,ROW*COL);
for r=1:ROW
for c=1:COL
imgdata((r-1)*COL+c)=bitand(R(r,c),224)+bitshift(bitand(G(r,c),224),-3)+bitshift(bitand(B(r,c),196),-6);
end
end
fidc=fopen('VGA_RS232_logo_2.txt','w+') ;
for i=1:ROW*COL
fprintf(fidc,'%02x ',imgdata(i));
end
fclose(fidc);
学习过程中常犯的错误有:
1、同步错误
VGA显示需要水平和垂直同步信号来确定图像的位置和大小。如果同步信号不正确,就会导致图像位置不正确或缩放不正确。解决这个问题的方法是检查同步信号是否正确,并根据需要调整代码。
2、时序错误
VGA显示需要按照特定的时序来生成图像,如果时序出错,就会导致显示不正常。例如,如果时钟频率不正确,就会导致图像闪烁或失真。解决这个问题的方法是检查时钟频率是否正确,并根据需要调整代码
3、时钟和数据同步错误
在VGA显示中,时钟和数据之间需要同步。如果同步不正确,就会导致数据丢失或错误。解决这个问题的方法是检查同步信号是否正确,并根据需要调整代码
4、内存错误
VGA显示需要从内存中读取图像数据。如果内存访问不正确,就会导致图像无法显示或显示不正常。解决这个问题的方法是检查内存访问是否正确,并根据需要调整代码。
个人学习总结与收获:
在进行学习过程中,需要先在物理层上有一定的理解,而波形的绘画以及Verilog的代码书写要求我们一定要在协议层上完全掌握。如不完全掌握,一旦出错将难以排查。如果发生错误可以按照上面4个常见错误进行逐步排查。这一点也比较重要,比无头苍蝇强很多。