Skip to content

Commit 23b773d

Browse files
committed
Refactor read & write protocols to take in extra address arg
1 parent 72e88f9 commit 23b773d

File tree

3 files changed

+73
-89
lines changed

3 files changed

+73
-89
lines changed

protocols/tests/wishbone_manager/hbexec.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060

6161
`define CMD_SUB_RD 2'b00 // Read request
6262
`define CMD_SUB_WR 2'b01 // Write request
63-
`define CMD_SUB_BUS 1'b0 // A request in general
63+
`define CMD_SUB_BUS 1'b0 // Bus request (either a read or a write)
6464
`define CMD_SUB_ADDR 2'b10 // Set an address
6565
`define CMD_SUB_SPECIAL 2'b11 // Bus reset
6666

protocols/tests/wishbone_manager/wishbone_manager.prot

Lines changed: 66 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct WBManager {
2727
in i_wb_data: u32,
2828
}
2929

30+
3031
prot reset<DUT: WBManager>() {
3132
DUT.i_reset := 1'b1;
3233

@@ -51,136 +52,127 @@ prot idle<DUT: WBManager>() {
5152
step();
5253
}
5354

54-
// Sets the Wishbone bus address to `addr`.
55-
// Sends a CMD_SUB_ADDR command where the "opcode" is i_cmd_word[33:32] = 2'b10:
56-
// i_cmd_word[31:2] = addr (30-bit absolute address)
57-
// i_cmd_word[1] = 0
58-
// i_cmd_word[0] = 0
59-
//
60-
// The manager echoes the new address back on the response channel one cycle
61-
// after the command is accepted. Specifically, after one cycle,
62-
// `o_rsp_stb` is set to 1 and `o_rsp_word` contains the address.
63-
//
64-
// response format in `o_rsp_word`: { 2'b10, addr[29:0], 1'b0, !inc }
65-
// where:
66-
// - RSP_SUB_ADDR = 2'b10 is the "opcode" for the response
67-
// - `inc` is an internal variable in the Verilog module.
68-
// When i_cmd_word[0]=0, inc=1, so !inc=0, i.e. the response is {2'b10, addr, 2'b00}.
69-
prot set_address<DUT: WBManager>(in addr: u30) {
55+
// This protocol writes a 32-bit `data` word to the Wishbone bus at `addr`,
56+
// assuming that the subordinate does not stall (i_wb_stall = 0 throughout).
57+
// Under the hood, this corresponds to a "set address" command (`CMD_SUB_ADDR`),
58+
// followed immediately by a "write" command (`CMD_SUB_WR`).
59+
// (The two commands can be issued back to back, since updating the address
60+
// only updates the address and doesn't affect `cyc` or `stb`, and the latter
61+
// is what governs when `read` / `write` protocols can fire.)
62+
// State progression:
63+
// 1. IDLE: send CMD_SUB_ADDR, step -> address updated
64+
// 2. IDLE: send CMD_SUB_WR, step -> cyc=1, stb=1, we=1 (bus request starts)
65+
// 3. BUS REQUEST (cyc=1, stb=1, we=1): subordinate accepts (stall=0), step
66+
// 4. BUS WAIT (cyc=1, stb=0): subordinate acknowledges (ack=1), step
67+
// 5. IDLE (cyc=0): RSP_WRITE_ACKNOWLEDGEMENT = {2'b01, 32'x0} on response channel
68+
prot write<DUT: WBManager>(in addr: u30, in data: u32) {
69+
// Issue a "set address" command (`CMD_SUB_ADDR`)
70+
// In `i_cmd_word`, we have:
71+
// - bits[33:32] = 2'b10 (opcode for `CMD_SUB_ADDR`)
72+
// - bits[31:2] = the actual address
7073
DUT.i_reset := 1'b0;
7174
DUT.i_cmd_stb := 1'b1;
72-
73-
// bit[33:32]=2'b10 (CMD_SUB_ADDR), bits[31:2]=addr, bit[1]=0 (absolute), bit[0]=0 (auto-increment)
7475
DUT.i_cmd_word := 30'b10 + addr + 30'b0;
7576
DUT.i_wb_stall := 1'b0;
7677
DUT.i_wb_ack := 1'b0;
7778
DUT.i_wb_err := 1'b0;
7879
assert_eq(DUT.o_cmd_busy, 1'b0);
79-
step();
80+
step(); // Address is updated in the Verilog during this step
8081

81-
// At this point, in the Verilog, `o_wb_addr` and `newaddr` are updated.
82-
// TODO: figure out how to express address increment since our langauge
83-
// doesn't have addition
84-
DUT.i_cmd_stb := 1'b0;
85-
step();
86-
87-
// Manager echoes the new address back on the response channel
88-
assert_eq(DUT.o_rsp_stb, 1'b1);
89-
assert_eq(DUT.o_rsp_word, 30'b10 + addr + 30'b0);
90-
step();
91-
}
92-
93-
// Writes a 32-bit `data` word to the Wishbone bus at the current address.
94-
// Sends the CMD_SUB_WR "opcode" (i_cmd_word[33:32] = 2'b01) with `data` in bits [31:0].
95-
// This assumes the subordinate does not stall (i_wb_stall = 0 throughout).
96-
//
97-
// State machine progression:
98-
// IDLE -> issue command -> step
99-
// BUS REQUEST (cyc=1, stb=1, we=1): subordinate accepts immediately (stall=0) -> step
100-
// BUS WAIT (cyc=1, stb=0): subordinate acknowledges (ack=1) -> step
101-
// IDLE (cyc=0): RSP_WRITE_ACKNOWLEDGEMENT = {2'b01, 32'x0} on response channel
102-
prot write<DUT: WBManager>(in data: u32) {
103-
// IDLE: issue write command
104-
DUT.i_reset := 1'b0;
82+
// Issue a write command immediately by setting `stb = 1`
83+
// (`o_cmd_busy = 0` since `cyc = 0`)
84+
// In `i_cmd_word`, we have:
85+
// - bits[33:32] = 2'b01 (opcode for `CMD_SUB_WR`)
86+
// - bits[31:0] = data
10587
DUT.i_cmd_stb := 1'b1;
10688
DUT.i_cmd_word := 32'x1 + data;
107-
DUT.i_wb_stall := 1'b0;
108-
DUT.i_wb_ack := 1'b0;
109-
DUT.i_wb_err := 1'b0;
11089
assert_eq(DUT.o_cmd_busy, 1'b0);
111-
step();
90+
assert_eq(DUT.o_wb_addr, addr);
91+
step(); // cyc=1, stb=1, we=1; address echo arrives on rsp channel simultaneously
11292

113-
// BUS REQUEST: manager asserts cyc=1, stb=1, we=1
93+
// BUS REQUEST: up to now, the manager has asserted cyc=1, stb=1, we=1
94+
// The manager now sets `stb = 0` (since the subordinate doesn't stall)
11495
DUT.i_cmd_stb := 1'b0;
115-
assert_eq(DUT.o_wb_cyc, 1'b1);
116-
assert_eq(DUT.o_wb_stb, 1'b1);
117-
assert_eq(DUT.o_wb_we, 1'b1);
96+
assert_eq(DUT.o_wb_cyc, 1'b1);
97+
assert_eq(DUT.o_wb_stb, 1'b1);
98+
assert_eq(DUT.o_wb_we, 1'b1);
11899
assert_eq(DUT.o_cmd_busy, 1'b1);
119-
// stall=0, so manager will drop `o_wb_stb` after this step
120100
step();
121101

122-
// BUS WAIT: stb has dropped (request accepted), cyc still high
102+
// BUS WAIT: We now have `stb = 0` (the request has been accepted)
103+
// `cyc` is still 1 since we're still in the same session
123104
assert_eq(DUT.o_wb_cyc, 1'b1);
124105
assert_eq(DUT.o_wb_stb, 1'b0);
125106
// Subordinate acknowledges the write
126107
DUT.i_wb_ack := 1'b1;
127108
step();
128109

129110
// IDLE: cyc dropped, write acknowledged on response channel
130-
assert_eq(DUT.o_wb_cyc, 1'b0);
111+
assert_eq(DUT.o_wb_cyc, 1'b0);
131112
assert_eq(DUT.o_cmd_busy, 1'b0);
132-
assert_eq(DUT.o_rsp_stb, 1'b1);
133-
113+
assert_eq(DUT.o_rsp_stb, 1'b1);
134114
// RSP_WRITE_ACKNOWLEDGEMENT = { RSP_SUB_ACK(2'b01), 32'x0 }
135115
assert_eq(DUT.o_rsp_word, 32'x1 + 32'x0);
136116
DUT.i_wb_ack := 1'b0;
137117
step();
138118
}
139119

140-
// Reads a 32-bit word from the Wishbone bus at the current address.
141-
// `rdata` is the value provided by the subordinate (driven on i_wb_data).
142-
// Sends CMD_SUB_RD (i_cmd_word[33:32] = 2'b00).
143-
// Assumes the subordinate does not stall (i_wb_stall = 0 throughout).
144-
//
120+
// This protocol reads a 32-bit word from the Wishbone bus at `addr`,
121+
// where `rdata` is the value provided by the subordinate (driven on i_wb_data)
122+
// (this is why `rdata` is an input parameter).
123+
// Like the `write` protocol above, we issue two commands back to back,
124+
// first by setting the address via `CMD_SUB_ADDR`
125+
// then by performing a read (`CMD_SUB_RD`)//
145126
// State progression:
146-
// IDLE -> issue command -> step
147-
// BUS REQUEST (cyc=1, stb=1, we=0): subordinate accepts immediately (stall=0) -> step
148-
// BUS WAIT (cyc=1, stb=0): subordinate acknowledges with data (ack=1) -> step
149-
// IDLE (cyc=0): { RSP_SUB_DATA(2'b00), rdata } on response channel
150-
prot read<DUT: WBManager>(in rdata: u32) {
151-
// IDLE: issue read command (lower 32 bits are ignored by the manager)
127+
// 1. IDLE: send CMD_SUB_ADDR, step -> addr latched, newaddr=1
128+
// 2. IDLE: send CMD_SUB_RD, step -> cyc=1, stb=1, we=0 (bus cycle starts)
129+
// 3. BUS REQUEST (cyc=1, stb=1, we=0): subordinate accepts (stall=0), step
130+
// 4. BUS WAIT (cyc=1, stb=0): subordinate acknowledges with data (ack=1), step
131+
// 5. IDLE (cyc=0): Send response
132+
prot read<DUT: WBManager>(in addr: u30, in rdata: u32) {
133+
// Set the bus address
152134
DUT.i_reset := 1'b0;
153135
DUT.i_cmd_stb := 1'b1;
154-
DUT.i_cmd_word := 34'x0;
136+
DUT.i_cmd_word := 30'b10 + addr + 30'b0;
155137
DUT.i_wb_stall := 1'b0;
156138
DUT.i_wb_ack := 1'b0;
157139
DUT.i_wb_err := 1'b0;
158140
DUT.i_wb_data := rdata;
159141
assert_eq(DUT.o_cmd_busy, 1'b0);
160-
step();
142+
step();
143+
144+
// Issue read command immediately
145+
// In `i_cmd_word`, we have `bits[33:32]=2'b00 (opcode for CMD_SUB_RD)`
146+
// and the lower 32 bits are ignored by the manager (i.e. all zeroes)
147+
DUT.i_cmd_stb := 1'b1;
148+
DUT.i_cmd_word := 34'x0;
149+
assert_eq(DUT.o_cmd_busy, 1'b0);
150+
assert_eq(DUT.o_wb_addr, addr);
151+
step();
161152

162-
// BUS REQUEST: manager asserts cyc=1, stb=1, we=0
153+
// BUS REQUEST: manager DUT has asserted cyc=1, stb=1, we=0
163154
DUT.i_cmd_stb := 1'b0;
164155
assert_eq(DUT.o_wb_cyc, 1'b1);
165156
assert_eq(DUT.o_wb_stb, 1'b1);
166157
assert_eq(DUT.o_wb_we, 1'b0);
167158
assert_eq(DUT.o_cmd_busy, 1'b1);
168-
// stall=0, so manager will drop stb after this step
159+
// We currently have stall=0, so the manager sets `stb = 0` after this step
169160
step();
170161

171-
// BUS WAIT: stb has dropped (request accepted), cyc still high
162+
// BUS WAIT: The manager sets `stb = 0` (request accepted), cyc still high
172163
assert_eq(DUT.o_wb_cyc, 1'b1);
173164
assert_eq(DUT.o_wb_stb, 1'b0);
174165
// Subordinate acknowledges with read data
175166
DUT.i_wb_ack := 1'b1;
176167
DUT.i_wb_data := rdata;
177168
step();
178169

179-
// IDLE: cyc dropped, read data on response channel
170+
// IDLE: `cyc` becomes 0 (to indicate the end of a session)
171+
// The read data is conveyed via the response
180172
assert_eq(DUT.o_wb_cyc, 1'b0);
181173
assert_eq(DUT.o_cmd_busy, 1'b0);
182174
assert_eq(DUT.o_rsp_stb, 1'b1);
183-
// { RSP_SUB_DATA(2'b00), rdata }
175+
// response format is { 2'b00 (opcode for RSP_SUB_DATA), rdata }
184176
assert_eq(DUT.o_rsp_word, 32'x0 + rdata);
185177
DUT.i_wb_ack := 1'b0;
186178
step();

protocols/tests/wishbone_manager/wishbone_manager.tx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,14 @@
22
trace {
33
reset();
44

5-
// Set the bus address to 0x10 (absolute, auto-increment enabled)
6-
set_address(30'h10);
5+
// Write 0xDEADBEEF to address 0x10
6+
write(16, 32'xDEADBEEF);
77

8-
// Write 0xDEADBEEF to address 0x10.
9-
// Address auto-increments to 0x11 after the request is accepted.
10-
// TODO: need to figure out how to increment the address since our
11-
// language doesn't have addition
12-
write(0xDEADBEEF);
8+
// Read from address 0x11; subordinate returns 0xCAFEF00D
9+
read(17, 32'xCAFEF00D);
1310

14-
// The subordinate returns 0xCAFEF00D from address 0x11.
15-
// Manager should echo it as { 2'b00, 0xCAFEF00D } in o_rsp_word.
16-
// Address auto-increments to 0x12.
17-
read(0xCAFEF00D);
18-
19-
// Write 0xABCD1234 to address 0x12.
20-
write(0xABCD1234);
11+
// Write 0xABCD1234 to address 0x12
12+
write(18, 32'xABCD1234);
2113

2214
idle();
2315
}

0 commit comments

Comments
 (0)