目录
APB接口描述
APB写传输
APB读传输
APB Slave 设计
module apb_slave(
//input signals
pclk,
presetn,
psel,
penable,
pwrite,
pwdata,
paddr,
//output signals
prdata
);
input pclk ;
input presetn;
input psel ;
input penable;
input pwrite ;
input [31:0] pwdata ;
input [31:0] paddr ;
output [31:0] prdata ;
parameter REG1_ADDR = 8'h00;
parameter REG2_ADDR = 8'h04;
parameter REG3_ADDR = 8'h08;
reg [31:0] prdata ;
wire apb_write ;
wire apb_read ;
reg [31:0] reg1 ;
reg [31:0] reg2 ;
reg [31:0] reg3 ;
reg [31:0] dummy_reg ;
assign apb_write = pwrite && psel && penable ;
assign apb_read = (!pwrite) && psel && penable;
//register write
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
reg1 <= 32'b0;
reg2 <= 32'b0;
reg3 <= 32'b0;
end
else if(apb_write)
begin
case (paddr[7:0])
REG1_ADDR : reg1 <= pwdata ;
REG2_ADDR : reg2 <= pwdata ;
REG3_ADDR : reg3 <= pwdata ;
default : dummy_reg <= pwdata ;
endcase
end
end
//register read
always @(*)
begin
if(apb_read)
begin
case (paddr[7:0])
REG1_ADDR : prdata <= reg1 ;
REG2_ADDR : prdata <= reg2 ;
REG3_ADDR : prdata <= reg3 ;
default : prdata <= dummy_reg ;
endcase
end
else
prdata = 32'b0;
end
endmodule
`timescale 1ns/1ps
module apb_slave_tb;
reg pclk ;
reg presetn;
reg psel ;
reg penable;
reg pwrite ;
reg [31:0] pwdata;
reg [31:0] paddr ;
wire[31:0] prdata;
reg [31:0] rdata;
//Rigster address
parameter REG1_ADDR = 8'h00;
parameter REG2_ADDR = 8'h04;
parameter REG3_ADDR = 8'h08;
apb_slave U_apb_slave(
.pclk (pclk),
.presetn (presetn),
.psel (psel),
.penable (penable),
.pwrite (pwrite),
.pwdata (pwdata),
.paddr (paddr),
.prdata (prdata)
);
//clock generate
initial begin
pclk = 0 ;
forever
#10 pclk = ~pclk;
end
//reset generate
initial begin
presetn = 0;
#128;
presetn = 1;
end
//initial statement
initial
begin
psel = 1'b0;
penable = 1'b0;
pwrite = 1'b0;
paddr = 32'b0;
pwdata = 32'b0;
wait(presetn);
apb_write(REG1_ADDR,32'h12345678);
apb_read (REG1_ADDR,rdata);
#100;
apb_write(REG2_ADDR,32'h55aaaa55);
apb_read (REG2_ADDR,rdata);
#100;
apb_write(REG3_ADDR,32'h5201314a);
apb_read (REG3_ADDR,rdata);
#1000;
$finish;
end
task apb_write(input [7:0] addr,input [31:0]wdata);
begin
@(posedge pclk); //T2
#1;
pwrite = 1'b1;
psel = 1'b1;
penable= 1'b0;
paddr = addr;
pwdata = wdata;
@(posedge pclk); //T3
#1;
penable= 1'b1;
@(posedge pclk); //T4
#1;
pwrite = 1'b0;
psel = 1'b0;
penable= 1'b0;
pwdata = 32'h0;
@(posedge pclk);
@(posedge pclk);
end
endtask
task apb_read(input [7:0] addr,output [31:0]rdata);
begin
@(posedge pclk); //T2
#1;
pwrite = 1'b0;
psel = 1'b1;
penable= 1'b0;
paddr = addr;
@(posedge pclk); //T3
#1;
penable= 1'b1;
@(posedge pclk); //T4
#1;
rdata = prdata;
psel = 1'b0;
penable= 1'b0;
@(posedge pclk);
end
endtask
initial begin
$fsdbDumpfile("apb_slave.fsdb");
$fsdbDumpvars(0);
end
endmodule