FPGA Player

好记性不如烂笔头

导航

FPGA之VGA控制

 

 

 VGA的接口很少,一个行,一个场,三个RGB信号口,不同的分辨率对应不同的时钟频率,

这里以800*600的50M的时钟为例,它的行同步脉冲长度为120,行同步后沿脉冲计数为

64,行可视区脉冲为800,行同步前沿脉冲为56,也就是说,用50M的时钟来驱动,行信号

先给120个时钟的低电平,然后是64个时钟的高平,用来指示到了后沿,再来800个时钟

的高电平信号表示到了行有效区,最后再来56个时钟的高电平表示,行同步前沿。如此循环

进行行扫描,。

场同步长度为6个时钟脉宽长度,场后沿为23个时钟脉宽长度,场可视区为600个脉宽长度,

场前沿为37个时钟脉宽长度。666行为一场。

有些东西不管你多么熟悉,总感觉过上一段时间就给忘掉了,有倒是好记性不如烂笔头

在这里做下记录。

以下是自己写的一个VGA的控制接口,只要给RGB信号赋值就能显示不同的颜色,要怎样显示

就看去怎样处理接口了。

由于想从SDRAM中读出数据来画出曲线,一时也不知道该怎么去显示,因为VGA显示是从上往下

一行一行的扫描,而数据要显示要用我们正常的坐标,便和同学聊了一下,他给提议,在每一行中

都把数据扫描一次,这才有了下面的第二个段程序。和大家一起聊聊总会有所收获的。

