当前位置:网站首页>AHB2Standard_handshake_bridge 设计
AHB2Standard_handshake_bridge 设计
2022-06-11 19:27:00 【Starry丶】
1. 功能描述
AHB协议毕竟与FIFO、RAM等读写协议不一样,而AHB是SoC系统片内常用的高速接口,所以就需要将AHB的时序转化为标准的握手时序,此处研究AHB到标准握手的桥接器,实现接口转化。
例如下图

是的,AHB2HANDSHAKE桥是作为AHB slave呈现的,由此可以得出桥接器的输入输出
2. 参数描述
| Group | Signal | Direction | Width(bits) | Description |
|---|---|---|---|---|
| AHB slave | hrstn | input | 1 | 复位信号 |
| hclk | input | 1 | 时钟 | |
| haddr | input | HADDR_WIDTH | 用于访问内部寄存器的地址 | |
| hburst | input | 3 | burst传输格式 | |
| hsize | input | 3 | 数据传输有效位 | |
| htrans | input | 2 | 传输状态 | |
| hwrite | input | 1 | 1表示写,0表示读 | |
| hsel | input | 1 | 选通 | |
| hwdata | input | HDATA_WIDTH | 写数据 | |
| hrdata | output | HDATA_WIDTH | 读出的数据 | |
| hreadyout | output | 1 | 准备标志 | |
| hresp | output | 1 | 反馈当前传输是否存在错误 | |
| Standard Handshake | waddr | output | HADDR_WIDTH | 写地址 |
| wdata | output | HDATA_WIDTH | 写数据 | |
| wr_en | output | 1 | 写使能 | |
| wready | input | 1 | 写准备 | |
| raddr | output | HADDR_WIDTH | 读地址 | |
| rdata | input | HDATA_WIDTH | 读数据 | |
| rdata_val | input | 1 | 读数据有效 | |
| rd_en | output | 1 | 读使能 | |
| rready | input | 1 | 读准备 |
之后是参数描述
| Parameter | Units | Description |
|---|---|---|
| HADDR_WIDTH | bit | 地址位宽 |
| HDATA_WIDTH | bit | 写入or读出的数据位宽 |
| ACCESS_ADDR1、ACCESS_ADDR2、ACCESS_ADDR3、ACCESS_ADDR4 | bit | 可访问地址 |
3. 逻辑设计

从上图可以看出,AHB2HANDSHAKE模块是作为AHB slave出现的,所以要从AHB Slave角度进行设计。
依然是按照状态机的思路。如果是状态机的思路,AHB协议中HTRANS有四种状态、HBURST有八种状态,我们使用哪一个呢?还是自己写状态机?
可选择思路是基于HTRANS的IDLE、BUSY、NONSEQ和SEQ四种状态进行设计,毕竟burst传输属于NONSEQ或SEQ状态。
3.1. HTRANS没法用
哈哈哈我根据HTRANS的四种状态设计了半天发现作为AHB slave压根就没法用状态机。
先看看下面这几张波形图,从AHB Slave的角度思考一下


上图中揭示了AHB比较膈应的地方,就是一次访问地址和数据是分两拍进行的,当然这也是实现流水的基础。这就导致了第二拍传数据的时候,地址可以发生变化。
所以如果对一个地址的访问需要两拍,注意这两拍中address phase与data phase可不在同一个HTRANS,data phase甚至会跨越多个HTRANS状态。
换句话说就是,HTRANS这个状态机不能决定hwdata和hrdata信号的变化规律。
这个与平时的状态机设计不同,平时设计的思路是整个模块被分成好几个状态,该模块的每个信号会根据不同状态变化规律不一。
但是AHB协议中HADDR会根据HTRANS的取值来决定是否有效,而HWDATA和HRDATA的变化并不会参照HTRANS这个状态。
但是作为AHB Slave不必关心有没有跨HTRANS、HTRANS某个状态是否要延迟,这个是AHB Master要做的事情。作为slave,只需要将数据正确写入或正确读出即可
那么如何对AHB到标准握手时序桥进行设计呢?还是状态机,不过我们采用最原始的状态机:读和写

3.2. IDLE
该状态下当然是啥都不干啦,当检测到AHB master要进行传输时,即htrans为NONSEQ时,检测hwrite判断转入WRITE还是READ,如下图

于是状态机重写为

3.3. 写
该状态下实现写,当标准握手时序下写完成该状态结束。
注意是标准握手时序,所以需要将地址和数据在时序上对齐。
怎么实现呢?时序图在IDLE已经展现了,如下图带反压的WRITE

