1、设计方案
首先定义一个缓存器,位宽为32位,深度为32位,然后根据读写时序,设置写使能和读使能wren = i_apb_pwrite && i_apb_penable && i_apb_psel; rden = ~i_apb_pwrite && ~i_apb_penable && i_apb_psel; 当写使能为高时,将数据写入缓存器,当读使能为高时,从缓存器中读取数据。
2、程序代码
module APB_w_r#(
parameter ADDR_WIDTH = 31,
parameter DATA_WIDTH = 32
) (
input clk ,
input i_apb_psel ,
input i_apb_pwrite ,
input i_apb_penable ,
input [ADDR_WIDTH-1:0] i_apb_paddr ,
input [DATA_WIDTH-1:0] i_apb_pwdata ,
output [DATA_WIDTH-1:0] o_apb_prdata
);
wire wren,rden;
reg [31:0] mem[31:0]; //定义一个位宽32位,深度32的memery
wire [31:0]addr;
reg [DATA_WIDTH-1:0]prdata;
assign o_apb_prdata = prdata;
assign wren = i_apb_pwrite && i_apb_penable && i_apb_psel;
assign rden = ~i_apb_pwrite && ~i_apb_penable && i_apb_psel;
assign addr = i_apb_paddr;
always @(posedge clk)
begin
if (wren)
mem[addr] <= i_apb_pwdata;
else
mem[addr] <= mem[addr] ;
end
always @(posedge clk)
begin
if (rden)
prdata <= mem[addr];
else
prdata <= 'h0;
End
Endmodule
3、仿真测试
module APB_w_r_tb;
reg clk ;
reg i_apb_psel ;
reg i_apb_pwrite ;
reg i_apb_penable ;
reg [31:0]i_apb_paddr ;
reg [31:0]i_apb_pwdata ;
wire [31:0]o_apb_prdata ;
always #5 clk = ~clk;
initial begin
$stop ;
clk = 0;
i_apb_psel = 0;
i_apb_pwrite = 0;
i_apb_penable = 0;
i_apb_paddr = 0;
i_apb_pwdata = 0;
#10
w_data('d1,'d2) ;
r_data('d1) ;
w_data('d2,'d3) ;
r_data('d2) ;
end
APB_w_r#(
.ADDR_WIDTH('d2),
.DATA_WIDTH('d32)
) APB_w_r(
.clk (clk) ,
.i_apb_psel (i_apb_psel) ,
.i_apb_pwrite (i_apb_pwrite) ,
.i_apb_penable (i_apb_penable) ,
.i_apb_paddr (i_apb_paddr) ,
.i_apb_pwdata (i_apb_pwdata) ,
.o_apb_prdata (o_apb_prdata)
);
task w_data(
input [31:0]w_addr,
input [31:0]w_wdata
);begin
@(posedge clk)
i_apb_psel = 'd1;
i_apb_pwrite = 'd1;
i_apb_penable ='d0;
i_apb_paddr = w_addr;
i_apb_pwdata = w_wdata;
@(posedge clk)
i_apb_psel = 'd1;
i_apb_pwrite = 'd1;
i_apb_penable = 'd1;
@(posedge clk)
i_apb_penable = 'd0;
i_apb_psel = 'd0;
//i_apb_pwdata = 'd0;
end
endtask
task r_data(
input [31:0]r_addr
// output [31:0]r_wdata
);
begin
//assign r_wdata =o_apb_prdata;
@(posedge clk)
i_apb_psel = 'd1;
i_apb_pwrite = 'd0;
i_apb_penable ='d0;
i_apb_paddr = r_addr;
//r_wdata = o_apb_prdata;
@(posedge clk)
i_apb_psel = 'd1;
i_apb_pwrite = 'd0;
i_apb_penable = 'd1;
//r_wdata = o_apb_prdata;
@(posedge clk)
i_apb_penable = 'd0;
i_apb_psel = 'd0;
end
endtask
endmodule
4、结果分析
当i_apb_psel为高,i_apb_penable为低,i_apb_pwrite为高时写入数据2和地址1,之后i_apb_penable为高时保持一个周期,之后读时序i_apb_psel为高,i_apb_penable为低,i_apb_pwrite为低时,地址1,读出数据2。进行下一次写入地址2数据3,读出数据3。