Zedboard学习(七):VGA显示

VGA硬件接口

到zedboard官方给出的原理图中查看:
Zedboard学习(七):VGA显示_第1张图片
RGB信号,各四位;这里的设计是使用了电阻分压模拟了DAC芯片实现了4X4X4的RGB信号,如果要更好的显示效果还是建议使用专门的DAC。

Zedboard学习(七):VGA显示_第2张图片
上面给出了所有的引脚分配。

信号 功能 引脚分配
Red 红色视频信号 V20, U20, V19, V18
Green 绿色视频信号 AB22, AA22, AB21, AA21
Blue 蓝色视频信号 Y21, Y20, AB20, AB19
Hsync 行同步信号 AA19
Vsync 列同步信号 Y19

VGA时序分析

Zedboard学习(七):VGA显示_第3张图片
如上图所示,就是VGA时序的表示。按照这个时序图,编写程序。

Hsync是行同步信号,表示一行的开始和上一行的结束;
Vsync是列同步信号,表示一场的开始和上一场的结束;
行时序是以像素为单位的, 场时序是以行为单位的;
像素点从左到右算一行,行数从上到下算一场。

在图上定义了很多区间,而根据这些区间我们可以看到整个时序图被分为了三个矩形:中间的Adressable Video,其外面的Border,还有最外面的Blanking。
传输数据的时间就是中间的Adressable Video的这段时间,同步到每个像素即可。中间的那个矩形就对应显示器显示的范围,其他的矩形可以看做是不可见的。

VGA的时序我只是简单介绍了下,详细的介绍可以查看:[笔记]VGA时序及其原理

列出几个常用的时序:
640×480 @60HZ
Zedboard学习(七):VGA显示_第4张图片

800×600@60HZ
Zedboard学习(七):VGA显示_第5张图片

上面给出了几个示例,图中给出了时序参数的计算步骤以及最后结果,可以到这下载:VGA时序标准
现在我们只提取出最后要用到的时序参数:
Zedboard学习(七):VGA显示_第6张图片
(这个图是我直接在网上截图的,不保证全部正确,最好参考VGA时序标准确认一遍,以手册为准)

编写代码

新建工程,添加Verilog代码,这些步骤不再赘述。
直接上代码了,代码中添加了注释。我选取的是800×600@60HZ。
程序的结构:
这里写图片描述

产生vga信号的代码:
vga_data_gen.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2017/07/27 23:15:37
// Design Name: 
// Module Name: vga_data_gen
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module vga_data_gen(
    input pixel_clk,        //像素时钟
    input rst,              //复位按键,高电平复位

    output [7:0] vga_r,     //vga信号红色视频信号
    output [7:0] vga_g,     //vga信号绿色视频信号
    output [7:0] vga_b,     //vga信号蓝色视频信号
    output vga_hs,          //行同步信号
    output vga_vs,          //场同步信号
    output vga_de,          //vga信号有效,如当前时刻传输数据有效,即为1;否则为0;

    input turn_mode,        //按键。按下为高电平,切换vga显示模式
    output [3:0] mode       //当前显示模式,用4位编码
    );

//---------------------------------//
// 水平扫描参数的设定 800*600 60HZ
//--------------------------------//
parameter H_Total = 1056 - 1;
parameter H_Sync = 128 - 1;
parameter H_Back = 88 - 1;
parameter H_Active = 800 - 1;
parameter H_Front = 40 - 1;
parameter H_Start = 216 - 1;
parameter H_End = 1016 - 1;

//-------------------------------//
// 垂直扫描参数的设定 1280*720 60HZ
//-------------------------------//
parameter V_Total = 628 - 1;
parameter V_Sync = 4 - 1;
parameter V_Back = 23 - 1;
parameter V_Active = 600 - 1;
parameter V_Front = 1 - 1;
parameter V_Start = 27 - 1;
parameter V_End = 627 - 1;

//行信号计数器
reg [11:0] x_cnt;
always @(posedge pixel_clk or posedge rst)
begin
    if(rst)
        x_cnt <= 12'd0;
    else if(x_cnt == H_Total)
        x_cnt <= 12'd0;
    else
        x_cnt <= x_cnt + 1'b1;
end