即便是burst写也可以

而WRITE下一个状态,则根据WRITE结束的那一拍htrans的值,状态机如下

关于那个BUSY作一下说明。AHB master在进入BUSY时会给出下一个传输的控制信号,但是在下一次传输真正来临时控制信号还会保持不变,所以在AHB slave检测到
wr_en && hready && (htrans == BUSY)时依旧可以转换为IDLE状态
3.4. 读
该状态下实现读,当确定读出数据了该状态结束。
同样要求rd_en与rdata时序对齐,如果与写类似,将haddr打拍成raddr,那么在data phase第一拍必然不会读出数据,最快也要第二拍。
也就是说,必然会反压一拍,如下图带延迟的情况。

由此状态机更新为

3.5. 代码
module ahb2standard_handshake_bridge#(
parameter HADDR_WIDTH = 32,
parameter HDATA_WIDTH = 32
parameter ACCESS_ADDR1 = 32'h0000_0000_0000_0010,
parameter ACCESS_ADDR2 = 32'h0000_0000_0000_0014,
parameter ACCESS_ADDR3 = 32'h0000_0000_0000_0018,
parameter ACCESS_ADDR4 = 32'h0000_0000_0000_001C
)(
input hrstn,
input hclk,
input [HADDR_WIDTH-1:0] haddr,
input [2:0] hburst,
input [2:0] hsize,
input [1:0] htrans,
input hwrite,
input hsel,
input [HDATA_WIDTH-1:0] hwdata,
output [HDATA_WIDTH-1:0] hrdata,
output hready,
output hresp,
output [HADDR_WIDTH-1:0] waddr,
output [HDATA_WIDTH-1:0] wdata,
output wr_en,
input wready,
output [HADDR_WIDTH-1:0] raddr,
input [HDATA_WIDTH-1:0] rdata,
input rdata_val,
output rd_en,
input rready
);
localparam IDLE = 2'b00;
localparam WRITE = 2'b01;
localparam READ = 2'b11;
reg [1:0] cur_state;
reg [1:0] nxt_state;
reg [HADDR_WIDTH-1:0] waddr_r;
reg [HADDR_WIDTH-1:0] raddr_r;
reg hready_r;
reg wr_en_r;
reg rd_en_r;
reg hresp_r;
[email protected](posedge hclk or negedge hrstn) begin
if(!hrstn)
cur_state <= IDLE;
else
cur_state <= nxt_state;
end
[email protected](*) begin
case(cur_state)
IDLE:
if(htrans[1]) begin
if(hwrite)
nxt_state = WRITE;
else
nxt_state = READ;
end
else
nxt_state = IDLE;
WRITE:
if(wr_en && hready) begin
if(!htrans[1])
nxt_state = IDLE;
else if(!hwrite)
nxt_state = READ;
else
nxt_state = WRITE;
end
else
nxt_state = WRITE;
READ:
if(rdata_val) begin
if(!htrans[1])
nxt_state = IDLE;
else if(hwrite)
nxt_state = WRITE;
else
nxt_state = READ;
end
else
nxt_state = READ;
default:
nxt_state = IDLE;
endcase
end
assign wdata = hwdata[(8 << hsize)-1:0];
[email protected](*) begin
case(cur_state)
IDLE:
hready_r = 1'b0;
WRITE:
hready_r = wready;
READ:
hready_r = rdata_val;
default:
hready_r = 1'b0;
endcase
end
assign hready = hready_r;
[email protected](posedge hclk or negedge hrstn) begin
if(!hrstn)
waddr_r <= 'd0;
else if(cur_state == IDLE) begin
if(htrans[1] && hwrite)
waddr_r <= haddr;
end
else if(cur_state == WRITE) begin
if(wr_en && hready && htrans[1] && hwrite)
waddr_r <= haddr;
end
else if(cur_state == READ) begin
if(rdata_val && htrans[1] && hwrite)
waddr_r <= haddr;
end
end
assign waddr = waddr_r;
[email protected](posedge hclk or negedge hrstn) begin
if(!hrstn)
wr_en_r <= 1'b0;
else if(cur_state == IDLE) begin
if(htrans[1] && hwrite)
wr_en_r <= 1'b1;
end
else if(cur_state == WRITE) begin
if(!hready)
wr_en_r <= wr_en_r;
else if(htrans[1]) begin
if(hwrite)
wr_en_r <= 1'b1;
else
wr_en_r <= 1'b0;
end
else
wr_en_r <= 1'b0;
end
else if(cur_state == READ) begin
if(rdata_val && htrans[1] && hwrite)
wr_en_r <= 1'b1;
end
end
assign wr_en = wr_en_r;
assign hrdata = rdata[(8 << hsize)-1:0];
[email protected](posedge hclk or negedge hrstn) begin
if(!hrstn)
raddr_r <= 'd0;
else if(cur_state == IDLE) begin
if(htrans[1] && !hwrite)
raddr_r <= haddr;
end
else if(cur_state == WRITE) begin
if(wr_en && hready && htrans[1] && !hwrite)
raddr_r <= haddr;
end
else if(cur_state == READ) begin
if(rdata_val && htrans[1] && !hwrite)
raddr_r <= haddr;
end
end
assign raddr = raddr_r;
[email protected](posedge hclk or negedge hrstn) begin
if(!hrstn)
rd_en_r <= 1'b0;
else if(cur_state == IDLE) begin
if(htrans[1] && !hwrite)
rd_en_r <= 1'b1;
end
else if(cur_state == WRITE) begin
if(wr_en && hready && htrans[1] && !hwrite)
rd_en_r <= 1'b1;
end
else if(cur_state == READ) begin
if(!rready)
rd_en_r <= rd_en_r;
else if(!rdata_val)
rd_en_r <= 1'b0;
else if(htrans[1]) begin
if(hwrite)
rd_en_r <= 1'b0;
else
rd_en_r <= 1'b1;
end
else
rd_en_r <= 1'b0;
end
else
rd_en_r <= 1'b0;
end
assign rd_en = rd_en_r;
[email protected](*) begin
if(cur_state == WRITE && wr_en && hready) begin
if(waddr != ACCESS_ADDR1
&& waddr != ACCESS_ADDR2
&& waddr != ACCESS_ADDR3
&& waddr != ACCESS_ADDR4)
hresp_r = 1'b1;
end
else if(cur_state == READ && rdata_val) begin
if(raddr != ACCESS_ADDR1
&& raddr != ACCESS_ADDR2
&& raddr != ACCESS_ADDR3
&& raddr != ACCESS_ADDR4)
hresp_r = 1'b1;
end
else
hresp_r = 1'b0;
end
assign hresp = hresp_r;
endmodule
边栏推荐
- Introduction to go language (V) -- branch statement
- Bottomsheetdialog usage details, setting fillet, fixed height, default full screen, etc
- Experience of remote office communication under epidemic situation | community essay solicitation
- [image denoising] impulse noise image denoising based on absolute difference median filter, weighted median filter and improved weighted median filter with matlab code attached
- Internet_ Business Analysis Overview
- Given a project, how will you conduct performance testing?
- E-commerce (njupt)
- leetcode:66.加一
- WinCC flexible 2008项目移植到博途WinCC的具体方法
- Cf:f. shifting string [string rearrangement in specified order + grouping into rings (cutting connected components) + minimum same moving cycle of each group + minimum common multiple]
猜你喜欢

