IP核具体设置如下,数据宽度64bit,深度32,启用了包传输。
打开Example Design
三个IP核和两个AXI读写模块。
clk_wiz_0是mmcm IP核,提供工作时钟,proc_sys_reset_0是系统复位 IP核,提供复位信号,axis_data_fifo是本次的仿真IP 核。
axis_data_fifo_example_master是写模块,向fifo中写入数据,axis_data_fifo_example_slave是读模块,从fifo中读出数据。
开始仿真,打开modelsim。
输入200M时钟,经clk_wiz_0输出10M时钟和locked信号(图中目前未置1)
clk_wiz_0输出的10M时钟信号作为全局时钟,连接slowest_sync_clock,dcm_locked来自clk_wiz_0的locked信号,ext_reset_in是来自外部的复位信号。
检测到dcm_locked为1,且ext_reset_in为1时,一段时间后peripheral_aresetn置1,作为全局的复位信号。
至此,时钟和复位介绍已结束,后续不展示这部分的波形。
如下为,写fifo和读fifo的波形,先来看写的过程,这里axis_data_fifo作为从,外部的axis_data_fifo_example_master作为主,涉及信号为s_axi_tvalid,s_axi_tready,s_axi_tlast,s_axi_tdata,axis_wr_data_count。
当s_axi_tvalid(来自axis_data_fifo_example_master),s_axi_tready(来自axis_data_fifo)均有效时,当前s_axi_tdata的数据会被写入fifo,如果该数据写入的同时s_axi_tlast为1,则该数据被读出的时候,tlast信号也为1,及与写入时的tlast信号保持一致。注意到axis_wr_data_count的数值更新要慢一个时钟周期,可能原因在于axis_wr_data_count指示的是当前fifo中的数据个数,在写第一个数据的时候,内部实际数据个数为0,在写第二个数据的时候,内部实际数据个数才为1。
再看读的过程,这里axis_data_fifo作为主,外部的axis_data_fifo_example_slave作为从,涉及信号为m_axi_tvalid,m_axi_tready,m_axi_tlast,m_axi_tdata,axis_rd_data_count。
m_axi_tdata上的数据实际要早于m_axi_tvalid,m_axi_tready被安置在m_axi_tdata上,当m_axi_tvalid,m_axi_tready同时有效的时候,m_axi_tdata上的数据会在下一个时钟周期更新,这样就保证了对于从来讲,m_axi_tvalid,m_axi_tready,m_axi_tdata是在同一个时钟周期里的。
由此我推论出,只有当一个可以读的数据出现在m_axi_tdata上时,m_axi_tvalid才会被置1,等到m_axi_tready为1时,判断目前axis_rd_data_count是否大于1,及fifo中可被读取的数据个数,如果axis_rd_data_count大于1,m_axi_tdata上的数据变为下一个,m_axi_tvalid继续为1,如果axis_rd_data_count不大于1,m_axi_tvalid置为0,表示不可读取。至于axis_rd_data_count为啥继续增加,因为这个周期已经写入了一个新数,而准备被读走的数要在下一个周期才能被送走,所以下个上升沿的时候axis_wr_data_count,axis_rd_data_count都没有变化,原因就在于下一个周期既写入了一个新数据,又被送走了一个旧数据,fifo总体的数据个数是不变的,可以注意到,axis_wr_data_count,axis_rd_data_count在大部分时间都是相等的,我们可以认为都代表fifo中存有的数据个数,但还有一点不同在于axis_rd_data_count是从0直接变为2的,这需要注意。
继续往后看,因为写的过程是一直不停的,而读的过程是间断一个时钟的,所以fifo里的数据一直都在增加,因为我的数据深度是32,很快就会满,所以后面写的过程也会断断续续。
这个时候s_axi_tready,m_axi_tready是反相的。先看s_axi_tready置0时候的过程。
第一部分,在axis_wr_data_count为32的时候,下个周期可能是31、32、33,我们取最差的情况,即下个周期为33的时候,当判断条件为s_axi_tready为1,m_axi_tready=0,即下个周期即将写入一个新数据,axis_wr_data_count将=34,如果继续s_axi_tready置1,那么就会在fifo里已有34个数据的情况下,数据继续被写入,这个过程可能会带来问题,所以置0,但此时判断条件为s_axi_tready为1,m_axi_tready=1,即下个周期即将写入一个新数据,也要读出一个旧数据,axis_wr_data_count将保持一个周期的33,所以s_axi_tready可以继续为1。
第二部分,在axis_wr_data_count为33的时候,下个周期可能是32、33、34,我们取最差的情况,即下个周期为34的时候,参考第一部分,当判断条件为s_axi_tready为0,m_axi_tready=1,即下个周期即将读出一个旧数据的时候,s_axi_tready可以为1,其他判断条件下,s_axi_tready都必须为0,即停止写入。
第三部分,在axis_wr_data_count为34的时候,下个周期可能是33、34,我们取最差的情况,即下个周期为34的时候(这种情况是这个周期既读了一个旧数据,又写了一个新数据的情况,如果这个周期,又写了一个新数据但没有读出一个旧数据,说明上个部分axis_wr_data_count为33的时候的逻辑判断不对)参考第一部分,axis_wr_data_count将继续=34,此时s_axi_tready必须为0
后面即重复上述的三个部分。
注意s_axi_tlast为1的最后一个数为64'hffffffffffffffff
读出64'hffffffffffffffff这个数据的时候m_axi_tlast也为1,这里64'h1f1f1f1f1f1f1f1f被写入时为1
64'h1f1f1f1f1f1f1f1f被读出时m_axi_tlast也为1
最后再看,m_axi_valid置0的过程
在axis_rd_data_count为1的时候,m_axi_tdata的数据是最后一个数据,所以当判断条件m_axi_tready=1的时候,m_axi_valid就可以置0了。
最后,本Example Design分析仅为个人分析推论,并作为记录,并非一定正确,还请自己判断思考。