【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
我自己读书那会,买的电脑还是以台式机居多,平板显示器也是才刚刚流行、且价格较高,视频接口也是以VGA为主。不像现在,基本上视频接口都是以HDMI为主。和HDMI相比较,VGA简单、方便,十分合适用来学习应用。
1、VGA接口
开发板上的VGA部分,接口还是非常简单的。虽然接口有15个,但是其中5个是悬空(NC),5个是接地,真正有用的信号其实只有5个。这5个信号分别是红、绿、蓝、行同步、场同步。
2、FPGA和VGA的连接
FPGA和VGA直接的接口还需要通过上面这一层电路转换,才能输出红、绿、蓝。其中红色有5位,绿色有6位,蓝色有5位,所以可以表现的颜色总共有16位,也就是65536种颜色。0也是一种颜色。
3、VGA的视频时序
VGA视频时序,是我们编写verilog代码的关键。比如说一个1024*768分辨率、60帧每秒的视频流来说,真正VGA处理过的数据是1344*806,这其中还包括了(HSYNC、HBP、HFP,VSYNC、VBP、VFP),这些都是不显示的,所以显示的只是中间一部分内容。整个带宽的话,如果按照1344*806*60来算,大约是65M左右。所以,在fpga实现的过程当中,需要对原来的50M时钟进行倍频处理。
另外需要注意的是,HBP处于前侧,而HFP是处于后侧。同样,VBP处于上方,而VFP处于下方的位置。但是编写verilog的时候,需要从HFP、VFP开始算起,这是比较容易引起疑问的一个地方。
4、准备PLL倍频
倍频之前讨论过。这里只有几个地方需要注意下即可。1)输入时钟为50M,
2)取消复位和lock锁定,
3)只生成一个65M的输出时钟,
5、有了基础的pll,下面可以构建top层代码
-
-
module vga_test(
-
input clk,
-
input rst_n,
-
//vga output
-
output vga_out_hs,
//vga horizontal synchronization
-
output vga_out_vs,
//vga vertical synchronization
-
output[
4:
0] vga_out_r,
//vga red
-
output[
5:
0] vga_out_g,
//vga green
-
output[
4:
0] vga_out_b
//vga blue
-
-
);
-
-
wire video_clk;
-
wire video_hs;
-
wire video_vs;
-
wire video_de;
-
wire[
7:
0] video_r;
-
wire[
7:
0] video_g;
-
wire[
7:
0] video_b;
-
-
assign vga_out_hs = video_hs;
-
assign vga_out_vs = video_vs;
-
assign vga_out_r = video_r[
7:
3];
//discard low bit data
-
assign vga_out_g = video_g[
7:
2];
//discard low bit data
-
assign vga_out_b = video_b[
7:
3];
//discard low bit data
-
-
//generate video pixel clock
-
video_pll video_pll_m0(
-
.inclk0(clk),
-
.c0(video_clk));
-
-
color_bar color_bar_m0(
-
.clk(video_clk),
-
.rst(~rst_n),
-
.hs(video_hs),
-
.vs(video_vs),
-
.de(video_de),
-
.rgb_r(video_r),
-
.rgb_g(video_g),
-
.rgb_b(video_b)
-
);
-
endmodule
top层代码比较简单,这里主要就是实例化video_pll和color_bar两个模块。video_pll刚才已经生成,下面就只需要谈谈color_bar。
6、关于color_bar.v代码
-
`include
"video_define.v"
-
module
color_bar(
-
input clk,
//pixel clock
-
input rst,
//reset signal high active
-
output hs,
//horizontal synchronization
-
output vs,
//vertical synchronization
-
output de,
//video valid
-
output[
7:
0] rgb_r,
//video red data
-
output[
7:
0] rgb_g,
//video green data
-
output[
7:
0] rgb_b
//video blue data
-
);
-
//video timing parameter definition
-
`ifdef VIDEO_1280_720
-
parameter H_ACTIVE =
16
'd1280;
//horizontal active time (pixels)
-
parameter H_FP =
16
'd110;
//horizontal front porch (pixels)
-
parameter H_SYNC =
16
'd40;
//horizontal sync time(pixels)
-
parameter H_BP =
16
'd220;
//horizontal back porch (pixels)
-
parameter V_ACTIVE =
16
'd720;
//vertical active Time (lines)
-
parameter V_FP =
16
'd5;
//vertical front porch (lines)
-
parameter V_SYNC =
16
'd5;
//vertical sync time (lines)
-
parameter V_BP =
16
'd20;
//vertical back porch (lines)
-
parameter HS_POL =
1
'b1;
//horizontal sync polarity, 1 : POSITIVE,0 : NEGATIVE;
-
parameter VS_POL =
1
'b1;
//vertical sync polarity, 1 : POSITIVE,0 : NEGATIVE;
-
`endif
-
-
//480x272 9Mhz
-
`ifdef VIDEO_480_272
-
parameter H_ACTIVE =
16
'd480;
-
parameter H_FP =
16
'd2;
-
parameter H_SYNC =
16
'd41;
-
parameter H_BP =
16
'd2;
-
parameter V_ACTIVE =
16
'd272;
-
parameter V_FP =
16
'd2;
-
parameter V_SYNC =
16
'd10;
-
parameter V_BP =
16
'd2;
-
parameter HS_POL =
1
'b0;
-
parameter VS_POL =
1
'b0;
-
`endif
-
-
//640x480 25.175Mhz
-
`ifdef VIDEO_640_480
-
parameter H_ACTIVE =
16
'd640;
-
parameter H_FP =
16
'd16;
-
parameter H_SYNC =
16
'd96;
-
parameter H_BP =
16
'd48;
-
parameter V_ACTIVE =
16
'd480;
-
parameter V_FP =
16
'd10;
-
parameter V_SYNC =
16
'd2;
-
parameter V_BP =
16
'd33;
-
parameter HS_POL =
1
'b0;
-
parameter VS_POL =
1
'b0;
-
`endif
-
-
//800x480 33Mhz
-
`ifdef VIDEO_800_480
-
parameter H_ACTIVE =
16
'd800;
-
parameter H_FP =
16
'd40;
-
parameter H_SYNC =
16
'd128;
-
parameter H_BP =
16
'd88;
-
parameter V_ACTIVE =
16
'd480;
-
parameter V_FP =
16
'd1;
-
parameter V_SYNC =
16
'd3;
-
parameter V_BP =
16
'd21;
-
parameter HS_POL =
1
'b0;
-
parameter VS_POL =
1
'b0;
-
`endif
-
-
//800x600 40Mhz
-
`ifdef VIDEO_800_600
-
parameter H_ACTIVE =
16
'd800;
-
parameter H_FP =
16
'd40;
-
parameter H_SYNC =
16
'd128;
-
parameter H_BP =
16
'd88;
-
parameter V_ACTIVE =
16
'd600;
-
parameter V_FP =
16
'd1;
-
parameter V_SYNC =
16
'd4;
-
parameter V_BP =
16
'd23;
-
parameter HS_POL =
1
'b1;
-
parameter VS_POL =
1
'b1;
-
`endif
-
-
//1024x768 65Mhz
-
`ifdef VIDEO_1024_768
-
parameter H_ACTIVE =
16
'd1024;
-
parameter H_FP =
16
'd24;
-
parameter H_SYNC =
16
'd136;
-
parameter H_BP =
16
'd160;
-
parameter V_ACTIVE =
16
'd768;
-
parameter V_FP =
16
'd3;
-
parameter V_SYNC =
16
'd6;
-
parameter V_BP =
16
'd29;
-
parameter HS_POL =
1
'b0;
-
parameter VS_POL =
1
'b0;
-
`endif
-
-
//1920x1080 148.5Mhz
-
`ifdef VIDEO_1920_1080
-
parameter H_ACTIVE =
16
'd1920;
-
parameter H_FP =
16
'd88;
-
parameter H_SYNC =
16
'd44;
-
parameter H_BP =
16
'd148;
-
parameter V_ACTIVE =
16
'd1080;
-
parameter V_FP =
16
'd4;
-
parameter V_SYNC =
16
'd5;
-
parameter V_BP =
16
'd36;
-
parameter HS_POL =
1
'b1;
-
parameter VS_POL =
1
'b1;
-
`endif
-
parameter H_TOTAL = H_ACTIVE + H_FP + H_SYNC + H_BP;
//horizontal total time (pixels)
-
parameter V_TOTAL = V_ACTIVE + V_FP + V_SYNC + V_BP;
//vertical total time (lines)
-
//define the RGB values for 8 colors
-
parameter WHITE_R =
8
'hff;
-
parameter WHITE_G =
8
'hff;
-
parameter WHITE_B =
8
'hff;
-
parameter YELLOW_R =
8
'hff;
-
parameter YELLOW_G =
8
'hff;
-
parameter YELLOW_B =
8
'h00;
-
parameter CYAN_R =
8
'h00;
-
parameter CYAN_G =
8
'hff;
-
parameter CYAN_B =
8
'hff;
-
parameter GREEN_R =
8
'h00;
-
parameter GREEN_G =
8
'hff;
-
parameter GREEN_B =
8
'h00;
-
parameter MAGENTA_R =
8
'hff;
-
parameter MAGENTA_G =
8
'h00;
-
parameter MAGENTA_B =
8
'hff;
-
parameter RED_R =
8
'hff;
-
parameter RED_G =
8
'h00;
-
parameter RED_B =
8
'h00;
-
parameter BLUE_R =
8
'h00;
-
parameter BLUE_G =
8
'h00;
-
parameter BLUE_B =
8
'hff;
-
parameter BLACK_R =
8
'h00;
-
parameter BLACK_G =
8
'h00;
-
parameter BLACK_B =
8
'h00;
-
reg hs_reg;
//horizontal sync register
-
reg vs_reg;
//vertical sync register
-
reg hs_reg_d0;
//delay 1 clock of 'hs_reg'
-
reg vs_reg_d0;
//delay 1 clock of 'vs_reg'
-
reg[
11:
0] h_cnt;
//horizontal counter
-
reg[
11:
0] v_cnt;
//vertical counter
-
reg[
11:
0] active_x;
//video x position
-
reg[
11:
0] active_y;
//video y position
-
reg[
7:
0] rgb_r_reg;
//video red data register
-
reg[
7:
0] rgb_g_reg;
//video green data register
-
reg[
7:
0] rgb_b_reg;
//video blue data register
-
reg h_active;
//horizontal video active
-
reg v_active;
//vertical video active
-
wire video_active;
//video active(horizontal active and vertical active)
-
reg video_active_d0;
//delay 1 clock of video_active
-
assign hs = hs_reg_d0;
-
assign vs = vs_reg_d0;
-
assign video_active = h_active & v_active;
-
assign de = video_active_d0;
-
assign rgb_r = rgb_r_reg;
-
assign rgb_g = rgb_g_reg;
-
assign rgb_b = rgb_b_reg;
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
begin
-
hs_reg_d0 <=
1
'b0;
-
vs_reg_d0 <=
1
'b0;
-
video_active_d0 <=
1
'b0;
-
end
-
else
-
begin
-
hs_reg_d0 <= hs_reg;
-
vs_reg_d0 <= vs_reg;
-
video_active_d0 <= video_active;
-
end
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
h_cnt <=
12
'd0;
-
else
if(h_cnt == H_TOTAL -
1)
//horizontal counter maximum value
-
h_cnt <=
12
'd0;
-
else
-
h_cnt <= h_cnt +
12
'd1;
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
active_x <=
12
'd0;
-
else
if(h_cnt >= H_FP + H_SYNC + H_BP -
1)
//horizontal video active
-
active_x <= h_cnt - (H_FP[
11:
0] + H_SYNC[
11:
0] + H_BP[
11:
0] -
12
'd1);
-
else
-
active_x <= active_x;
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
v_cnt <=
12
'd0;
-
else
if(h_cnt == H_FP -
1)
//horizontal sync time
-
if(v_cnt == V_TOTAL -
1)
//vertical counter maximum value
-
v_cnt <=
12
'd0;
-
else
-
v_cnt <= v_cnt +
12
'd1;
-
else
-
v_cnt <= v_cnt;
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
hs_reg <=
1
'b0;
-
else
if(h_cnt == H_FP -
1)
//horizontal sync begin
-
hs_reg <= HS_POL;
-
else
if(h_cnt == H_FP + H_SYNC -
1)
//horizontal sync end
-
hs_reg <= ~hs_reg;
-
else
-
hs_reg <= hs_reg;
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
h_active <=
1
'b0;
-
else
if(h_cnt == H_FP + H_SYNC + H_BP -
1)
//horizontal active begin
-
h_active <=
1
'b1;
-
else
if(h_cnt == H_TOTAL -
1)
//horizontal active end
-
h_active <=
1
'b0;
-
else
-
h_active <= h_active;
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
vs_reg <=
1
'd0;
-
else
if((v_cnt == V_FP -
1) && (h_cnt == H_FP -
1))
//vertical sync begin
-
vs_reg <= HS_POL;
-
else
if((v_cnt == V_FP + V_SYNC -
1) && (h_cnt == H_FP -
1))
//vertical sync end
-
vs_reg <= ~vs_reg;
-
else
-
vs_reg <= vs_reg;
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
v_active <=
1
'd0;
-
else
if((v_cnt == V_FP + V_SYNC + V_BP -
1) && (h_cnt == H_FP -
1))
//vertical active begin
-
v_active <=
1
'b1;
-
else
if((v_cnt == V_TOTAL -
1) && (h_cnt == H_FP -
1))
//vertical active end
-
v_active <=
1
'b0;
-
else
-
v_active <= v_active;
-
end
-
-
always@(posedge clk or posedge rst)
-
begin
-
if(rst ==
1
'b1)
-
begin
-
rgb_r_reg <=
8
'h00;
-
rgb_g_reg <=
8
'h00;
-
rgb_b_reg <=
8
'h00;
-
end
-
else
if(video_active)
-
if(active_x ==
12
'd0)
-
begin
-
rgb_r_reg <= WHITE_R;
-
rgb_g_reg <= WHITE_G;
-
rgb_b_reg <= WHITE_B;
-
end
-
else
if(active_x == (H_ACTIVE/
8) *
1)
-
begin
-
rgb_r_reg <= YELLOW_R;
-
rgb_g_reg <= YELLOW_G;
-
rgb_b_reg <= YELLOW_B;
-
end
-
else
if(active_x == (H_ACTIVE/
8) *
2)
-
begin
-
rgb_r_reg <= CYAN_R;
-
rgb_g_reg <= CYAN_G;
-
rgb_b_reg <= CYAN_B;
-
end
-
else
if(active_x == (H_ACTIVE/
8) *
3)
-
begin
-
rgb_r_reg <= GREEN_R;
-
rgb_g_reg <= GREEN_G;
-
rgb_b_reg <= GREEN_B;
-
end
-
else
if(active_x == (H_ACTIVE/
8) *
4)
-
begin
-
rgb_r_reg <= MAGENTA_R;
-
rgb_g_reg <= MAGENTA_G;
-
rgb_b_reg <= MAGENTA_B;
-
end
-
else
if(active_x == (H_ACTIVE/
8) *
5)
-
begin
-
rgb_r_reg <= RED_R;
-
rgb_g_reg <= RED_G;
-
rgb_b_reg <= RED_B;
-
end
-
else
if(active_x == (H_ACTIVE/
8) *
6)
-
begin
-
rgb_r_reg <= BLUE_R;
-
rgb_g_reg <= BLUE_G;
-
rgb_b_reg <= BLUE_B;
-
end
-
else
if(active_x == (H_ACTIVE/
8) *
7)
-
begin
-
rgb_r_reg <= BLACK_R;
-
rgb_g_reg <= BLACK_G;
-
rgb_b_reg <= BLACK_B;
-
end
-
else
-
begin
-
rgb_r_reg <= rgb_r_reg;
-
rgb_g_reg <= rgb_g_reg;
-
rgb_b_reg <= rgb_b_reg;
-
end
-
else
-
begin
-
rgb_r_reg <=
8
'h00;
-
rgb_g_reg <=
8
'h00;
-
rgb_b_reg <=
8
'h00;
-
end
-
end
-
-
endmodule
color_bar.v的内容比较多,但是真正有意义的部分还是在于hs_reg、vs_reg、rgb_r_reg、rgb_g_reg、rgb_b_reg的生成。因为它们和最终输出有关。代码中的一大部分内容属于配置部分,因为我们选用的是1024*768,所以相关参数如下所示。video_define.v也只是添加了一行`define VIDEO_1024_768而已。
-
//1024x768 65Mhz
-
`ifdef VIDEO_1024_768
-
parameter H_ACTIVE =
16
'd1024;
-
parameter H_FP =
16
'd24;
-
parameter H_SYNC =
16
'd136;
-
parameter H_BP =
16
'd160;
-
parameter V_ACTIVE =
16
'd768;
-
parameter V_FP =
16
'd3;
-
parameter V_SYNC =
16
'd6;
-
parameter V_BP =
16
'd29;
-
parameter HS_POL =
1
'b0;
-
parameter VS_POL =
1
'b0;
-
`endif
有了这几行定义,相当于规定了VGA数据的范围。HS_POL和VS_POL代表了起始值。下面就可以看看其他寄存器的含义了。hs_reg_d0、vs_reg_d0主要是为了延迟一拍,因为rgb_r_reg、rgb_g_reg、rgb_b_reg其实也相当于延迟一拍输出的。h_cnt计算一行的数据总数,active_x计算当前行中有效数据索引,v_cnt计算总的行数,hs_reg输出行同步,h_active输出行数据有效,vs_reg输出场同步,v_active输出场数据有效,rgb_r_reg & rgb_g_reg & rgb_b_reg则输出最终的rgb数据。
另外在color_bar.v中,有一个信号de。这主要是为了后续bmp、camera做准备的,本次vga测试其实并没有用到。
7、pin脚信号的bind
8、实验
有了video_define.v、vga_test.v、color_bar.v和pll这几个文件,经过编译、综合之后就可以生成对应的sof文件。烧入到fpga开发板之后,不出意外,就可以看到这样的显示效果了,
转载:https://blog.csdn.net/feixiaoxing/article/details/128429476