原创 FPGA学习笔记6——VGA显示图片

2015-11-18 21:40 5107 12 13 分类: FPGA/CPLD

VGA显示图片

在上一个笔记熟悉了VGA的时序后,显示了一个翡翠台彩条的图片,采用的思想是在vga_output模块上,根据x,y坐标的不同,把图片分成了三个800*200的区域,分别在三个区域上显示蓝,绿,红的颜色,如果我们要显示一副图片的话,同样也可以采取这个思路,不过每个像素的数据不像彩条那么简单了,我们需要建立一个ROM,根据x和y的的坐标,也就是是地址,来实时获取每个像素点的数据,显示一副图像,下面就以显示一个这样的图片为例。
       20151118202715554.jpg


这个图片像素为640*640,我们打开画图软件,把它的像素调整为240*240,并保存为24bit的位图格式,即bmp格式。然后我们再打开一个BMP2MIF的软件,把BMP转化为一个MIF文件,这样我们使用ROM的IP核时,便可以加载这个MIF文件了。笔者使用的FPGA芯片型号为EP4CE6F17C8,这款芯片的Memory Bits一共有276480,我们显示一个240*240的RGB565图像一共需要240*240*16=921600bits,明显是不够的,所以我们只能显示黑白图像,这样的话只需用到240*240*1=57600bits,是可以满足需要的。

整个设计采用的模块架构仍与笔记5大体相同,只是多了一个ROM模块,vga_out模块需要多一个addr和q的接口。
20151118204148215.jpg

我们仍然使用的是800*600*60Hz分辨率的VGA时序,但是我们要显示的是一副240*240的画面,并显示在屏幕的中间,我们只需改变一下vga_ctrl模块的参数便可以。对于笔记5中,valid信号对于800*600的有效显示区域为高电平,我们现在只需修改为240*240这个区域valid才为高电平,同样的,x坐标以前为1-800,y坐标以前为1-600,我们修改后的x坐标和y坐标都为1-240。如以下代码所示,加粗部分即为修改的部分。对于x坐标,我们规定了495-735这240个像素才为有效的,而这也刚好处在屏幕的中间,而y坐,我们规定了194-434这240个像素点为有效像素点。
module vga_ctrl(clk,rst_n,hs,vs,valid,x,y);
input clk;
input rst_n;
output hs;
output vs;
output valid;
output [10:0] x,y;

reg [10:0]count_h;
reg [10:0]count_v;
reg valid;

