电子设计自动化课程设计报告电子设计自动化课程设计报告学生姓名:学号:课设题目: VGA彩条信号显示控制器设计同组人:电子设计自动化课程设计报告郝欣欣一、课程设计内容1、使用Verilog语言和Modelsim仿真器完成可显示横彩条、竖彩条、棋盘格相间的VGA控制器的设计和验证2、设计并验证可显示英语单词”HIT”的VGA 控制器3、使用Quartus II和SOPC实验箱验证设计的正确性4、Verilog代码要符合微电子中心编码标准二、FPGA原理CPLD、FPGA是在PAL、GAL等基础上发展起来的一种具有丰富的可编程I/O 引脚、逻辑宏单元、门电路以及RAM空间的可编程逻辑器件,几乎所有应用门阵列、PLD和中小规模通用数字集成电路的场合均可应用FPGA和CPLD器件。
CPLD的设计是基于乘积项选择矩阵来实现的,而FPGA基于查找表来设计的。
查找表就是实现将输入信号的各种组合功能以一定的次序写入RAM中,然后在输入信号的作用下,输出特定的函数运算结果。
其结构图如图1所示:图1. FPGA查找表单元一个N输入查找表(LUT,Look Up Table)可以实现N个输入变量的任何逻辑功能,如N输入“与”、N输入“异或”等。
输入多于N个的函数、方程必须分开用几个查找表(LUT)实现(如图2所示)。
图2 FPGA查找表单元内部结构该系统设计中,FPGA芯片用的是ALTERA公司的EP1K30QC208-2,它的系统结构如图3所示。
它由若干个逻辑单元和中央布线池加I/O端口构成图3 EP1K30QC208内部结构三、VGA接口VGA的全称为Video Graphic Array,即显示绘图阵列。
在PC行业发展的初期,VGA以其支持在640X480的较高分辨率下同时显示16种色彩或256种灰度,同时在320X240分辨率下可以同时显示256种颜色的良好特性得到广泛支持。
后来,厂商们纷纷在VGA基础上加以扩充,如将显存提高至1M并使其支持更高分辨率如800X600或1024X768,这些扩充的模式就称之为VESA(Video Electronics Standards Association,视频电子标准协会)的Super VGA模式,简称SVGA,现在的显卡和显示器都支持SVGA模式。
图4 VGA接口VGA接口就是显卡上输出模拟信号的接口,也叫D-Sub接口。
VGA接口是一种D型接口,上面共有15针空,分成三排,每排五个。
VGA接口是显卡上应用最为广泛的接口类型,绝大多数的显卡都带有此种接口。
表1 VGA管脚定义管脚定义1 红基色 red2 绿基色 green3 蓝基色 blue4 地址码 ID Bit5 自测试 (各家定义不同)6 红地7 绿地8 蓝地9 保留(各家定义不同)10 数字地11 地址码12 地址码13 行同步14 场同步15 地址码 (各家定义不同)通过模拟VGA接口和计算机连接的显示器的工作原理,是计算机内部以数字方式生成的显示图像信息,被显卡中的数字/模拟转换器转变为R、G、B三原色信号和行、场同步信号,信号通过电缆传输到显示设备中。
对于模拟显示设备,如模拟CRT显示器,信号被直接送到相应的处理电路,驱动控制显像管生成图像。
而对于LCD、DLP等数字显示设备,显示设备中需配置相应的A/D(模拟/数字)转换器,将模拟信号转变为数字信号。
在经过D/A和A/D2次转换后,不可避免地造成了一些图像细节的损失。
VGA接口应用于CRT显示器无可厚非,但用于连接液晶之类的显示设备,则转换过程的图像损失会使显示效果略微下降。
CRT显示器因为设计制造上的原因,只能接受模拟信号输入,也就是我们为什么在CRT显示器上只看到VGA接口的原因。
四、VGA显示接口原理计算机显示器的显示有许多标准,常见的有VGA、SVGA等。
本系统采用FPGA 来实现图像显示控制器,这在产品开发设计中有许多实际应用。
常见的彩色显示器,一般由CRT(阴极射线管)构成,彩色是由G、R、B(绿:Green,红:Red,蓝:Blue)三基色组成。
显示是用逐行扫描的方式解决,阴极射线枪发出电子束打在涂有荧光粉的荧光屏上,产生GRB三基色,合成一个彩色像素。
扫描从屏幕的左上方开始,从左到右,从上到下,进行扫描,每扫完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行行同步;扫描完所有行,用场同步信号进行场同步,并使扫描回到屏幕的左上方,同时进行场消隐,预备下一场的扫描。
对于普通的VGA显示器,其引出线共含5个信号:G、R、B:三基色信号;HS:行同步信号;VS:场同步信号。
对于5个信号的时序驱动,对于VGA显示器要严格遵循“VGA工业标准”,即640×480×60Hz模式。
通常我们用的显示器都满足工业标准,因此我们设计VGA控制器时要参考显示器的技术规格。
图5是VGA行扫描、场扫描的时序图:图5 VGA行扫描、场扫描时序图表2 VGA参考时序设计VGA工业标准所要求的频率:时钟频率(Clock frequency):25.175MHz(像素输出的频率);行频(Line frequency):31469Hz;场频(Field frequency):59.94Hz(每秒图像刷新频率)。
五、FPGA的设计实现设计VGA图像显示控制需要注意两个问题:一个是时序的驱动,这是完成设计的关键,时序稍有偏差,显示必然不正常,甚至会损坏彩色显示器;另一个是VGA信号的电平驱动。
显示控制器设计提示:显示器的技术规格提供的行频一般都满足在30-45KHz(保守数据),场频一般满足在50-75Hz(保守数据),针对以上保守数据,我们以30KHz的行频进行扫描时所需时钟频率为:30KHz×800(行周期)=24MHz,则场频为:30KHz÷525(场周期)=57.14Hz,针对实验箱的条件,可以用12MHz的信号经过倍频(EP1K30QC208-2芯片特有的功能,在MaxPlusII软件中调用参数可设置兆功能元件库mega_lpm的CLKLOCK元件来倍频)来产生24MHz 的时钟频率,参考设计的顶层文件如下图所示:图6.VGA接口实现顶视图VGACORE模块包含了扫描时序产生模块、图像描述模块。
时序产生模块的设计可参考图5所示来设计,图像描述模块主要通过640×480个像素点来描述图像。
如本项设计的彩条信号发生器可通过图像描述模块产生如下表所示的3种显示模式,共6种显示变化的图像。
1 行彩条1:白黄青绿品红蓝黑2:黑蓝红品绿青黄白2 竖彩条1:白黄青绿品红蓝黑2:黑蓝红品绿青黄白3 棋盘格1:棋盘格显示模式1 2:棋盘格显示模式2颜色黑蓝红品绿青黄白G 0 0 0 0 1 1 1 1R 0 0 1 1 0 0 1 1B 0 1 0 1 0 1 0 1计是对视频数据进行处理,用普通的设计方法(不使用专用芯片),在单芯片上实现是不可思议的,而在此用FPGA设计,轻松地达到了面积和速度上的要求。
六、程序及仿真(一)、管脚分配本设计采用主板上的VGA接口实验模式:模式5时钟及控制clk----->pin_29 clock9 实验要求采用12M的时钟rst----->pin_240 键8,低电平有效,作为使能信号MD ----->pin_233 键1,模式选择信号,共有6种模式显示器输出R ----->pin_180 PIO29G ----->pin_181 PIO30B ----->pin_182 PIO31HS ----->pin_183 PIO32VS ----->pin_185 PIO34(二)、彩条发生器程序实现及仿真1、主程序module vga( clk_25m,rst_n, //系统控制hsync,vsync,vga_rgb,MD // VGA控制);input clk_25m; // 25MHzinput rst_n; //低电平复位input MD;// FPGA与VGA接口信号output hsync; //行同步信号output vsync; //场同步信号output[2:0] vga_rgb;//--------------------------------------------------// 坐标计数reg[9:0] x_cnt; //行坐标reg[9:0] y_cnt; //列坐标always @ (posedge clk_25m or negedge rst_n)if(!rst_n) x_cnt <= 10'd0;else if(x_cnt == 10'd799) x_cnt <= 10'd0;else x_cnt <= x_cnt+1'b1;always @ (posedge clk_25m or negedge rst_n)if(!rst_n) y_cnt <= 10'd0;else if(y_cnt == 10'd524) y_cnt <= 10'd0;else if(x_cnt == 10'd799) y_cnt <= y_cnt+1'b1;//--------------------------------------------------// 产生VGA场同步,行同步信号reg hsync_r,vsync_r;always @ (posedge clk_25m or negedge rst_n)if(!rst_n) hsync_r <= 1'b1;else if(x_cnt == 10'd0) hsync_r <= 1'b0; //产生hsync信号else if(x_cnt == 10'd96) hsync_r <= 1'b1;always @ (posedge clk_25m or negedge rst_n)if(!rst_n) vsync_r <= 1'b1;else if(y_cnt == 10'd0) vsync_r <= 1'b0; //产生vsync信号else if(y_cnt == 10'd2) vsync_r <= 1'b1;assign hsync = hsync_r;assign vsync = vsync_r;//--------------------------------------------------//有效显示标志位产生reg valid_yr; //行显示有效信号always @ (posedge clk_25m or negedge rst_n)if(!rst_n) valid_yr <= 1'b0;else if(y_cnt == 10'd32) valid_yr <= 1'b1;else if(y_cnt == 10'd512) valid_yr <= 1'b0;wire valid_y = valid_yr;reg valid_r; // VGA有效显示区标志位always @ (posedge clk_25m or negedge rst_n)if(!rst_n) valid_r <= 1'b0;else if((x_cnt == 10'd141) && valid_y) valid_r <= 1'b1;else if((x_cnt == 10'd781) && valid_y) valid_r <= 1'b0; wire valid = valid_r;wire[9:0] x_dis; //横坐标显示有效区域相对坐标值0-639 wire[9:0] y_dis; //竖坐标显示有效区域相对坐标值0-479 assign x_dis = x_cnt - 10'd142;assign y_dis = y_cnt - 10'd33;//--------------------------------------------------//---------------------------------------------reg[2:0] cnt;always @ (posedge MD or negedge rst_n) beginif(!rst_n)cnt <= 3'd0;else if(cnt==3'd5)cnt<=3'd0;elsecnt<=cnt+3'd1;end//--------------------------------------------------// VGA色彩信号产生/*RGB = 000 黑色RGB = 100 红色= 001 蓝色= 101 紫色= 010 绿色= 110 黄色= 011 青色= 111 白色*///----------------------------------------------------reg[2:0] vga_rgb;always@( posedge clk_25m)beginif(!valid) vga_rgb <= 3'd0;else beginif (cnt==3'd0)begin //竖彩条模式if(x_dis >= 10'd0 && x_dis < 10'd80) vga_rgb <= 3'd0;else if(x_dis >= 10'd80 && x_dis < 10'd160) vga_rgb <= 3'd1;else if(x_dis >= 10'd160 && x_dis < 10'd240) vga_rgb <= 3'd2;else if(x_dis >= 10'd240 && x_dis < 10'd320) vga_rgb <= 3'd3;else if(x_dis >= 10'd320 && x_dis < 10'd400) vga_rgb <= 3'd4;else if(x_dis >= 10'd400 && x_dis < 10'd480) vga_rgb <=3'd5;else if(x_dis >= 10'd480 && x_dis < 10'd560) vga_rgb <= 3'd6;else if(x_dis >= 10'd560 && x_dis < 10'd640) vga_rgb <= 3'd7;endif (cnt==3'd1)begin //竖彩条模式if(x_dis >= 10'd0 && x_dis < 10'd80) vga_rgb <= 3'd7;else if(x_dis >= 10'd80 && x_dis < 10'd160) vga_rgb <= 3'd6;else if(x_dis >= 10'd160 && x_dis < 10'd240) vga_rgb <= 3'd5;else if(x_dis >= 10'd240 && x_dis < 10'd320) vga_rgb <= 3'd4;else if(x_dis >= 10'd320 && x_dis < 10'd400) vga_rgb <= 3'd3;else if(x_dis >= 10'd400 && x_dis < 10'd480) vga_rgb <=3'd2;else if(x_dis >= 10'd480 && x_dis < 10'd560) vga_rgb <= 3'd1;else if(x_dis >= 10'd560 && x_dis < 10'd640) vga_rgb <= 3'd0;endif(cnt==3'd2)begin //横彩条模式if(y_dis >= 10'd0 && y_dis < 10'd60) vga_rgb <= 3'd0;else if(y_dis >= 10'd60 && y_dis < 10'd120) vga_rgb <= 3'd1;else if(y_dis >= 10'd120 && y_dis < 10'd180) vga_rgb <= 3'd2;else if(y_dis >= 10'd180 && y_dis < 10'd240) vga_rgb <= 3'd3;else if(y_dis >= 10'd240 && y_dis < 10'd300) vga_rgb <= 3'd4;else if(y_dis >= 10'd300 && y_dis < 10'd360) vga_rgb <= 3'd5;else if(y_dis >= 10'd360 && y_dis < 10'd420) vga_rgb <= 3'd6;else if(y_dis >= 10'd420 && y_dis < 10'd480) vga_rgb <=3'd7; endif(cnt==3'd3)begin //横彩条模式if(y_dis >= 10'd0 && y_dis < 10'd60) vga_rgb <= 3'd7;else if(y_dis >= 10'd60 && y_dis < 10'd120) vga_rgb <= 3'd6;else if(y_dis >= 10'd120 && y_dis < 10'd180) vga_rgb <= 3'd5;else if(y_dis >= 10'd180 && y_dis < 10'd240) vga_rgb <= 3'd4;else if(y_dis >= 10'd240 && y_dis < 10'd300) vga_rgb <= 3'd3;else if(y_dis >= 10'd300 && y_dis < 10'd360) vga_rgb <= 3'd2;else if(y_dis >= 10'd360 && y_dis < 10'd420) vga_rgb <= 3'd1;else if(y_dis >= 10'd420 && y_dis < 10'd480) vga_rgb <=3'd0;endif(cnt==3'd4)begin //棋盘格模式case(x_dis)10'd0: beginif(y_dis >= 10'd0 && y_dis < 10'd60) vga_rgb <= 3'd0;else if(y_dis >= 10'd60 && y_dis < 10'd120) vga_rgb <= 3'd1;else if(y_dis >= 10'd120 && y_dis < 10'd180) vga_rgb <= 3'd2;else if(y_dis >= 10'd180 && y_dis < 10'd240) vga_rgb <= 3'd3;else if(y_dis >= 10'd240 && y_dis < 10'd300) vga_rgb <= 3'd4;else if(y_dis >= 10'd300 && y_dis < 10'd360) vga_rgb <= 3'd5;else if(y_dis >= 10'd360 && y_dis < 10'd420) vga_rgb <= 3'd6;else if(y_dis >= 10'd420 && y_dis < 10'd480) vga_rgb <= 3'd7;end10'd80,10'd160,10'd240,10'd320,10'd400,10'd480,10'd560,10'd640: vga_rgb <= vga_rgb+3'd1; //每80个横坐标像素点后显示色彩数据增1变化default: ;endcaseendif(cnt==3'd5)begin //棋盘格模式case(x_dis)10'd0: beginif(y_dis >= 10'd0 && y_dis < 10'd60) vga_rgb <= 3'd7;else if(y_dis >= 10'd60 && y_dis < 10'd120) vga_rgb <= 3'd6;else if(y_dis >= 10'd120 && y_dis < 10'd180) vga_rgb <= 3'd5;else if(y_dis >= 10'd180 && y_dis < 10'd240) vga_rgb <= 3'd4;else if(y_dis >= 10'd240 && y_dis < 10'd300) vga_rgb <= 3'd3;else if(y_dis >= 10'd300 && y_dis < 10'd360) vga_rgb <= 3'd2;else if(y_dis >= 10'd360 && y_dis < 10'd420) vga_rgb <= 3'd1;else if(y_dis >= 10'd420 && y_dis < 10'd480) vga_rgb <= 3'd0;end10'd80,10'd160,10'd240,10'd320,10'd400,10'd480,10'd560,10'd640: vga_rgb <= vga_rgb+3'd1; //每80个横坐标像素点后显示色彩数据增1变化default: ;endcaseendendendendmodule2、验证程序`timescale 1 ns/ 1 psmodule tb_vga ();reg t_clk_25m;reg t_rst_n;wire t_hsync;wire [2:0] t_vga_rgb;wire t_vsync;wire t_MD;vgahct dut( .clk_25m(t_clk_25m),.hsync(t_hsync),.rst_n(t_rst_n),.vga_rgb(t_vga_rgb),.vsync(t_vsync),.MD(t_MD));initialbegint_clk_25m=0;t_rst_n=1;t)MD=0;#20;t_rst_n=0;#50;t_rst_n=1;$display("Running testbench");#10000000000 $stop;endalways #0.04 t_clk_25m=~t_clk_25m;always #200 t_MD=~t_MD;endmodule3、仿真波形(三)、字符显示程序及仿真1、主程序`timescale 1ns / 1psmodule vga_char( clk_25m,rst_n, //系统控制hsync,vsync,vga_rgb // VGA控制);input clk_25m; // 25MHzinput rst_n; //低电平复位// FPGA与VGA接口信号output hsync; //行同步信号output vsync; //场同步信号output[2:0] vga_rgb;//--------------------------------------------------// 坐标计数reg[9:0] x_cnt; //行坐标reg[9:0] y_cnt; //列坐标always @ (posedge clk_25m or negedge rst_n)if(!rst_n) x_cnt <= 10'd0;else if(x_cnt == 10'd799) x_cnt <= 10'd0;else x_cnt <= x_cnt+1'b1;always @ (posedge clk_25m or negedge rst_n)if(!rst_n) y_cnt <= 10'd0;else if(y_cnt == 10'd524) y_cnt <= 10'd0;else if(x_cnt == 10'd799) y_cnt <= y_cnt+1'b1;//--------------------------------------------------// VGA场同步,行同步信号reg hsync_r,vsync_r; //同步信号always @ (posedge clk_25m or negedge rst_n)if(!rst_n) hsync_r <= 1'b1;else if(x_cnt == 10'd0) hsync_r <= 1'b0; //产生hsync信号else if(x_cnt == 10'd96) hsync_r <= 1'b1;always @ (posedge clk_25m or negedge rst_n)if(!rst_n) vsync_r <= 1'b1;else if(y_cnt == 10'd0) vsync_r <= 1'b0; //产生vsync信号else if(y_cnt == 10'd2) vsync_r <= 1'b1;assign hsync = hsync_r;assign vsync = vsync_r;//--------------------------------------------------//有效显示标志位产生reg valid_yr; //行显示有效信号always @ (posedge clk_25m or negedge rst_n)if(!rst_n) valid_yr <= 1'b0;else if(y_cnt == 10'd32) valid_yr <= 1'b1;else if(y_cnt == 10'd512) valid_yr <= 1'b0;wire valid_y = valid_yr;reg valid_r; // VGA有效显示区标志位always @ (posedge clk_25m or negedge rst_n)if(!rst_n) valid_r <= 1'b0;else if((x_cnt == 10'd141) && valid_y) valid_r <= 1'b1;else if((x_cnt == 10'd781) && valid_y) valid_r <= 1'b0;wire valid = valid_r;//wire[9:0] x_dis; //横坐标显示有效区域相对坐标值0-639wire[9:0] y_dis; //竖坐标显示有效区域相对坐标值0-479//assign x_dis = x_cnt - 10'd142;assign y_dis = y_cnt - 10'd33;//--------------------------------------------------//--------------------------------------------------// VGA色彩信号产生/*RGB = 000 黑色R GB = 100 红色= 001 蓝色= 101 紫色= 010 绿色= 110 黄色= 011 青色= 111 白色*//*HIT字模参数*/parameter char_line0=24'h000000,char_line1=24'h000000,char_line2=24'h000000,char_line3=24'he77cfe,char_line4=24'h421092,char_line5=24'h421010,char_line6=24'h421010,char_line7=24'h421010,char_line8=24'h7e1010,char_line9=24'h421010,char_linea=24'h421010,char_lineb=24'h421010,char_linec=24'h421010,char_lined=24'he77c38,char_linee=24'h000000,char_linef=24'h000000;reg[4:0] char_bit; //显示位计算always @(posedge clk_25m or negedge rst_n)if(!rst_n) char_bit <= 5'h1f;else if(x_cnt == 10'd442) char_bit <= 5'd23; //显示最高位数据else if(x_cnt > 10'd442 && x_cnt < 10'd466) char_bit <= char_bit-1'b1; //依次显示后面的数据reg[2:0] vga_rgb; // VGA色彩显示寄存器always @ (posedge clk_25m)if(!valid) vga_rgb <= 3'd0;else if(x_cnt > 10'd442 && x_cnt < 10'd467) begincase(y_dis)10'd231: if(char_line0[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd232: if(char_line1[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd233: if(char_line2[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd234: if(char_line3[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd235: if(char_line4[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd236: if(char_line5[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd237: if(char_line6[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd238: if(char_line7[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd239: if(char_line8[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd240: if(char_line9[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd241: if(char_linea[char_bit]) vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd242:if(char_lineb[char_bit])vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd243:if(char_linec[char_bit])vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd244:if(char_lined[char_bit])vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd245:if(char_linee[char_bit])vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色10'd246:if(char_linef[char_bit])vga_rgb <= 3'b100; //红色else vga_rgb <= 3'b010; //绿色default: vga_rgb <= 3'b000;endcaseendelse vga_rgb <=3'b000 ;endmodule2、验证程序`timescale 1 ns/ 1 psmodule tb_vga_char();reg t_clk_25m;reg t_rst_n;wire t_hsync;wire [1:0] t_vga_b; wire [2:0] t_vga_g; wire [2:0] t_vga_r; wire t_vsync;vga_char dut(.clk_25m(t_clk_25m), .hsync(t_hsync),.rst_n(t_rst_n),.vga_b(t_vga_b),.vga_g(t_vga_g),.vga_r(t_vga_r),.vsync(t_vsync));initialbegint_clk_25m=0;t_rst_n=1;#20;t_rst_n=0;#50;t_rst_n=1;$display("Running testbench");#1000 $stop;endalways #0.04 t_clk_25m=~t_clk_25m; endmodule3、仿真波形六、总结在本次课程设计中,对VGA显示的原理有了一定的了解,在团队的分工合作下使用Verilog语言和Modelsim仿真器完成了可显示横彩条、竖彩条、棋盘格相间的VGA控制器的设计和验证,设计并验证了可显示英语单词”HIT”的VGA 控制器,并掌握了Quartus II软件和SOPC实验箱的使用。