简易APB4 slave实践
一个简易的(不完整的)APB4 slave的可以没有PREADY和PSLVERR,这两个信号都被赋予常数,以及没有PPROT。
两种不同类型的寄存器:

图: 普通寄存器电路图

图: 带读写控制寄存器电路图

图:带读写控制寄存器时序图
一般来讲,一个模块的interface到内部reg之间,需要的信号为地址信号addr,读写使能信号(分开),byte_strobe字节选通信号,读写数据信号(分开)。
注意:在传输结束后不要立即更改地址和写信号,保持当前状态知道开始下一个传输,这样可以降低功耗。
interface spec:

寄存器表:

代码:apb4的顶层
module apb4_slave #(
parameter ADDRWIDTH = )
(
input wire PCLK,
input wire PRESETn, input wire PSEL,
input wire[ADDRWIDTH -:] PADDR,
input wire PENABLE,
input wire PWRITE,
input wire[:] PWDATA,
input wire[:] PSTRB, input wire[:] ECOREVNUM, output wire[:] PRDATA,
output wire PREADY,
output wire PSLVERR
);
wire [ADDRWIDTH-:] reg_addr;
wire reg_read_en;
wire reg_write_en;
wire [:] reg_byte_strobe;
wire [:] reg_wdata;
wire [:] reg_rdata;
apb4_slave #(.ADDRWIDTH (ADDRWIDTH))
u_apb_slave_interface(
.pclk (PCLK),
.presetn (PRESETn), .psel (PSEL),
.paddr (PADDR),
.penable (PENABLE),
.pwrite (PWRITE),
.pwdata (PWDATA),
.pstrb (PSTRB), .prdata (PRDATA),
.pready (PREADY),
.pslverr (PSLVERR), .addr (reg_addr),
.read_en (reg_read_en),
.write_en (reg_write_en),
.byte_strobe (reg_byte_strobe),
.wdata (reg_wdata),
.tdata (reg_rdata) );
如何在interface这个模块中确定APB的建立周期信号?
其实APB的建立周期信号可以理解为一个使能信号,在第一周期拉高这个使能信号,那么下个周期就可以判断使能信号,并进入到传输周期了。这里使用组合逻辑去解决使能信号问题,一个是读使能read_en,一个是写使能write_en。read_en = psel &(~pwrite); write_en = psel &(~penable) & pwrite; 这里peanble是主机发过来的输入信号,这里说的从机不用管。
代码:apb4的逻辑接口
u_apb_slave_interfacef #(
parameter ADDRWIDTH = )
(
// IO declaration
input wire pclk,
input wire presetn,
// apb interface input
input wire psel,
input wire[ADDRWIDTH-:] paddr,
input wire penable,
input wire pwite,
input wire[:] pwdata,
input wire[:] pstrb,
// apb interface output
output wire[:] prdata,
output wire pready,
// Register interface
output wire[ADDRWIDTH-:] addr,
output wire read_en,
output wire write_en,
output wire[:] byte_pstrb,
output wire[:] wdata,
output wire[:] rdata
); assign pready = 'b1;
assign pslverr = 'b0; assign addr = paddr;
assign read_en = psel & (~pwrite); // 当pwrite为0,psel为1的时候,才读
assign write_en = psel & (~penable) & pwrite; // 在PCLK中,第一拍为psel有效,penable为低,第二拍才是psel和penable同时有效; assign byte_pstrb = pstrb;
assign wdata = pwdata;
assign prdata = rdata;
如何设计有等待状态的写传输?
从模块的pready输出之前一直是高,现在想延迟一个时钟周期,做成脉冲形式。
可以使用组合逻辑如:
assgin pready_1 = psel & peanble & pwrite;

