AMBA片上总线设计之Ahb2ApbBridge总结

一、设计前需注意


(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总结_第1张图片

二、状态机设计

状态控制信号:
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总结_第2张图片


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


三、地址与控制信号逻辑

从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;

always@(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总结_第4张图片

代码如下:


`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 
always@(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		C_STATE<=S_IDLE;
	else
		C_STATE<=N_STATE;
end

//state transfer
always@(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;

always@(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		HreadyReg<=1;
	else
		HreadyReg<=HreadyNext;
end

//when ACRegEn effective ,sampling start
always@(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;

always@(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.
always@(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;
always@(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn)
		PWDATA<=0;
	else if(PwriteNext)
		PWDATA<=HWDATA;
end

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

always@(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

always@(*)
begin
	PSELMux=0;
	if(APBEn)
	PSELMux=PSELint;
	else if(N_STATE==S_IDLE||N_STATE==S_WWAIT)
	PSELMux=0;
	else
	PSELMux=PSELReg;
end

always@(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)

always@(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
		
always@(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

always@(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;

always@(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

always@(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









你可能感兴趣的:(verilog,HDL,ARM,Amba片上总线)