根据PRX100T-D原理图和项目设计要求,我们设计了hdmi 图像显示项目的框图:
其中:
虚线中的是fpga内部逻辑,IN_CLK_50M 为板子上的时钟输入给FPGA;PB[7:1] 代表7个按键;HDMI_CLK 为fpga 输出的pixel 时钟(adv7511 视频输入时钟); IIC_SDA,IIC_SCL 为fpga 输出用来配置adv7511 寄存器; HDMI_HS,HDMI_VS,HDMI_D[23:0], HDMI_EN 有fpga 输出, 提供给adv7511 作为VESA视频格式信号。
FPGA主要分为几个主要的模块:
- pll:输入的时钟源50M 时钟, 产生50M 系统时钟; 产生VESA 标准所需要的148.5M 时钟(1920 x 1080 @60Hz)。
- key_filter: 使用148.5M 时钟, 将输入按键滤波,同时产生和148.5M时钟同步的单沿脉冲。
- rom: 存储莲花图像数据,之后会根据VESA 标准 ,将数据输出到adv7511 上。
- vga_driver: 产生VESA标准的1920 x 1080 @ 60Hz 所需要的h,v,de 信号。
- vga_show: 根据h,v,de等信号,平时输出莲花图像在屏幕中心,当有按键信号时, 根据按键信号的含义,将图像上下左右移动, 按OK 键 ,回到初始位置。
- iic_cfg: 用于配置adv7511 芯片, 包括adv7511 输入视频格式, 输出视频格式等。
设计需求:
- 要求使用100T开发板上的ADV7511进行图片显示;
- 显示区域分辨率为1920*1080,要显示的图片分辨率480 * 270pix;
- 要求图片显示在屏幕中央,可以通过按键进行上下移动, 按下中心按键可以返回中心;
项目顶层代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
`timescale 1ns / 1ps module hdmi_pic_show ( input IN_CLK_50M, input [7:1] PB, output HDMI_CLK, output HDMI_HS, output HDMI_VS, output HDMI_EN, output [23:0] HDMI_D, inout IIC_SDA, inout IIC_SCL ); //==================================== //pll wire sys_clk_50m,vga_clk; wire locked,sys_rst_n; pll pll_inst ( .clk_out1 (sys_clk_50m), // output clk_out1 .clk_out2 (vga_clk), // 148.5MHz .reset (1'b0), // input reset .locked (locked), // output locked .clk_in1 (IN_CLK_50M) ); // input clk_in1 assign sys_rst_n = locked; //===================================== //key wire center_flag; wire up_flag; wire down_flag; wire left_flag; wire right_flag; key_filter #( .DVI_CNT(148) ) key_filter_inst( .clk (vga_clk), .rst_n (sys_rst_n), .pb (PB), .center_flag(center_flag), .up_flag (up_flag), .down_flag (down_flag), .left_flag (left_flag), .right_flag (right_flag) ); //================================= //vga_driver wire h_sync; wire v_sync; wire hv_de; vga_driver #( .h_sync_pola (1), .v_sync_pola (1) ) vga_driver_inst( .vga_clk (vga_clk), .rst_n (sys_rst_n), .h_sync (h_sync), .v_sync (v_sync), .hv_de (hv_de) ); //================================= //rom wire [16:0] rd_rom_addr; wire [23:0] rd_rom_data; pic_rom pic_rom_inst ( .clka (vga_clk), // input wire clka .addra (rd_rom_addr), // input wire [16 : 0] addra .douta (rd_rom_data) // output wire [23 : 0] douta ); //================================= // i2c iic_cfg iic_cfg_inst( .clk (sys_clk_50m), //50m .rst_n (sys_rst_n), .iic_sda (IIC_SDA), .iic_scl (IIC_SCL) ); //================================ vga_show #( .h_pix (1920), .v_pix (1080) ) vga_show_inst( .vga_clk (vga_clk), .rst_n (sys_rst_n), .h_sync (h_sync), .v_sync (v_sync), .hv_de (hv_de), .center_flag(center_flag), .up_flag (up_flag), .down_flag (down_flag), .left_flag (left_flag), .right_flag (right_flag), .rd_rom_data(rd_rom_data), .rd_rom_addr(rd_rom_addr), .hdmi_hs (HDMI_HS), .hdmi_vs (HDMI_VS), .hdmi_en (HDMI_EN), .hdmi_d (HDMI_D) ); //assign HDMI_CLK = vga_clk; ODDR # ( .DDR_CLK_EDGE ("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" .INIT (1'b0), // Initial value of Q: 1'b0 or 1'b1 .SRTYPE ("ASYNC") // Set/Reset type: "SYNC" or "ASYNC" ) pclk_clk_out ( .Q (HDMI_CLK), // 1-bit DDR output .C (vga_clk), .CE (1'b1), // 1-bit clock enable input .D1 (1'b1), // 1-bit data input (positive edge) .D2 (1'b0), // 1-bit data input (negative edge) .R (1'b0), // 1-bit reset .S (1'b0) // 1-bit set ); endmodule |
pll 产生的时钟vga_clk (148.5M)没有直接使用assign 输出到pin 上, 而是使用了xilinx 的原语ODDR,这样可以保证时钟比较稳定,不受片外负载的影响。相当于将ODDR 的D1, D2 的数据 输出到HDMI_CLK 上了。