//根据时序图参数,产生行同步信号
reg hsync_r;
always @(posedge pixel_clk or posedge rst)
begin
    if(rst)
        hsync_r <= 1'b1;
    else if(x_cnt>=0 && x_cnt < H_Sync)
        hsync_r <= 1'b0;
    else
        hsync_r <= 1'b1;
end

//行信号有效,即当前数据有效
reg hs_de;
always @(posedge pixel_clk or posedge rst)
begin
    if(rst)
        hs_de <= 1'b0;
    else if(x_cnt>=H_Start && x_cnt1'b1;
    else
        hs_de <= 1'b0;
end

//场信号计数器
reg [11:0] y_cnt;
always @(posedge pixel_clk or posedge rst)
begin
    if(rst)
        y_cnt <= 12'd0;
    else if(y_cnt == V_Total)
        y_cnt <= 12'd0;
    else if(x_cnt == H_Total)
        y_cnt <= y_cnt + 1'b1;
end

//根据时序图参数,产生场同步信号
reg vsync_r;
always @(posedge pixel_clk or posedge rst)
begin
    if(rst)
        vsync_r <= 1'b1;
    else if(y_cnt>=0 && y_cnt1'b0;
    else
        vsync_r <= 1'b1;
end

//列信号有效,即当前数据有效
reg vs_de;
always @(posedge pixel_clk or posedge rst)
begin
    if(rst)
        vs_de <= 1'b0;
    else if(y_cnt>=V_Start && y_cnt1'b1;
    else
        vs_de <= 1'b0;
end

//按键消抖,按下后延时一段时间,再检测是否按下
reg [16:0] key_counter;
always @(posedge pixel_clk)
begin
    if(turn_mode)
        key_counter <= 17'd0;
    else if((turn_mode == 1'b0) && (key_counter <= 17'h11704))
        key_counter <= key_counter + 1'b1;
end

//显示模式技术,每次按下按键,模式改变,最多有12种显示模式
reg [3:0] dis_mode;
assign mode = dis_mode;
always @(posedge pixel_clk)
begin
    if(key_counter == 17'h11704)
    begin
        if(dis_mode == 4'd12)
            dis_mode <= 4'd0;
        else 
            dis_mode <= dis_mode +1'b1;
    end
end

//产生小格子,黑白棋盘
reg [7:0] grid_data_1;
always @(posedge pixel_clk)
begin
    if((x_cnt[4] == 1'b0) ^ (y_cnt[4] == 1'b0))
        grid_data_1 <= 8'h00;
    else
        grid_data_1 <= 8'hff;
end

//产生大格子,黑白棋盘
reg [7:0] grid_data_2;
always @(posedge pixel_clk)
begin
    if((x_cnt[6] == 1'b0) ^ (y_cnt[6] == 1'b0))
        grid_data_2 <= 8'h00;
    else
        grid_data_2 <= 8'hff;
end

//产生彩条
reg [23:0] color_bar;
always @(posedge pixel_clk)
begin
    if(x_cnt>=216 && x_cnt<316)
        color_bar <= 24'hff0000;
    else if(x_cnt>=316 && x_cnt<416)
        color_bar <= 24'h00ff00;
    else if(x_cnt>=416 && x_cnt<516)
        color_bar <= 24'h0000ff;
    else if(x_cnt>=516 && x_cnt<616)
        color_bar <= 24'hff00ff;
    else if(x_cnt>=616 && x_cnt<716)
        color_bar <= 24'hffff00;
    else if(x_cnt>=716 && x_cnt<816)
        color_bar <= 24'h00ffff;
    else if(x_cnt>=816 && x_cnt<916)
        color_bar <= 24'hffffff;
    else if(x_cnt>=916 && x_cnt<1016)
        color_bar <= 24'h000000;
    else
        color_bar <= color_bar;
end

//根据显示模式传输rgb信号到缓存器中
reg [7:0] vga_r_reg;
reg [7:0] vga_g_reg;
reg [7:0] vga_b_reg;
always @(posedge pixel_clk or posedge rst)
begin
    if(rst)
    begin
        vga_r_reg <= 8'd0;
        vga_g_reg <= 8'd0;
        vga_b_reg <= 8'd0;
    end
    else
    begin
        case(dis_mode)
            4'd0:                   //全黑
            begin
                vga_r_reg <= 8'd0;
                vga_g_reg <= 8'd0;
                vga_b_reg <= 8'd0;
            end

            4'd1:                   //全白
            begin
                vga_r_reg <= 8'b1111_1111;
                vga_g_reg <= 8'b1111_1111;
                vga_b_reg <= 8'b1111_1111;
            end

            4'd2:                   //全红
            begin
                vga_r_reg <= 8'b1111_1111;
                vga_g_reg <= 8'd0;
                vga_b_reg <= 8'd0;
            end

            4'd3:                   //全绿
            begin
                vga_r_reg <= 8'd0;
                vga_g_reg <= 8'b1111_1111;
                vga_b_reg <= 8'd0;
            end

            4'd4:                   //全蓝
            begin
                vga_r_reg <= 8'd0;
                vga_g_reg <= 8'd0;
                vga_b_reg <= 8'b1111_1111;
            end

            4'd5:                   //小格子,黑白棋盘
            begin
                vga_r_reg <= grid_data_1;
                vga_g_reg <= grid_data_1;
                vga_b_reg <= grid_data_1;
            end

            4'd6:                   //大格子,黑白棋盘
            begin
                vga_r_reg <= grid_data_2;
                vga_g_reg <= grid_data_2;
                vga_b_reg <= grid_data_2;
            end

            4'd7:                   //根据行信号渐变,周期性从黑到白
            begin
                vga_r_reg <= x_cnt[7:0];
                vga_g_reg <= x_cnt[7:0];
                vga_b_reg <= x_cnt[7:0];
            end

            4'd8:                   //根据场信号渐变,周期性从黑到白
            begin
                vga_r_reg <= y_cnt[7:0];
                vga_g_reg <= y_cnt[7:0];
                vga_b_reg <= y_cnt[7:0];
            end

            4'd9:                   //根据行信号渐变,周期性红色从浅到深
            begin
                vga_r_reg <= x_cnt[7:0];
                vga_g_reg <= 8'd0;
                vga_b_reg <= 8'd0;
            end

            4'd10:                  //根据列信号渐变,周期性绿色从浅到深
            begin
                vga_r_reg <= 8'd0;
                vga_g_reg <= x_cnt[7:0];
                vga_b_reg <= 8'd0;
            end

            4'd11:                  //根据行信号渐变,周期性蓝色从浅到深
            begin
                vga_r_reg <= 8'd0;
                vga_g_reg <= 8'd0;
                vga_b_reg <= x_cnt[7:0];
            end

            4'd12:                 //彩条信号
            begin
                vga_r_reg <= color_bar[23:16];
                vga_g_reg <= color_bar[15:8];
                vga_b_reg <= color_bar[7:0];
            end

            default:
            begin
                vga_r_reg <= 8'b1111_1111;
                vga_g_reg <= 8'b1111_1111;
                vga_b_reg <= 8'b1111_1111;
            end
        endcase
    end
end

//将这些寄存器中的信号输出
assign vga_hs = hsync_r;
assign vga_vs = vsync_r;
assign vga_de = hs_de & vs_de;  //只有当行信号和场信号同时有效时数据才有效
assign vga_r = (hs_de & vs_de) ? vga_r_reg : 8'h0;
assign vga_g = (hs_de & vs_de) ? vga_g_reg : 8'h0;
assign vga_b = (hs_de & vs_de) ? vga_b_reg : 8'h0;

endmodule

由于VGA信号是800×600@60HZ,我们还需要一个像素时钟40MHZ。zedboard的PL部分默认的时钟是100MHZ,所以我们还需要一个时钟单元来产生40MHZ的特定时钟。分频的方法不稳定,不推荐。

点击这里写图片描述准备添加IP核。
如下图所示找到clocking wizard。打开它,开始配置其功能。
Zedboard学习(七):VGA显示_第7张图片

这些都默认不改动,时钟是100MHZ。
Zedboard学习(七):VGA显示_第8张图片

修改输出时钟为40MHZ,其他不做修改。
Zedboard学习(七):VGA显示_第9张图片
直接点击OK,创建IP核。

点击generate产生IP核。
Zedboard学习(七):VGA显示_第10张图片
最后会产生这个,我们可以通过Verilog调用这个模块。
这里写图片描述

最后编写顶层Verilog代码:只是把前面几个模块包进来。
vga_disp.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2017/07/27 23:12:46
// Design Name: 
// Module Name: vga_disp
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module vga_disp(
    input clk100M,
    input rst,
    input key,
    output [3:0] vga_r,
    output [3:0] vga_g,
    output [3:0] vga_b,
    output vga_hs,
    output vga_vs,
    output [3:0] led
    );

    wire pixel_clk;
    wire [7:0] R, G, B;
    wire HS, VS, DE;

    assign vga_r = R[7:4];
    assign vga_g = G[7:4];
    assign vga_b = B[7:4];
    assign vga_hs = HS;
    assign vga_vs = VS;

    vga_data_gen vga_data_gen(
        .pixel_clk(pixel_clk),
        .rst(rst),

        .vga_r(R),
        .vga_g(G),
        .vga_b(B),
        .vga_hs(HS),
        .vga_vs(VS),
        .vga_de(DE),

        .turn_mode(key),
        .mode(led)
        );

    clk_wiz_0 clk
    (
      .clk_out1(pixel_clk),
      .reset(1'b0),
      .locked(),
      .clk_in1(clk100M)
     );

endmodule

编写引脚约束文件,在官方给出的原理图中都可以查到。
pins.xdc

# Clk(板子上的GCLK)
set_property PACKAGE_PIN Y9 [get_ports {clk100M}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk100M}]

# Rst(板子上的BTNU)
set_property PACKAGE_PIN T18 [get_ports {rst}]
set_property IOSTANDARD LVCMOS33 [get_ports {rst}]

# key 板子上的按键
set_property PACKAGE_PIN P16 [get_ports {key}]
set_property IOSTANDARD LVCMOS33 [get_ports {key}]

# Led0
set_property PACKAGE_PIN T22 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]

# Led1
set_property PACKAGE_PIN T21 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]

# Led2
set_property PACKAGE_PIN U22 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]

# Led3
set_property PACKAGE_PIN U21 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]

set_property PACKAGE_PIN  Y19  [get_ports {vga_vs}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_vs}]

