可编程逻辑
前面我们设计了基于FPGA的静态图片显示,并对一幅彩色图片提取了灰度,学习了RGB转Gray算法。这是基于一幅静态图片的,那么后面我们要模拟一下一幅动态图片的显示,最终对动态数据进行滤波、边缘检测等算法,下来我们首先来建立一个基于FPGA的动态图片显示基础框架,本实验内容为:由PC端上位机软件通过串口发送一幅图像数据至FPGA,FPGA内部将图像数据存储,最后扫描到VGA屏幕上显示。
从系统框图上我们可以看到,可以划分为三个部分进行设计,一个是串口接收部分,然后是RAM数据存储部分,最后是VGA驱动显示部分。这里串口接收部分只需要用到串口接收代码,代码很多书上都有,我这里就不贴出来了,
数据存储部分需要使用的是双口RAM IP Core,一端将数据写入RAM中,一端将数据读出来用VGA显示,下面是基于Vivado的双口RAM IP Core调用方法。
打开IP Catalog,选择block memory Generater
这里按如图所示选择,我这里将写使能信号去掉,wea也可以代表写使能
设置写数据位宽和深度,使能选择always enable
设置读数据参数
这里因为我们是往RAM里面写数据,所以这里不需要添加初始化RAM文件
点击OK
最后generate综合完成。
双口RAM IP调用完成以后,接下来是在用顶层文件把串口接收模块和存储模块和VGA驱动模块连接起来。这里需要注意的是,双口RAM的读地址和写地址都是需要在其他模块进行计数的,我这里把写使能信号设置为标串口接收完成标志即rx_done,读使能设置为always enable。对于VGA显示图片部分可以参考这个图像处理系列文章第一篇基于FPGA的静态图片显示。
按照系统流图,还需要添加串口接收和发送模块,这里我们可以把以前做过的串口代码直接拿过来用,代码都是可以移植的只需要稍微修改端口顶层例化即可。按照系统框图把顶层例化好之后,接下来就是仿真了,真是惭愧我到现在才学会了串口的仿真技巧,其实是自己悟到的,如下图,我这里的串口接收是以发送波特率的16倍进行接收的,在仿真时,波特率9600还是很慢,所以,我直接将接收波特率这里设置成50Mhz的两个时钟周期,那么发送也就是32个50Mhz的时钟周期,这里是50Mhz的原因是因为但是写串口接收发送这块的时候,使用的板子的系统时钟是50Mhz,这里移植的时候也要注意,最好使用PLL将系统时钟分频成50Mhz再给接收发送这两个模块。仿真图我就不贴了,这里把testbench的核心代码部分贴出来!
1 //串口接收模块波特率查找表
2 always @(posedge mclk or negedge rst_n) begin
3 if(!rst_n)
4 bps_DR <= 0;
5 else begin
6 case(baud_set)
7 0: bps_DR <= 324;//bps_9600x16
8 //0: bps_DR <= 1;//bps_9600x16 just test
9 1: bps_DR <= 162;//bps_19200x16
10 2: bps_DR <= 80;//bps_38400x16
11 3: bps_DR <= 53;//bps_57600x16
12 4: bps_DR <= 26;//bps_115200x16
13 default: bps_DR <= 324;//bps_9600x16
14 endcase
15 end
16 end
17 //串口发送模块波特率查找表DR_LUT
18 always @(posedge mclk or negedge rst_n)begin
19 if(!rst_n)
20 bps_DR <= 16'b0;
21 else begin
22 case(baud_set)
23 0: bps_DR <= 5207;//bps_9600
24 //0: bps_DR <= 31;//bps_9600 just test
25 1: bps_DR <= 2603;//bps_19200
26 2: bps_DR <= 1302;//bps_38400
27 3: bps_DR <= 867;//bps_57600
28 4: bps_DR <= 433;//bps_115200
29 default: bps_DR <= 5207;//bps_9600
30 endcase
31 end
32 end
那么参数调整小了,仿真这块这么写呢?在test_bench文件中,我直接调用上面的工程顶层和串口发送模块,只需要将发送模块的数据给顶层模块,这样就方便了查看接收模块是否正确,
1 VGA_display_picture uut_VGA_display_picture(
2 .clk (clk),//50mhz
3 .rst_n (rst_n),
4 .lcd_data (lcd_data),
5 .lcd_hs (lcd_hs),
6 .lcd_vs (lcd_vs),
7 .baud_set (baud_set),//uart baud
8 .data_byte (data_byte),
9 .send_en (send_en)
10
11 );
12 always #4 clk = ~clk;
13
14 always #10 mclk = ~mclk;
15
16 UART_Byte_Tx uut_UART_Byte_Tx(
17 .mclk (mclk),
18 .rst_n (rst_n), 19 .send_en (send_en),//时钟分频使能
20 .baud_set (4'b0),//选择波特率
21 .data_byte (data_byte),//需要发送的信号
22 .tx_done (),//标志串口结束信号
23 .rs232_tx (rs232_rx)//串口信号输出
24 );
然后是写激励,在工程代码中我们尽量少用for循环,但是在测试文件中便可以使用for循环来减少激励的书写量,提高仿真效率,这里的#7040是我在上面仿真的时候计算出来的,为什么是延时7040呢?这是因为上面串口发送模块波特率设置的是32个50Mhz时钟周期,那么它就是每隔7040ns会发送一次,同样的接收模块也是每隔7040ns接收一次,所以我这里每隔7040ns给一次数据,就可以实现仿真上连续发送了。
1 integer i;
2
3 initial begin
4 clk = 0;
5 mclk = 0;
6 rst_n = 0;
7 send_en = 0;
8 data_byte = 0;
9 #100; rst_n = 1'b1;
10 send_en = 1;
11 for(i = 1; i <= 100; i = i + 1)begin
12 #7040 data_byte = i;
13 end
14 end
这样硬件部分其实就已经完成了,现在我们需要的是一幅图片的像素数据然后通过上位机串口调试助手发送给FPGA开发板,首先找一幅200x200的图像数据,因为我这里是开出的200x200的显示区域(参考如上链接),使用MATLAB就可以直接生成你想要的这幅图像的像素数据,这里的MATLAB代码我给出链接:http://pan.baidu.com/s/1dFAMPjj 密码:uu71,只需要修改下面如图所示的imread(””)这里就好了,就可以直接转化你想转化的图片。注意图片必须和这个.m文件在同一个文件夹,最后生成一个txt文件,这个txt文件里面的数据就是我们所需要的图像数据
其实这三个文件里面的数据是完全相同的,那为什么不直接用前面那两个文件的数据呢?这里博主亲身体验过,那是绝对不行的,因为前面两个文件的数据其实是有回车的,可能会被串口默认为一个字符,txt文件中是没有的,空格的话这里被串口调试助手忽略了!如下图,点击发送就OK啦!
最后通过串口发送到开发板最终显示的效果如图所示,我们可以看到这里MATLAB代码生成的就直接是彩色图像,最终发送过程中其实是动态显示的,因为串口波特率的速度比VGA的扫描速度是要慢很多的
串口发送小姐姐图片用VGA显示出来
最后经过测试我们的lena女神的显示效果最好了,看来真不愧是我们图像处理届的模特鼻祖呀!最后看来,显示效果还是不错的呢!
全部0条评论
快来发表一下你的评论吧 !