四川网站建设 招标,wix和wordpress哪个好,网站首页地址 网站域名,厦门seo网站优化本文的参考资料为官方文档AMBA™3 APB Protocol specification文档下载地址#xff1a; https://pan.baidu.com/s/1Vsj4RdyCLan6jE-quAsEuw?pwdw5bi 提取码#xff1a;w5bi APB端口介绍介绍总线具体握手规则之前#xff0c;需要先熟悉一下APB总线端口#xff0c;APB的端口… 本文的参考资料为官方文档AMBA™3 APB Protocol specification 文档下载地址 https://pan.baidu.com/s/1Vsj4RdyCLan6jE-quAsEuw?pwdw5bi 提取码w5bi APB端口介绍介绍总线具体握手规则之前需要先熟悉一下APB总线端口APB的端口如下 大体可以分为以下三组 系统信号PCLK系统时钟、PRESETn系统复位低有效 master信号PADDR地址信号确定读写的地址、PSELx片选信号拉出来接给搭载APB总线的slave选中slave时PSELx信号拉高、PNEABLE使能信号在PSELx拉高一个周期后必定拉高、PWRITE写使能信号PWRITE为高时写有效为低时读有效、PWDATA写数据 slave信号PREADYready为高时代表着一次APB数据传输的结束、PRDATA读数据、PSLVERR错误数据由slave发出具体逻辑由slave内部决定当slave发现内部逻辑出现故障譬如状态机状态出错、计数器数字异常等slave都可以使用内部逻辑把该信号拉高使得master接收到PSLVERR为高时哪怕ready拉高表示APB结束了也可以使master放弃该次传输或做出其他应对策略。APB写传输 如文档所示APB的写分为两种情况①没有等待状态的写②有等待状态的写。 APB和AHB最大的不同就是APB不采用pipeline形式的写读方式因此对于APB协议来说最快的写入或者读出一个数据的周期是两周期先给地址再写数据或者先给地址再读数据。APB 协议文档中将上述这种传输方式分为两个阶段phase给地址的阶段称为Set up phase紧接着下一周期PENABLE信号拉高标志着进入写/读数据的阶段该阶段称为Access phase。Write with no wait states 一次没有等待状态的写传输如上图所示计划写数据时第一周期PSEL拉高表示选中某个slave同时给出地址信息Addr1和写入数据信息Data1紧接着下一周期PENABLE信号拉高PREADY信号也拉高这时数据写入完成。 没有等待状态的APB连续写波形如上所示代码见后文笔者将数据分为了两组group1为APB slave的端口信号group2为APB接的单端口SRAM信号。在第一个周期也就是Setup phasepsel信号拉高表示slave被选中值得注意的是此时要将SRAM的写信号和使能信号同步拉高因为我们写的是一个no wait states的APB接口数据要在第二周期写进SRAM的话就需要提前一拍拉高使能信号和写信号。然后到了第二周期penable信号拉高pready信号也拉高标志着这一次APB传输的结束。另外也正是因为在setup phase我们把SRAM的en信号和we信号拉高了因此在access phase数据传输结束的同时数据也被写入到SRAM中。Write with wait states在文档中对有等待周期的APB写传输描述如上即 一开始的setup phase和write with no wait没有区别psel拉高penable为低紧跟着第二周期penable拉高之后进入access phase进入access phase之后penable不会拉低直到pready为高标志着一次传输结束时penable才会随着pready一起拉低。penable等待pready拉高的这段等待时间为additional cycles在这个阶段PADDR、PWRITE、PSEL、PENABLE、PWDATA都应该保持不变可以说总线被hold住了。APB读传输APB的读传输也分为两种情况①没有等待状态的读②有等待状态的读。Read with no wait states 一次没有等待状态的读传输如上图所示读状态和写状态不同写数据时PWRITE1读数据时应该令PWRITE0计划读数据时第一周期PSEL拉高表示选中某个slave同时给出地址信息Addr1紧接着下一周期PENABLE信号拉高PREADY信号也拉高这时数据被读出master接受到读出数据PRDATA。 上图为连续读的APB传输波形图从第一次读数据可以看到随着psel信号拉高PWRITE0标志着为读状态此时传入地址给APB的SRAMSRAM端口en1we0标志着SRAM为读模式数据在下一周期从SRAM给到prdata。 这边还要提一个APB的特点也是大多人容易忽略的点APB总线完成一次读传输或者写传输之后PADDR和PWRITE不会改变会一直维持到下一次的传输这可以减少功耗。spec中描述如下手撕代码 笔者写了一个Write和Read都是with no states的APB SRAM因为含有SRAM部分所以在apb_sram中需要例化一个单端口ram单端口ram代码如下dprammodule spram_generic#(parameter ADDR_BITS 7, //outside input 10parameter ADDR_AMOUNT 128, //outside input 1024parameter DATA_BITS 32 //outside input 32
)(input clk ,input en ,input we ,input [ADDR_BITS-1:0] addr ,input [DATA_BITS-1:0] din ,output reg [DATA_BITS-1:0] dout
);
reg [DATA_BITS-1:0] mem [0:ADDR_AMOUNT-1];always (posedge clk)beginif(en)beginif(we 1b1)beginmem[addr] din;endelse dout mem[addr];end
endendmoduleapb_srammodule apb_sram#(parameter ADDR_BITS 9,parameter DATA_BITS 32,parameter MEM_DEPTH 512
)(input pclk ,input prstn ,input psel ,input penable ,input [ADDR_BITS-1:0] paddr ,input pwrite ,input [DATA_BITS-1:0] pwdata ,output pready ,output [DATA_BITS-1:0] prdata
);// write part
wire apb_write_setup;
reg apb_ram_write;assign apb_write_setup (pwrite) (!penable) (psel);always (posedge pclk or negedge prstn)beginif(!prstn)beginapb_ram_write 1b0; endelse if(apb_write_setup)beginapb_ram_write 1b1;endelse if(pready)beginapb_ram_write 1b0;end
end// read part
wire apb_read_setup;
reg apb_ram_read;assign apb_read_setup (!pwrite) (!penable) (psel);always (posedge pclk or negedge prstn)beginif(!prstn)beginapb_ram_read 1b0; endelse if(apb_read_setup)beginapb_ram_read 1b1;endelse if(pready)beginapb_ram_read 1b0;end
endassign pready pwrite ? apb_ram_write : apb_ram_read;wire mem_en,mem_we;
assign mem_en apb_write_setup || apb_read_setup;
assign mem_we apb_write_setup;spram_generic #(.ADDR_BITS (ADDR_BITS ),.DATA_BITS (DATA_BITS ),.ADDR_AMOUNT (2(ADDR_BITS-1) )
)u_spram_generic(.clk (pclk ),.en (mem_en ),.we (mem_we ),.addr (paddr ),.din (pwdata ),.dout (prdata )
);endmoduletb testbench例化apb_sram并给出激励我这边在tb中发起了10次连续的随机写然后再发起10次连续读发现读出来的数据和写入的数据一致。接着又测试了写和读无缝衔接在一起的apb传输结果符合spec。tb代码如下timescale 1ns/1ns
define MEM_PATH u_apb_sram.u_spram_generic
module tb#(parameter ADDR_BITS 9,parameter DATA_BITS 32,parameter MEM_DEPTH 512
)();reg clk, rstn;
always #5 clk ~clk;reg psel, penable, pwrite;
reg [DATA_BITS-1:0] pwdata, ref_data;
reg [ADDR_BITS-1:0] paddr ;
wire pready;
wire [DATA_BITS-1:0] prdata;reg [DATA_BITS-1:0] pwdata_rand;
reg [DATA_BITS-1:0] prdata_read;task apb_write;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
begin(posedge clk);#1;penable 0; psel 1; pwrite 1; paddr addr; pwdata wdata;(posedge clk);#1;penable 1;
end
endtasktask apb_read;
input [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
begin(posedge clk); #1;penable 0; psel 1; pwrite 0; paddr addr;(posedge clk); #1;penable 1;(negedge clk); #1;rdata prdata;
end
endtaskinteger i,j;
initial beginclk 1b0;rstn 1b0;pwrite 1b1;psel 1b0;penable 1b0;pwdata 32d0;repeat(2) (posedge clk);rstn 1b1;repeat(3) (posedge clk);// SRAM data initialfor (i 0; i MEM_DEPTH; i i 1)beginpwdata $random();MEM_PATH.mem[i] pwdata;endrepeat(5) (posedge clk); #1;$display(\ncontinuous writing);// SRAM data continuous writingfork begin(posedge clk);#1paddr 32d0; for (j 0; j 10; j j 1)beginrepeat(2) (posedge clk) #1;paddr paddr 1;(negedge clk) #1;ref_data MEM_PATH.mem[paddr-1];$display(ref_data %d, addr %d, ref_data, paddr-1);endendbegin for (i 0; i 10; i i 1)beginpwdata_rand $random();apb_write(paddr, pwdata_rand);$display(pwdata %d, pwdata);endendjoin_nonerepeat(21) (posedge clk);#1;penable 1b0;psel 1b0;pwrite 1b0;repeat(5) (posedge clk);#1;$display(\ncontinuous reading);//SRAM continuous readingfork begin(posedge clk);#1;paddr 32d0;for (j 0; j 10; j j 1)beginrepeat(2) (posedge clk);#1;paddr paddr 1;endendbeginfor (i 0; i 10; i i 1)beginapb_read(paddr, prdata_read);$display(prdata_read %d, prdata_read);endendjoinpenable 0;psel 0;repeat(5) (posedge clk);#1;$display(\ncontinuos writing and reading);//SRAM continuous write and readfork begin(posedge clk);#1;paddr 32d0;for (j 0; j 10; j j 1)beginrepeat (4) (posedge clk); #1;paddr paddr 1;endendbeginfor (i 0; i 10; i i 1)beginpwdata_rand $random();apb_write(paddr, pwdata_rand);apb_read(paddr, prdata_read);$display(write data is %d, read data is %d, pwdata_rand, prdata_read);endendjoinpenable 0;psel 0;// finish simulationrepeat(20) (posedge clk);$finish();
endinitial begin$fsdbDumpfile(apb_sram.fsdb);$fsdbDumpvars(0);
endapb_sram #(.ADDR_BITS(ADDR_BITS),.DATA_BITS(DATA_BITS),.MEM_DEPTH(MEM_DEPTH)
) u_apb_sram(.pclk (clk ),.prstn (rstn ),.psel (psel ),.penable(penable),.paddr (paddr ),.pwrite (pwrite ),.pwdata (pwdata ),.pready (pready ),.prdata (prdata )
);endmodulevcs仿真结果如下continuous writingpwdata 620927818ref_data 620927818, addr 0pwdata 1557269945ref_data 1557269945, addr 1pwdata 160312595ref_data 160312595, addr 2pwdata 164115731ref_data 164115731, addr 3pwdata 853295461ref_data 853295461, addr 4pwdata 684074833ref_data 684074833, addr 5pwdata 3684186807ref_data 3684186807, addr 6pwdata 3432517785ref_data 3432517785, addr 7pwdata 2635204666ref_data 2635204666, addr 8pwdata 3102358129ref_data 3102358129, addr 9continuous readingprdata_read 620927818prdata_read 1557269945prdata_read 160312595prdata_read 164115731prdata_read 853295461prdata_read 684074833prdata_read 3684186807prdata_read 3432517785prdata_read 2635204666prdata_read 3102358129continuos writing and readingwrite data is 830211938, read data is 830211938write data is 4063587044, read data is 4063587044write data is 353623338, read data is 353623338write data is 3201975421, read data is 3201975421write data is 753819481, read data is 753819481write data is 1925424101, read data is 1925424101write data is 1994288109, read data is 1994288109write data is 3836215497, read data is 3836215497write data is 2695810113, read data is 2695810113write data is 1472319919, read data is 1472319919波形图连续10次写、连续10次读、连续10次读写波形如下