//---------------------------------------------------------------------
 //
 //-----------------------------------------------------------------------
 `define tend_h_syn   ( Clk_H_cnt == (11'd119) )//行同步计数脉冲个数
 `define tend_h_pre         ( Clk_H_cnt == (11'd1039) ) //行同步前沿计数脉冲个数
 `define tend_h_back   ( Clk_H_cnt == (11'd183) )//行同步后沿脉冲计数个数
 `define tend_h_visible   ( Clk_H_cnt == (11'd983) )//行可视区脉冲个数
 `define tend_v_syn   ( Clk_V_cnt == (11'd5) ) //场同步计数脉冲个数
 `define tend_v_pre    ( Clk_V_cnt == (11'd665) ) //场同步前沿计数脉冲个数
 `define tend_v_visible  ( Clk_V_cnt == (11'd628) )//场可视区脉冲个数
 `define tend_v_back   ( Clk_V_cnt == (11'd28) )//场同步后沿脉冲计数个数
 //----------------------------------------------------------------
 //行同步状态
 //-----------------------------------------------------------------
  `define H_SYN    2'd0//行同步
 `define H_PRE         2'd1 //行同步前沿
 `define H_BACK   2'd2 //行同步后沿
 `define H_VISIBLE   2'd3//行可视区
 //-----------------------------------------------------------------
 //场同步状态
 //-----------------------------------------------------------------
  `define V_SYN    2'd0 //场同步
 `define V_PRE    2'd1 //场同步
 `define V_VISIBLE   2'd2//场可视区
 `define V_BACK   2'd3 //场同步后沿
 
module VGA_Ctrl(Clk,Rst_n,Hsync,Col_Ctrl,
   Vsync,Vga_r,Vga_g,Vga_b,H_Coord,
   V_Coord,Data_Valid
   );
input Clk;//输入50M时钟
input Rst_n;// reset signal
input [7:0] Col_Ctrl;
output [2:0] Vga_r;
output [2:0] Vga_g;
output [1:0] Vga_b;
output Hsync;//行同步信号
output Vsync;//场同步信号
output [9:0] H_Coord;//行坐标
output [9:0] V_Coord;//列坐标
output Data_Valid;//有效显示区指示信号

reg[1:0] H_State;
reg[1:0] V_State;
assign {Vga_r,Vga_g,Vga_b} = Data_Valid ? Col_Ctrl : 8'hzz;

如果在无效区就不显示RGB就不发送数据。
//****************************************************************
//计数脉冲控制信号
//*****************************************************************
reg [10 : 0] Clk_H_cnt;
reg [10 : 0] Clk_V_cnt;
always@( posedge Clk or negedge Rst_n) //行扫描计数器
if(!Rst_n) Clk_H_cnt <= 11'd0;
else if(Clk_H_cnt == 11'd1039) Clk_H_cnt <= 11'd0;
else Clk_H_cnt <= Clk_H_cnt + 1'b1;

wire V_Clk = (Clk_H_cnt ==11'd1039);

always@( posedge V_Clk or negedge Rst_n) //场扫描计数器
if(!Rst_n)  Clk_V_cnt <= 11'd0;
else if(Clk_V_cnt == 11'd665) Clk_V_cnt <= 11'd0;
else  Clk_V_cnt <= Clk_V_cnt + 1'b1;

//*****************************************************************
//行扫描状态机
//***************************************************************

always@( posedge Clk or negedge Rst_n) begin
 if(!Rst_n) begin
   H_State <= `H_SYN;
   end
 else begin
  case( H_State )
   `H_SYN : begin   
     H_State <= `tend_h_syn ? `H_BACK:`H_SYN;
    end
   `H_BACK : begin     
     H_State <= `tend_h_back ? `H_VISIBLE : `H_BACK;
    end
   `H_VISIBLE : begin
     H_State <= `tend_h_visible ? `H_PRE : `H_VISIBLE;
    end
   `H_PRE : begin
     H_State <= `tend_h_pre ? `H_SYN : `H_PRE;
    end
   default :;
   endcase
   end
end
//*********************************************************************
//场扫描状态机
//************************************************************************
always@( posedge V_Clk  or negedge Rst_n) begin
 if(!Rst_n) begin
  V_State <= `V_SYN;

  end
 else
  case(V_State)
    `V_SYN : begin
     V_State <= `tend_v_syn  ? `V_BACK: `V_SYN;
    end
    `V_BACK : begin
     V_State <= `tend_v_back ? `V_VISIBLE : `V_BACK;
    end
   `V_VISIBLE : begin
     V_State <= `tend_v_visible ? `V_PRE : `V_VISIBLE;
    end
   `V_PRE : begin
     V_State <= `tend_v_pre ? `V_SYN : `V_PRE;
    end
   default:;
  endcase

end
//******************************************************************
//行场有效区计数扫描 接 口
//*****************************************************************
reg[9:0] H_Cnt;
reg[9:0] V_Cnt;
always@( posedge Clk or negedge Rst_n) begin
if(!Rst_n) H_Cnt <= 10'd0;
else if(H_Cnt == 10'd799) H_Cnt <= 10'd0;
else  if(H_State == `H_VISIBLE)
 H_Cnt <= H_Cnt + 1'b1;
else H_Cnt <= 10'd0;
 end
always@( posedge V_Clk or negedge Rst_n) begin
if(!Rst_n) V_Cnt <= 10'd0;
else if( V_Cnt == 10'd599) V_Cnt <= 10'd0;
else if( V_State == `V_VISIBLE)
 V_Cnt <= V_Cnt + 1'b1;
else V_Cnt <= 10'd0;
 end
 reg [7:0]test_r;
/*always@(posedge Clk or negedge Rst_n)
begin
if(!Rst_n) test_r <= 8'd0;
else if((H_Cnt >= 20 && H_Cnt <= 100 ) &&(V_Cnt >= 20 && V_Cnt <= 100))
 test_r <= 8'hf0;
 else test_r <= 8'hzz;
end*/
assign Hsync = ~(H_State == `H_SYN);
assign Vsync = ~(V_State == `V_SYN);
assign H_Coord = H_Cnt;
assign V_Coord = V_Cnt;
assign Data_Valid = ((H_State == `H_VISIBLE) && (V_State == `V_VISIBLE));
endmodule

*************************************************************************

以下为一个VGA的RGB产生一段程序

*************************************************************************

module VGA_Data(H_Coord,V_Coord,Clk,Rst_n,Col_Ctrl);

input Clk;
input Rst_n;
input[9 : 0] H_Coord;//读出的行
input[9 : 0] V_Coord;//读出的场
output[7 : 0] Col_Ctrl;

reg[7 : 0] Col_Ctrl_R;
wire[9 : 0] X_Coord = (H_Coord - 200) ;//转换成相应的X坐标
wire[9 : 0] Y_Coord = (500 - V_Coord) ;//转换成相应的Y坐标

always@(posedge Clk ) begin
if((X_Coord > 10'd0) && (X_Coord <= 10'd500) && Y_Coord == 10'd0 ||
 (Y_Coord >= 10'd0 && Y_Coord <= 10'd400 && X_Coord == 10'd0))
  Col_Ctrl_R <= 8'h00;
else if(Y_Coord == Cnt && X_Coord >= 0 && X_Coord <=500)
 Col_Ctrl_R <= 8'h00;
else Col_Ctrl_R <= 8'hff;

end
reg [7 : 0] Cnt;
always@(posedge Clk or negedge Rst_n) begin
if(!Rst_n) Cnt <= 8'd0;
else if(X_Coord >= 0 && X_Coord <256)Cnt <= Cnt + 1'b1;
else Cnt <= 8'd0;
end
assign Col_Ctrl = Col_Ctrl_R;
endmodule

posted on 2012-09-24 17:22  中国的孩子  阅读(1619)  评论(0编辑  收藏  举报