Skip to content

Commit 1a110d9

Browse files
authored
Add files via upload
Initial commit
1 parent eb7320e commit 1a110d9

File tree

6 files changed

+1621
-0
lines changed

6 files changed

+1621
-0
lines changed

APB_README.md

Lines changed: 995 additions & 0 deletions
Large diffs are not rendered by default.

apb_decoder.v

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// APB Decoder Module
2+
// Decodes address and generates PSEL for each slave
3+
4+
module apb_decoder #(
5+
parameter ADDR_WIDTH = 32,
6+
parameter NUM_SLAVES = 4
7+
)(
8+
input wire [ADDR_WIDTH-1:0] PADDR,
9+
input wire PSEL, // Master PSEL
10+
output reg [NUM_SLAVES-1:0] slave_sel // One-hot slave select
11+
);
12+
13+
// Address ranges for each slave (can be parameterized)
14+
// Slave 0: 0x0000_0000 - 0x0000_0FFF
15+
// Slave 1: 0x0000_1000 - 0x0000_1FFF
16+
// Slave 2: 0x0000_2000 - 0x0000_2FFF
17+
// Slave 3: 0x0000_3000 - 0x0000_3FFF
18+
19+
always @(*) begin
20+
slave_sel = 0;
21+
if (PSEL) begin
22+
case (PADDR[15:12])
23+
4'h0: slave_sel[0] = 1'b1;
24+
4'h1: slave_sel[1] = 1'b1;
25+
4'h2: slave_sel[2] = 1'b1;
26+
4'h3: slave_sel[3] = 1'b1;
27+
default: slave_sel = 0; // No slave selected
28+
endcase
29+
end
30+
end
31+
32+
endmodule
33+

apb_master.v

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// APB Master Module
2+
// Implements APB master interface per AMBA APB specification
3+
4+
module apb_master #(
5+
parameter ADDR_WIDTH = 32,
6+
parameter DATA_WIDTH = 32
7+
)(
8+
input wire PCLK,
9+
input wire PRESETn,
10+
11+
// Internal interface (from processor/controller)
12+
input wire req, // Transfer request
13+
input wire [ADDR_WIDTH-1:0] addr, // Address
14+
input wire write, // 1=write, 0=read
15+
input wire [DATA_WIDTH-1:0] wdata, // Write data
16+
output reg [DATA_WIDTH-1:0] rdata, // Read data
17+
output reg ready, // Transfer complete
18+
output reg error, // Transfer error
19+
20+
// APB interface
21+
output reg PSEL,
22+
output reg PENABLE,
23+
output reg [ADDR_WIDTH-1:0] PADDR,
24+
output reg PWRITE,
25+
output reg [DATA_WIDTH-1:0] PWDATA,
26+
input wire [DATA_WIDTH-1:0] PRDATA,
27+
input wire PREADY,
28+
input wire PSLVERR
29+
);
30+
31+
// APB State Machine
32+
localparam IDLE = 2'b00;
33+
localparam SETUP = 2'b01;
34+
localparam ACCESS = 2'b10;
35+
36+
reg [1:0] state;
37+
reg [1:0] next_state;
38+
39+
// State machine
40+
always @(posedge PCLK or negedge PRESETn) begin
41+
if (!PRESETn) begin
42+
state <= IDLE;
43+
end else begin
44+
state <= next_state;
45+
end
46+
end
47+
48+
// Next state logic
49+
always @(*) begin
50+
case (state)
51+
IDLE: begin
52+
if (req)
53+
next_state = SETUP;
54+
else
55+
next_state = IDLE;
56+
end
57+
SETUP: begin
58+
next_state = ACCESS;
59+
end
60+
ACCESS: begin
61+
if (PREADY) begin
62+
if (req)
63+
next_state = SETUP;
64+
else
65+
next_state = IDLE;
66+
end else begin
67+
next_state = ACCESS;
68+
end
69+
end
70+
default: next_state = IDLE;
71+
endcase
72+
end
73+
74+
// APB signal generation
75+
always @(posedge PCLK or negedge PRESETn) begin
76+
if (!PRESETn) begin
77+
PSEL <= 1'b0;
78+
PENABLE <= 1'b0;
79+
PADDR <= 0;
80+
PWRITE <= 1'b0;
81+
PWDATA <= 0;
82+
ready <= 1'b0;
83+
error <= 1'b0;
84+
rdata <= 0;
85+
end else begin
86+
case (state)
87+
IDLE: begin
88+
PSEL <= 1'b0;
89+
PENABLE <= 1'b0;
90+
ready <= 1'b0;
91+
error <= 1'b0;
92+
if (req) begin
93+
PADDR <= addr;
94+
PWRITE <= write;
95+
if (write)
96+
PWDATA <= wdata;
97+
end
98+
end
99+
SETUP: begin
100+
PSEL <= 1'b1;
101+
PENABLE <= 1'b0;
102+
PADDR <= addr;
103+
PWRITE <= write;
104+
if (write)
105+
PWDATA <= wdata;
106+
end
107+
ACCESS: begin
108+
PSEL <= 1'b1;
109+
PENABLE <= 1'b1;
110+
if (PREADY) begin
111+
if (!PWRITE)
112+
rdata <= PRDATA;
113+
ready <= 1'b1;
114+
error <= PSLVERR;
115+
if (!req) begin
116+
PSEL <= 1'b0;
117+
PENABLE <= 1'b0;
118+
end
119+
end else begin
120+
ready <= 1'b0;
121+
end
122+
end
123+
endcase
124+
end
125+
end
126+
127+
endmodule
128+

