AHB2APB Bridge位置

  • AHB子系统时钟在200Mhz左右,APB时钟在几十Khz到几十Mhz
  • 所以要进行跨时钟域处理,从AHB高时钟频率转到APB低时钟频率

AHB2APB Bridge规格说明

  • Bridge是APB总线上唯一的主机(也可以通过设计使APB支持多个Master)

AHB2APB Bridge接口

  • Bridge是连接AHB总线和APB总线的桥梁,所以接口有AHB总线和APB总线
  • Bridge是APB总线的Master,是AHA的Slave
  • psel - 有多少个外设就有多少个psel信号
  • penable - 时钟选通信号

AHB2APB Bridge状态机

  • Bridge开始的时候处于IDLE状态,当Bridge收到AHB总线的传输信号之后,进入到setup状态,在setup状态将AHB控制和地址信号进行锁存并将psel置于1,进入到enable状态,可以进行apb的读写操作

AHB2APB Bridge读时序

AHB2APB Bridge 写时序

AHB2APB Bridge设计

设计规格

  • 对于输入输出数据进行寄存或者不寄存,由模块控制,主要是为了时序

接口信号

  • APBACTIVE - APB激活信号

状态机1:输入输出不寄存

状态机2:输入输出数据寄存

状态机:发生传输错误

RTL