pready想延迟多个时钟节拍,可以使用时序电路,建立周期完成后,等待多个clock之后,再讲pready拉高。
代码:apb的寄存器读写
module apb4_slave_reg #(
parameter ADDRWIDTH = )
(
input wire pclk,
input wire presetn, input wire[ADDRWIDTH-:] addr,
input wire read_en,
input wire write_en,
input wire[:] byte_pstrb,
input wire[:] wdata,
input wire ecorevnum,
output wire[:] rdata ); localparam ARM_CMSDK_APB4_EG_SLAVE_PID4 = 'h00000004; // 12'hFD0;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID5 = 'h00000000; // 12'hFD4;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID6 = 'h00000000; // 12'hFD8;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID7 = 'h00000000; // 12'hFDC;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID0 = 'h00000019; // 12'hFE0;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID1 = 'h000000B8; // 12'hFE4;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID2 = 'h0000001B; // 12'hFE8;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID3 = 'h00000000; // 12'hFEC; wire [:] wr_sel; // 取地址的高10位出来,地址是4K对其的,之后高12bits是不一样的,从0xfff~0x000,其中的高10位就可以判断出是要操作那个寄存器了
// 地址是32为对其的,末尾都是0(0000)、4(0100)、8(1000)、C(1100)循环的,低两位都是一样的,只有高10位不一样
assign wr_sel[] = ((addr[(ADDRWIDTH-):]=='b0000000000)&(write_en)) ? 1'b1: 'b0;
assign wr_sel[] = ((addr[(ADDRWIDTH-):]=='b0000000001)&(write_en)) ? 1'b1: 'b0;
assign wr_sel[] = ((addr[(ADDRWIDTH-):]=='b0000000010)&(write_en)) ? 1'b1: 'b0;
assign wr_sel[] = ((addr[(ADDRWIDTH-):]=='b0000000011)&(write_en)) ? 1'b1: 'b0; // write_en = psel & (~penable) & pwrite; 时序要求在penable为高这一拍把数据写下去,所以要在其前一拍判断是否要写。 // 寄存器的写操作
// Data register: data0
always @(posedge pclk or negedge presetn) begin
if (~presetn) begin
data0 <= {{'b0}};
end
else if (wr_sel[]) begin
if (byte_strobe[])
data0[ :] <= wdata[:];
if (byte_strobe[])
data0[:] <= wdata[:];
if (byte_strobe[])
data0[:] <= wdata[:];
if (byte_strobe[])
data0[:] <= wdata[:];
end
end
// Data register: data1
always @(posedge pclk or negedge presetn) begin
if (~presetn) begin
data1 <= {{'b0}};
end
else if (wr_sel[]) begin
if (byte_strobe[])
data1[ :] <= wdata[:];
if (byte_strobe[])
data1[:] <= wdata[:];
if (byte_strobe[])
data1[:] <= wdata[:];
if (byte_strobe[])
data1[:] <= wdata[:];
end
end
// Data register: data2
always @(posedge pclk or negedge presetn) begin
if (~presetn) begin
data2 <= {{'b0}};
end
else if (wr_sel[]) begin
if (byte_strobe[])
data2[ :] <= wdata[:];
if (byte_strobe[])
data2[:] <= wdata[:];
if (byte_strobe[])
data2[:] <= wdata[:];
if (byte_strobe[])
data2[:] <= wdata[:];
end
end
// Data register: data3
always @(posedge pclk or negedge presetn) begin
if (~presetn) begin
data3 <= {{'b0}};
end
else if (wr_sel[]) begin
if (byte_strobe[])
data3[ :] <= wdata[:];
if (byte_strobe[])
data3[:] <= wdata[:];
if (byte_strobe[])
data3[:] <= wdata[:];
if (byte_strobe[])
data3[:] <= wdata[:];
end
end // 寄存器的读操作
always @(read_en or addr or data0 or data1 or data2 or data3 or ecorevnum) begin
case (read_en)
'b1: begin
if (addr[:] == 'h00) begin // 判断为RW类型的寄存器
case (addr[:])
'b00: rdata = data0;
'b01: rdata = data1;
'b10: rdata = data2;
'b11: rdata = data3;
default: rdata = {{'bx}};
endcase
end
else if (addr[:] == 'h3F) begin // 判断为RO类型的寄存器
case(addr[:])
'b0100:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID4;
'b0101:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID5;
'b0110:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID6;
'b0111:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID7;
'b1000:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID0;
'b1001:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID1;
'b1010:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID2;
'b1011:rdata = {ARM_CMSDK_APB4_EG_SLAVE_PID3[31:0],ecorevnum[3:0],4'h0};
default: rdata = {{'bx}};
endcase
end
else begin
rdata = {{'b0}};
end
end
'b0: begin
rdata = {{'b0}};
end
default: rdata = {{'bx}};
endcase
end endmodule
简易APB4 slave实践的更多相关文章
- php+websocket搭建简易聊天室实践
1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...
- Redis Master/Slave 实践
本次我们将模拟 Master(1) + Slave(4) 的场景,并通过ASP.NET WEB API进行数据的提交及查询,监控 Redis Master/Slave 数据分发情况,只大致概述,不会按 ...
- proto3 不支持内建类型的非空判断即 hasXXX
proto3 移除了内建类型的非空判断方法 即代码生成工具不会为 bool int 等类型生成has方法 有使用过proto2 或者其它rpc 框架的人都知道使用has 方法去判断消息里的值是否设置, ...
- Vue2.0 + Element-UI + WebAPI实践:简易个人记账系统
最近正在学习Vue2.0相关知识,正好近期饿了么桌面端组件Element-UI发布,便动手做了一款简易个人记账系统,以达到实践及巩固目的. 1.开发环境 Win10 + VS2015 + Sqlser ...
- 【原创 Hadoop&Spark 动手实践 13】Spark综合案例:简易电影推荐系统
[原创 Hadoop&Spark 动手实践 13]Spark综合案例:简易电影推荐系统
- docker简易实践
docker简易实践 实验环境 操作系统:deepin 15.4 安装步骤 1.安装docker sudo apt-get install docker.io 2.启动docker服务 sudo se ...
- 基于OVS的VLAN虚拟化简易实践方案
基于OVS的VLAN虚拟化简易实践方案 前言 本实验基于ovs的vlan流表匹配,根据端口进行vlan标签插入.手工配置ovs,使其具有vlan虚拟化方案. 实验拓扑 ---- ---- | h1 | ...
- 《Java 程序设计》课堂实践项目-简易计算器
<Java 程序设计>课堂实践项目简易计算器 课后学习总结 目录 改变 简易计算器实验要求 课堂实践成果 课后思考 改变 修改了博客整体布局,过去就贴个代码贴个图很草率,这次布局和内容都有 ...
- c++开发ocx入门实践三--基于opencv的简易视频播发器ocx
原文:http://blog.csdn.net/yhhyhhyhhyhh/article/details/51404649 利用opencv做了个简易的视频播放器的ocx,可以在c++/c#/web ...
随机推荐
- [Training Video - 6] [File Reading] [Java] Read Excel File Using Apache POI API
读取以下两种格式的Excel : *.xls and *.xlsx 用Apache POI API来实现,需要用到 HSSF 和 XSSF 的类库 HSSF is the POI Project's ...
- [SoapUI] 通过Groovy写文本文件
如果文件已经存在,先删除,然后向文件中追加失败信息 if(maxRecordFail>0){ def testResultFile = new File(projectDir+"\\T ...
- 基于redis实现分布式Session
学习到好的知识还是需要记录下来的. 开发环境 asp.net mvc4,iis.asp.net 自带的session机制存在诸多不好的地方.先只要列出几点. asp.net mvc 默认的sessio ...
- Qt之QML开发常用知识
小技巧: 1. QML的内部逻辑可以直接调试 2. ctrl+ alt + space,在写QML时,可以直接调出工具条 3. 属性以小写字母开发 4. 属性改变事件,基本都是on+Property+ ...
- 【转载】Redis优化经验
转载地址:http://blog.sina.com.cn/s/blog_4be888450100z2ze.html 内存管理优化 Redis Hash是value内部为一个HashMap,如果该Map ...
- kalilinux-漏洞评估
Nessus\OpenVAS http://www.tenable.com/products/nessus/select-your-operating-system http://www.nessus ...
- Opengl中的GLUT下的回调函数
void glutDisplayFunc(void (*func)(void)); 注册当前窗口的显示回调函数 参数: func:形为void func()的函数,完成具体的绘制操作 这个函数告诉GL ...
- asp.net 汉字转拼音类
前段时间公司人员反应OA里的汉字拼音首字母不准他们又要用,没办法自己就从网上搜有没有好的,看了很多都是首字母拼不出来或有些字母变为另一个,但最后找了很多还是有一个好用的,暂未发现有不准的. using ...
- lua luna工具库
luna工具库 概述 luna库提供了几个lua开发的常见辅助功能: lua/c++绑定 lua序列化与反序列化 变长整数编码,用于lua序列化,当然也可以方便的用于其他场合 这里把代码编译成了动态库 ...
- OCP新题库,052新加的考题及答案整理-24题
24. YOUR DB_RECOVERY_FILE_DEST_SIZE Is 8G. Currently, 5G of the space Is used of which 4G consists o ...