Ahb2ApbBridge

article/2025/10/14 0:02:54

一、设计前需注意


(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

http://chatgpt.dhexx.cn/article/fTZH8bNa.shtml

相关文章

AHB总线协议

文章目录 1.说明2.简介3. SOC中的AHB4.完整的AHB架构5.AHB接口信号列表6.htrans[1:0]/hsize[2:0]/hburst[2:0]/hresp[1:0]信号解读1.htrans[1:0]2.hsize[2:0]3.hburst[2:0]4. hresp[1:0] 7.基本传输1. 没有等待的读写操作2.有等待的传输3. 多个流水传输3.WRAP4的传输 8. hready…

AMBA AHB介绍

AMBA AHB介绍 AHB是为提出高性能可综合设计的要求而产生的新一代AMBA总线。它是一种支持多总线主机和提供高带宽操作的高性能总线。 AMBA AHB实现了高性能&#xff0c;高时钟频率系统的以下特征要求&#xff1a; 突发传输分块处理单周期总线主机移交非三态执行更宽的数据总线…

qspi AHB总线学习 - 01

经过几天的学习发现如果不了解AHB总线有些知识get不到&#xff0c;下面是转 qixin_william的博客 http://blog.163.com/qixin_william/blog/static/240217035201491133626819/ 一、AHB的基本介绍 AHB是ARM退出的AMBA总线系列中的其中一种&#xff0c;它是一种高性能的pipe系统总…

AMBA5 AHB协议规范(AHB5,AHB-Lite)中文版-第五章 从机响应信号

第五章 从机响应信号 介绍从机响应信号。它包括以下部分: – 从机传输响应on page 5-56. 5.1 Slave transfer responses 在主机开始传输后&#xff0c;控制传输的进展。在传输开始后&#xff0c;主机不能取消传输。 对于支持AHB5 Exclusive_Transfers属性的组件&#xff0c;…

AHB总线学习汇总

博客不是写书&#xff0c;基本的背景也不做什么介绍了&#xff0c;了解的人是不会介意这些东西的。 一、AHB的基本介绍 AHB是ARM退出的AMBA总线系列中的其中一种&#xff0c;它是一种高性能的pipe系统总线。 1. AHB总线有一下特性&#xff1a; a.Burst 传输 b.Split 事务处理…

AHB协议相关

AHB协议相关 Created: November 9, 2021 7:19 PM Tags: AMBA &#x1f340;简介 AHB(Advanced High Performance Bus)总线规范是AMBA(Advanced Microcontroller Bus Architecture) V2.0总线规范的一部分&#xff0c;AMBA总线规范是ARM公司提出的总线规范&#xff0c;被大多数…

AHB协议

文章目录 什么是AHB总线协议AHB总线组成AHB信号描述AHB传输Bust传输 AMBA高级处理器总线架构&#xff0c;不同的速率要求构成了高性能SOC设计的通信标准: AHB高级高性能总线APB高级外围总线AXI高级可拓展接口 什么是AHB总线协议 AHB&#xff1a;主要是针对高速率、高频宽及快…

AHB 协议学习

文章目录 AHB 协议学习一、 AHB 协议 信号二、 AHB 协议 传输2.1 a read transfer with two wait states2.2 a write transfer with one wait states2.3 transfer with HTRANS&#xff08;控制信号&#xff09;**2.4 transfer &#xff1a;Eight-beat incrementing burst, INCR…

AMBA5 AHB协议规范(AHB5,AHB-Lite)中文版-第三章 传输

第三章 Transfers 本章描述读写传输。它包括以下部分: – 基本传输 on page 3-28. – 传输类型 on page 3-30. – 锁定传输 on page 3-32. – 传输大小 on page 3-33. – 突发操作 on page 3-34. – 等待传输 on page 3-39. – 保护控制 on page 3-44. – 内存类型 on page 3-…

AMBA 系列之 AHB 协议

目录 1. 简介 1.1 AHB总线的架构 1.2 AHB基本特性 2. AHB总线的组成 3. 信号描述 3.1 AHB Slave 接口 3.2 AHB Master 接口 3.3 AHB Arbiter 接口 3.4 AHB Decoder 接口 4. 总线操作 5. 基本传输 5.1 没有等待状态的单次传输&#xff08;Single Transfer&#xff0…

AHB总线

大部分的总结在csdn里面都有。这里只是总结自己理解的。 AHB基本特性有&#xff1a; Burst传输&#xff08;一共有Hburst[2 : 0]的类型&#xff09;&#xff0c;single&#xff0c;incr&#xff0c;wrap4&#xff0c;incr4&#xff0c;wrap8&#xff0c;incr8&#xff0c;wra…

AMBA5 AHB协议规范(AHB5,AHB-Lite)中文版-第一章 引言

ARM AMBA 5 AHB 协议规范 AHB5, AHB-Lite 发行信息 变更历史 日期版本保密性更改2006/6/26A非保密First release for v1.02015/6/25B.a保密Update for AMBA 5 AHB Protocol Specification2015/10/30B.b非保密Confidential to Non-Confidential Release Contents ARM AMBA 5 A…

AHB协议详解

AHB总线 AHB总线在AMBA2中就已经定义&#xff0c;AHB总线一开始主要是作为系统高速总线使用&#xff0c;适用于高性能&#xff0c;低功耗的系统设计。目前因为AXI总线作为高速总线的优势更加明显&#xff0c;AHB会用在相对低速的系统设计中。基本排序就是APB适用于低速设计&am…

AHB学习笔记

1.AHB概述 AHB总线是一种专为高性能同步传输设计的总线&#xff0c;层次高于APB总线&#xff0c;支持以下特性&#xff1a; 突发传输拆分事务主设备单时钟周期传输单时钟沿操作非三态实现宽数据总线配置&#xff08;64/128bit&#xff09; 1.1.典型AHB系统 典型的AHB系统包括以…

AHB协议学习

AHB协议总结 AHB协议学习1. AHB简介2. AHB的接口信号2.1 Global signals2.2 Master signals2.3 slave signals2.4 decoder signals2.5 multiplexor signals 3. 传输4. Decoder5. Multiplexor6. 大小端Endianness&#xff1a;7. Exclusive transfer AHB协议学习 1. AHB简介 AH…

AHB总线介绍【1】

1.简介 AHB总线规范是amba总线的一部分&#xff0c;全称是Advanced high performance bus。AMBA总线常用的有AXI&#xff0c;AHB&#xff0c;APB。APB 的全称&#xff1a;Advanced Peripheral Bus 作为 AMBA 总线的一层&#xff0c;APB 总线是为了功耗最小化和减低接口复杂度而…

AMBA总线—AHB总线协议详解

文章目录 一、AMBA总线介绍1.1.AMBA发展史1.2.典型的AMBA系统 二、AHB总线&#xff08;宏观构造&#xff09;2.1.AHB总线组成2.2.AHB总线组成互连2.3.AHB操作概述2.4.AHB基本传输阶段 三、AHB总线传输&#xff08;时序&#xff09;3.1.AHB信号描述&#xff08;重要&#xff09;…

Docker详解之EXPOSE

EXPOSE <端口1> [<端口2>...] 大家都知道以上代码是Dockerfile中来声明端口的命令&#xff0c;但是你真的了解过它吗&#xff1f;现在我带大家来深入了解我们的EXPOSE命令。 首先&#xff0c;我们最应该明确的一点就是&#xff0c;EXPOSE命令只是声明了容器应该打…

Network: use `--host` to expose

vite启动后提示&#xff1a; Network: use --host to expose&#xff0c;且无法通过网络IP访问服务 你遇到的问题是不是跟下图这样&#xff1a; 此问题的原因 当 局域网 中另一台设备需要访问该服务时&#xff0c;必须通过本机 IP 端口 访问。 尝试访问后&#xff0c;发现找…

AE(Auto Expose)自动曝光

AE Auto Expose自动曝光 1.作者&#xff1a;一隅生 自动曝光就是相机根据光线条件自动确定曝光量。 从根本测光原理上分可分两种&#xff1a;入射式和反射式。入射式就是测量照射到相机上的光线的亮度来确定曝光组合&#xff0c;这是一种简单粗略的控制&#xff0c;多用于低档相…