testing software:ISE14.7 author: Rose Island
APB总线介绍
APB总线
APB(Advanced Peripheral Bus) 遵循 AMBA协议(Advanced Microcontroller Bus Architecture Protocol)。信号转换和时钟上升沿相关,每次读写传输至少两个周期,读数据和写数据不能同时发生。APB桥为APB总线中唯一主设备,UART/SPI/I2C等均为从设备。
APB接口信号
APB | Width | Source | Direction | Function |
---|
pclk | 1 bit | 系统时钟源 | input | APB总线从设备的时钟源 | preset_n | 1 bit | 系统复位信号 | input | 系统复位 | rst | 1 bit | 复位信号 | input | 从设备复位 | psel | 1 bit | APB桥 | input | 高电平表示APB桥与从设备进行数据传输 | paddr | 10 bits | APB桥 | input | 对从设备寄存器进行读写的相应地址 | penable | 1 bit | APB桥 | input | 读写使能信号,指示一次APB传输的第二个时钟周期,存储阶段 | pwrite | 1 bit | APB桥 | input | 指示信号,高写,低读 | pwdata | 32 bits | APB桥 | input | 写数据 | prdata | 32 bits | 从设备 | output | 读数据 | pready | 1 bit | 从设备 | output | 从设备就绪时为1,从设备在下一个上升沿可以完成传输,引入等待,传输周期可大于2 |
Transfer States
- Setup phase:需要数据传输时psel置1,这个阶段只会有一个时钟周期,下一个上升沿就进入Access phase
- Access phase:传输的第二个时钟周期penable置1,pwrite/paddr/pwdata/prdata/psel保持。等待pready,这个阶段的时钟周期个数由pready决定,pready为1后有一个时钟周期,之后传输完成。
写数据 With no wait states
-
APB:T1(Setup phase):上升沿时,pwrite输出1(写),paddr输出写地址,pwdata输出写数据,psel输出1,penable输出0; ? T2(Access phase):penable输出1,pwrite/paddr/pwdata/psel保持; ? T3(Idle phase):传输结束后penable才能输出0,如果下一个传输不是立即到达的话,psel输出0。 -
UART: T2:采样写数据并更新数据。 -
Recommendation:pwrite/paddr/pwdata保持直到下一个传输开始,可以减少功耗。
写数据 With wait states
- pready:由从设备输出,在Access phase阶段,当penable为高时,pready保证了一次传输至少两个时钟周期或更长,只有当pready为高时一次传输才算结束。
读数据 With no wait states
-
APB: T1(Setup phase):上升沿时,pwrite输出0(读),paddr输出写地址,psel输出1,penable输出0; ? T2(Access phase):penable输出1,prdata输出写数据(从设备提供),pwrite/paddr/psel保持; ? T3(Idle phase):传输结束后penable才能输出0,如果下一个传输不是立即到达的话,psel输出0。 -
UART:T2:采样指令并发送读数据。
读数据 With wait states
- pready:由从设备输出,在Access phase阶段,可拉长传输周期。
APB对寄存器的读写仿真
输入激励
apb信号:pclk、prest_n、rst、psel、paddr、penable、pwrite、pwdata
CSDN的markdown竟然不支持verilog代码了,差评!就用C语言的代码块凑合一下吧……
reg [31:0] pwdata_buff;
reg [31:0] prdata_buff;
reg [9:0] pwaddr_buff;
reg [9:0] praddr_buff;
reg pclk;
reg preset_n;
reg rst;
reg psel;
reg [9:0] paddr;
reg penable;
reg pwrite;
reg [31:0] pwdata;
wire [31:0] prdata;
wire pready;
task apb_write(input [9:0] addr, input [31:0] data);
begin
@(negedge pclk);
psel = 1'b1;
penable = 1'b0;
pwrite = 1'b1;
paddr = addr;
pwdata = data;
@(posedge pclk);
@(negedge pclk);
penable = 1'b1;
@(posedge pclk);
while(pready != 1'b1) @(posedge pclk);
psel = 1'b0;
penable = 1'b0;
repeat (10) @(posedge pclk);
end
endtask
task apb_read(input [9:0] addr, output [31:0] data);
begin
@(negedge pclk);
psel = 1'b1;
penable = 1'b0;
pwrite = 1'b0;
paddr = addr;
@(posedge pclk);
@(negedge pclk);
penable = 1'b1;
@(posedge pclk);
while(pready != 1'b1) @(posedge pclk);
data = prdata;
psel = 1'b0;
penable = 1'b0;
repeat(10) @(posedge pclk);
end
endtask
initial begin
pwaddr_buff = 10'h000;
pwdata_buff = 32'b1101;
apb_write(pwaddr_buff,pwdata_buff);
praddr_buff = 10'h000;
apb_read(praddr_buff,prdata_buff);
if(prdata_buff == 32'b1101) begin
$display("\n ------ write and read successfully -------");
end
else begin
$display("\n ------ write or read failed -------");
end
end
观察信号
- 写数据:e.g. 写CR寄存器,观察CR_EN位是否被置1
- 读数据:e.g. 读取CR寄存器里的值
波形
-
写数据:e.g. CR_EN -
读数据:e.g. 读取CR寄存器
实际结果
- 写入成功,通过√
- 读出成功,通过√
Conclusion
在上一篇里说好要周更的,可惜又没有做到,今天国庆节,国庆快乐呀!
最近就是好像每天都在忙,但也没啥进度,但总算有点东西可以写一下啦。加班比较多,我很讨厌硬性加班,可是还是被卷了进去。
我想要生活但生活需要我赚钱。
分享一部日剧《我,到点下班》
|