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

3 篇文章 2 订阅

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

file

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

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

2、AXI-Full源代码关键信号分析

2.1AXI-Full-Slave

2.2.1 Slave地址逻辑——AXI究竟如何寻址?

答案是:突发模式:包括以下三种
fixed burst
incremental burst
Wrapping burst

信号方向描述
AWLEN主机to从机AWLEN[7:0]决定写传输的突发长度。AXI3只支持116次的突发传输(Burst_length=AxLEN[3:0]+1),AXI4扩展突发长度支持INCR突发类型为1256次传输,对于其他的传输类型依然保持1~16次突发传输(Burst_Length=AxLEN[7:0]+1)。burst传输具有如下规则:wraping burst ,burst长度必须是2,4,8,16burst不能跨4KB边界不支持提前终止burst传输
AWSIZE主机to从机写突发大小,给出每次突发传输的字节数支持1、2、4、8、16、32、64、128
AWBURST主机to从机突发类型:2’b00 FIXED:突发传输过程中地址固定,用于FIFO访问 2’b01 INCR :增量突发,传输过程中,地址递增。增加量取决AxSIZE的值。 2’b10 WRAP:回环突发,和增量突发类似,但会在特定高地址的边界处回到低地址处。回环突发的长度只能是2,4,8,16次传输,传输首地址和每次传输的大小对齐。最低的地址整个传输的数据大小对齐。回环边界等于(AxSIZE*AxLEN)2’b11 Reserved

我们来分析突发模式代码:
复位逻辑

284if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_awaddr <= 0;
	      axi_awlen_cntr <= 0;
	      axi_awburst <= 0;
	      axi_awlen <= 0;

S_AXI_AWVALID信号传来时,开启地址锁存和awlen计数器的计数

293if (~axi_awready && S_AXI_AWVALID && ~axi_awv_awr_flag)
	        begin
	          axi_awaddr <= S_AXI_AWADDR[C_S_AXI_ADDR_WIDTH - 1:0];  
	           axi_awburst <= S_AXI_AWBURST; 
	           axi_awlen <= S_AXI_AWLEN;     	        
	          axi_awlen_cntr <= 0;
	        end 

这段代码很重要:如果awlen计数器还没有计数到突发长度,并且此时写数据ready和vaild有效,这时候awlen计数器加一,并且引出axi_awburst类型的判断和响应操作

302else if((axi_awlen_cntr <= axi_awlen) && axi_wready && S_AXI_WVALID)        
	        begin

	          axi_awlen_cntr <= axi_awlen_cntr + 1;

axi_awburst类型判断开始:
fixed burst 传输类型:awaddr是多少就是多少
incremental burst 传输类型:以字节寻址并且加一,字如其名自增突发
Wrapping burst 传输类型:回环突发,首先判断是不是到达回环的末尾地址:aw_wrap_en,如果不是,那么地址自己加一(字节寻址);如果是,地址回到突发地址的首位axi_awaddr <= (axi_awaddr - aw_wrap_size);

307case (axi_awburst)
	            2'b00: // fixed burst	         
	              begin
	                axi_awaddr <= axi_awaddr;          
	              end   
	            2'b01: //incremental burst
	              begin
	                axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
	                axi_awaddr[ADDR_LSB-1:0]  <= {ADDR_LSB{1'b0}};   
	              end   
	            2'b10: //Wrapping burst
	              if (aw_wrap_en)
	                begin
	                  axi_awaddr <= (axi_awaddr - aw_wrap_size); 
	                end
	              else 
	                begin
	                  axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
	                  axi_awaddr[ADDR_LSB-1:0]  <= {ADDR_LSB{1'b0}}; 
	                end                      
	            default: //reserved (incremental burst for example)
	              begin
	                axi_awaddr <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;

读地址araddr与写地址awaddr类似,就不多分析了

2.2.1 Slave数据逻辑——AXI究竟如何写\读数据?

答案是:从BRAM中读出数据

547行	generate
	     if (USER_NUM_MEM >= 1)
	    begin
	      assign mem_select  = 1;
	      assign mem_address = (axi_arv_arr_flag? axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]:(axi_awv_awr_flag? axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]:0));
	    end
	endgenerate

mem_address是多少呢?
axi_arv_arr_flag有效,那mem_address就是axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]
axi_awv_awr_flag有效,那mem_address就是axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]
都不满足,那mem_address就是0

其中: OPT_MEM_ADDR_BITS = 3;
The axi_awv_awr_flag代表 write address 有效
The axi_arv_arr_flag 代表 read address 有效

下面讲解 Block RAM(s)的实现

556行	generate 
	  for(i=0; i<= USER_NUM_MEM-1; i=i+1)
	    begin:BRAM_GEN
	      wire mem_rden;
	      wire mem_wren;
	      assign mem_wren = axi_wready && S_AXI_WVALID ;	
	      assign mem_rden = axi_arv_arr_flag ; //& ~axi_rvalid
   

生成Bram,mem_rden和mem_rden 设定启动条件

567for(mem_byte_index=0; mem_byte_index<= (C_S_AXI_DATA_WIDTH/8-1); mem_byte_index=mem_byte_index+1)
 begin:BYTE_BRAM_GEN
	        wire [8-1:0] data_in ;
	        wire [8-1:0] data_out;
	        reg  [8-1:0] byte_ram [0 : 15];
	        integer  j;
	     
	        //assigning 8 bit data
	        assign data_in  = S_AXI_WDATA[(mem_byte_index*8+7) -: 8];
	        assign data_out = byte_ram[mem_address];
	     
	        always @( posedge S_AXI_ACLK )
	        begin
	          if (mem_wren && S_AXI_WSTRB[mem_byte_index])
	            begin
	              byte_ram[mem_address] <= data_in;
	            end   
	        end    
	      
	        always @( posedge S_AXI_ACLK )
	        begin
	          if (mem_rden)
	            begin
	              mem_data_out[i][(mem_byte_index*8+7) -: 8] <= data_out;
	            end   
	        end

567行的代码:表示按字节寻址
下一行启动Bram生成代码BYTE_BRAM_GEN
后面定义了位宽为8,深度为16的一段存储[8-1:0] byte_ram [0 : 15];
data_in按字节赋值
data_out = byte_ram[mem_address]; 其中mem_address在之前代码给出

577行	        always @( posedge S_AXI_ACLK )
	        begin
	          if (mem_wren && S_AXI_WSTRB[mem_byte_index])
	            begin
	              byte_ram[mem_address] <= data_in;
	            end   
	        end 

写数据阶段data_in就把数据写入ram中

 always @( posedge S_AXI_ACLK )
	        begin
	          if (mem_rden)
	            begin
	              mem_data_out[i][(mem_byte_index*8+7) -: 8] <= data_out;
	            end   
	        end    

读数据阶段就字节寻址给出

	endgenerate

读写数据结束

2.2AXI-Full-Master

AXI-Full-Master暂时不分析,跟lite类似

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值