【学习笔记】基于RS232实现Vga图像显示

        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个常见错误进行逐步排查。这一点也比较重要,比无头苍蝇强很多。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值