当前位置:网站首页>APB2standard_handshake_bridge 设计

APB2standard_handshake_bridge 设计

2022-06-11 19:27:00 Starry丶


1. 功能描述

由于SoC的外围设备,例如USART、SPI、I2C等板级慢速通信接口,以及外围存储设备如RAM等,都是通过APB进行总线通信的。

而上述这些设备的常用接口并不是基于APB,所以就需要一个APB到标准握手的桥接器,实现接口转化,例如下图

在这里插入图片描述

是的,APB2HANDSHAKE桥是作为APB slave呈现的,由此可以得出桥接器的输入输出

2. 参数描述

Group Signal Direction Width(bits) Description
APB slaveprstninput1复位信号
pclkinput1时钟
paddrinputPADDR_WIDTH用于访问内部寄存器的地址
pwriteinput11表示写,0表示读
pselinput1选通
penableinput1APB使能
pwdatainputPDATA_WIDTH写数据
prdatainputPDATA_WIDTH读出的数据
preadyoutput1准备标志
pslverroutput1传输错误标志,地址无效时传输也就无效
Standard HandshakewaddroutputPADDR_WIDTH写地址
wdataoutputPDATA_WIDTH写数据
wr_enoutput1写使能
wreadyinput1写准备
raddroutputPADDR_WIDTH读地址
rdatainputPDATA_WIDTH读数据
rdata_valinput1读数据有效
rd_enoutput1读使能
rreadyinput1读准备

之后是参数描述

Parameter Units Description
PADDR_WIDTHbit访问SPI内部FIFO的地址位宽
PDATA_WIDTHbit写入or读出的数据位宽
ACCESS_ADDR1、ACCESS_ADDR2、ACCESS_ADDR3、ACCESS_ADDR4bit可访问地址

3. 逻辑设计

按照状态机的思路,可将传输过程按照APB的状态机分为IDLE、SETUP和ACCESS。

如果是写操作,就比较简单,只需在ACCESS阶段pwdata就是wdata、paddr就是waddr,而pready就是wready,检测到pready && psel && penable 就说明写入完成,如下波形图

在这里插入图片描述

读操作有两点需要注意,一个是读出有效数据需要两拍,还有就是读数据时pready表示的是读数据有效而不是读准备。

所以可以通过组合逻辑在APB的SETUP阶段就拉高rd_en 开始读,然后检测rready,一旦发现rready为高就说明rdata将在下一拍读出新数据,并且rdata_val与pready也是组合逻辑等于。

在这里插入图片描述

3.1. 代码

在实际写代码的时候,发现rd_en必须通过组合逻辑实现上述波形,所以不需要检测rready为高再拉低这种时序逻辑

module apb2standard_handshake_bridge#(
	parameter	PADDR_WIDTH = 32,
	parameter	PDATA_WIDTH = 32
	parameter	ACCESS_ADDR1 = 32'h0000_0000_0000_0010,
	parameter	ACCESS_ADDR2 = 32'h0000_0000_0000_0014,
	parameter	ACCESS_ADDR3 = 32'h0000_0000_0000_0018,
	parameter	ACCESS_ADDR4 = 32'h0000_0000_0000_001C
	)(
	input 						prstn,
	input 						pclk,
	input	[PADDR_WIDTH-1:0]	paddr,
	input						pwrite,
	input						psel,
	input						penable,
	input	[PDATA_WIDTH-1:0]	pwdata,
	output	[PDATA_WIDTH-1:0]	prdata,
	output						pready,
	output						pslverr,
	
	output	[PADDR_WIDTH-1:0]	waddr,
	output	[PDATA_WIDTH-1:0]	wdata,
	output						wr_en,
	input						wready,
	
	output	[PADDR_WIDTH-1:0]	raddr,
	input	[PDATA_WIDTH-1:0]	rdata,
	input						rdata_val,
	output						rd_en,
	input						rready
	);

reg						wr_en_r;
reg						rd_en_r;

[email protected](posedge pclk or negedge prstn) begin
	if(!prstn)
		wr_en_r <= 1'b0;
	else if(pwrite && psel) begin
			if(!penable)
				wr_en_r <= 1'b1;
			else if(!wready)
				wr_en_r <= 1'b1;
			else
				wr_en_r <= 1'b0;
		end
	else
		wr_en_r <= 1'b0;
end

assign wr_en = wr_en_r;

assign waddr = paddr;

assign raddr = paddr;

assign wdata = pwdata;

assign pready = (pwrite)? wready:rdata_val;

assign prdata = rdata;

[email protected](*) begin
	if(!pwrite && psel && !rdata_val)
		rd_en_r = 1'b1;
	else
		rd_en_r = 1'b0;
end

assign rd_en = rd_en_r;

assign pslverr = pready && (paddr != ACCESS_ADDR1)
						&& (paddr != ACCESS_ADDR2)
						&& (paddr != ACCESS_ADDR3)
						&& (paddr != ACCESS_ADDR4);

endmodule
原网站

版权声明
本文为[Starry丶]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Starry__/article/details/125229745