Skip to content

Commit add0ca9

Browse files
dpcarryrishyak
authored andcommitted
feat: AHB-APB bridge
1 parent f26544f commit add0ca9

File tree

2 files changed

+80
-4
lines changed

2 files changed

+80
-4
lines changed

dv/ahb/SimpleDecoder/SimpleDecoder_tb.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ TEST_CASE("SimpleDecoder, Basic Functionality") {
1717
decoder->clk = 1;
1818
decoder->eval();
1919

20-
//test for addresses 1 to 20
20+
//test for addresses 1 to 3
2121
for (int address = 1; address <= 3; ++address) {
2222
int expected_sel = 1 << (address - 1);
2323

rtl/apb/devices/Bridge.sv

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,85 @@
44
@note See https://developer.arm.com/documentation/ihi0011/a/AMBA-APB/APB-bridge/Interface-diagram
55
*/
66
module Bridge (
7-
AHBCommon_if.subordinate sub,
8-
APBCommon_if.bridge bridge
7+
AHBCommon_if.subordinate sub,
8+
APBCommon_if.bridge bridge
99
);
10-
// Interface the two modports here
10+
//three states
11+
typedef enum logic [1:0] {
12+
IDLE,
13+
SETUP,
14+
ENABLE
15+
} state_t;
1116

17+
//signals
18+
state_t state = IDLE;
19+
logic [31:0] write_data_buffer;
20+
logic [31:0] read_data_buffer;
21+
logic [31:0] address_buffer;
22+
logic write_buffer;
23+
logic setup_done;
24+
25+
//interface the two modports here
26+
always_ff @(posedge sub.clk or negedge sub.nReset) begin
27+
if (!sub.nReset) begin
28+
state <= IDLE;
29+
sub.readyOut <= 1'b0; //will be set when finished
30+
sub.rData <= 32'd0; //Clear the read data buffer on the AHB side
31+
sub.resp <= 2'b00; //set default response to ok
32+
bridge.addr <= 32'd0;//this buffer holds the address for the next APB transaction.
33+
bridge.write <= 1'b0; //this is used to indicate the next operation is not a write by default
34+
bridge.wData <= 32'd0; // store data that is to be written to the APB bus during a write transaction
35+
bridge.selectors <= 1'b0; //select which peripheral on the APB bus should be active for the next transaction
36+
bridge.enable <= 1'b0;
37+
write_data_buffer <= 32'd0;
38+
read_data_buffer <= 32'd0;
39+
address_buffer <= 32'd0;
40+
write_buffer <= 1'b0; //if set, write operation; if not, read operation
41+
setup_done <= 1'b0; //flag that indicates if the setup stage of the current APB transaction is complete
42+
end else begin
43+
case (state)
44+
IDLE: begin //wait for AHB signal
45+
if (sub.sel && !setup_done) begin
46+
address_buffer <= sub.addr;
47+
write_buffer <= sub.write;
48+
write_data_buffer <= sub.wData;
49+
state <= SETUP;
50+
end
51+
end
52+
SETUP: begin
53+
//set up APB transfer
54+
bridge.selectors <= 1'b1; //select the peripheral
55+
bridge.addr <= address_buffer;
56+
bridge.write <= write_buffer;
57+
bridge.wData <= write_data_buffer;
58+
bridge.enable <= 1'b0;
59+
setup_done <= 1'b1;
60+
state <= ENABLE;
61+
end
62+
ENABLE: begin
63+
//enable APB transfer and wait for the ready signal
64+
bridge.enable <= 1'b1;
65+
if (bridge.ready) begin
66+
//complete the AHB transfer
67+
sub.readyOut <= 1'b1;
68+
if (!write_buffer) begin
69+
read_data_buffer <= bridge.rData;
70+
end
71+
sub.resp <= 2'b00; //okresponse
72+
state <= IDLE;
73+
setup_done <= 1'b0;
74+
end
75+
end
76+
endcase
77+
end
78+
end
79+
80+
//read data back to AHB
81+
always_comb begin
82+
if (!write_buffer && sub.sel) begin
83+
sub.rData = read_data_buffer;
84+
end else begin
85+
sub.rData = 32'bz;
86+
end
87+
end
1288
endmodule

0 commit comments

Comments
 (0)