APB Slave
APB Slave
PCLK
PRESETn
PCLK
PRESETn
PSEL
PWRITE
PADDR[31:0]
APB SLAVE
CS
REGISTER BANK
PENABLE
W/Rn
PWDATA[31:0]
ADDR[4:0]
PSEL
PWRITE
PADDR[31:0]
ADDRESS
PENABLE
PWDATA[31:0]
DATA
CS
W/Rn
ADDR[4:0]
ADDRESS [4:0]
WDATA[31:0]
DATA
READ CYCLE
PSEL
PWRITE
PADDR[31:0]
ADDRESS
PENABLE
PRDATA[31:0]
DATA
CS
W/Rn
ADDR[4:0]
ADDRESS [4:0]
RDATA[31:0]
DATA
STATE MACHINE
PSEL=0
IDLE
PSEL=1
NO CONDITION
BUSY
BUSY STATE THIS STATE INCLUDES THE DATA PHASE WHICH OCCURS ONLY WHEN PENABLE IS HIGH (ACCESS). IDLE STATE THIS STATE INCLUDES THE ADDRESS PHASE (SETUP) AND THE SLAVE GOES INTO THE IDLE STATE ALSO WHEN THE TRANSACTION IS COMPLETED OR IF PSEL = 0.
CLK
PSEL 0 1 1 1 0 1
PWRITE 0 0 1 1 1 1
PENABLE 0 1 0 1 0 1
Qn S0 S0 S1 S0 S1 S0
Qn+1 S0 S1 S0 S1 S0 S1
CS 1 0 0 1 0 1
W/Rn 0 0 1 1 1 1
VERILOG CODE
OUTPUT
IDLE
BUSY
CS
PSEL, !PWRITE
ADDR [4:0]
PADDR[4:0]
W/Rn
PWRITE
PWRITE
WDATA
PWDATA
PRDATA
module apb_interface (pclk,presetn,psel,pwrite,paddr,penable,prdata,pwdata, cs,wrn,addr,wdata,rdata); input pclk,presetn,psel,pwrite,penable; input [31:0] paddr, pwdata; output [31:0] prdata; inout cs,wrn; inout [4:0] addr; inout [31:0] wdata,rdata; reg [31:0] dataread; reg [31:0] datacap,status,control,slaveaddr,datacount; reg state; parameter idle = 0; parameter busy = 1; assign wrn <= pwrite; assign addr [4:0] <= paddr [4:0]; assign wdata [31:0] <= pwdata [31:0]; assign prdata [31:0] <= dataread [31:0]; case (state) idle: cs = (psel & (!pwrite)); busy: cs = (psel & pwrite & penable); endcase if ((cs == 1) && (wrn ==0)) begin casex (addr) 3b000xx : rdata [31:0] = datacap [31:0]; 3b001xx : rdata [31:0] = status [31:0] ; 3b010xx : rdata [31:0] = control [31:0]; 3b011xx : rdata [31:0] = slaveaddr [31:0] ; 3b100xx : rdata [31:0] = datacount [31:0] ; Endcase
always @ (posedge clk || negedge presetn) begin if (presetn == 0) begin state <= idle; dataread [31:0] = 32d0; datacap [31:0] = 32d0; status [31:0] = 32d0; control [31:0] = 32d0; slaveaddr [31:0] = 32d0; datacount [31:0] = 32d0; end else if (presetn ==1) begin case (state) idle : state <= (psel)? Busy : idle; busy: state <= idle; status [0] <= (addr[4] & (addr[3] | addr[2]));end endcase if ((cs == 1) && (wrn ==1) ) begin casex addr 3b000xx : datacap [31:0] = wdata [31:0]; 3b001xx : status [31:0] = wdata [31:0]; 3b010xx : control [31:0] = wdata [31:0]; 3b011xx : slaveaddr [31:0] = wdata [31:0]; 3b100xx : datacount [31:0] = wdata [31:0]; endcase end else if ((cs == 1) && (wrn ==0)) dataread [31:0] = rdata [31:0]; end endmodule