【信号去噪】基于FFT和FIR实现信号去噪附matlab代码

Review of software testing technology

Practice of Flink CDC in Dajian cloud warehouse

An adaptive chat site - anonymous online chat room PHP source code

Multimodal learning toolkit paddlemm based on propeller

Crop disease detection using image processing technology and convolutional neural network (CNN)

cf:C. Restoring the Duration of Tasks【找规律】

Flash ckeditor rich text compiler can upload and echo images of articles and solve the problem of path errors

更换目标检测的backbone(以Faster RCNN为例)

图床:PicGo+腾讯云+typora
随机推荐
Common - name of conference room
【信号去噪】基于非线性滤波器实现语音自适应去噪附matlab代码
[Multisim Simulation] using operational amplifier to generate sawtooth wave
[image segmentation] image segmentation based on Markov random field with matlab code
Image transformation torchvision Transforms notes
电子商务(njupt)
Record the phpstudy configuration php8.0 and php8.1 extension redis
On Workflow selection
30讲 线性代数第二讲 矩阵
[assembly] analysis of Experiment 7 of the fourth edition of assembly language
Key contents that wwdc22 developers need to pay attention to
程序员10年巨变,一切都变了又好像没变...
MongoDB 什么兴起的?应用场景有哪些?
使用canvas给页面添加文字水印
Anaconda installation, jupyter notebook default startup path modification and nbextensions plug-in installation
[help] how can wechat official account articles be opened in an external browser to display the selected messages below?
【Multisim仿真】利用运算放大器产生方波、三角波发生器
CMU 15-445 database course lesson 5 text version - buffer pool
Automated test requirements analysis
CMU 15-445 database course lesson 5 text version - buffer pool