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。
二、状态机设计
状态控制信号:
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;
状态转移图:
手绘时序图:
三、地址与控制信号逻辑
从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
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的重要性了。
仿真图:
代码如下:
`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