FPGA uart+sdram+vga传图

项目介绍 注意事项
这个练手项目本来在七月份就完成了,但是其中有个bug我怎么改也改不了,其中的sdram看了下b站上明德扬的sdram视频,然后借鉴了他们的摄像头采集模块的sdram代码,这里的主要改动是这个bank以及addr,fifo里面的内容也注意改一下应该没什么问题了,但是没有问题就是最大的问题 ,我做出图传成这个亚子(还有一点要注意,用野火的串口调试助手)
然后我百思不得其姐,开始在就是上面说的addr和bank上面做文章,看了好多个培训班的视频代码都找不到原因,暑假因为其他事情搁置了 暑假老板带我们出差了,我全程混子(bushi),顺便说一句海南真好玩,开学突发奇想,改了下fifo的模式,明德扬传统的show-ahead模式在这块就会出现这个错误,改完之后就好了 。
我只能说绝了 。
解题思路 第一步
首先你得有像我桌面上的这样一只鸭子 首先你还是先得把串口改成接收16位的,这里说一下,以前写的8位并16位代码写的有些难看,看下我的改进(我也是偷看了人家的)
下面展示一些 内联代码片 。
// 8位转16位接收(注意前面+1条件uart_done)
//8位转16位always @(posedge clk or negedge rst_n)beginif(!rst_n)beginbyte_cnt <= 0;endelse if(add_byte_cnt)beginif(end_byte_cnt)byte_cnt <= 0;else byte_cnt <= byte_cnt +1'b1;endelse beginbyte_cnt <= byte_cnt;endendassign add_byte_cnt = uart_done;assign end_byte_cnt = add_byte_cnt && byte_cnt == 2-1;always @(posedge clk or negedge rst_n)beginif(!rst_n)begindout <= 0;endelse if(add_byte_cnt)begindout <= {dout[7:0],data_out};endendalways@(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begindout_vld <= 0;endelse if(end_byte_cnt) begindout_vld <= 1;endelse begindout_vld <= 0;endend
第二步
其次就是fifo控制了,包括读写两个FIFO,注意这里都是异步FIFO同时还要注意读写时钟到底是多少兆的,包括将数据写入sdram以及将数据读到vga显示层,FIFO的控制也不难,我拿的摄像头模块代码改的,前面讲了就是bank和addr,明德扬开发板的sdram突发长度是512,所以这里设置FIFO深度到达512时就往下一模块传数据,图片尺寸是,所以一共要传/512=600次 。
第三步
下一步就是sdram的控制模块了,sdram每隔1562个时钟周期刷新一次,现在1562-512(突发长度)-2(预充电时间)-2(激活时间)=1046,刷新逻辑是每隔1046个周期将自刷新请求拉高,若此时处于idle状态则响应刷新请求,若不处于则继续进行读或写操作后刷新,等待的最长时间是512个周期 。这样一来,就不用考虑仲裁模块了,不过代码中还是要有仲裁的思想 。这里说一下为什么要对bank和addr改动,因为明德扬的摄像头采集代码,sdram模块采用的是乒乓操作,两个bank来回的切换
下面展示一些 内联代码片 。
状态机跳转要满足的条件可能看着有一点复杂,但是还是很好理解的
assign nop_to_pre_start= state_c==NOP&& end_cnt;assign pre_to_ref_start= state_c==PRECHARGE && flag_init&& end_cnt;assign ref_to_ref_start= state_c==REF&& flag_init&& cnt1==0&& end_cnt;assign idle_to_ref_start= state_c==IDLE&& ref_req;assign ref_to_mode_start= state_c==REF&& flag_init&& end_cnt1;assign ref_to_idle_start= state_c==REF&& flag_init==0&& end_cnt ;assign pre_to_idle_start= state_c==PRECHARGE && flag_init==0&& end_cnt ;assign mode_to_idle_start= state_c==MODE&& flag_init&& end_cnt ;assign idle_to_active_start= state_c==IDLE&& ref_req==0&& (rd_req || wr_req);assign active_to_rd_start= state_c==ACTIVE&& ((flag_syn==1 && flag_rd==0) || (flag_syn==0 && rd_req)) && end_cnt;assign active_to_wr_start= state_c==ACTIVE&& ((flag_syn==1 && flag_rd==1) || (flag_syn==0 && wr_req)) && end_cnt;assign wr_to_pre_start= state_c==WRITE&& end_cnt;assign rd_to_pre_start= state_c==READ&& end_cnt;