admin管理员组

文章数量:1794759

FPGA

FPGA

VGA显示8色彩条的实现

使用软件:Quartus II 13.1
使用语言 :Verilog HDL
板载芯片:EP4CE6E22C8

VGA显示8色彩条的实现

  • VGA显示8色彩条的实现
    • 写在前面
    • 准备工作
      • VGA接口
      • VGA 时序
      • 开始Coding
    • 结果显示
    • 写在最后

写在前面

由于之前在学校学习的FPGA基础是基于VHDL(Very-High-Speed Integrated Circuit Hardware Description Language)的,但大都已经忘记不太想从头再来,所以再次学习并接触FPGA,想用另一种更接近C语言的HDL(硬件描述语言)–也就是Verilog HDL。

VHDL有entity(实体),architecture(结构体)configuration(配置)package(包),和library(库)

  • entity内部主要包括端口的声明,建立一个黑盒子的模型。

  • architecture内部主要包括行为级的内部逻辑设计,进行各个进程或状态机的配置。

  • library 用于引用所需要的库文件。常使用库文件library ieee;

  • package用于引用需要的包文件。例如,如果要使用std_logic(标准逻辑)类型,应对类型所在包进行声明use ieee.std_logic_1164.all;,否则会报错;如果行为级建模是需要运算符重载,则要声明use ieee.std_logic_unsigned.all,如果需要类型转换从整型转化为逻辑矢量类型的函数CONV_STD_LOGIC_VECTOR(begin,end),则需要引用use ieee.std_logic_arith.all

