VGA系列文章目录:
(1)VGA成像原理与简单实现
(2)VGA显示板级验证
(3)VGA显示-多分辨率输入
(4)串口发送+RAM+VGA传图
前言
本篇文章记录使用ACX720开发板实现VGA板级验证,将8中颜色通过VGA接口输出到指定位置。
提示:以下是本篇文章正文内容,下面案例可供参考
一、板级验证功能设计
我们设计一个测试工程,该工程中我们测试上述提到的8种颜色,通过颜色的位置,不但能确定是否能够正确输出指定颜色的图像,还能间接确定是否能够精确指定像素位置。 因此,我们对屏幕进行划分,将屏幕划分成4行2列总共八个像素阵列,每个阵列分别显示一种颜色。据此,我们可以首先定义每种顔色的具体数据编码,然后再定义每个像素阵列的基本显示颜色,这里首先使用 parameter定义每种顔色的具体数据编码。
代码如下(示例):
1.设置颜色参数
parameter
BLACK = 24'h000000, //黑色
BLUE = 24'h0000FF, //蓝色
RED = 24'hFF0000, //红色
PURPPLE = 24'hFF00FF, //紫色
GREEN = 24'h00FF00, //绿色
CYAN = 24'h00FFFF, //青色
YELLOW = 24'hFFFF00, //黄色
WHITE = 24'hFFFFFF; //白色
parameter
R0_C0 = BLACK , //第0行0列像素块
R0_C1 = BLUE , //第0行1列像素块
R1_C0 = RED , //第1行0列像素块
R1_C1 = PURPPLE , //第1行1列像素块
R2_C0 = GREEN , //第2行0列像素块
R2_C1 = CYAN , //第2行1列像素块
R3_C0 = YELLOW , //第3行0列像素块
R3_C1 = WHITE ; //第3行1列像素块
2.确定位置区间
代码如下(示例):
wire C0_act,C1_act;
assign C0_act = (H_count >= 0) && (H_count < 320);//正在扫描第0列
assign C1_act = (H_count >= 320 ) && (H_count < 640); //正在扫描第1列
wire R0_act,R1_act,R2_act,R3_act;
assign R0_act = (V_count >= 0) && (V_count < 120); //正在扫描第0行
assign R1_act = (V_count >= 120) && (V_count < 240); //正在扫描第1行
assign R2_act = (V_count >= 240) && (V_count < 360); //正在扫描第2行
assign R3_act = (V_count >= 360) && (V_count < 480); //正在扫描第3行
wire R0_C0_ACT,R0_C1_ACT,R1_C0_ACT,R1_C1_ACT,R2_C0_ACT,R2_C1_ACT,R3_C0_ACT,R3_C1_ACT;
assign R0_C0_ACT = R0_act & C0_act; //第0行0列像素块处于被扫描中标志信号
assign R0_C1_ACT = R0_act & C1_act; //第0行1列像素块处于被扫描中标志信号
assign R1_C0_ACT = R1_act & C0_act; //第1行0列像素块处于被扫描中标志信号
assign R1_C1_ACT = R1_act & C1_act; //第1行1列像素块处于被扫描中标志信号
assign R2_C0_ACT = R2_act & C0_act; //第2行0列像素块处于被扫描中标志信号
assign R2_C1_ACT = R2_act & C1_act; //第2行1列像素块处于被扫描中标志信号
assign R3_C0_ACT = R3_act & C0_act; //第3行0列像素块处于被扫描中标志信号
assign R3_C1_ACT = R3_act & C1_act; //第3行1列像素块处于被扫描中标志信号
3.确定VGA输出颜色
代码如下(示例):
always @ (*)
case ({R0_C0_ACT,R0_C1_ACT,R1_C0_ACT,R1_C1_ACT,
R2_C0_ACT,R2_C1_ACT,R3_C0_ACT,R3_C1_ACT})
8'b1000_0000 : disp_data =R3_C1;
8'b0100_0000 : disp_data =R0_C1;
8'b0010_0000 : disp_data =R1_C0;
8'b0001_0000 : disp_data =R1_C1;
8'b0000_1000 : disp_data =R2_C0;
8'b0000_0100 : disp_data =R2_C1;
8'b0000_0010 : disp_data =R3_C0;
8'b0000_0001 : disp_data =R0_C0;
default : disp_data =R3_C1;
endcase
二、V_count、H_count产生
根据上面的描述需要首先产生H_count、V_count来确定扫描位置。于是对上篇文章《VGA成像原理与简单实现》代码稍作修改,产生H_count、V_count。
always @ (posedge clk)
VGA_BLK <= Data_request;
always @ (posedge clk)
H_count <= (Data_request) ?(H_cnt-Hdata_begin):0;
always @ (posedge clk)
V_count <= (Data_request) ?(V_cnt-Vdata_begin):0;
三、时钟IP核
由于VGA成像显示为640480分辨率,实际所用60帧刷新率为800525*60 = 25.175Mhz,于是需要产生25Mhz的时钟频率。更多标准可参考(分辨率VES标准)。
产生方式可以参考《DDS结构的FPGA实现》。
1.将搜索内容ROM换为Clocking。
2.双击蓝色部分进入IP配置
clk_in1为开发板输入时钟频率(我的ACX720为50MHZ)。
设置clk_out1为想要的输出时钟25Mhz。
四、TOP文件设计
`timescale 1ns / 1ps
//
// Create Date: 2022/12/05 17:00:16
// Module Name: VGA_CTRL_TOP
// Tool Versions:Vivado 2018.3
// Revision 0.01 - File Created
// NAME: 小王在努力...
//
module VGA_CTRL_TOP(
clk,
reset,
HS_YS,
VS_YS,
VGA_BLK,
clk25M,
RGB_output
);
input clk; //50MHZ
input reset;
output HS_YS; //行同步脉冲信号
output VS_YS; //场同步脉冲信号
output VGA_BLK; //VGA有效数据显示脉冲信号
output clk25M; //系统输入时钟25MHZ
output [23:0]RGB_output; //RGB输出值
wire [23:0]disp_data;
wire [11:0]H_count;
wire [11:0]V_count;
wire Data_request;
CLK25M_pll CLK25M_pll(
.clk_out1(clk25M), // output clk_out1
.clk_in1(clk) // input clk_in1
);
VGA_CTRL_640x480 VGA_CTRL_640x480(
.clk(clk25M), //系统输入时钟25MHZ
.reset(reset),
.Data(disp_data),
.Data_request(Data_request),
.HS_YS(HS_YS),
.VS_YS(VS_YS),
.H_count(H_count),
.V_count(V_count),
.VGA_BLK(VGA_BLK),
.RGB_output(RGB_output)
);
VGA_CTRL_TEST VGA_CTRL_TEST(
.H_count(H_count),
.V_count(V_count),
.disp_data(disp_data)
);
endmodule
五、VGA_CTRL_TEST模块设计
module VGA_CTRL_TEST(
H_count,
V_count,
disp_data
);
input [11:0]H_count;
input [11:0]V_count;
output reg [23:0]disp_data;
parameter
BLACK = 24'h000000, //黑色
BLUE = 24'h0000FF, //蓝色
RED = 24'hFF0000, //红色
PURPPLE = 24'hFF00FF, //紫色
GREEN = 24'h00FF00, //绿色
CYAN = 24'h00FFFF, //青色
YELLOW = 24'hFFFF00, //黄色
WHITE = 24'hFFFFFF; //白色
parameter
R0_C0 = BLACK , //第0行0列像素块
R0_C1 = BLUE , //第0行1列像素块
R1_C0 = RED , //第1行0列像素块
R1_C1 = PURPPLE , //第1行1列像素块
R2_C0 = GREEN , //第2行0列像素块
R2_C1 = CYAN , //第2行1列像素块
R3_C0 = YELLOW , //第3行0列像素块
R3_C1 = WHITE ; //第3行1列像素块
`include "vga_parameter.v"
wire R0_act = (vcount >= 0 && vcount < `V_Data_Time/4); //正在扫描第0行
wire R1_act = (vcount >= `V_Data_Time/4 && vcount < `V_Data_Time/2);//正在扫描第1行
wire R2_act = (vcount >= `V_Data_Time/2 && vcount < `V_Data_Time*3/4);//正在扫描第2行
wire R3_act = (vcount >= `V_Data_Time*3/4 && vcount < `V_Data_Time);//正在扫描第3行
wire C0_act = (hcount >= 0 && hcount < `H_Data_Time/2); //正在扫描第0列
wire C1_act = (hcount >= `H_Data_Time/2 && hcount < `H_Data_Time);//正在扫描第1列
wire R0_C0_ACT,R0_C1_ACT,R1_C0_ACT,R1_C1_ACT,R2_C0_ACT,R2_C1_ACT,R3_C0_ACT,R3_C1_ACT;
assign R0_C0_ACT = R0_act & C0_act; //第0行0列像素块处于被扫描中标志信号
assign R0_C1_ACT = R0_act & C1_act; //第0行1列像素块处于被扫描中标志信号
assign R1_C0_ACT = R1_act & C0_act; //第1行0列像素块处于被扫描中标志信号
assign R1_C1_ACT = R1_act & C1_act; //第1行1列像素块处于被扫描中标志信号
assign R2_C0_ACT = R2_act & C0_act; //第2行0列像素块处于被扫描中标志信号
assign R2_C1_ACT = R2_act & C1_act; //第2行1列像素块处于被扫描中标志信号
assign R3_C0_ACT = R3_act & C0_act; //第3行0列像素块处于被扫描中标志信号
assign R3_C1_ACT = R3_act & C1_act; //第3行1列像素块处于被扫描中标志信号
always @ (*)
case ({R0_C0_ACT,R0_C1_ACT,R1_C0_ACT,R1_C1_ACT,
R2_C0_ACT,R2_C1_ACT,R3_C0_ACT,R3_C1_ACT})
8'b1000_0000 : disp_data =R3_C1;
8'b0100_0000 : disp_data =R0_C1;
8'b0010_0000 : disp_data =R1_C0;
8'b0001_0000 : disp_data =R1_C1;
8'b0000_1000 : disp_data =R2_C0;
8'b0000_0100 : disp_data =R2_C1;
8'b0000_0010 : disp_data =R3_C0;
8'b0000_0001 : disp_data =R0_C0;
default : disp_data =R3_C1;
endcase
endmodule
六、VGA_CTRL_640x480模块设计
`timescale 1ns / 1ps
//
// Create Date: 2022/11/30 15:18:34
// Module Name: VGA_CTRL_640x480
// Project Name: 640x480图像输出
// Revision: VIVADO 2018.3
// Name:小王在努力...
//
module VGA_CTRL_640x480(
clk,
reset,
Data,
Data_request,
HS_YS,
VS_YS,
H_count,
V_count,
VGA_BLK,
RGB_output
);
input clk;
input reset;
input [23:0]Data; //输入数据
output reg Data_request; //数据请求脉冲信号
output reg HS_YS; //行同步脉冲信号
output reg VS_YS; //场同步脉冲信号
output reg [11:0]H_count; //行有效输出值(实际行像素有效值)
output reg [11:0]V_count; //场有效输出值(实际场像素有效值)
output reg VGA_BLK; //VGA有效数据显示脉冲信号
output RGB_output; //RGB输出值
`include "vga_parameter.v"
parameter Hsync_end = `H_Total_Time;
parameter HS_END = `H_Sync_Time;
parameter Vsync_end = `V_Total_Time;
parameter VS_END = `V_Sync_Time;
parameter Hdata_begin = `H_Sync_Time + `H_Back_Porch + `H_Left_Border;
parameter Hdata_end = `H_Sync_Time + `H_Left_Border + `H_Back_Porch + `H_Data_Time;
parameter Vdata_begin = `V_Sync_Time + `V_Back_Porch + `V_Top_Border;
parameter Vdata_end = `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time;
reg [11:0]H_cnt; //行扫描计数器
always @ (posedge clk or negedge reset)
if(!reset)
H_cnt <= 0;
else if(H_cnt >= Hsync_end -1 )
H_cnt <= 0;
else
H_cnt <= H_cnt + 1'b1;
// 行同步脉冲信号
always @ (posedge clk)
HS_YS <= (H_cnt <= HS_END-1 )?0:1;
reg [11:0]V_cnt;//场扫描计数器
always @ (posedge clk or negedge reset)
if(!reset)
V_cnt <= 0;
else if( H_cnt == Hsync_end -1)begin
if(V_cnt >= Vsync_end-1)
V_cnt <= 0;
else
V_cnt <= V_cnt + 1;
end
else
V_cnt <= V_cnt ;
//场同步脉冲信号
always @ (posedge clk)
VS_YS <= (V_cnt <= VS_END-1 )?0:1;
always @ (posedge clk)
Data_request <= (H_cnt >= Hdata_begin - 1 )&&(H_cnt <= Hdata_end - 2)&&(V_cnt >= Vdata_begin)&&(V_cnt <= Vdata_end -1);
always @ (posedge clk)
VGA_BLK <= Data_request;
always @ (posedge clk)
H_count <= (Data_request) ?(H_cnt-Hdata_begin):0;
always @ (posedge clk)
V_count <= (Data_request) ?(V_cnt-Vdata_begin):0;
//always @ (posedge clk)
wire [23:0]RGB_output;
assign RGB_output = (VGA_BLK) ?(Data):0;
endmodule
七、vga_parameter.v
//`define Resolution_480x272 1 //刷新率为60Hz时像素时钟为9MHz
//`define Resolution_640x480 1 //刷新率为60Hz时像素时钟为25.175MHz
`define Resolution_800x480 1 //刷新率为60Hz时像素时钟为33MHz
//`define Resolution_800x600 1 //刷新率为60Hz时像素时钟为40MHz
//`define Resolution_1024x768 1 //刷新率为60Hz时像素时钟为65MHz
//`define Resolution_1280x720 1 //刷新率为60Hz时像素时钟为74.25MHz
//`define Resolution_1920x1080 1 //刷新率为60Hz时像素时钟为148.5MHz
`ifdef Resolution_480x272
`define H_Right_Border 0
`define H_Front_Porch 2
`define H_Sync_Time 41
`define H_Back_Porch 2
`define H_Left_Border 0
`define H_Data_Time 480
`define H_Total_Time 525
`define V_Bottom_Border 0
`define V_Front_Porch 2
`define V_Sync_Time 10
`define V_Back_Porch 2
`define V_Top_Border 0
`define V_Data_Time 272
`define V_Total_Time 286
`elsif Resolution_640x480
`define H_Total_Time 12'd800
`define H_Right_Border 12'd8
`define H_Front_Porch 12'd8
`define H_Sync_Time 12'd96
`define H_Data_Time 12'd640
`define H_Back_Porch 12'd40
`define H_Left_Border 12'd8
`define V_Total_Time 12'd525
`define V_Bottom_Border 12'd8
`define V_Front_Porch 12'd2
`define V_Sync_Time 12'd2
`define V_Data_Time 12'd480
`define V_Back_Porch 12'd25
`define V_Top_Border 12'd8
`elsif Resolution_800x480
`define H_Total_Time 12'd1056
`define H_Right_Border 12'd0
`define H_Front_Porch 12'd40
`define H_Sync_Time 12'd128
`define H_Data_Time 12'd800
`define H_Back_Porch 12'd88
`define H_Left_Border 12'd0
`define V_Total_Time 12'd525
`define V_Bottom_Border 12'd8
`define V_Front_Porch 12'd2
`define V_Sync_Time 12'd2
`define V_Data_Time 12'd480
`define V_Back_Porch 12'd25
`define V_Top_Border 12'd8
`elsif Resolution_800x600
`define H_Total_Time 12'd1056
`define H_Right_Border 12'd0
`define H_Front_Porch 12'd40
`define H_Sync_Time 12'd128
`define H_Data_Time 12'd800
`define H_Back_Porch 12'd88
`define H_Left_Border 12'd0
`define V_Total_Time 12'd628
`define V_Bottom_Border 12'd0
`define V_Front_Porch 12'd1
`define V_Sync_Time 12'd4
`define V_Data_Time 12'd600
`define V_Back_Porch 12'd23
`define V_Top_Border 12'd0
`elsif Resolution_1024x768
`define H_Total_Time 12'd1344
`define H_Right_Border 12'd0
`define H_Front_Porch 12'd24
`define H_Sync_Time 12'd136
`define H_Data_Time 12'd1024
`define H_Back_Porch 12'd160
`define H_Left_Border 12'd0
`define V_Total_Time 12'd806
`define V_Bottom_Border 12'd0
`define V_Front_Porch 12'd3
`define V_Sync_Time 12'd6
`define V_Data_Time 12'd768
`define V_Back_Porch 12'd29
`define V_Top_Border 12'd0
`elsif Resolution_1280x720
`define H_Total_Time 12'd1650
`define H_Right_Border 12'd0
`define H_Front_Porch 12'd110
`define H_Sync_Time 12'd40
`define H_Data_Time 12'd1280
`define H_Back_Porch 12'd220
`define H_Left_Border 12'd0
`define V_Total_Time 12'd750
`define V_Bottom_Border 12'd0
`define V_Front_Porch 12'd5
`define V_Sync_Time 12'd5
`define V_Data_Time 12'd720
`define V_Back_Porch 12'd20
`define V_Top_Border 12'd0
`elsif Resolution_1920x1080
`define H_Total_Time 12'd2200
`define H_Right_Border 12'd0
`define H_Front_Porch 12'd88
`define H_Sync_Time 12'd44
`define H_Data_Time 12'd1920
`define H_Back_Porch 12'd148
`define H_Left_Border 12'd0
`define V_Total_Time 12'd1125
`define V_Bottom_Border 12'd0
`define V_Front_Porch 12'd4
`define V_Sync_Time 12'd5
`define V_Data_Time 12'd1080
`define V_Back_Porch 12'd36
`define V_Top_Border 12'd0
`endif
八、TB模块展示
`timescale 1ns / 1ps
//
// Create Date: 2022/11/30 16:07:54
// Design Name: VGA_CTRL
// Module Name: VGA_CTRL_TB
// Project Name: VGA_CTRL
// Revision:2018.3
// Revision 0.01 - File Created
// Name:小王在努力...
//
module VGA_CTRL_TB();
reg clk;
reg reset;
wire HS_YS; //行同步脉冲信号
wire VS_YS; //场同步脉冲信号
wire VGA_BLK; //VGA有效数据显示脉冲信号
wire clk25M;
wire [23:0]RGB_output; //RGB输出值
VGA_CTRL_TOP VGA_CTRL_TOP(
clk,
reset,
HS_YS,
VS_YS,
VGA_BLK,
clk25M,
RGB_output
);
initial clk = 1;
always #10 clk = ~clk;
initial begin
reset = 0;
#201;
reset = 1;
#20000000;
$stop;
end
endmodule
九、仿真结果展示
1.全局展示
2.细节展示
可以看出在V_count = 120时RGB_output数据发生改变,更多细节可以动手仿真测试。
【附件:】链接:https://pan.baidu.com/s/1InHtHoJm-U3Kt9YSqk1oAw?pwd=2t8y
提取码:2t8y
评论(0)
您还未登录,请登录后发表或查看评论