module ahb_to_apb_bridge
#(
parameter ADDRWIDTH = 16 ,
parameter REGISTER_RDATA = 1,
parameter REGISTER_WDATA = 0
)
(
input wire hclk,
input wire hresetn,
input wire pclken, input wire hsel,
input wire [ADDRWIDTH-1:0] haddr,
input wire [1:0] htrans,
input wire [2:0] hsize,
input wire [4:0] hprot,
input wire hwrite,
input wire hready,
input wire [31:0] hwdata, output reg hreadyout,
output wire [31:0] hrdata,
output wire hresp, output wire [ADDRWIDTH-1:0] paddr,
output wire penable,
output wire pwrite,
output wire [3:0] pstrb,
output wire [2:0] pprot,
output wire [31:0] pwdata,
output wire psel, output wire apbactive, input wire [31:0] prdata,
input wire pready,
input wire pslverr
); // 寄存写信号和写地址
reg [ADDRWIDTH-1:0] addr_reg;
reg [2:0] wr_reg;
reg [31:0] rwdata_reg; // 定义当前状态变量和下一状态变量
reg [2:0] state_reg;
reg [2:0] next_state; reg [3:0] pstrb_reg;
wire [3:0] pstrb_nxt; reg [1:0] pprot_reg;
wire [1:0] pprot_nxt; // apb bridge选择信号
wire apb_select; // 传输完成信号
wire apb_tran_end; // 判断数据是否寄存的变量
wire reg_rdata_cfg;
wire reg_wdata_cfg; // 定义写控制信号寄存的寄存器
reg sample_wdata_reg; localparam ST_BITS=3; localparam [ST_BITS-1:0] ST_IDLE =3'b000;
localparam [ST_BITS-1:0] ST_APB_WAIT =3'b001;
localparam [ST_BITS-1:0] ST_APB_TRNF =3'b010;
localparam [ST_BITS-1:0] ST_APB_TRNF2 =3'b011;
localparam [ST_BITS-1:0] ST_APB_NODOK =3'b100;
localparam [ST_BITS-1:0] ST_APB_ERR1 =3'b101;
localparam [ST_BITS-1:0] ST_APB_ERR2 =3'b110;
localparam [ST_BITS-1:0] ST_APB_ILLEGAL =3'b111; // main code // 产生读写数据是否寄存的信号
assign reg_rdata_cfg = REGISTER_RDATA == 0? 1'b0 : 1'b1;
assign reg_rdata_cfg = REGISTER_WDATA == 0? 1'b0 : 1'b1; // 产生bridge被选中的信号
assign apb_select = hsel && htrans[1] && hready; // apb传输完成信号
assign apb_tran_end = (state_reg == 3'b011) & pready; //pprot信号产生
assign pprot_nxt[0] = hprot[1];
assign pprot_nxt[1] = ~hprot[0]; // pstrb信号产生
assign pstrb_nxt[0] = hwrite & ((hsize[1]) |(hsize[0] & (~haddr[1])) | (haddr[1:0]==2'b00));
assign pstrb_nxt[1] = hwrite & ((hsize[1]) |(hsize[0] & (~haddr[1])) | (haddr[1:0]==2'b01));
assign pstrb_nxt[2] = hwrite & ((hsize[1]) |(hsize[0] & haddr[1]) | (haddr[1:0]==2'b10));
assign pstrb_nxt[3] = hwrite & ((hsize[1]) |(hsize[0] & haddr[1]) | (haddr[1:0]==2'b11)); // sample control signals 打拍信号
// data和addr对齐
always @(posedge hclk or negedge hresetn) begin
if(!hresetn) begin
addr_reg <= {ADDRWIDTH-2{1'b0}};
wr_reg <= 1'b0;
pprot_reg <= 2'b0;
pstrb_reg <= 4'b0;
end
else if(apb_select) begin
addr_reg <= haddr[ADDRWIDTH-1:2];
wr_reg <= hwrite;
pprot_reg <= pprot_nxt;
pstrb_reg <= pstrb_nxt;
end
end // 采样写数据的控制信号
wire sample_wdata_set = apb_select & hwrite & reg_wdata_cfg;
wire sample_wdata_clt = sample_wdata_set & pclken; always @ (posedge hclk or negedge hresetn) begin
if(!hresetn) begin
sample_wdata_reg <= 1'b0;
end
else if(sample_wdata_set | sample_wdata_clt) begin
sample_wdata_reg <= sample_wdata_set;
end
end // 第一段状态机
always @ (posedge hclk or negedge hresetn) begin
if(!hresetn) begin
state_reg <= 3'b000;
end
else
state_reg <= next_state;
end // 第二段状态机描述状态转移
always @ (*) begin
case(state_reg)
ST_IDLE:
begin
if(apb_select & pclken & ~(reg_wdata_cfg&hwrite)) begin
next_state = ST_APB_TRNF;
end
else if(apb_select)
next_state = ST_APB_WAIT;
else
next_state = ST_IDLE;
end
ST_APB_WAIT:
begin
if(pclken)
next_state = ST_APB_TRNF;
else
next_state = ST_IDLE;
end
ST_APB_TRNF:
begin
if(pclken)
next_state = ST_APB_TRNF2;
else
next_state = ST_APB_TRNF;
end
ST_APB_TRNF2:
begin
if(pready & pslverr & pclken)
next_state = ST_APB_ERR1;
else if(pready & (~pslverr)&pclken)
begin
if(reg_rdata_cfg)
next_state = ST_APB_NODOK;
else
next_state = ST_APB_TRNF2;
end
end
ST_APB_NODOK:
begin
if(apb_select & pclken & ~(reg_wdata_cfg&hwrite)) begin
next_state = ST_APB_TRNF;
end
else if(apb_select)
next_state = ST_APB_WAIT;
else
next_state = ST_IDLE;
end
ST_APB_ERR1:
next_state = ST_APB_ERR2;
ST_APB_ERR2:
if(apb_select & pclken & ~(reg_wdata_cfg&hwrite)) begin
next_state = ST_APB_TRNF;
end
else if(apb_select)
next_state = ST_APB_WAIT;
else
next_state = ST_IDLE;
default : next_state = 3'bxxx;
endcase
end // 采样数据
always @ (posedge hclk or negedge hresetn) begin
if(!hresetn)
rwdata_reg = 32'b0;
else if(sample_wdata_reg & reg_wdata_cfg & pclken)
rwdata_reg <= hwdata;
else if(apb_tran_end & reg_rdata_cfg & pclken)
rwdata_reg <= prdata;
end // 产生输出信号
assign paddr = {addr_reg,2'b00};
assign pwrite = wr_reg;
assign pwdata = reg_wdata_cfg ? rwdata_reg : hwdata;
assign psel = (state_reg == ST_APB_TRNF | state_reg == ST_APB_TRNF2);
assign penable = (state_reg == ST_APB_TRNF2);
assign pprot = {pprot_reg[1],1'b0,pprot_reg[0]};
assign pstrb = pstrb_reg[3:0]; //产生hready_out
always @(*) begin
case(state_reg)
ST_IDLE:hreadyout = 1'b1;
ST_APB_WAIT:hreadyout=1'b0;
ST_APB_TRNF:hreadyout=1'b0;
ST_APB_TRNF2:hreadyout=(~reg_rdata_cfg) & pready & (~pslverr)&pclken;
ST_APB_NODOK:hreadyout = 1'b0;
ST_APB_ERR1:hreadyout = 1'b0;
ST_APB_ERR1:hreadyout = 1'b1;
default:hreadyout=1'bx;
endcase
end assign hrdata = reg_rdata_cfg ? rwdata_reg : prdata;
assign hresp = (state_reg == ST_APB_ERR1) |(state_reg == ST_APB_ERR2);
assign apbactive = (hsel & htrans[1]) | state_reg; endmodule

AHB2APB设计的更多相关文章

  1. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  2. 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

    阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...

  3. 设计爬虫Hawk背后的故事

    本文写于圣诞节北京下午慵懒的午后.本文偏技术向,不过应该大部分人能看懂. 五年之痒 2016年,能记入个人年终总结的事情没几件,其中一个便是开源了Hawk.我花不少时间优化和推广它,得到的评价还算比较 ...

  4. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

  5. 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

    一.前言     DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...

  6. 如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

    阅读目录 前言 明确业务细节 建模 实现 结语 一.前言 上一篇我们已经确立的购买上下文和销售上下文的交互方式,传送门在此:http://www.cnblogs.com/Zachary-Fan/p/D ...

  7. 如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

    阅读目录 前言 如何在一个项目中实现多个上下文的业务 售价上下文与购买上下文的集成 结语 一.前言 前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西.比如促销.会员价等,在我们的 ...

  8. 如何一步一步用DDD设计一个电商网站(五)—— 停下脚步,重新出发

    阅读目录 前言 单元测试 纠正错误,重新出发 结语 一.前言 实际编码已经写了2篇了,在这过程中非常感谢有听到观点不同的声音,借着这个契机,今天这篇就把大家提出的建议一个个的过一遍,重新整理,重新出发 ...

  9. 如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户

    阅读目录 前言 怎么卖 领域服务的使用 回到现实 结语 一.前言 上篇中我们讲述了“把商品卖给用户”中的商品和用户的初步设计.现在把剩余的“卖”这个动作给做了.这里提醒一下,正常情况下,我们的每一步业 ...

  10. 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域

    一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...

随机推荐

  1. 整一个工具类【根据URL地址获取file文件对象】

    整一个工具类[根据URL地址获取file文件对象] 直接将网络url文件转换为file对象 import java.io.*; import java.net.URL; public class Im ...

  2. 一键式调试工具—Reqable 使用指南

    简介 Reqable是一款跨平台的专业HTTP开发和调试工具,在全平台支持HTTP1.HTTP2和HTTP3(QUIC)协议,简单易用.功能强大.性能高效,助力程序开发和测试人员提高生产力!本产品需要 ...

  3. Zabbix自带模板监控MySQL服务

    Zabbix的服务端与客户端的安装这里不再赘述了,前面也有相应的文章介绍过了,感兴趣的伙伴们可以看看历史文章就可以了,今天主要介绍下如何利用zabbix自带的模板来监控MySQL服务的一些状态,同时通 ...

  4. CUDA驱动深度学习发展 - 技术全解与实战

    全面介绍CUDA与pytorch cuda实战 关注TechLead,分享AI全维度知识.作者拥有10+年互联网服务架构.AI产品研发经验.团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云 ...

  5. 使用IO流写一个随机点名程序

    前言 最近学习了关于IO流的一些知识点,但是应用还不够,所以今天做个简单案例: 随机创建名字导入文件中: package ioandcollection; import java.io.Buffere ...

  6. 鱼和熊掌兼得:C++代码在编译时完成白盒测试

    摘要:如果能够让代码在编译的时候,自动完成白盒测试,这不是天方夜谭. 白盒测试也叫开发者测试,是对特定代码函数或模块所进行的功能测试.当前主流的白盒测试方法是:先针对仿真或者生产环境编译出可执行文件, ...

  7. 云小课|MRS基础原理之Hudi介绍

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:Hudi是数据湖的 ...

  8. 实践丨手把手教你用STM32设计WiFi语音播报日程表

    摘要:随着电子产品的发展,数字日程表这项应用在人们工作和生活中起到越来越重要的作用.本文带领大家基于STM32自己动手制作一个WiFi语音播报日程表. 本文分享自华为云社区<基于STM32设计的 ...

  9. 高性能 Jsonpath 框架,Snack3 3.2.54 发布(支持 kotlin data 类反序化)

    Snack3,一个高性能的 JsonPath 框架 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表示,ONode也 ...

  10. Linux--修改会话超时时间

    控制用户在一段时间内没有活动时会话的自动注销时间 1.修改ssh配置文件(适用于SSH会话) vim /etc/ssh/sshd_config ClientAliveInterval 1800 #秒 ...