当前位置:   article > 正文

AXI_HP_axihp

axihp

ZYNQ AXI协议学习(AXI_HP)

在ZYNQ AXI文章中介绍了 HP接口用于访问DDR和OCM

vivado版本用的2019,创建一个带HP接口的IP核(先分析官方的Demo,后续给出自己工程代码)

IP配置

在这里插入图片描述

在这个IP里面,接口就比AXI_Lite多很多了,首先还是附上整理的接口

在这里插入图片描述

在这里插入图片描述

分析端口信号

  1. status

     INIT_AXI_TXN 这个代码的开始信号
    
     TXN_DONE    数据对比无误(整个Demo是读写数据进行对比)
    
     ERROR       出错信号
    
    • 1
    • 2
    • 3
    • 4
    • 5
  2. Write Addr

     M_AXI_AWID = 0  主机写地址ID
     M_AXI_AWBURST = 2'b01  确定每次突发的地址如何计算
     M_AXI_AWLOCK = 0    传输的原子性
     M_AXI_AWCACHE = 4'b0010 内存类型
     M_AXI_AWPROT = 0    保护类型
     M_AXI_AWQOS = 0     
     M_AXI_AWUSER = 1    写地址通道中的可选用户定义信号
    
     M_AXI_AWADDR 写地址端口,基地址由上面配置可得0x10000000
     M_AXI_AWLEN  突发的数据长度,由配置可得16(最大256)
     M_AXI_AWSIZE 突发的数据大小,由配置可得2
     M_AXI_AWVALID和M_AXI_AWREADY 一对握手信号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  3. Write Data

     M_AXI_WSTRB = 4'b1111 写选通
     M_AXI_WUSER = 0 写入数据通道中的可选用户定义信号
    
     M_AXI_WDATA     写数据端口,位宽32
     M_AXI_WLAST     写突发最后一次的信号
     M_AXI_WVALID和M_AXI_WREADY 一对握手信号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  4. Write resp

     M_AXI_BID       在代码里无逻辑存在
     M_AXI_BRESP     此信号位宽2,第1位用于表示是否出错,高电平为错误状态
     M_AXI_BUSER     在代码里无逻辑存在
     M_AXI_BVALID和M_AXI_BREADY 一对握手信号
    
    • 1
    • 2
    • 3
    • 4
  5. Read Addr

     M_AXI_ARID = 0  主机读地址ID
     M_AXI_ARBURST = 2'b01  确定每次突发的地址如何计算
     M_AXI_ARLOCK = 0    传输的原子性
     M_AXI_ARCACHE = 4'b0010 内存类型
     M_AXI_ARPROT = 0    保护类型
     M_AXI_ARQOS = 0     
     M_AXI_ARUSER = 1    写地址通道中的可选用户定义信号
    
     M_AXI_ARADDR 读地址端口,基地址由上面配置可得0x10000000
     M_AXI_ARLEN  突发的数据长度,由配置可得16(最大256)
     M_AXI_ARSIZE 突发的数据大小,由配置可得2
     M_AXI_ARVALID和M_AXI_ARREADY 一对握手信号       
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  6. Read Data

     M_AXI_RID       在代码里无逻辑存在
     M_AXI_RDATA     读数据端口,位宽32
     M_AXI_RRESP     此信号位宽2,第1位用于表示是否出错,高电平为错误状态
     M_AXI_RLAST     读突发最后一次的信号
     M_AXI_RUSER     在代码里无逻辑存在
     M_AXI_RVALID和M_AXI_RREADY 一对握手信号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

写操作

在线Debug波形图

