上一篇介绍了vga显示图像的基础知识。这一节我们来实现vga彩条显示。实现步骤:
1、接口分析。module的接口,除了一般的clk,rst,还需要输出水平同步信号,垂直同步信号,以及RGB颜色值。
2、扫描过程各个参数的值。这个可以通过查阅VISA手册(见附件),得到想要输出分辨率下的各个参数值。主要有时钟频率、同步信号极性、同步信号宽度、后沿宽度、边框、显示区域、前沿等。
3、调用PLL。VGA时钟频率一般和输入钟频率不同,为了得到比较精确的VGA始终频率,需要使用PLL输出。
4、水平和垂直扫描计数。通过设置水平和垂直两个计数器来确定当前扫描位置,也可以看作当前扫描像素的坐标。
5、同步信号输出。根据当前扫描点位置和第二步中参数值来决定水平、垂直同步信号的输出。
6、判断是否在显示区域。根据当前扫描点的位置和各个参数值,判断行是否在显示区域,列是否在显示区域,如果行、列都在显示区域,则当前扫描点在显示区域。
7、输出RGB值。当扫描点进入显示区域后,输出RGB的值。否则,RGB应当输出零。
程序参考代码如下:
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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | module VGA_colorbar( input wire sysclk, //系统时钟,也就是板子的时钟 input wire rst, output reg [3:0] R, //输出的颜色值 output reg [3:0] G, //输出的颜色值 output reg [3:0] B, //输出的颜色值 output wire HS, //水平同步信号 output wire VS //垂直同步信号 ); //显示分辨率 640*480@60Hz //时钟25.175M localparam HPOLA = 0; //水平同步信号极性 localparam VPOLA = 0; //垂直同步信号极性 localparam HTOTAL = 800;//水平总像素数 localparam HSYNCP = 96; //水平同步信号像素数 localparam HBACKP = 40; //扫描后沿像素数 localparam LBorder = 8; //左边框 localparam HDISP = 640;//显示区域 localparam RBorder = 8; //右边框 localparam HFRONTP = 8; //扫描前沿像素数 localparam VTOTAL = 525;//垂直总像素数 localparam VSYNCP = 2; //垂直同步信号 localparam VBACKP = 25; //扫描后沿像素数 localparam TBorder = 8; //顶边框 localparam VDISP = 480;//显示区域 localparam BBorder = 8; //底边框 localparam VFRONTP = 2; //扫描前沿像素数 wire vgaclk; wire locked; wire vgarst; assign vgarst = ~locked; //locked为高表示时钟正常,此时不复位 //使用锁相环来输出指定时钟 pll pll_inst ( .areset ( rst ), .inclk0 ( sysclk ), .c0 ( vgaclk ), .locked ( locked ) ); reg [9:0] hcnt; //行计数 reg [9:0] vcnt; //场计数 //行计数 always@(posedge vgaclk or posedge vgarst) begin if(vgarst) hcnt <= 0; else if(hcnt == HTOTAL - 1) hcnt <= 0; else hcnt <= hcnt + 1; end //场计数 always@(posedge vgaclk or posedge vgarst) begin if(vgarst) vcnt <= 0; else if((hcnt == HTOTAL - 1) && (vcnt == VTOTAL - 1)) vcnt <= 0; else if(hcnt == HTOTAL - 1) vcnt <= vcnt + 1; else vcnt <= vcnt; end //行同步信号输出 assign HS = (hcnt <= HSYNCP - 1) ? HPOLA : ~HPOLA; //场同步信号输出 assign VS = (vcnt <= VSYNCP - 1) ? VPOLA : ~VPOLA; //显示区域的判断 wire h_disp; assign h_disp = (hcnt > (HSYNCP + HBACKP + LBorder - 1) && hcnt < (HSYNCP + HBACKP + LBorder + HDISP - 1)) ? 1'b1 : 1'b0; wire v_disp; assign v_disp = (vcnt > (VSYNCP + VBACKP + TBorder - 1) && vcnt < (VSYNCP + VBACKP + TBorder + VDISP- 1)) ? 1'b1 : 1'b0; wire disp; assign disp = h_disp && v_disp; //如果扫描到显示区域内部,则输出颜色值 always@(posedge vgaclk or posedge vgarst) begin if(vgarst) begin R <= 4'b0000; G <= 4'b0000; B <= 4'b0000; end else if(disp) begin if(hcnt < (HSYNCP + HBACKP + LBorder) + HDISP/5 - 1) begin R <= 4'b1111; G <= 4'b0000; B <= 4'b0000; end else if(hcnt < (HSYNCP + HBACKP + LBorder) + HDISP*2/5 - 1) begin R <= 4'b0000; G <= 4'b1111; B <= 4'b0000; end else if(hcnt < (HSYNCP + HBACKP + LBorder) + HDISP*3/5 - 1) begin R <= 4'b0000; G <= 4'b0000; B <= 4'b1111; end else if(hcnt < (HSYNCP + HBACKP + LBorder) + HDISP*4/5 - 1) begin R <= 4'b1111; G <= 4'b1111; B <= 4'b0000; end else if(hcnt < (HSYNCP + HBACKP + LBorder) + HDISP - 1) begin R <= 4'b1111; G <= 4'b1111; B <= 4'b1111; end end else begin R <= 4'b0000; G <= 4'b0000; B <= 4'b0000; end end endmodule |