set_property PACKAGE_PIN  AA19  [get_ports {vga_hs}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_hs}]

set_property PACKAGE_PIN  V20   [get_ports {vga_r[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_r[0]}]
set_property PACKAGE_PIN    U20 [get_ports {vga_r[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_r[1]}]
set_property PACKAGE_PIN   V19  [get_ports {vga_r[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_r[2]}]
set_property PACKAGE_PIN   V18  [get_ports {vga_r[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_r[3]}]

set_property PACKAGE_PIN  AB22   [get_ports {vga_g[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_g[0]}]
set_property PACKAGE_PIN   AA22  [get_ports {vga_g[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_g[1]}]
set_property PACKAGE_PIN   AB21  [get_ports {vga_g[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_g[2]}]
set_property PACKAGE_PIN   AA21  [get_ports {vga_g[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_g[3]}]

set_property PACKAGE_PIN   Y21  [get_ports {vga_b[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_b[0]}]
set_property PACKAGE_PIN   Y20  [get_ports {vga_b[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_b[1]}]
set_property PACKAGE_PIN   AB20  [get_ports {vga_b[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_b[2]}]
set_property PACKAGE_PIN   AB19  [get_ports {vga_b[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_b[3]}]

分析综合产生比特流文件,后进行下载。
Zedboard学习(七):VGA显示_第11张图片

按键设置:
图中BTNU键位复位键;BTNC键位模式切换键,每按一次切换显示模式。
Zedboard学习(七):VGA显示_第12张图片

连上vga线,可以看到现象如下:
Zedboard学习(七):VGA显示_第13张图片

Zedboard学习(七):VGA显示_第14张图片

Zedboard学习(七):VGA显示_第15张图片

Zedboard学习(七):VGA显示_第16张图片

Zedboard学习(七):VGA显示_第17张图片

Zedboard学习(七):VGA显示_第18张图片

Zedboard学习(七):VGA显示_第19张图片

Zedboard学习(七):VGA显示_第20张图片

Zedboard学习(七):VGA显示_第21张图片

Zedboard学习(七):VGA显示_第22张图片

Zedboard学习(七):VGA显示_第23张图片

Zedboard学习(七):VGA显示_第24张图片

你可能感兴趣的:(zedboard)