AXI4 full master ip转rgb,研读大佬的代码 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

说明

  • github上大佬写的代码,基于axi4 full master的模板,添加了一个data_receive.v模块,实现了主动从ddr burst读取图像数据,然后通过data_receive模板转成rgb发送出去。 这个相当于是实现了一个dma,可以为我所用。后期我可以基于这个,改造成一个ddr->qspi的模块。
  • 本文对这个代码的思路进行一个剖析,看大佬是如何基于axi4 full master ip进行修改适配的。

myip的代码,与官方axi4 full master代码的对比

  • 首先添加了rgb相关的时序接口信号,并注释了INIT_AXI_TXN信号,因为这个信号后续由data_receive模块自动产生,而不是由外部产生。 image

  • 直接将C_NO_BURSTS_REQ改为4,也就是单次突发进行16次 image

  • 增加repeat_one信号,由data_receive模块产生 image

  • 用repeat_one信号取代INIT_AXI_TXN。可以看出,repeat_one信号的宽度至少需要2拍,才能产生一个init_txn_pulse脉冲。 一次repeat_one触发16次长度为64,位宽为32的传输,总数据量=16*64=1024个u32 image

  • 这里的复位,需要提前一点,video_vs比init_txn_pulse更早一点,这个合理。 image

  • 例化data_receive模块 image

  • 我们只有IDLE和READ这2个阶段,没有WRITE和COMPARE阶段。因此注释掉WRITE,并修改一下状态机。 image image

进一步分析

关键控制信号

image image image

C_M_AXI_BURST_LEN的参数默认值是16,但是应用时,会在bd中配置成64,因为一次burst长度是64个。 因此read_index计数器范围是0-63
read_burst_counter计数器的范围也是0-15,当计数到16后就维持不变了
read_done的结束条件:64个突发长度为16的数据读,总数据量=64*16=1024个u32

image image C_M_AXI_BURST_LEN的参数默认值是16,但是应用时,会在bd中配置成64,因为一次burst长度是64个。 因此burst_size_bytes=64*32/8=256 bytes,注意地址是一个byte为单位增加的。

给data_receive模块提供的信号

image

我们站在master与slave的角度看这些控制信号: repeat_one相当于是req信号,init_txn_pulse相当于是ack信号。在主机侧,通过req信号产生ack信号,方法是造一个脉冲,这要求req信号的宽度至少2个cycle以上。

image rnext信号我们比较熟悉,就是rvalid&&rready

现在再分析一下data_receive的逻辑

image

可以看到,内部写一个1024x32的data_memory,最后会综合成一个bram。可以看到,数据写入到reg不依赖于vs/hs时序。只要init_txn_one拉高就复位,只要r_next来就开始写入。 写入的过程是持续1024个axi_clk,应该是很快的。假设axi_clk=100MHz,那么1024个axi_clk是10us左右,大约一行的时间,是在vs期间执行的。

image image image 显示控制部分,先定义2个计数器vs_cnt/hs_cnt,然后就可以产生vs/hs/de/video_data信号了,这个没什么可说的。注意它是如何从data_memory读取数据的,是用的计数器。

image 所有信号都向vs_cnt/hs_cnt计数器靠齐。burst_reset也就是req信号,会提前发出,会在960行的位置就发出(总共1024行)。但是注意到,它在V_SYNC期间也会产生2个宽度的高电平,那意味着在一帧内,req信号会产生2次,这是为什么?

关键时序信号

image image image 可见wnext信号,在一个burst期间,持续为高电平

image image image 可见rnext信号,在一个burst期间,不是持续为高电平,而是很多个脉冲。可见读的效率不如写,写一个1个cycle写一个,读需要2个cyle读一个。 因为写地址和数据可以同时给。读需要先给地址到slave,从机返回数据后再读数据,因此不能同时发生。