apb_slave.v

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// APB Slave Module
2+
// Implements APB slave interface per AMBA APB specification
3+
4+
module apb_slave #(
5+
parameter ADDR_WIDTH = 32,
6+
parameter DATA_WIDTH = 32,
7+
parameter BASE_ADDR = 32'h0000_0000,
8+
parameter ADDR_MASK = 32'hFFFF_0000 // Address mask for decoding
9+
)(
10+
input wire PCLK,
11+
input wire PRESETn,
12+
13+
// APB interface
14+
input wire PSEL,
15+
input wire PENABLE,
16+
input wire [ADDR_WIDTH-1:0] PADDR,
17+
input wire PWRITE,
18+
input wire [DATA_WIDTH-1:0] PWDATA,
19+
output reg [DATA_WIDTH-1:0] PRDATA,
20+
output reg PREADY,
21+
output reg PSLVERR,
22+
23+
// Internal register interface
24+
output reg [DATA_WIDTH-1:0] reg_data [0:15], // 16 registers
25+
output reg reg_write_en,
26+
output reg [3:0] reg_addr
27+
);
28+
29+
// Address decoding
30+
wire slave_sel;
31+
assign slave_sel = ((PADDR & ADDR_MASK) == (BASE_ADDR & ADDR_MASK)) && PSEL;
32+
33+
// Internal address (offset from base address)
34+
wire [3:0] internal_addr;
35+
assign internal_addr = PADDR[5:2]; // 4-bit address for 16 registers (word-aligned)
36+
37+
// PREADY generation (can be modified for wait states)
38+
always @(posedge PCLK or negedge PRESETn) begin
39+
if (!PRESETn) begin
40+
PREADY <= 1'b0;
41+
end else begin
42+
if (slave_sel && PENABLE) begin
43+
PREADY <= 1'b1; // Ready in access phase (can add wait states)
44+
end else if (slave_sel && !PENABLE) begin
45+
PREADY <= 1'b0; // Setup phase
46+
end else begin
47+
PREADY <= 1'b0;
48+
end
49+
end
50+
end
51+
52+
// Write operation
53+
always @(posedge PCLK or negedge PRESETn) begin
54+
if (!PRESETn) begin
55+
reg_write_en <= 1'b0;
56+
reg_addr <= 0;
57+
for (integer i = 0; i < 16; i = i + 1) begin
58+
reg_data[i] <= 0;
59+
end
60+
end else begin
61+
reg_write_en <= 1'b0;
62+
if (slave_sel && PENABLE && PWRITE) begin
63+
reg_data[internal_addr] <= PWDATA;
64+
reg_write_en <= 1'b1;
65+
reg_addr <= internal_addr;
66+
end
67+
end
68+
end
69+
70+
// Read operation
71+
always @(posedge PCLK or negedge PRESETn) begin
72+
if (!PRESETn) begin
73+
PRDATA <= 0;
74+
end else begin
75+
if (slave_sel && !PWRITE) begin
76+
PRDATA <= reg_data[internal_addr];
77+
end else begin
78+
PRDATA <= 0;
79+
end
80+
end
81+
end
82+
83+
// Error generation (optional - can be customized)
84+
always @(posedge PCLK or negedge PRESETn) begin
85+
if (!PRESETn) begin
86+
PSLVERR <= 1'b0;
87+
end else begin
88+
if (slave_sel && PENABLE) begin
89+
// Example: Error if accessing reserved register (addr > 15)
90+
if (internal_addr > 15) begin
91+
PSLVERR <= 1'b1;
92+
end else begin
93+
PSLVERR <= 1'b0;
94+
end
95+
end else begin
96+
PSLVERR <= 1'b0;
97+
end
98+
end
99+
end
100+
101+
endmodule
102+

0 commit comments

Comments
 (0)