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