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。


二、状态机设计

状态控制信号:
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;

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的重要性了。



仿真图:

代码如下:


`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=(HSEL1’b1)&&(HTRANS<span class="hljs-type">TRN_NONSEQ</span>||<span class="hljs-type">HTRANS</span>==TRN_SEQ);
//if write/read process enters a enable phase or HREADY takes place,sample Address and
//Control signals
assign ACRegEn=HREADY||(C_STATES_WENP||C_STATES_WEN||C_STATES_REN);
//APB access signal (effective when APB slave will be read or written)
assign APBEn=(N_STATE
S_WRITE||N_STATES_WRITEP||N_STATES_READ);
//PriteNext effective when APB slave will be writen(similar with APBEn)
assign PwriteNext=(N_STATES_WRITE||N_STATES_WRITEP);
assign HREADYout=HreadyReg;
assign HRDATA=PRDATA;
assign PENABLE=(C_STATES_WENP||C_STATES_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_STATES_READ)||(N_STATES_WRITEP)||((N_STATES_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_STATES_READ)&&(C_STATES_WEN||C_STATES_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)
<span class="hljs-type">S0ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">0</span>]=<span class="hljs-number">1</span>;S1ADD:PSELint[1]=1;
<span class="hljs-type">S2ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">2</span>]=<span class="hljs-number">1</span>;S3ADD:PSELint[3]=1;
<span class="hljs-type">S4ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">4</span>]=<span class="hljs-number">1</span>;S5ADD:PSELint[5]=1;
<span class="hljs-type">S6ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">6</span>]=<span class="hljs-number">1</span>;S7ADD:PSELint[7]=1;
<span class="hljs-type">S8ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">8</span>]=<span class="hljs-number">1</span>;S9ADD:PSELint[9]=1;
<span class="hljs-type">S10ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">10</span>]=<span class="hljs-number">1</span>;S11ADD:PSELint[11]=1;
<span class="hljs-type">S12ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">12</span>]=<span class="hljs-number">1</span>;S13ADD:PSELint[13]=1;
<span class="hljs-type">S14ADD</span>:<span class="hljs-type">PSELint</span>[<span class="hljs-number">14</span>]=<span class="hljs-number">1</span>;S15ADD:PSELint[15]=1;
default:PSELint=0;
endcase
end

always@(*)
begin
PSELMux=0;
if(APBEn)
PSELMux=PSELint;
else if(N_STATES_IDLE||N_STATES_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 <span class="hljs-number">2</span><span class="hljs-symbol">'b00</span>define TRN_BUSY 2’b01
define TRN_NONSEQ <span class="hljs-number">2</span><span class="hljs-symbol">'b10</span>define TRN_SEQ 2’b11

// HRESP transfer response signal encoding:
define RSP_OKAY <span class="hljs-number">2</span><span class="hljs-symbol">'b00</span>define RSP_ERROR 2’b01
define RSP_RETRY <span class="hljs-number">2</span><span class="hljs-symbol">'b10</span>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[(78-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=<span class="hljs-string">"BUSY"</span>;TRN_IDLE:HTRANS_show=“IDLE”;
TRN_NONSEQ:HTRANS_show=<span class="hljs-string">"NONSEQ"</span>;TRN_SEQ:HTRANS_show=“SEQ”;
endcase
end

initial
begin
mem_HADDR[0]={<!-- -->{4’b0},{S0ADD},{<span class="hljs-number">24</span><span class="hljs-symbol">'b0</span>}}; mem_HADDR[<span class="hljs-number">1</span>]={&lt;!-- --&gt;{<span class="hljs-number">4</span><span class="hljs-symbol">'b0</span>},{S1ADD},{24’b0}};
mem_HADDR[2]={<!-- -->{4’b0},{S2ADD},{<span class="hljs-number">24</span><span class="hljs-symbol">'b0</span>}}; mem_HADDR[<span class="hljs-number">3</span>]={&lt;!-- --&gt;{<span class="hljs-number">4</span><span class="hljs-symbol">'b0</span>},{S3ADD},{24’b0}};
mem_HADDR[4]={<!-- -->{4’b0},{S4ADD},{<span class="hljs-number">24</span><span class="hljs-symbol">'b0</span>}}; mem_HADDR[<span class="hljs-number">5</span>]={&lt;!-- --&gt;{<span class="hljs-number">4</span><span class="hljs-symbol">'b0</span>},{S5ADD},{24’b0}};
mem_HADDR[6]={<!-- -->{4’b0},{S6ADD},{<span class="hljs-number">24</span><span class="hljs-symbol">'b0</span>}}; mem_HADDR[<span class="hljs-number">7</span>]={&lt;!-- --&gt;{<span class="hljs-number">4</span><span class="hljs-symbol">'b0</span>},{S7ADD},{24’b0}};
mem_HADDR[8]={<!-- -->{4’b0},{S8ADD},{<span class="hljs-number">24</span><span class="hljs-symbol">'b0</span>}}; mem_HTRANS[<span class="hljs-number">0</span>]=TRN_NONSEQ;
mem_HTRANS[1]=TRN_SEQ; mem_HTRANS[<span class="hljs-number">2</span>]=TRN_SEQ;
mem_HTRANS[3]=TRN_NONSEQ; mem_HTRANS[<span class="hljs-number">4</span>]=TRN_SEQ;
mem_HTRANS[5]=TRN_NONSEQ; mem_HTRANS[<span class="hljs-number">6</span>]=TRN_IDLE;
mem_HTRANS[7]=TRN_NONSEQ; mem_HTRANS[<span class="hljs-number">8</span>]=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










转载:https://blog.csdn.net/CallMeIvanWay/article/details/72556652
  • 10
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值