-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapb_top.v
More file actions
136 lines (121 loc) · 4.25 KB
/
apb_top.v
File metadata and controls
136 lines (121 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// APB Top Module
// Connects APB Master, Decoder, and Slaves
module apb_top #(
parameter ADDR_WIDTH = 32,
parameter DATA_WIDTH = 32,
parameter NUM_SLAVES = 4
)(
input wire PCLK,
input wire PRESETn,
// Master interface
input wire req,
input wire [ADDR_WIDTH-1:0] addr,
input wire write,
input wire [DATA_WIDTH-1:0] wdata,
output wire [DATA_WIDTH-1:0] rdata,
output wire ready,
output wire error,
// Slave register interfaces (for monitoring)
output wire [DATA_WIDTH-1:0] slave0_reg [0:15],
output wire [DATA_WIDTH-1:0] slave1_reg [0:15],
output wire [DATA_WIDTH-1:0] slave2_reg [0:15],
output wire [DATA_WIDTH-1:0] slave3_reg [0:15]
);
// Master signals
wire master_PSEL;
wire master_PENABLE;
wire [ADDR_WIDTH-1:0] master_PADDR;
wire master_PWRITE;
wire [DATA_WIDTH-1:0] master_PWDATA;
wire [DATA_WIDTH-1:0] master_PRDATA;
wire master_PREADY;
wire master_PSLVERR;
// Decoder signals
wire [NUM_SLAVES-1:0] slave_sel;
// Slave signals
wire [NUM_SLAVES-1:0] slave_PSEL;
wire [DATA_WIDTH-1:0] slave_PRDATA [0:NUM_SLAVES-1];
wire [NUM_SLAVES-1:0] slave_PREADY;
wire [NUM_SLAVES-1:0] slave_PSLVERR;
// Internal register interfaces
wire [DATA_WIDTH-1:0] slave_reg_data [0:NUM_SLAVES-1] [0:15];
wire [NUM_SLAVES-1:0] slave_reg_write_en;
wire [3:0] slave_reg_addr [0:NUM_SLAVES-1];
// Assign slave PSEL from decoder
assign slave_PSEL = slave_sel;
// Multiplex slave responses (only one slave should respond at a time)
assign master_PRDATA = (slave_sel[0] ? slave_PRDATA[0] : 0) |
(slave_sel[1] ? slave_PRDATA[1] : 0) |
(slave_sel[2] ? slave_PRDATA[2] : 0) |
(slave_sel[3] ? slave_PRDATA[3] : 0);
assign master_PREADY = slave_PREADY[0] | slave_PREADY[1] | slave_PREADY[2] | slave_PREADY[3];
assign master_PSLVERR = slave_PSLVERR[0] | slave_PSLVERR[1] | slave_PSLVERR[2] | slave_PSLVERR[3];
// Assign slave register outputs
genvar j;
generate
for (j = 0; j < 16; j = j + 1) begin : gen_regs
assign slave0_reg[j] = slave_reg_data[0][j];
assign slave1_reg[j] = slave_reg_data[1][j];
assign slave2_reg[j] = slave_reg_data[2][j];
assign slave3_reg[j] = slave_reg_data[3][j];
end
endgenerate
// Instantiate APB Master
apb_master #(
.ADDR_WIDTH(ADDR_WIDTH),
.DATA_WIDTH(DATA_WIDTH)
) u_master (
.PCLK(PCLK),
.PRESETn(PRESETn),
.req(req),
.addr(addr),
.write(write),
.wdata(wdata),
.rdata(rdata),
.ready(ready),
.error(error),
.PSEL(master_PSEL),
.PENABLE(master_PENABLE),
.PADDR(master_PADDR),
.PWRITE(master_PWRITE),
.PWDATA(master_PWDATA),
.PRDATA(master_PRDATA),
.PREADY(master_PREADY),
.PSLVERR(master_PSLVERR)
);
// Instantiate APB Decoder
apb_decoder #(
.ADDR_WIDTH(ADDR_WIDTH),
.NUM_SLAVES(NUM_SLAVES)
) u_decoder (
.PADDR(master_PADDR),
.PSEL(master_PSEL),
.slave_sel(slave_sel)
);
// Instantiate APB Slaves
genvar k;
generate
for (k = 0; k < NUM_SLAVES; k = k + 1) begin : gen_slaves
apb_slave #(
.ADDR_WIDTH(ADDR_WIDTH),
.DATA_WIDTH(DATA_WIDTH),
.BASE_ADDR(k * 32'h1000),
.ADDR_MASK(32'hFFFF_F000)
) u_slave (
.PCLK(PCLK),
.PRESETn(PRESETn),
.PSEL(slave_PSEL[k]),
.PENABLE(master_PENABLE),
.PADDR(master_PADDR),
.PWRITE(master_PWRITE),
.PWDATA(master_PWDATA),
.PRDATA(slave_PRDATA[k]),
.PREADY(slave_PREADY[k]),
.PSLVERR(slave_PSLVERR[k]),
.reg_data(slave_reg_data[k]),
.reg_write_en(slave_reg_write_en[k]),
.reg_addr(slave_reg_addr[k])
);
end
endgenerate
endmodule