always @(posedge clk or negedge rst_n)
if (!rst_n)
count_h<=11'd0;
else if (count_h==11'd1055)
count_h<=11'd0;
else 
count_h<=count_h+11'd1;
always @(posedge clk or negedge rst_n)
if (!rst_n)
count_v<=11'd0;
else if (count_v==11'd627)
count_v<=11'd0;
else if(count_h==11'd1055)
count_v<=count_v+11'd1;
always @(posedge clk or negedge rst_n)
if (!rst_n)
valid<=1'b0;
else if(count_h>=11'd495&&count_h<11'd735&&count_v>=11'd194&&count_v<11'd434)
valid<=1'b1;
else 
valid<=1'b0;
assign hs=(count_h<=11'd127)? 1'b0:1'b1;
assign vs=(count_v<=11'd3)? 1'b0:1'b1;
assign x=valid?count_h-11'd495:11'd0;
assign y=valid?count_v-11'd194:11'd0;

endmodule


对于vga_out模块,我们也要作出一些修改,在这个模块中,增加了16bit的地址接口和q接口,这是与ROM连接的,我们根据地址坐标来获取像素点,如果q为1'b1,RGB信号就取16'd65535即为白色,若q为1'b0,则RGB信号就取1'b0,即为黑色。在不是有效区域的地方,我们同样显示黑色,即16'd0。对于地址,240*240的图像一共有57600个像素点,即有0-57599一共57600个地址,对于第1行第1个像素 地址为16'd0,第240个像素,地址为16'd239,第2行第1个像素,地址为16'd240,第y行第x个像素地址为x+y*9'd240,即计算公式为addr=x+y*9'd240。
module vga_output(clk,rst_n,x,y,valid,rs,gs,bs,addr,q);

input clk,rst_n;
input [10:0]x,y;
input valid;
input q;
output [15:0]addr;
output [4:0]rs;
output [5:0]gs;
output [4:0]bs;

reg [4:0]rs;
reg [5:0]gs;
reg [4:0]bs;
always @(posedge clk or negedge rst_n)
if(!rst_n)
{rs[4:0],gs[5:0],bs[4:0]}<=16'd0;
else if(valid)
case (q)
1'b1:{rs[4:0],gs[5:0],bs[4:0]}<=16'd65535;
1'b0:{rs[4:0],gs[5:0],bs[4:0]}<=16'd0;
endcase
else 
{rs[4:0],gs[5:0],bs[4:0]}<=16'd0;

assign addr=x+y*9'd240;
 
endmodule


关于ROM的配置,同样的我们可以根据PLL那样。我们选用一个ROM:1-PORT。
20151118210548508.jpg



注意红色部分,因为我们显示的是一个黑白图像,所以数据只有1个位,而240*240的图像有57600个像素,即57600个地址,我们需要用16个位的地址,即2的16次方为65536,下面选择使用M4K块资源。
20151118210920709.jpg

我们再找个位置添加我们的mif文件。然后即可完成ROM的配置了。

20151118211157297.jpg


综合过后,把sof文件烧到FPGA上,即可看到在800*600分辨率的液晶屏上显示一副240*240的图片了。 
20151118212737832.jpg
 




如果我们要显示480*480的图片怎么办呢,此时像素点一共为480*480=230400,地址有230400个,而芯片地址最多只能有16位,一共65536个,硬件资源并不能满足,我们仍然使用240*240的图片,但是我们可以对这幅图片进行放大,4个像素点公用一个地址便可,即第1行第1,2个像素,第2行第1,2个像素这4个像素点的地址为0,第1行第3,4个像素,第2行第3,4个像素地址为1,即addr=x[10:1]+y[10:1]*9'd240这样的逻辑。而对于480*480的区域,我们的修改也非常简单,只用修改valid为高电平的有效矩形区域即可了,即如下代码所示。

always @(posedge clk or negedge rst_n)
if (!rst_n)
valid<=1'b0;
else if(count_h>=11'd375&&count_h<11'd855&&count_v>=11'd74&&count_v<11'd554)
valid<=1'b1;
else 
valid<=1'b0;
assign x=valid?count_h-11'd375:11'd0;
assign y=valid?count_v-11'd74:11'd0;


在vga_out 和vga_ctrl模块作了以上修改后,我们观察现象,发现图像变成了480*480,大体上图像的质量也是可以接受的。20151118213551823.jpg



文章评论1条评论)

登录后参与讨论

用户411430 2016-2-21 10:14

博主也是广工的,同校,可以的话互加QQ776231646,交流学习,一起做项目
相关推荐阅读
广州老伯 2015-11-07 23:51
FPGA学习笔记5——VGA驱动
VGA驱动     VGA接口是一个常用到的接口,今天笔者带大家来探讨下怎么样编写VGA驱动。从数据手册上我们可以看到VGA接口一共有15个引脚,但其实真正需要我们去操作的只有5个引脚,他们分...
广州老伯 2015-11-05 21:24
FPGA学习笔记4——PLL的IP核使用
PLL的IP核使用    PLL锁相环的IP核应该是在FPGA开发中用得最多的一个模块了,下面介绍如何使用PLL的IP核。首先,我们新建一个工程,新建一个verilog文件,保存。    然后选择to...
广州老伯 2015-11-05 13:18
FPGA学习笔记3——booth乘法器设计
Booth乘法器设计booth乘法器是一种可以计算带符号数的乘法器,他的实现思维较为简单,具体的重要逻辑是设乘数分别为a[3:0]和b[3:0],积为y[8:1],在这里y其实是一个9位的寄存器,只不...
广州老伯 2015-11-03 17:24
FPGA学习笔记2——传统乘法器设计
传统乘法器设计传统乘法器我们以传统的乘法竖式计算为例说明一下。以10*9为例,即二进制1010*1001有  1 0 1 0                   X    1 0 0 1     ...
广州老伯 2015-10-30 23:29
FPGA学习笔记1——分频电路设计
    分频就是用一个时钟信号通过一定的电路结构变成不同频率的时钟信号,这里介绍一下整数分频电路的设计方法。整数分频电路有偶数分频和奇数分频两种,我们以实现占空比为50%的分频电路为例子来解释一下...
我要评论
1
12
关闭 站长推荐上一条 /2 下一条