基于fpga显示图片(VGA)

以640*480@60Hz分辨率显示(意思最大可以显示640*480大小的图片),首先通过fpga的VGA显示图像包括四个部分:分频模块,vga驱动模块,显示模块,顶层模块。

1.分频模块,用的是xilinx spartan_6 的板子,输出晶振50M;640*480@60Hz的时钟是25MHz(800*525*60)。就简单计数翻转分频,效果如图:

2.VGA驱动模块

显示顺序:从屏幕上到下,从左到右。

时序图:行时序分为5个进程(a.行地址复位b.行地址复位完成 准备录入数据 c.数据显示d.准备复位行地址)


场时序分为四个进程:(a.场地址复位b.场地址复位完成 准备录入数据 c.数据显示d.准备复位场地址)

!!!!对于驱动部分检查,首先看时序图:一个场信号的翻转包含多个行信号(一场中扫描多行)


`timescale 1ns / 1ps
`define H_FRONT 11'd16
`define H_SYNC  11'd96
`define H_BACK  11'd48
`define H_DIP   11'd640
`define H_TOTAL 11'd800


`define V_FRONT 11'd10
`define V_SYNC  11'd2
`define V_BACK 11'd33
`define V_DIP   11'd480
`define V_TOTAL 11'd525
//////////////////////////////////////////////////////////////////////////////////
//640*480@60hz
//
//////////////////////////////////////////////////////////////////////////////////
module driver(
clk,
reset,
lcd_hs,
lcd_vs,
lcd_en,
lcd_xpos,
lcd_ypos
);
input clk,reset;//VGA_clk
output lcd_hs,lcd_vs,lcd_en;
output[10:0] lcd_xpos,lcd_ypos;
wire lcd_request;
reg[11:0] h_cnt;//行扫描单位计数
reg[11:0] v_cnt;//列扫描单位计数




////////////////////////////////
//行扫描单位计数
always@(posedge clk or negedge reset)
begin
if(!reset)begin h_cnt<=11'd0; end
else 
  begin
if(h_cnt<`H_TOTAL-1'b1) begin h_cnt<=h_cnt+1'b1;end
else h_cnt<=11'd0;
end
end
assign lcd_hs=(h_cnt<=`H_SYNC-1'b1)?1'b0:1'b1; //行同步信号
////////////////////////////////
//列扫描单位计数
always@(posedge clk or negedge reset)
begin
if(!reset)begin v_cnt<=11'd0; end
else if(h_cnt==`H_TOTAL-1'b1)//横扫完
  begin
if(v_cnt<`V_TOTAL-1'b1)begin v_cnt<=v_cnt+1'b1;end
else v_cnt<=11'd0;
end
end
assign lcd_vs=(v_cnt<=`V_SYNC-1'b1)?1'b0:1'b1; //场同步信号                                              
////////////////////////////////
//数据使能信号
assign lcd_en=(h_cnt >= `H_SYNC + `H_BACK  && h_cnt < `H_SYNC + `H_BACK + `H_DIP) &&
              (v_cnt >= `V_SYNC + `V_BACK  && v_cnt < `V_SYNC + `V_BACK + `V_DIP) 
              ? 1'b1 : 1'b0;
////////////////////////////////
//外部数据请求
assign  lcd_request = (h_cnt >= `H_SYNC + `H_BACK - 1'b1 && h_cnt < `H_SYNC + `H_BACK + `H_DIP - 1'b1) &&
                      (v_cnt >= `V_SYNC + `V_BACK && v_cnt < `V_SYNC + `V_BACK + `V_DIP) 
                       ? 1'b1 : 1'b0;
//lcd xpos & ypos
assign  lcd_xpos    =   lcd_request ? (h_cnt - (`H_SYNC + `H_BACK - 1'b1)) : 11'd0;////////????
assign  lcd_ypos    =   lcd_request ? (v_cnt - (`V_SYNC + `V_BACK)) : 11'd0;///////????/???????


endmodule

3.显示部分(该板子VGA565)

1>对于静态图片的显示,将一张图片通过img2lcd软件转成一个个8bit数据,存入ip rom/ram中,通过输入地址调用其中数据。

2>对于动态数据的接收,可以通过串口输入,存入一个ram/rom再调用。(写数据的clk用串口输入数据完成标志的上升沿来驱动,读数据的clk直接用VGA扫描时钟)


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
module displayimg(
input clk,
input clkin,//ram写入时钟
input start_flag,
input reset,
input lcd_en,
input[10:0] lcd_xpos,
input[10:0] lcd_ypos,
output reg[15:0] lcd_data,
input[7:0]     data_out
 );
reg[4:0] rgb_r;
reg[5:0] rgb_g;
reg[4:0] rgb_b;
reg[15:0] counter_in;
reg[15:0] counter_out;
wire[7:0] data_get;
wire[14:0] displyarea;
reg start_enter_flag;
vga_uart_ram u8(
  .clka(clkin),
  .wea(1),
  .addra(counter_in),
  .dina(data_out),
  .clkb(clk),
  .addrb(counter_out),
  .doutb(data_get)
);


always@(posedge clkin or negedge reset)//接收数据完成进来
begin
if(!reset) begin counter_in <= 'd0;end
else if(counter_in < 'd30000)//200*150的图片
     begin 
counter_in <= counter_in + 1'b1;
end
else counter_in <= 'd0;//
end


//区域
assign displyarea=lcd_xpos>=11'd10&&lcd_xpos<11'd210&&lcd_ypos>=11'd10&&lcd_ypos<11'd160;


//rgb
always@(posedge clk or negedge reset)
begin
if(!reset) begin
rgb_r <= 'd0;
rgb_g <= 'd0;
rgb_b <= 'd0;
end
else begin
rgb_r[4:0] <= data_get[7:3];
rgb_g[5:0] <= data_get[7:2];
rgb_b[4:0] <= data_get[7:3];
end
end


always@(posedge clk or negedge reset)
begin
if(!reset)
counter_out <= 'd0;
else if(lcd_ypos > 'd160)
counter_out <= 'd0;
else if(displyarea == 1'b1)
counter_out <= counter_out + 1'b1;
end

always@(posedge clk or negedge reset)
begin
if(!reset)
lcd_data <= 'd0;
else if(displyarea == 1'b1)
lcd_data <= {rgb_r,rgb_g,rgb_b};
else lcd_data<='d0;
end


endmodule

4.top




猜你喜欢

转载自blog.csdn.net/qq_35705332/article/details/80017016