【蛋糕店老板手把手教你系列——AXI:从入门到进阶(不断更新)】第二讲:AXI4-Lite源代码分析

3 篇文章 2 订阅

我是 蛋糕店老板,一名国科大数字IC在读研究生,研究兴趣是类脑神经网络芯片设计。

file

关注公众号,拉你进“IC设计交流群”。

蛋糕店老板 致力于写原创文章,希望将有深度、有帮助的干货文章带给大家~】

我们重点关注代码的写入逻辑和输出逻辑

1 AXI-Lite源代码关键信号分析

1.1AXI-Lite-Slave 源码分析

12行	    parameter integer C_S_AXI_DATA_WIDTH	= 32,
14行		parameter integer C_S_AXI_ADDR_WIDTH	= 4

源码中首先定义了数据位宽和地址位宽,我在生成该源码时设定DATA_WIDTH= 32,ADDR_WIDTH= 4
问题来了:ADDR_WIDTH 在这里为什么只有4?看一下代码:

231case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
101行	localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
102行	localparam integer OPT_MEM_ADDR_BITS = 1;

以上三行代码要一起看:
这段的意思是对寄存器寻址,学过计组就应该知道,计算机中1word = 32bit = 4Bytes, CPU按照字节寻址,
所以寻字节的过程地址+1,寻字就是地址+4;这里是寻找一个word(一个寄存器存一个word),就应该地址增4;故 ADDR_LSB=2
本代码设定该接口有四个寄存器,故OPT_MEM_ADDR_BITS = 1代表寻址范围是【3:2】也就是4个

ADDR_LSB在32bits datawith 下是2,OPT_MEM_ADDR_BITS在定义4个寄存器情况下为1,地址总线的2、3位从00变换到01、10、11其实就是地址信号axi_awaddr在不停加4。也就验证了不同寄存器的地址偏移4。即地址总线的第2、3bit位决定了数据总线访问哪一个寄存器。

231case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	          2'h0:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
238行	     end

这里展示了对字节寻址的逻辑:数据发来每次以字节写入,分四次写完一个寄存器。整个always块的解释为: 在一个时钟周期内,对寄存器写操作时,地址以4递增寻址,如果寻址到slv_reg0【31:0】就分四次,每次一字节对slv_reg0进行赋值(32bits位宽)。如果寻址到slv_reg1就分四次,每次1字节对slv_reg0进行赋值,依此类推

其中(byte_index*8) +: 8解释:
如果byte_index = 0,那么以上可计算为0 *8+:8 = 0+:8 , A+:B的意思是A向上增加B位,0+:8代表[7:0] 数据段

一定要注意,这里展示的是写数据逻辑,AXI源码写和读是分开的

369行	always @(*)
		begin
	      // Address decoding for reading registers
	      case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	        2'h0   : reg_data_out <= slv_reg0;
	        2'h1   : reg_data_out <= slv_reg1;
	        2'h2   : reg_data_out <= slv_reg2;
	        2'h3   : reg_data_out <= slv_reg3;
	        default : reg_data_out <= 0;
	      endcase
379行	end

这里展示的是AXI4读逻辑,只不过采用的是组合逻辑,axi_araddr信号寻址然后对应地址数据(寄存器中的数据)输出。
这里需要注意的是
四个寄存器从一个固定端口reg_data_out输出,我们以后在修改逻辑时可能需要注意这个端口。

393if (slv_reg_rden)
	        begin
	          axi_rdata <= reg_data_out;     // register read data
396行	    end 
124行	assign S_AXI_RDATA	= axi_rdata;

这里可以看到,读出的信号从S_AXI_RDATA 端口送出,也符合S_AXI_RDATA是读地址端口

1.2AXI-Lite-Master 源码分析

首先分析Master如何判断地址

1.2.1 Master地址逻辑——AXI究竟如何寻址?