在这里插入图片描述

  1. 写地址

     由前面分析端口可以得出,在写地址通道里面,我们只需要主要
     M__AXI_AWADDR     M_AXI_AWVALID     M_AXI_AW_READY      (其余得端口都是在初始化就固定了)
    
     assign M_AXI_AWADDR	= C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;
     //代码243行  写地址等于基地址加上偏移地址 基地址C_M_TARGET_SLAVE_BASE_ADDR = 0x10000000(自己修改)
    
     //axi_awaddr 偏移地址 大小等于突发长度*4。突发长度在初始化可以看到是16的长度,地址增长就是0x40.图中可以看到0x10000000后就是0x10000040
    
     //M_AXI_AWVALID和M_AXI_AW_READY信号握手成功后,传输地址,之后准备新的地址,等待下一轮突发
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  2. 写数据

     图中看出写数据的第一个和写地址是同一个时钟,只有在M_AXI_WVALID和M_AXI_WREADY 同时为高电平时传输数据,当传输突发的最后一个数据时,M_AXI_WLAST拉高一个周期,表示突发一次结束
    
    • 1
  3. 写回应

     写回应通道中,其实只需要分析M_AXI_BRESP端口,握手信号如图所示。BRESP的第1位用于表示是否突发写数据出错。只有在写回应通道收到正确信号后,才能开始下一次的突发写操作
    
    • 1

    分析代码:

     always @(posedge M_AXI_ACLK)                                   
     begin                                                                                                                    
     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                           
       begin                                                            
         axi_awvalid <= 1'b0;                                           
       end                                                              
     // If previously not valid , start next transaction                
     else if (~axi_awvalid && start_single_burst_write)                 
       begin                                                            
         axi_awvalid <= 1'b1;                                           
       end                                                              
     /* Once asserted, VALIDs cannot be deasserted, so axi_awvalid      
     must wait until transaction is accepted */                         
     else if (M_AXI_AWREADY && axi_awvalid)                             
       begin                                                            
         axi_awvalid <= 1'b0;                                           
       end                                                              
     else                                                               
       axi_awvalid <= axi_awvalid;                                      
     end     
    
     //此逻辑是写地址有效信号,(写地址准备好信号是PS控制)start_single_burst_write 该信号是由状态机控制的 
    
     INIT_WRITE:                                                                                 
     if (writes_done)                                                                                
     begin                                                                                         
             mst_exec_state <= INIT_READ;//                                                              
     end                                                                                           
     else                                                                                            
     begin                                                                                         
             mst_exec_state  <= INIT_WRITE;                                                              
                                                                                                     
             if (~axi_awvalid && ~start_single_burst_write && ~burst_write_active)                       
             begin                                                                                     
             start_single_burst_write <= 1'b1;                                                       
             end                                                                                       
             else                                                                                        
             begin                                                                                     
             start_single_burst_write <= 1'b0; //Negate to generate a pulse                          
             end                                                                                       
     end                           
     //此逻辑是截取的状态机写操作
    
    
     always @(posedge M_AXI_ACLK)                                                                             begin                                                                                           
     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 
       burst_write_active <= 1'b0;                                                                                                                                                        
     //The burst_write_active is asserted when a write burst transaction is initiated                        
     else if (start_single_burst_write)                                                                      
       burst_write_active <= 1'b1;                                                                           
     else if (M_AXI_BVALID && axi_bready)                                                                    
       burst_write_active <=0;                                                                              end 
     
     //此逻辑是写回应逻辑
    
     //分析这3段逻辑:
         axi_awvalid  start_single_burst_write  burst_write_active 其实就这3个信号的跳变,默认3个信号都是0,当状态机进入写状态时,
         start_single_burst_write=1,axi_awvalid = 0 burst_write_active = 0
         下一个时钟start_single_burst_write = 0,axi_awvalid = 1 burst_write_active = 1
         下一个时钟start_single_burst_write = 0,axi_awvalid = 0 burst_write_active = 1
         只有在写回应通道握手信号都有效时:3个信号同时为0,若此时状态机还在写状态,那么开启下一轮的写地址
         
     always @(posedge M_AXI_ACLK)                                         
     begin                                                                
             if (M_AXI_ARESETN == 0 || init_txn_pulse ==             1'b1)                                            
             begin                                                            
                     axi_awaddr <= 'b0;                                             
             end                                                              
             else if (M_AXI_AWREADY && axi_awvalid)                             
             begin                                                            
                     axi_awaddr <= axi_awaddr + burst_size_bytes;                   
             end                                                              
             else                                                               
                     axi_awaddr <= axi_awaddr;                                        
     end             
    
     //在axi_awvalid = 1 的一个有效周期内 改变地址
    
     assign write_resp_error = axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]; 
     //判断写是否出错
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

写数据就不一一分析了,写数据就是按照突发长度一直送数据就是了

读操作

在线Debug波形图

在这里插入图片描述

  1. 读地址

     读地址通道和写地址通道逻辑是一样的,都是基地址加上偏移地址,每次加上突发长度*4
    
    • 1
  2. 读数据

     由图中可以看出,当M_AXI_RVALID 拉高的同时,地址数据已经准备好了。当M_AXI_RREADY拉高时,就可以接收突发长度的数据(注:这里也是16的长度,我的理解是这个长度是自己定义不需要和写操作一样,不超过256都行)。 
    
    • 1

分析代码:

    因为读写地址逻辑是一样的,直接按照写地址逻辑分析读地址就可以了。

    分析读数据:
    
  always @(posedge M_AXI_ACLK)                                          
  begin                                                                 
    if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                  
      begin                                                             
        axi_rready <= 1'b0;                                             
      end                                                               
    // accept/acknowledge rdata/rresp with axi_rready by the master     
    // when M_AXI_RVALID is asserted by slave                           
    else if (M_AXI_RVALID)                       
      begin                                      
         if (M_AXI_RLAST && axi_rready)          
          begin                                  
            axi_rready <= 1'b0;                  
          end                                    
         else                                    
           begin                                 
             axi_rready <= 1'b1;                 
           end                                   
      end                                        
    // retain the previous value                 
  end 
    //读数据通道的握手信号逻辑,    当M_AXI_RVALID = 1
      下一个周期     M_AXI_RVALID = 1  axi_rready = 1.开始传输数据
      直到M_AXI_RLAST = 1时结束当前突发传输,查看调试图,可以看到3个信号是同时变成低电平的

    assign read_resp_error = axi_rready & M_AXI_RVALID & M_AXI_RRESP[1];  
    //用于判断是否出错
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

AXI_RVALID = 1
下一个周期 M_AXI_RVALID = 1 axi_rready = 1.开始传输数据
直到M_AXI_RLAST = 1时结束当前突发传输,查看调试图,可以看到3个信号是同时变成低电平的

    assign read_resp_error = axi_rready & M_AXI_RVALID & M_AXI_RRESP[1];  
    //用于判断是否出错
  • 1
  • 2

读数据的其他代码其实是用于进行数据对比,在此不分析

至此HP接口读写DDR已分析完毕,后续我会写一个自己的Demo进行在线调试分析

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/999921
推荐阅读
相关标签
  

闽ICP备14008679号