当前位置:网站首页>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
边栏推荐
- Anaconda installation, jupyter notebook default startup path modification and nbextensions plug-in installation
- Multimodal learning toolkit paddlemm based on propeller
- Cf:d. black and white stripe
- Chrome tips - browser web page setting coding, solving the problem of web page garbled code, obtaining the latest version of charset plug-in, UTF-8 coding setting
- [C language questions -- 10 simple questions for leetcode]
- 更换目标检测的backbone(以Faster RCNN为例)
- Automated test requirements analysis
- [Multisim Simulation] generate square wave and triangular wave generators by operational amplifier
- Flask CKEditor 富文本编译器实现文章的图片上传以及回显,解决路径出错的问题
- Key contents that wwdc22 developers need to pay attention to
猜你喜欢

Web3游戏:游戏体验的探寻与重塑
[help] how can wechat official account articles be opened in an external browser to display the selected messages below?

Multimodal learning toolkit paddlemm based on propeller

电子商务(njupt)

Use Mysql to determine the day of the week
CMU 15-445 database course lesson 5 text version - buffer pool

无监督图像分类《SCAN:Learning to Classify Images without》代码分析笔记(1):simclr

The Economist: WTO MC12 restarts the digital economy and becomes the core engine of global economic recovery and growth

Introduction to go language (VI) -- loop statement

Operator new and placement new
随机推荐
图床:PicGo+腾讯云+typora
Flask CKEditor 富文本编译器实现文章的图片上传以及回显,解决路径出错的问题
CMU 15 - 445 cours de base de données Leçon 5 version texte - Pool tampon
MOS transistor 24n50 parameters of asemi, 24n50 package, 24n50 size
Gmail: how do I recall an outgoing message?
Experience of remote office communication under epidemic situation | community essay solicitation
Highcharts sets the histogram width, gradient, fillet, and data above the column
collect.stream().collect()方法的使用
[video denoising] video denoising based on salt with matlab code
leetcode:926. 将字符串翻转到单调递增【前缀和 + 模拟分析】
2022各大厂最新总结的软件测试宝典,看完不怕拿不到offer
【Laravel系列7.5】事件系统
Longest strictly increasing subsequence
Leetcode: sword finger offer 56 - ii Number of occurrences of numbers in the array II [simple sort]
YOLOv3 Pytorch代码及原理分析(一):跑通代码
Practice of tag recognition based on Huawei cloud image
Programmers have changed dramatically in 10 years. Everything has changed, but it seems that nothing has changed
Performance of MOS transistor 25n120 of asemi in different application scenarios
Go语言入门(六)——循环语句
[solution] codeforces round 798 (Div. 2)