12行   parameter  C_M_START_DATA_VALUE	= 32'hAA000000,
15行   parameter  C_M_TARGET_SLAVE_BASE_ADDR	= 32'h40000000,

Slave的定义基地址C_M_TARGET_SLAVE_BASE_ADDR

183行 assign M_AXI_AWADDR	= C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;

下面这个逻辑是自定义的寻址代码,毕竟我们是用状态机来控制Master,一般我们都是采用MCU来控制
所以下面的地址生成和数据生成逻辑是User Logic

446行	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                
	          begin                                                 
	            axi_awaddr <= 0;                                    
	          end                                                                          
	        else if (M_AXI_AWREADY && axi_awvalid)                  
	          begin                                                 
	            axi_awaddr <= axi_awaddr + 32'h00000004;            
	                                                                
	          end                                                   
459行	   end

M_AXI_AWADDR即写地址端口,在基地址的基础上自增4进行寻址

1.2.2 Master写数据逻辑

462行	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                
	          begin                                                 
	            axi_wdata <= C_M_START_DATA_VALUE;                  
	          end                                                                       
	        else if (M_AXI_WREADY && axi_wvalid)                    
	          begin                                                 
	            axi_wdata <= C_M_START_DATA_VALUE + write_index;    
	          end                                                   
474行	  end          	                                                   

关键代码:axi_wdata <= C_M_START_DATA_VALUE + write_index;

274行always @(posedge M_AXI_ACLK)                                                 
	  begin                                                                        
	    if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                   
	      begin                                                                    
	        write_index <= 0;                                                      
	      end                                                                                                                   
	    else if (start_single_write)                                               
	      begin                                                                    
	        write_index <= write_index + 1;                                        
	      end                                                                      
286行 end 

可以看到,数据生成User Logic是采用自增一的方式记录写索引

1.2.3 Master状态机分析

202行	assign init_txn_pulse	= (!init_txn_ff2) && init_txn_ff;

206行	always @(posedge M_AXI_ACLK)										      
	 	 begin                                                                         
	    if (M_AXI_ARESETN == 0 )                                                   
	      begin                                                                    
	        init_txn_ff <= 1'b0;                                                   
	        init_txn_ff2 <= 1'b0;                                                   
	      end                                                                               
	    else                                                                       
	      begin  
	        init_txn_ff <= INIT_AXI_TXN;
	        init_txn_ff2 <= init_txn_ff;                                                                 
	      end                                                                      
219行	 end

init_txn_pulse 采用脉冲信号激活状态机

257if (start_single_write)                                                
	             begin                                                                
259行           axi_awvalid <= 1'b1; 

当start_single_write有效,开始一次写传输,设置axi_awvalid有效

257if (start_single_write)                                                
	          begin                                                                
	            axi_awvalid <= 1'b1;                                               
	          end                                                                  
	      	  else if (M_AXI_AWREADY && axi_awvalid)                                 
	          begin                                                                
264行            axi_awvalid <= 1'b0;

写数据有效

	     else if (start_single_write)                                                
	       begin                                                                     
	         axi_wvalid <= 1'b1;                                                     
	       end                                                                       
	     //Data accepted by interconnect/slave (issue of M_AXI_WREADY by slave)      
	     else if (M_AXI_WREADY && axi_wvalid)                                        
	       begin                                                                     
	        axi_wvalid <= 1'b0;    

写有效

总结:start_single_write信号会引发一次传输的写数据有效和写有效

类似的,start_single_read开启一次读传输,具体代码就不再分析
在这里插入图片描述
借用米联客uisrc的一张图,展示Master的核心状态机逻辑。

状态机代码有些长,就不再博文上贴出,仔细分析会发现:

从代码本身的注释说明的顺序能看出来,master执行写后读的顺序。
写后读之所以重要,为什么该lite协议能够明白何时写,何时读。就是采用状态机将master划分为四个状态。写状态运行完毕后再读,避免冲突。
以下是之前写的一页ppt
在这里插入图片描述

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值