欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AMBA片上总线设计之Ahb2ApbBridge总结

程序员文章站 2024-02-22 21:22:16
...

一、设计前需注意


(1)要做总线,协议是关键,每个控制信号与输入输出的时序一定要搞清楚,直接看amba官方spec,链接已贴出http://pan.baidu.com/s/1gfwxTWB。
(2)Ahb2Apb桥作为逻辑连接器,一方面是在AHB的Slave,另一方面也是AHB的Master。弄清这个概念,就可以定义输入输出的端口,以及需要满足的时序。
(3)HREADY是arbiter收集各个AHBslave设备的HREADYout信号然后做出判断再送给AHBslave作为输入的,本设计测试时直接把HREADYout与HREADY相连就可以。
(4)AHB有pipeline,而APB没有,这就需要让AHB在合适的时候拉低HREADYout添加一个等待周期。
(5)本设计的APB为Lite,Ahb2Apb桥为简易版,无PREADY输入,且HRESP一直输出OKAY。
AMBA片上总线设计之Ahb2ApbBridge总结

二、状态机设计

状态控制信号:
valid:AHBmaster选中桥,HSEL有效,并且输入为NONSEQ或SEQ,valid有效,注意这里并不需要HREADY有效,这是由状态机的转移机制决定的。

assign valid=(HSEL==1'b1)&&(HTRANS==`TRN_NONSEQ||HTRANS==`TRN_SEQ);

HWRITE:S_IDLE,S_REN,S_WEN状态下,AHB送来的指令都”消化“完了,所以状态转移信号直接由AHBmaster送来的控制信号读取。

HwriteReg:若HREADY有效,或者此时状态在S_WEN,S_WENP,S_REN,AHBmaster送来的控制信号和地址信号,HWRITE都会被寄存(设计一个ACRegEn信号控制)。在WENP状态下,因为pending的缘故,状态机会读取寄存的HwriteReg而不是现在送来的控制信号HWRITE来判断下一状态。


状态定义:

S_IDE:空状态,没有收到读写指令。

S_READ:Read Setup过程,这个时候APB端地址被译码后对应的寄存器片选信号拉高,PADDR端在此时就已经送出了相应的地址(这里很关键,后面解释HaddrMux组合模块会详细解释),而下一个时钟上升沿到来时,APB进入data phase,所以此时AHBslave应该告诉master等待一个周期,所以送出一个HREADY低信号。

S_REN:由READ状态无条件进入。PENABLE使能拉高,APB进入data phase。

S_WWAIT:这个就对应了READ状态,但为什么会有一个等待状态而不直接是WRITE呢?因为AHB端是pipeline的,从IDLE或者从REN,WEN状态过来,HWDATA还没送到,而如果从WRITE的pending状态转入时,则不需要进入等待状态。

S_WRITE:在WWAIT状态下,没有收到写的指令,这时候就进入一个直接“消化”的状态,被地址译码后选中的寄存器片选信号拉高,地址被送入,APB进入setup phase。那么为什么WRITE状态又不把HREADYout信号直接拉低从而添加一个等待周期呢?因为状态机在WRITE状态时,会根据当前输入判断下一个状态是进入一个带有pending的WENP或是不带有PENDING的WEN,而WENP这个状态,有些情况是会让HREADY拉低的(后面会详细解释)。这就与REN的无脑拉高HREADYout不同了,所以WRITE不用急着加等待周期。(这里在手写版仿真图的红圈3处可以充分体现)。

S_WEN:如果在WRITE下,状态机还是没有收到新的读写指令,那就跳转到此状态,这就与REN完全一致了,包括转移条件。APB端写动作进入data phase。

S_WRITEP:在WRITE状态下,如果收到了有效的读写信号(valid),无论读写都将会进入此状态,意思是“积食”了,这时候就要挂起(pending)了,当然HREADYout就会被拉低,告诉AHBmaster不要再送新的指令了。这时候,APB端写动作也开始了,与WRITE类似,被地址译码后选中的寄存器片选信号拉高,地址被送入,APB进入setup phase。

S_WENP:这个状态是WRITEP无条件转来的。write之后当然要en,但write状态的时候已经“积食”了,en当然也是在pending状态,虽说在pending状态,但HREADYout信号不一定是继续保持低的。
下面就来解释两种在即将到来的WENP状态下,让HREADYout变成“HIGH”的情况:
(1)我们已经知道了只有两种状态可以转移到WENP,第一种就是WRITEP无条件转来的,在这种状态下,HREADYout是”LOW“,也就是说在下一个时钟上升沿到来时,HwriteReg是不会更新的(理解HwriteReg采样使能便知),WENP状态末端,状态机通过采样HWRITEreg & valid,发现下一状态还是一个WRITEP,并且这个valid还是一个WRITE的指令,这就意味着处理完下一个write,还得再处理一个write,这时候可以把HREADYout拉高,让AHBmaster再送一口“食物”,当然下一状态的WRITEP会自动拉低HREADYout,而WRITEP后无条件转过去的WENP,又回到了这种需要判断的情况了。其实这样过了两个周期,相当于“消化了”一个write,AHBMaster又“喂”了一口,所以这种连续write的情况下,WENP就和REN一样,将HREAYout拉高(见手绘时序图红圈1就可以理解了)。
(2)还是由WRITEP转来,同样的道理,在WRITEP末尾采到~HwriteReg,并且这个~HwriteReg在下一周期(WENP)不会变,在WENP末尾通过~HwriteReg,状态机发现下一状态终于是READ了,下一个该处理这个积压的"READ"指令了,而此时AHBMaster已经pending了很久的valid & READ 指令终于可以在下一个周期处理了,此时可以愉快地拉高HREADYout,让新的指令送进来。(见手绘时序图红圈2);解释完需要拉高HREADYout地情况。
我们来看两种需要保持“LOW”的情况:
(1)这种情况的WENP也是由WRITEP无条件转来,通过WRITEP末端采样到的HwriteReg和valid,可以知道在下一周期即WENP末端采样的也是HwriteReg和valid,从而得知下一状态是WRITEP,但又通过AHBmaster直送的valid和HWRITE,发现此时接受的是一个read指令,也就是说下一状态继续执行没有“消化”完的write而AHBmaster送来的read已经就位了,故需要让AHBmaster挂起这个读指令,直到把先前write的指令全部“消化“完。(红圈4)
(2)在这种情况下,WENP是由WRITE收到valid信号转来的,这说明说明在write状态下,AHBmaster送来了新的read/write指令,注意到WRITE是没有把HREADYout拉低的,而WENP后一定会有两周期需要处理WRITE状态时接收到的write或者read指令,所以WENP会把HREADYout拉低,请求一个等待周期。(红圈3)
我们用HreadyNext信号来描述HREADY下一刻的值,再用寄存器打一拍,表述如下:
assign HreadyNext=((N_STATE==S_READ)||(N_STATE==S_WRITEP)||((N_STATE==S_WENP)&&((~HWRITE&valid)&&(HwriteReg==1'b1))||(C_STATE==S_WRITE)))?1'b0:1'b1;


状态转移图:
AMBA片上总线设计之Ahb2ApbBridge总结


手绘时序图:
AMBA片上总线设计之Ahb2ApbBridge总结


三、地址与控制信号逻辑

从spec上可以看出,APB的信号输出分为两个相位:建立和数据,当片选与地址送入后,下一个上时钟升沿使能拉高,数据传递,而AHB端pipeline结构使得数据会比地址晚一个周期入,所以地址的选择、APB访问使能信号、APB读写使能信号的生成、APB片选信号的输出、以及HREADYout的输出,是设计的关键。HREADYout的输出之前已经讲过,下面分析APBEn、PADDR、PENABLE、PSEL、PWRITE以及PWDATA的生成。

APBEn:
APBEn有效则表示下一时刻会访问APB,所以无论下一状态是写或读(WRITE,WRITEP或READ),APBEn都会被拉高。这个信号直接驱动PADDR,PWRITE。

PADDR:
HaddrMux是一个组合逻辑模块,用来选择不同来源的地址。总的来说地址的来源有两个:一是AHBmaster端直接送入的HADDR,二是经过寄存的HaddrReg,与HwriteReg信号一样,寄存是通过ACRegEn信号控制的。只有当下一状态是READ,并且此时状态为REN,WEN,或者IDLE时,HaddrMUX会直接从AHBmaster端选择地址来源,这是因为在Read Setup过程刚开始时(也就是刚进入READ状态),这个时候APB端地址被译码后对应的寄存器片选信号拉高,PADDR端则在APB访问使能APBEn的驱动下已经送出了相应的地址,而在上一状态为IDLE,REN或者WEN这三种没有pending的状态下,”相应地址“的来源只能时AHBmaster直接送来的地址HADDR。而与之相对应的write过程,则是因为之前有一个WWAIT缓冲状态,地址已被寄存,便可以从HwriteReg读取地址了。

PENABLE:
这个输出很简单,对应状态机所有带EN的状态,直接拉高就可以了。

PWRITE:
与APBEn相似,只是下一状态是写动作的时候才会拉高。

PWDATA:
由PWRITE作使能驱动,在HCLK时钟上升沿,寄存HWDATA输出。

PSEL:
16位总线,由HaddrMux地址的27至24位通过地址译码器选择对应的高位(one-hot)输出,作APBslave的片选信号。同样是要遵循APB的时序。


四、仿真技巧


由于设计到状态机,以及一些预先定义的宏变量,Modelsim直接输出的数字不直观清晰,可以在tb定义reg变量,然后通过组合逻辑把相应信号译成ASCII数组,然后在Modelsim信号查看中替换。
ex:
reg[(9*8-1):0]Current_State;

aaa@qq.com(i1.C_STATE)
begin
case(i1.C_STATE)
S_IDLE:Current_State="S_IDLE";
S_READ:Current_State="S_READ";
S_REN:Current_State="S_REN";
S_WWAIT:Current_State="S_WWAIT";
S_WRITE:Current_State="S_WRITE";
S_WEN:Current_State="S_WEN";
S_WRITEP:Current_State="S_WRITEP";
S_WENP:Current_State="S_WENP";
default:Current_State="error";
endcase
end


此外,注意输出要对应与AHBmaster协议输出,这时候就可以看出BFM的重要性了。



仿真图:
AMBA片上总线设计之Ahb2ApbBridge总结

代码如下:


`define S0ADD 4'b0000
  `define S1ADD 4'b0001
  `define S2ADD 4'b0010
  `define S3ADD 4'b0011
  `define S4ADD 4'b0100
  `define S5ADD 4'b0101
  `define S6ADD 4'b0110
  `define S7ADD 4'b0111
  `define S8ADD 4'b1000
  `define S9ADD 4'b1001
  `define S10ADD 4'b1010
  `define S11ADD 4'b1011
  `define S12ADD 4'b1100
  `define S13ADD 4'b1101
  `define S14ADD 4'b1110
  `define S15ADD 4'b1111
  `define TRN_IDLE 2'b00
  `define TRN_BUSY 2'b01
  `define TRN_NONSEQ 2'b10
  `define TRN_SEQ 2'b11
  `define RSP_OKAY 2'b00
  `define RSP_ERROR 2'b01
  `define RSP_RETRY 2'b10
  `define RSP_SPLIT 2'b11

module Ahb2Apb(HCLK,HRESETn,HWDATA,HADDR,HSEL,HTRANS,HWRITE,HREADY,PRDATA,
PWDATA,PADDR,PWRITE,HRDATA,HRESP,HREADYout,PENABLE,PSEL);
//APB lite(no PREADY)
//*********************************************************************
//AHB slave inputs
input HCLK,HRESETn,HWRITE,HREADY,HSEL;
input[1:0] HTRANS;
input[31:0] HADDR,HWDATA;
//APB master input
input[31:0] PRDATA;
//AHB slave outputs
output[31:0] HRDATA;
output HREADYout;
output[1:0] HRESP;
//APB master outputs
output reg[31:0] PWDATA,PADDR;
output[15:0] PSEL;            //16 slot APB 
output PENABLE;
output reg PWRITE;

//lite version:RESP is always "OKAY"
assign HRESP=`RSP_OKAY; 

//define state
parameter S_IDLE  =8'b0000_0001;		//IDLE
parameter S_READ  =8'b0000_0010;		//READ SETUP
parameter S_REN   =8'b0000_0100;		//READ ENABLE
parameter S_WWAIT =8'b0000_1000;		//WAITING FOR HWDATA
parameter S_WRITE =8'b0001_0000;		//WRITE SETUP(no need for a pending)
parameter S_WRITEP=8'b0010_0000;		//WRITE SETUP(need a pending cycle)
parameter S_WENP  =8'b0100_0000;		//WRITE ENABLE(insert a pedning cycle)
parameter S_WEN   =8'b1000_0000;		//WRITE ENBALE(no need for a pending)

//internal signals

reg HreadyReg;
reg[31:0] HaddrReg;
reg HwriteReg;
reg[15:0] PSELint,PSELMux,PSELReg;
reg[7:0] C_STATE,N_STATE;
wire[3:0] address27to24;
wire APBEn,ACRegEn;
wire PwriteNext;
wire valid;
wire HreadyNext;
wire[31:0] HaddrMux;
// Valid AHB transfers only take place when a non-sequential or sequential
//  transfer is shown on HTRANS - an idle or busy transfer should be ignored.
assign valid=(HSEL==1'b1)&&(HTRANS==`TRN_NONSEQ||HTRANS==`TRN_SEQ);
//if write/read process enters a enable phase or HREADY takes place,sample Address and 
//Control signals
assign ACRegEn=HREADY||(C_STATE==S_WENP||C_STATE==S_WEN||C_STATE==S_REN);
//APB access signal (effective when APB slave will be read or written)
assign APBEn=(N_STATE==S_WRITE||N_STATE==S_WRITEP||N_STATE==S_READ);
//PriteNext effective when APB slave will be writen(similar with APBEn)
assign PwriteNext=(N_STATE==S_WRITE||N_STATE==S_WRITEP);
assign HREADYout=HreadyReg;
assign HRDATA=PRDATA;
assign PENABLE=(C_STATE==S_WENP||C_STATE==S_REN||C_STATE==S_WEN);


//state machine 
aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		C_STATE<=S_IDLE;
	else
		C_STATE<=N_STATE;
end

//state transfer
aaa@qq.com(C_STATE or valid or HwriteReg or HWRITE)
begin
	N_STATE=S_IDLE;
	case(C_STATE)
		S_IDLE:
			if(valid&~HWRITE)
				N_STATE=S_READ;
			else if(valid&HWRITE)
				N_STATE=S_WWAIT;
			else
				N_STATE=S_IDLE;
		S_READ:
				N_STATE=S_REN;
		S_REN:
			if(valid&~HWRITE)
				N_STATE=S_READ;
			else if(valid&HWRITE)
				N_STATE=S_WWAIT;
			else
				N_STATE=S_IDLE;
		S_WWAIT:
			if(~valid)
				N_STATE=S_WRITE;
			else
				N_STATE=S_WRITEP;
		S_WRITE:
			if(~valid)
				N_STATE=S_WEN;
			else
				N_STATE=S_WENP;
		S_WRITEP:
				N_STATE=S_WENP;
		S_WENP:
			if(HwriteReg&valid)
				N_STATE=S_WRITEP;
			else if(HwriteReg&~valid)
				N_STATE=S_WRITE;
			else
				N_STATE=S_READ;
		S_WEN:
			if(valid&HWRITE)
				N_STATE=S_WWAIT;
			else if(valid&~HWRITE)
				N_STATE=S_READ;
			else
				N_STATE=S_IDLE;
		default:N_STATE=S_IDLE;
	endcase
end

//wait states are inserted when
//(1)READ;
//(2)WRITEP; 
//(3)WENP when HWRITE shows a "read" indication but HwriteReg remains a "write"
//indication;
assign HreadyNext=((N_STATE==S_READ)||(N_STATE==S_WRITEP)||((N_STATE==S_WENP)&&
((~HWRITE&valid)&&(HwriteReg==1'b1))||(C_STATE==S_WRITE)))?1'b0:1'b1;

aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		HreadyReg<=1;
	else
		HreadyReg<=HreadyNext;
end

//when ACRegEn effective ,sampling start
aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		begin
			HwriteReg<=1;
			HaddrReg<=0;
		end
	else if(ACRegEn)
		begin
			HwriteReg<=HWRITE;
			HaddrReg<=HADDR;
		end
end

//HaddrMux combinational module will select the right address which will be 
//sampled with the enable signal APBEn for PADDR output.There are two source
//from where we can get address:(1)direct AHB input;(2)address register.And
//a new read, sequential read following another read, or a read following a
//write with no pending transfer are the only transfers that are generated
//directly from the AHB inputs. All other transfers are generated from the
//pipeline registers. 

assign HaddrMux=((N_STATE==S_READ)&&(C_STATE==S_WEN||C_STATE==S_IDLE||
C_STATE==S_REN))?HADDR:HaddrReg;

aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		PADDR<=0;
	else if(APBEn)
		PADDR<=HaddrMux;
end

//Likewise,PWRITE  will be drived to APB port when APBEn effective.
aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		PWRITE<=1;
	else if(APBEn)
		PWRITE<=PwriteNext;
end
	
//PWDATA will be drived to APB port when PWRITE effective;
aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		PWDATA<=0;
	else if(PwriteNext)
		PWDATA<=HWDATA;
end

//decoder
assign address27to24=HaddrMux[27:24];

aaa@qq.com(address27to24)
begin
	PSELint=0;
	case(address27to24)
		`S0ADD:PSELint[0]=1; 
		`S1ADD:PSELint[1]=1; 
		`S2ADD:PSELint[2]=1; 
		`S3ADD:PSELint[3]=1;  
		`S4ADD:PSELint[4]=1;  
		`S5ADD:PSELint[5]=1;  
		`S6ADD:PSELint[6]=1;  
		`S7ADD:PSELint[7]=1;  
		`S8ADD:PSELint[8]=1;  
		`S9ADD:PSELint[9]=1;  
		`S10ADD:PSELint[10]=1;  
		`S11ADD:PSELint[11]=1;  
		`S12ADD:PSELint[12]=1;  
		`S13ADD:PSELint[13]=1; 
		`S14ADD:PSELint[14]=1; 
		`S15ADD:PSELint[15]=1;
		default:PSELint=0;
	endcase
end

aaa@qq.com(*)
begin
	PSELMux=0;
	if(APBEn)
	PSELMux=PSELint;
	else if(N_STATE==S_IDLE||N_STATE==S_WWAIT)
	PSELMux=0;
	else
	PSELMux=PSELReg;
end

aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		PSELReg<=0;
	else
		PSELReg<=PSELMux;
end

assign PSEL=PSELReg;

endmodule


附TB:
//Peripherals address decoding values:
  `define S0ADD 4'b0000
  `define S1ADD 4'b0001
  `define S2ADD 4'b0010
  `define S3ADD 4'b0011
  `define S4ADD 4'b0100
  `define S5ADD 4'b0101
  `define S6ADD 4'b0110
  `define S7ADD 4'b0111
  `define S8ADD 4'b1000
  `define S9ADD 4'b1001
  `define S10ADD 4'b1010
  `define S11ADD 4'b1011
  `define S12ADD 4'b1100
  `define S13ADD 4'b1101
  `define S14ADD 4'b1110
  `define S15ADD 4'b1111

// HTRANS transfer type signal encoding:
  `define TRN_IDLE 2'b00
  `define TRN_BUSY 2'b01
  `define TRN_NONSEQ 2'b10
  `define TRN_SEQ 2'b11

// HRESP transfer response signal encoding:
  `define RSP_OKAY 2'b00
  `define RSP_ERROR 2'b01
  `define RSP_RETRY 2'b10
  `define RSP_SPLIT 2'b11

`timescale 1 ps/ 1 ps
module Ahb2Apb_tb();

reg [31:0] HADDR;
reg HCLK;
//reg HREADY;
reg HRESETn;
reg HSEL;
reg [1:0] HTRANS;
reg [31:0] HWDATA;
reg HWRITE;
reg [31:0] PRDATA;
// wires                                               
wire [31:0]  HRDATA;
wire HREADYout;
wire [1:0]  HRESP;
wire [31:0]  PADDR;
wire PENABLE;
wire [15:0]  PSEL;
wire [31:0]  PWDATA;
wire PWRITE;


//memory HTRANS HADDR HWRITE HWDATA
reg[1:0] mem_HTRANS[0:8];
reg[31:0] mem_HADDR[0:8];
reg mem_HWRITE[0:8];
reg[31:0] mem_HWDATA[0:8];
reg[(7*8-1):0]PSEL_show;
reg[(7*8-1):0]HTRANS_show;
reg[(9*8-1):0]Current_State;
reg[3:0] cnt;

parameter S_IDLE  =8'b0000_0001;		//IDLE
parameter S_READ  =8'b0000_0010;		//READ SETUP
parameter S_REN   =8'b0000_0100;		//READ ENABLE
parameter S_WWAIT =8'b0000_1000;		//WAITING FOR HWDATA
parameter S_WRITE =8'b0001_0000;		//WRITE SETUP(no need for a pending)
parameter S_WRITEP=8'b0010_0000;		//WRITE SETUP(need a pending cycle)
parameter S_WENP  =8'b0100_0000;		//WRITE ENABLE(insert a pedning cycle)
parameter S_WEN   =8'b1000_0000;		//WRITE ENBALE(no need for a pending)

aaa@qq.com(PSEL)
begin
	case(PSEL)
		16'h0001:PSEL_show="SEL_0";
		16'h0002:PSEL_show="SEL_1";
		16'h0004:PSEL_show="SEL_2";
		16'h0008:PSEL_show="SEL_3";
		16'h0010:PSEL_show="SEL_4";
		16'h0020:PSEL_show="SEL_5";
		16'h0040:PSEL_show="SEL_6";
		16'h0080:PSEL_show="SEL_7";
		16'h0100:PSEL_show="SEL_8";
		16'h0200:PSEL_show="SEL_9";
		16'h0400:PSEL_show="SEL_10";
		16'h0800:PSEL_show="SEL_11";
		16'h1000:PSEL_show="SEL_12";
		16'h2000:PSEL_show="SEL_13";
		16'h4000:PSEL_show="SEL_14";
		16'h8000:PSEL_show="SEL_15";
		default:PSEL_show="NONE";
	endcase
end
		
aaa@qq.com(i1.C_STATE)
begin
	case(i1.C_STATE)
		S_IDLE:Current_State="S_IDLE";
		S_READ:Current_State="S_READ";
		S_REN:Current_State="S_REN";
		S_WWAIT:Current_State="S_WWAIT";
		S_WRITE:Current_State="S_WRITE";
		S_WEN:Current_State="S_WEN";
		S_WRITEP:Current_State="S_WRITEP";
		S_WENP:Current_State="S_WENP";
		default:Current_State="error";
	endcase
end

aaa@qq.com(HTRANS)
begin
	case(HTRANS)
		`TRN_BUSY:HTRANS_show="BUSY";
		`TRN_IDLE:HTRANS_show="IDLE";
		`TRN_NONSEQ:HTRANS_show="NONSEQ";
		`TRN_SEQ:HTRANS_show="SEQ";
	endcase
end

initial
begin
mem_HADDR[0]={{4'b0},{`S0ADD},{24'b0}};
mem_HADDR[1]={{4'b0},{`S1ADD},{24'b0}};
mem_HADDR[2]={{4'b0},{`S2ADD},{24'b0}};
mem_HADDR[3]={{4'b0},{`S3ADD},{24'b0}};
mem_HADDR[4]={{4'b0},{`S4ADD},{24'b0}};
mem_HADDR[5]={{4'b0},{`S5ADD},{24'b0}};
mem_HADDR[6]={{4'b0},{`S6ADD},{24'b0}};
mem_HADDR[7]={{4'b0},{`S7ADD},{24'b0}};
mem_HADDR[8]={{4'b0},{`S8ADD},{24'b0}};
mem_HTRANS[0]=`TRN_NONSEQ;
mem_HTRANS[1]=`TRN_SEQ;
mem_HTRANS[2]=`TRN_SEQ;
mem_HTRANS[3]=`TRN_NONSEQ;
mem_HTRANS[4]=`TRN_SEQ;
mem_HTRANS[5]=`TRN_NONSEQ;
mem_HTRANS[6]=`TRN_IDLE;
mem_HTRANS[7]=`TRN_NONSEQ;
mem_HTRANS[8]=`TRN_IDLE;
mem_HWRITE[0]=1'b1;
mem_HWRITE[1]=1'b1;
mem_HWRITE[2]=1'b1;
mem_HWRITE[3]=1'b0;
mem_HWRITE[4]=1'b0;
mem_HWRITE[5]=1'b1;
mem_HWRITE[6]=1'b1;
mem_HWRITE[7]=1'b0;
mem_HWRITE[8]=1'b1;
mem_HWDATA[0]=32'bx;
mem_HWDATA[1]="WD0";
mem_HWDATA[2]="WD1";
mem_HWDATA[3]="WD2";
mem_HWDATA[4]=32'bx;
mem_HWDATA[5]=32'bx;
mem_HWDATA[6]="WD3";
mem_HWDATA[7]=32'bx;
mem_HWDATA[8]=32'bx;

end


// assign statements (if any)                          
Ahb2Apb i1 (
// port map - connection between master ports and signals/registers   
	.HADDR(HADDR),
	.HCLK(HCLK),
	.HRDATA(HRDATA),
	.HREADY(HREADYout),
	.HREADYout(HREADYout),
	.HRESETn(HRESETn),
	.HRESP(HRESP),
	.HSEL(HSEL),
	.HTRANS(HTRANS),
	.HWDATA(HWDATA),
	.HWRITE(HWRITE),
	.PADDR(PADDR),
	.PENABLE(PENABLE),
	.PRDATA(PRDATA),
	.PSEL(PSEL),
	.PWDATA(PWDATA),
	.PWRITE(PWRITE)
);


initial                                                
begin                                                  
HCLK=0;
HTRANS=`TRN_IDLE;
HSEL=1;
HRESETn=0;
HWRITE=1;
HWDATA=0;
PRDATA=0;
end                                                    
always                                                 
#5 HCLK=~HCLK;

aaa@qq.com(posedge HCLK)
begin
	if(PSEL_show=="SEL_3")
		PRDATA<="RD3";
	else if(PSEL_show=="SEL_4")
		PRDATA<="RD4";
	else if(PSEL_show=="SEL_7")
		PRDATA<="RD7";
	else
		PRDATA<=32'bx;
end

aaa@qq.com(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		cnt<=0;
	else if(HREADYout)
		begin
			cnt<=cnt+1;
			HWRITE<=mem_HWRITE[cnt];
			HWDATA<=mem_HWDATA[cnt];
			HADDR<=mem_HADDR[cnt];
			HTRANS<=mem_HTRANS[cnt];
		end
end


initial
begin
repeat(5) @(negedge HCLK) 
HRESETn=1;                                                  
end

endmodule