FPGA计算3行同列数据之和

实验:FPGA计算3行同列数据之和

实验要求:PC机通过串口发送3行数据(一行有56个数据,3行共有56*3=168个数据)给FPGA,FPGA计算3行同一列数据的和,并将结果通过串口返回给上位机。

实现方法:使用两个FIFO IP Core,将串口接收到的数据进行缓存,当第一个FIFO1的数据存满后,将FIFO1的数据读出来给FIFO2,当FIFO2的数据存满时,当前两个FIFO的数据和串口正在接收的数据就可以看做为三行数据了。我们将3行数据同时读出,进行求和,然后用串口发送到上位机,这里要注意的是三个数据必须对齐,要不然是最终结果是不正确的。我这里为了验证方便,只生成了一行16个数据。

  本设计是为了基于FPGA的Sobel边缘检测做基础,使用2/3个FIFO将图片数据缓存成3x3矩阵,不过偶然发现Xilinx也有shift_ram IP Core,这个IP简直是为生成3x3矩阵而生的,不过为了学习FIFO的使用,还是在这里用FIFO实现,我这里使用的是Xilinx的Vivado开发套件调用FIFO IP Core流程如下:

点击如图所示图标

按上图所示配置即可,这里的full信号是当FIFO写满后full会为1,否则为0,empty是当FIFO为空时FIFO为1,否则为0。

这里设置读写位宽和深度,添加复位信号,注意Xilinx的FIFO是高电平复位,设置复位类型为异步复位。剩下的按如图设置即可。其他均保持默认,点击OK。

点击generate生成IP Core。

         生成好两个FIFO之后,按照系统流图,还需要添加串口接收和发送模块,这里我们可以把以前做过的串口代码直接拿过来用,代码都是可以移植的只需要稍微修改端口顶层例化即可。按照系统框图把顶层例化好之后,接下来就是仿真了,真是惭愧我到现在才学会了串口的仿真技巧,其实是自己悟到的,如下图,我这里的串口接收是以发送波特率的16倍进行接收的,在仿真时,波特率9600还是很慢,所以,我直接将接收波特率这里设置成50Mhz的两个时钟周期,那么发送也就是32个50Mhz的时钟周期,这里是50Mhz的原因是因为但是写串口接收发送这块的时候,使用的板子的系统时钟是50Mhz,这里移植的时候也要注意,最好使用PLL将系统时钟分频成50Mhz再给接收发送这两个模块。

 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 uart_fifo_tx uut_uart_fifo_tx(
 2     .clk                (clk),//125Mhz
 3     .rst_n                (rst_n),
 4     .rs232_rx            (rs232_rx),
 5     .rs232_tx            (rs232_tx)
 6     );    
 7 
 8 always #4 clk = ~clk;
 9     
10 always #10 mclk = ~mclk;
11 
12 UART_Byte_Tx uut_UART_Byte_Tx(
13     .mclk                (mclk),
14     .rst_n                (rst_n),    
15     .send_en            (send_en),//时钟分频使能    
16     .baud_set            (4'b0),//选择波特率    
17     .data_byte            (data_byte),//需要发送的信号    
18     .uart_state            (),//串口状态    
19     .tx_done            (),//标志串口结束信号    
20     .rs232_tx            (rs232_rx)//串口信号输出   
21  );

  然后是写激励,在工程代码中我们尽量少用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一年了,才终于学会了仿真技巧能力,下面是我仿真这个实验的波形图,上面设置了很多不同颜色,增加了仿真效率,modelsim虽然好用,但是用vivado级联modelsim还是很慢的,所以还不如直接用vivado自带的仿真工具isim,只要掌握了使用isim的仿真技巧,再大的工程仿真起来也不怕!关于isim的使用技巧可以参考我的另一篇博客:Isim你不得不知道的技巧(整理)。这虽然是ISE那个版本的isim但是使用起来还是一样的!

  这可能是我做过最漂亮的仿真了!

  最后下载板子进行功能验证,发送3组00-0f的数据,最后由串口返回上位机的数据查看,三行数据一列求和的结果是完全正确的。至此实验结束,下面要进入基于FPGA的Sobel边缘检测实验了。

转载请注明出处:NingHeChuan(宁河川)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Netkiller

高级软件工程师(面试题)

高级软件工程师(面试题) 出题者:netkiller 出处:http://www.netkiller.cn/ 高级软件工程师 下面的面试题不分语言,适用于所有...

42130
来自专栏杨建荣的学习笔记

Oracle数据误操作全面恢复实战(r11笔记第78天)

对于DBA来说,面对误操作带来的数据恢复难度,其实很大。主要有以下几个方面: 误操作的影响范围极大,很可能不是删点,改点数据的操作,有时候可能是让人望而兴叹...

35250
来自专栏嵌入式程序猿

你的代码敢上Polyspace跑吗?

嵌入式代码动态验证 在嵌入式开发中,代码静态分析工具相信大家应该都熟悉,都用过像PClint,understand C等,但对于动态验证,运行时错误验证工具还是...

81860
来自专栏SDNLAB

ONOS高可用性和可扩展性实现初探

ONOS的发布直面OpenDaylight 进行挑战,直接将 SDN领域两大阵营(运营商和设备商)的竞争瞬间升级,之所以 ONOS能做到这一点,首先,ONOS的...

27550
来自专栏轮子工厂

Wox一款国产开源的快捷启动器辅助工具神器

如果你也不喜欢电脑桌面上满是程序的快捷方式,如果你也喜欢博主这样干干净净的桌面,甚至喜欢高效的键盘操作,那么你需要一款好用的快速启动器软件。

10710
来自专栏SDNLAB

SDNLAB技术分享(十四):ONOS项目介绍(下)

第二部分,创新项目及ONOS特性增强项目介绍 NFV相关 随着云计算、SDN、虚拟化等理念和技术的不断成熟,以通用替代专有将原本传统专业的网元设备上的网络功能提...

45790
来自专栏小狼的世界

Ajax与REST

REST(Representational State Transfer)是一种开发思想,互联网不断发展,富媒体越来越多的应用,不断地冲击着我们的应用,使应用的...

11520
来自专栏跨界架构师

分布式系统中的必备良药 —— RPC

  在上一篇分布式系统系列中《分布式系统中的必备良药 —— 服务治理》中阐述了服务治理的一些概念,那么与服务治理配套的必然会涉及到RPC框架。在当前互联网的大背...

25210
来自专栏Flutter入门到实战

深入理解什么是RESTful API ?

越来越多的人开始意识到,网站即软件,而且是一种新型的软件。   这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(hi...

1.9K20
来自专栏JackieZheng

可视化工具gephi源码探秘(二)---导入netbeans

  在上篇《可视化工具gephi源码探秘(一)》中主要介绍了如何将gephi的源码导入myeclipse中遇到的一些问题,此篇接着上篇而来,主要讲解当下通过my...

30080

扫码关注云+社区

领取腾讯云代金券