AMBA总线协议-ahb总线互联结构结合协议的理解

总线互联结构(以4*4的总线互联结构为例,其中对于master来说优先级3>2>0>1
,其中2是dummy master,1是defalult master):1.结构中最多可以有16个master,除去dummy master,也就是总线中支持的master数量最多为15个。这一点主要是为了适配hmaster信号一共4bit,对应16;多个master通过仲裁器来决定谁获得总线优先权,获得总线优先权的master通过地址信息和译码电路实现对具体哪个slave进行访问。仲裁器会保证同一时刻只会有一个master在工作。

2.对于dummpy master来说,在slave支持split的系统中需要存在。在如下情况中需要dummy master进行工作:(1)lock传输的时候返回split(2)slave返回split响应的时候其他master也正在split过程中。

具体代码如下:

always @ (posedge hclk or negedge hrst_n)begin
	if(!hrst_n)begin
		grant	<=	'b0;
	end
	else begin
		if(is_locked && (hresp == `SPLIT) || req_mask == 'b0 || (hgrantx1 && hresp == `SPLIT && !hbusreqx2 && !hbusreqx3))begin
			grant	<=	'b0;
		end
		else if(is_degrant)begin
			grant	<=	next_grant;
		end
	end
end

分析:传输过程中+split;所有slave都在split;最低优先级master掌握总线并且该master被回应split。

3.slave关于split的逻辑产生:

always @ (posedge hclk or negedge hrst_n)begin
		if(!hrst_n)begin
			pending_split	<=	'b0;
			ready_split		<=	'b0;
		end
		else if(current_state == SPLIT1)begin
			case(hmaster)
				4'h1: pending_split <= pending_split | 4'b0010;
				4'h2: pending_split <= pending_split | 4'b0100;
				4'h3: pending_split <= pending_split | 4'b1000;
				default: pending_split <= pending_split | 4'b0001;
			endcase
		end
		else begin
			if(deassert_split)begin
				ready_split <= pending_split | ready_split;
			end
			else begin
				if(hsel)begin
					case(hmaster)
						4'h1: begin
							if(ready_split[1]) begin
								ready_split <= ready_split & 4'b1101;
							end
						end
						4'h2: begin
							if(ready_split[2]) begin
							ready_split <= ready_split & 4'b1011;
							end
						end
						4'h3: begin
							if(ready_split[3]) begin
							ready_split <= ready_split & 4'b0111;
							end
						end
						default: begin
							if(ready_split[0]) begin
							ready_split <= ready_split & 4'b1110;
						end
				end
			end
		end
	end

首先slave在需要进行分段传输的时候需要给master回应hresp信号,同时内部的状态机应该跳转到split的状态中,这个逻辑的产生是根据slvae自身需要发起的;

当前如果slave处在split状态,slave通过master给到自己的hmaster信号感知是哪个mater此时在和我进行数据传输,并且通过pending_split 信号记录下来这个信息,这个信息相当于记录了哪个master的数据传输被split。在slave将数据准备好的时候,deassert_split信号拉高。随后将pending的split信号给到ready的split信号,这里或了一个ready的split信号目的在于记录原来处在split状态的但是数据还没准备好的slave的信息,由于一次只会有一个master工作,清除split的时候一次只能清除一个,因此需要将这个信息保留。需要注意的是在deassert_split拉高的当前拍并不会立刻将这个slave被split的数据准备好的信息告诉mater。当deassert_split信号拉高后表示对应的slave数据已经准备好了,ready_split对应的那一位也拉高了,当ready_split对应的那一位拉高后将其清除掉进而告诉master分段数据已经准备好了(在这里为0表示准备好了,为1表示没有准备好)。

4.arbiter关于被split的master的处理:

always @ (*) begin
  // Free HBUSREQ mask based on HSPLIT
  next_req_mask = req_mask | HSPLIT;
  // Mask bits if is_split
  if(is_split) begin
    case(HMASTER)
      2'b00: next_req_mask[0] = 1'b0;
      2'b01: next_req_mask[1] = 1'b0;
      2'b10: next_req_mask[2] = 1'b0;
      2'b11: next_req_mask[3] = 1'b0;
    endcase
  end
end

always @ (posedge HCLK or negedge HRESETn) begin
  if(!HRESETn) begin
    req_mask <= 4'b1111;
  end
  else begin
    req_mask <= next_req_mask;
  end
end

这里需要注意is_split信号表示slave回应给master一个split的信号,表示于当前slave建立传输的master需要被mask,直到slave准备好数据(也就是将对应的req_mask变为0)。可以观察下面对next_grant的判断的时候,在给master权限的时候都加了req_mask信号。也就是req_mask信号如果为0,那么仲裁器是不会给对应master的权限。

always @(*)begin
	if(hbusreqx3 && req_mask[3])begin
		next_grant	=	4'h3;
	end
	else if(hbusreqx2 && req_mask[2])begin
		next_grant	=	4'h2;
	end
	else begin
		next_grant	=	4'h1;
	end
end

5.arbiter中一次master的burst传输何时结束需要考虑以下几点:

(1)是否是定长传输,在定长传输的时候,由于hbusreq信号在获得总线授权的情况下该信号就会拉低,因此需要在arbiter内部设置计数器,自己计算传输什么时候结束,代码如下:

always @ (posedge hclk or negedge hrst_n)begin
	if(!hrst_n)begin
		count	<=	'b0;
	end
	else begin
		count <= next_count;
	end
end

always @(*)begin
	if(htrans == `NONSEQ)begin
		if(hready)begin
			case(hburst)
				`WRAP4:  next_count = 6'h3;
				`INCR4:  next_count = 6'h3;
				`WRAP8:  next_count = 6'h7;
				`INCR8:  next_count = 6'h7;
				`WRAP16: next_count = 6'hf;
				`WRAP16: next_count = 6'hf;
			endcase
		end
		else begin
			case(hburst)
				`WRAP4:  next_count = 6'h4;
				`INCR4:  next_count = 6'h4;
				`WRAP8:  next_count = 6'h8;
				`INCR8:  next_count = 6'h8;
				`WRAP16: next_count = 6'h10;
				`WRAP16: next_count = 6'h10;
			endcase
		end
	end
	else if(htrans == `BUSY)begin
		next_count = count;
	end
	else if(htrans == `IDLE)begin
		next_count = 'b0;
	end
	else begin
		if(hready)begin
			next_count = count - 1;
		end
		else begin
			next_count = count;
		end
	end
end

在count赋值的时候需要考虑当前拍的ready信号,如果ready信号为高说明当前拍已经算一次传输周期了,因此count值要减一。

(2)不是定长传输的时候,由于hbusreq需要持续拉高,因此可以用hbusreq和对应的hgrant信号合并判断什么时候数据传输结束。此外还需要考虑split、retry、idle情况时,也是相当于需要开启一下新的传输。整体逻辑如下:

always @ (*)begin
	if(!is_fixed_length && ((hgrantx0 && !hbusreqx0)||
							(hgrantx1 && !hbusreqx1)||
							(hgrantx2 && !hbusreqx2)||
							(hgrantx3 && !hbusreqx3)))begin
		is_degrant = 'b1;					
	end
	else if(htrans == `IDLE)begin
		is_degrant = 'b1;
	end
	else if(is_fixed_length && (!is_locked) && (next_count == 'b0 || next_count == 'b1))begin
		is_degrant	= 'b1;
	end
	else if(is_split || is_retry)begin
		is_degrant	= 'b1;
	end
	else begin
		is_degrant	= 'b0;
	end
end

5.slave的lock逻辑产生:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值