1. Bank地址未激活
根据sdram手册可知,激活命令ACT给出bank地址和行地址,写命令WR给出bank地址和列地址
通过仿真观察可知,wr模块中的act_cmd并没有送到顶层模块的对外接口cmd上,反查代码发现act_cmd和pre_cmd并没有赋给wr模块的输出wr_cmd!
更新后缺陷解决:
2. fifo深度不足导致数据错位
tb文件模拟的是串口给出的一幅图像数据6404808bit,一行数据由0-255循环给出。最后存到sdram的是一个300行512列16bit的数据矩阵,因此sdram中最后2字节数据应该是16’hFEFF=16’d32838。
仿真分析发现,tb产生的数据fifo_wr_data[7:0]和写使能fifo_wr_en是正常的,每行数据从00开始,7f结束
第一行的读使能fifo_rd_en和数据fifo_dout[15:0]也是正常的,fifo为FWFT模式,预读取数据从0001开始,7e7f结束
但是第2行开始位置的数据开始错乱,row_cnt=1,col_cnt=2的数据为828e,发生了跳变错位
进一步分析,查看wr模块内部wfifo发现在读第1行的时候full有拉高(从fifo_wr_cnt=1023时开始写请求,到从fifo中读数据,这中间还需要经过REQ-ACT等状态),即数据把 FIFO 的深度写满了,数据将不能再进去,也不会覆盖原有的数据。所以是fifo深度设置裕量过小,导致了部分数据的缺失。(full拉高前后的数据刚好是828e)
深度1024的fifo(FWFT)实际深度有1027。
3. 刷新中断导致sdram数据异常
当有刷新请求时col_cnt重新计数导致列地址错乱,修改代码后正常。
4. 图像行数异常
一幅图像最后的数据是在row=1,col=511,而tb设计的是6404808bit的一幅图像数据,理论上sdram中存储的是30051216bit数据。但从仿真中确实看出在image_end拉高后仍传输了2行数据。
进一步查看波形发现,在row=15时出现错误:
正常逻辑是fifo_wr_cnt计数=1023时表示fifo存满sdram的一行数据量,此时sdram_wr_start拉高,状态机跳转至WRREQ写请求状态,等到arbiter模块响应返回wr_en信号,开始进行ACT-WR操作。在跳转至WR状态的同时拉高fifo_rd_en开始从fifo中取数,当一行数据取完或者有刷新请求时跳出WR状态,同时拉低fifo_rd_en。当刷新结束且sdram一行数据没有写完时,重新回到WR状态继续从fifo中取数。
这里存在逻辑缺陷:当有刷新请求ref_req和一行数据写完标志row_end同时到达时,在PRE状态下中断响应的优先级高于正常写操作,所以当PRE结束后会直接跳转到WRREQ状态,从而缺失了fifo_wr_cnt统计,导致fifo没有数据却直接进行读取。
修改代码,调整响应刷新和写行结束的优先级,当两者同步到达时,arbiter模块接收到wr_data_en||wr_ref_break后会跳转到ABT状态优先响应ref_req,刷新结束后等待wr_req跳转至WR状态;write模块则优先跳回IDLE状态,重新开始fifo_wr_cnt一行计数。
5. 刷新请求失效
如仿真结果,当有刷新请求ref_req时,arbiter状态机始终没有收到refresh模块返回的刷新授权操作ref_en信号,所以并未跳转到刷新REF状态。
反查refresh模块代码发现,ref_req刷新请求信号仅保持一个时钟周期,逻辑错误。