当然与VHDL 类似的 ,Verilog HDL 也有着类似的结构,比如module(模块)procedural(过程块) `include(头文件)对应 于 VHDLportprocess,package。所以如果有C语言和VHDL语言的基础,VerilogHDL是不成问题的。

准备工作

书归正传,了解了使用语言的语法有利于代码的编写和代码的阅读。

我们应该再了解一下VGA相关的知识。

VGA接口

VGA接口是一种D型接口,采用非对称分布连接方式,共有15针.对用户来说,其引出线常用的有5个信号:红色 R,绿色 G,蓝色B,行同步信号HS,场同步信号 VS.HS和 VS的作用是处理输入模拟信号,并联合起来控制VGA的显示时序,分别对应PIN1、PIN2、PIN3、PIN13、PIN14。

是不是有点抽象?这边上图最为直接明了

当然,美术生和 Photoshop使用者应该对色彩不会太陌生,Red、Green、Blue正是三原色,经过不同的混合碰撞,产生色彩缤纷的世界,进而显示再屏幕上,但是硬件内部实现输出的是数字信号,无法被显示在VGA显示屏上,因而需要进行数模转换DAC(Digital Analog Convertor),常用的数模转换芯片是ADV7125,是3个8位视频信号的DAC信号的转换。

但是,芯片开销会比较大,所以一般VGA视频图像信号都使用权电阻网络(如下图所示)来完成

当 R s = 8 R {R_s = 8R } Rs​=8R, V o = − V r e f 2 8 D n {V_o = -\frac{V_{ref}}{2^8}D_n} Vo​=−28Vref​​Dn​, D n 是 高 位 ( M S B ) 或 低 位 ( L S B ) 电 阻 权 重 {D_n}是高位(MSB)或低位(LSB)电阻权重 Dn​是高位(MSB)或低位(LSB)电阻权重

VGA 时序

了解了VGA接口的相关知识,进一步了解一下VGA时序的知识,因为书写代码一般是以时序为准。以一般工业标准来说,640*480@60是显示比较稳定且易于掌握的,因而下文皆是根据640*480@60讲述的。
@Attention:640*480@60,表示行列总共有307200个像素点,同时显示一帧图像的速率是60MHz

由上图可知行扫描周期以像素为单位,分别由行同步、后沿、图像有效区域、前沿直到下一帧图像开始,当完成一行的扫描后,场扫描周期开始,同时经过场同步、上沿,图像有效区域、下沿构成。

开始Coding

根据前面的讲解应该对VGA显示有所了解,因而开始Coding。

/*
* @author: LangZi
* @data:2021.12.26
* @modulename:VGA
* @header:include"vga_param.v"
*/
`include"vga_param.v"
module VGA(
clock	,
switch	,
out_RGB	,
hsync	,
vsync
);
input  clock		;    //系统时钟 50MHz
input  [1:0] switch	;	//用于切换模式,显示棋盘格output [2:0] out_RGB;   //VGA输出颜色
output  hsync		;   //VGA扫描信号
output  vsync		;   //VGA场扫描信号reg [9:0]    hcount	;   //VGA行计数器
reg [9:0]    vcount	;  //VGA场计数器
reg [2:0]    data		;
reg [2:0]    h_dat		;
reg [2:0]    v_dat		;reg   flag				;	//标志位
wire  hcount_ov			; 	//溢出信号
wire  vcount_ov			;
wire  dat_act			;
wire  hsync				;
wire  vsync				;
reg  vga_clk			;//分频操作活得25MHz的时钟
always @(posedge clock)
begin
vga_clk = ~vga_clk;
end//************************VGA驱动******************************* 
//行计数
always @(posedge vga_clk)
begin
if (hcount_ov)// 若溢出则清零
hcount <= 10'd0;
else
hcount <= hcount + 10'd1;
end
assign hcount_ov = (hcount == hpixel_end);
//场计数
always @(posedge vga_clk)
begin
if (hcount_ov)
begin
if (vcount_ov)
vcount <= 10'd0;
else
vcount <= vcount + 10'd1;
end
end
assign  vcount_ov = (vcount == vline_end);
//判断是否处于有效数据区域
assign dat_act =    ((hcount >= hdat_begin) && (hcount < hdat_end))
&& ((vcount >= vdat_begin) && (vcount < vdat_end));
assign hsync = (hcount > hsync_end);
assign vsync = (vcount > vsync_end);
assign disp_RGB = (dat_act) ?  data : 3'h00;       //************************VGA 显示处理操作******************************* 
always @(posedge vga_clk)
begin
case(switch[1:0])
2'd0: data <= h_dat;      //行数据
2'd1: data <= v_dat;      //列数据
2'd2: data <= (v_dat ^ h_dat); //棋盘格
2'd3: data <= (v_dat ~^ h_dat); //转置棋盘
endcase
endalways @(posedge vga_clk)  //行彩条计数时序
begin
if(hcount < 223)
v_dat <= 3'h7;         
else if(hcount < 303)
v_dat <= 3'h6;   
else if(hcount < 383)
v_dat <= 3'h5;   
else if(hcount < 463)
v_dat <= 3'h4;    
else if(hcount < 543)
v_dat <= 3'h3;   
else if(hcount < 623)
v_dat <= 3'h2;   
else if(hcount < 703)
v_dat <= 3'h1;   
else 
v_dat <= 3'h0;   
endalways @(posedge vga_clk)  //列彩条计数时序
begin
if(vcount < 94)
h_dat <= 3'h7;        
else if(vcount < 154)
h_dat <= 3'h6;   
else if(vcount < 214)
h_dat <= 3'h5;   
else if(vcount < 274)
h_dat <= 3'h4;    
else if(vcount < 334)
h_dat <= 3'h3;   
else if(vcount < 394)
h_dat <= 3'h2;   
else if(vcount < 454)
h_dat <= 3'h1;   
else 
h_dat <= 3'h0;   
endendmodule

时序参数的头文件(vga_param.v)

`ifndef __VGA_PARAM_
`define __VGA_PARAM_640_480_60MHz
`define hsync_end    10'd95
`define hdat_begin   10'd143
`define hdat_end     10'd783
`define hpixel_end   10'd799
`define vsync_end 	 10'd1
`define vdat_begin   10'd34
`define vdat_end     10'd514
`define vline_end  	 10'd524
`endif

引入头文件,可以提升代码的可移植性,同时可以将文件的代码风格显示的更简洁,易懂

结果显示




写在最后

FPGA的首篇作文,尚有不足,愿共勉。

本文标签: FPGA