【FPGA】基於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中,通過輸入地址調用其中數據。

img2lcd的使用教程

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];//5bit
rgb_g[5:0] <= data_get[7:2];//6bit
rgb_b[4:0] <= data_get[7:3];//5bit
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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章