Skip to content

Commit 33bdbd4

Browse files
committed
use common master subtb & make nack combinational
1 parent 79b5482 commit 33bdbd4

File tree

7 files changed

+30
-230
lines changed

7 files changed

+30
-230
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ install:
2121
- stat /home/travis/intelFPGA/19.1/modelsim_ase || (curl 'http://download.altera.com/akdlm/software/acdsinst/19.1std/670/ib_installers/ModelSimSetup-19.1.0.670-linux.run' -o ModelSimSetup.run && chmod +x ModelSimSetup.run && travis_wait 30 ./ModelSimSetup.run --mode unattended --accept_eula 1 && sed -i 's/linux_rh60/linux/g' /home/travis/intelFPGA/19.1/modelsim_ase/vco )
2222
script:
2323
- export PATH=$PATH:/home/travis/intelFPGA/19.1/modelsim_ase/bin
24-
- cd ./sim/master_tb/ && hdlmake fetch && hdlmake && make
24+
- cd ./sim/slow_master_tb/ && hdlmake fetch && hdlmake && make
2525
- cd -
2626
- cd ./sim/fast_master_tb/ && hdlmake fetch && hdlmake && make
2727
- cd -

sim/master_tb/Manifest.py renamed to sim/slow_master_tb/Manifest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
action = "simulation"
22
sim_tool = "modelsim"
3-
sim_top = "master_tb"
3+
sim_top = "slow_master_tb"
44

5-
sim_post_cmd = "vsim -novopt -do ../vsim.do -c master_tb"
5+
sim_post_cmd = "vsim -novopt -do ../vsim.do -c slow_master_tb"
66

77
modules = {
88
"local" : [ "../../test/" ],

src/i2c_master.sv

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module i2c_master #(
3737

3838
output logic interrupt = 1'b0, // A transaction has completed or an error occurred.
3939
output logic transaction_complete, // ready for a new transaction
40-
output logic nack = 1'b0, // When a transaction is complete, whether ACK/NACK was received/sent for the last transaction (0 = ACK, 1 = NACK).
40+
output logic nack, // When a transaction is complete, whether ACK/NACK was received/sent for the last transaction (0 = ACK, 1 = NACK).
4141
output logic [7:0] data_rx,
4242

4343
// The below errors matter ONLY IF there are multiple masters on the bus
@@ -123,22 +123,23 @@ assign start_by_a_master = last_sda && !sda && scl;
123123
assign stop_by_a_master = !last_sda && sda && scl;
124124
`endif
125125

126+
// transmitter notes whether ACK/NACK was received
127+
// receiver notes whether ACK/NACK was sent
128+
// treats a start by another master as as an ACK
129+
`ifdef MODEL_TECH
130+
assign nack = sda === 1'bz;
131+
`else
132+
assign nack = sda;
133+
`endif
134+
126135
always @(posedge clk_in)
127136
begin
128137
start_err = MULTI_MASTER && start_by_a_master && !(transaction_progress == 4'd0 || (transaction_progress == 4'd11 && transfer_start && counter == COUNTER_RECEIVE));
129138

130139
// transmitter listens for loss of arbitration
131140
arbitration_err = MULTI_MASTER && (counter == COUNTER_RECEIVE && transaction_progress >= 4'd2 && transaction_progress < 4'd10 && !latched_mode && sda != latched_data[4'd9 - transaction_progress] && !start_err);
132141

133-
transaction_complete = counter == COUNTER_RECEIVE - 2 && transaction_progress == 4'd10 && !start_err && !arbitration_err;
134-
// transmitter notes whether ACK/NACK was received
135-
// receiver notes whether ACK/NACK was sent
136-
// treats a start by another master as as an ACK
137-
`ifdef MODEL_TECH
138-
nack = !(transaction_complete && sda === 1'b0);
139-
`else
140-
nack = !(transaction_complete && !sda);
141-
`endif
142+
transaction_complete = counter == COUNTER_RECEIVE - 2 && transaction_progress == (COUNTER_RECEIVE - 2 == COUNTER_TRANSMIT ? 4'd9 : 4'd10) && !start_err && !arbitration_err;
142143

143144
interrupt = start_err || arbitration_err || transaction_complete;
144145

test/Manifest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
files = [
22
"clock_tb.sv",
33
"master_tb.sv",
4-
"fast_master_tb.sv"
4+
"fast_master_tb.sv",
5+
"slow_master_tb.sv"
56
]
67

78
modules = {

test/fast_master_tb.sv

Lines changed: 1 addition & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1,213 +1,6 @@
11
module fast_master_tb();
22

33
localparam INPUT_CLK_RATE = 48000000;
4-
localparam TARGET_SCL_RATE = 100000;
5-
localparam SLOWEST_DEVICE_RATE = 10000;
6-
7-
logic sda_in = 1'bz;
8-
logic inoutmode = 1'b0;
9-
wire scl;
10-
wire sda;
11-
assign scl = 1'bz;
12-
assign sda = inoutmode ? sda_in : 1'bz;
13-
14-
15-
logic clk_in = 1'b0;
16-
always #2 clk_in = ~clk_in;
17-
logic bus_clear;
18-
logic mode = 1'b0;
19-
logic transfer_start = 1'b0;
20-
logic transfer_continues = 1'b0;
21-
logic transfer_ready;
22-
logic interrupt;
23-
logic transaction_complete;
24-
logic nack;
25-
logic start_err;
26-
logic arbitration_err;
27-
logic [7:0] data_tx = 8'd0;
28-
logic [7:0] data_rx;
29-
30-
i2c_master #(
31-
.INPUT_CLK_RATE(INPUT_CLK_RATE),
32-
.TARGET_SCL_RATE(TARGET_SCL_RATE),
33-
.CLOCK_STRETCHING(0),
34-
.MULTI_MASTER(0),
35-
.SLOWEST_DEVICE_RATE(SLOWEST_DEVICE_RATE),
36-
.FORCE_PUSH_PULL(0)
37-
) master (
38-
.scl(scl),
39-
.clk_in(clk_in),
40-
.bus_clear(bus_clear),
41-
.sda(sda),
42-
.mode(mode),
43-
.transfer_start(transfer_start),
44-
.transfer_continues(transfer_continues),
45-
.transfer_ready(transfer_ready),
46-
.interrupt(interrupt),
47-
.transaction_complete(transaction_complete),
48-
.nack(nack),
49-
.start_err(start_err),
50-
.arbitration_err(arbitration_err),
51-
.data_tx(data_tx),
52-
.data_rx(data_rx)
53-
);
54-
55-
integer i, j;
56-
57-
logic [7:0] TEST1 = 8'b10110100;
58-
logic [63:0] TEST2 = 128'hFEEDFACECAFEBEEF;
59-
logic [63:0] TEST3 = 128'hFAC3B00CBAAAAAAD;
60-
61-
initial
62-
begin
63-
$display("Parameters: COUNTER_END %d, COUNTER_HIGH %d, COUNTER_RECEIVE %d, COUNTER_TRANSMIT %d", master.COUNTER_END, master.COUNTER_HIGH, master.COUNTER_RECEIVE, master.COUNTER_TRANSMIT);
64-
wait (!clk_in && transfer_ready);
65-
$display("Beginning transmission ending with NACK");
66-
mode <= 1'b0;
67-
transfer_start <= 1'b1;
68-
transfer_continues <= 1'b0;
69-
data_tx <= TEST1;
70-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) && !clk_in);
71-
assert (master.busy) else $fatal(1, "Master should be busy");
72-
for (i = 0; i < 8; i++)
73-
begin
74-
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
75-
assert (master.transaction_progress == 4'(i + 2)) else $fatal(1, "Unexpected TX progress: %d should be ", master.transaction_progress, i + 2);
76-
assert (master.busy) else $fatal(1, "Master should be busy in %d", 3'(i));
77-
assert (master.sda_internal === TEST1[7 - i]) else $fatal(1, "Loop %d TX progress %d expected %b but was %b", i, master.transaction_progress, TEST1[7 - i], master.sda_internal);
78-
wait (master.counter == master.COUNTER_TRANSMIT && !clk_in);
79-
end
80-
wait (interrupt && !clk_in);
81-
assert (transaction_complete) else $fatal(1, "Transaction did not complete successfully");
82-
assert (nack) else $fatal(1, "Slave sent NACK, master should've noted it");
83-
transfer_start <= 1'b0;
84-
transfer_continues <= 1'b0;
85-
86-
wait (!clk_in && transfer_ready);
87-
$display("Beginning transmission ending with ACK");
88-
mode <= 1'b0;
89-
transfer_start <= 1'b1;
90-
transfer_continues <= 1'b0;
91-
data_tx <= TEST1;
92-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) && !clk_in);
93-
assert (master.busy) else $fatal(1, "Master should be busy");
94-
for (i = 0; i < 8; i++)
95-
begin
96-
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
97-
assert (master.transaction_progress == 4'(i + 2)) else $fatal(1, "Unexpected TX progress: %d should be ", master.transaction_progress, i + 2);
98-
assert (master.busy) else $fatal(1, "Master should be busy in %d", 3'(i));
99-
assert (master.sda_internal === TEST1[7 - i]) else $fatal(1, "Loop %d TX progress %d expected %b but was %b", i, master.transaction_progress, TEST1[7 - i], master.sda_internal);
100-
wait (master.counter == master.COUNTER_TRANSMIT && !clk_in);
101-
end
102-
inoutmode <= 1'b1;
103-
sda_in <= 1'b0;
104-
wait (interrupt && !clk_in);
105-
inoutmode <= 1'b0;
106-
assert (transaction_complete) else $fatal(1, "Transaction did not complete successfully");
107-
assert (!nack) else $fatal(1, "Slave sent ACK, master should've noted it");
108-
109-
110-
$display("Beginning repeated start reception ending with NACK");
111-
mode <= 1'b1;
112-
transfer_start <= 1'b1;
113-
transfer_continues <= 1'b0;
114-
data_tx <= 8'd0;
115-
inoutmode <= 1'b1;
116-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) && !clk_in);
117-
wait (master.counter == (master.COUNTER_RECEIVE) % (master.COUNTER_END + 1) && !clk_in);
118-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) && !clk_in);
119-
assert (master.busy) else $fatal(1, "Master should be busy");
120-
for (i = 0; i < 8; i++)
121-
begin
122-
wait (master.counter == master.COUNTER_TRANSMIT && !clk_in);
123-
wait (clk_in);
124-
sda_in <= TEST1[7 - i] ? 1'bz : 1'b0;
125-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) && !clk_in);
126-
assert (master.transaction_progress == 4'(i + 2)) else $fatal(1, "Unexpected TX progress: %d should be ", master.transaction_progress, i + 2);
127-
assert (master.latched_data[7 - i] == TEST1[7 - i]) else $fatal(1, "Loop %d RX progress %d expected %b but was %b", i, master.transaction_progress, TEST1[7 - i], master.latched_data[7 - i]);
128-
end
129-
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
130-
inoutmode <= 1'b0;
131-
wait (interrupt && !clk_in);
132-
assert (transaction_complete) else $fatal(1, "Transaction did not complete successfully");
133-
assert (nack) else $fatal(1, "Master should've sent NACK");
134-
assert (data_rx == TEST1) else $fatal(1, "Expected %b, was %b", TEST1, data_rx);
135-
transfer_start <= 1'b0;
136-
transfer_continues <= 1'b0;
137-
138-
139-
140-
wait (transfer_ready && !clk_in);
141-
$display("\nBeginning bulk transmission");
142-
mode <= 1'b0;
143-
transfer_start <= 1'b1;
144-
transfer_continues <= 1'b1;
145-
data_tx <= TEST2[7:0];
146-
for (j = 0; j < 8; j++)
147-
begin
148-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) + (j == 0 ? 0 : 1) && !clk_in);
149-
$display("Byte %d (%h)", j, TEST2[7:0]);
150-
assert (master.busy) else $fatal(1, "Master should be busy");
151-
wait (master.counter == master.COUNTER_TRANSMIT && !clk_in);
152-
assert (master.latched_data == TEST2[7:0]) else $fatal(1, "Master didn't latch current byte expected %h but was %h", TEST2[7:0], master.latched_data);
153-
inoutmode <= 1'b0;
154-
for (i = 0; i < 8; i++)
155-
begin
156-
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
157-
assert (master.transaction_progress == 4'(i + 2)) else $fatal(1, "Unexpected TX progress: %d should be ", master.transaction_progress, i + 2);
158-
assert (master.busy) else $fatal(1, "Master should be busy");
159-
assert (master.sda_internal == TEST2[7 - i]) else $fatal(1, "Loop %d TX progress %d expected %b but was %b", 3'(i), master.transaction_progress, TEST2[7 - i], master.sda_internal);
160-
wait (master.counter == master.COUNTER_TRANSMIT && !clk_in);
161-
end
162-
inoutmode <= 1'b1;
163-
sda_in <= j == 7 ? 1'bz : 1'b0; // NACK or ACK
164-
wait (interrupt && !clk_in);
165-
assert (transaction_complete) else $fatal(1, "Transaction did not complete successfully");
166-
assert (j == 7 ? nack : !nack) else $fatal(1, "Unexpected ACK/NACK for %d", j);
167-
transfer_start <= 1'b0;
168-
transfer_continues <= 1'(j + 1 != 7);
169-
if (j != 7)
170-
begin
171-
TEST2 <= {8'd0, TEST2[63:8]};
172-
data_tx <= TEST2[15:8];
173-
end
174-
end
175-
176-
wait (transfer_ready && !clk_in);
177-
$display("\nBeginning bulk reception");
178-
mode <= 1'b1;
179-
transfer_start <= 1'b1;
180-
transfer_continues <= 1'b1;
181-
for (j = 0; j < 8; j++)
182-
begin
183-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) + (j == 0 ? 0 : 1) && !clk_in);
184-
$display("Byte %d (%h)", j, TEST3[7:0]);
185-
assert (master.busy) else $fatal(1, "Master should be busy");
186-
inoutmode <= 1'b1;
187-
for (i = 0; i < 8; i++)
188-
begin
189-
wait (master.counter == master.COUNTER_TRANSMIT && clk_in);
190-
sda_in <= TEST3[7 - i] ? 1'bz : 1'b0;
191-
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) && !clk_in);
192-
assert (master.latched_data[7 - i] == TEST3[7 - i]) else $fatal(1, "Loop %d RX progress %d expected %b but was %b", i, master.transaction_progress, TEST3[7 - i], master.latched_data[7 - i]);
193-
end
194-
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
195-
inoutmode <= 1'b0;
196-
wait (interrupt && !clk_in);
197-
assert (transaction_complete) else $fatal(1, "Transaction did not complete successfully");
198-
assert (j == 7 ? nack : !nack) else $fatal(1, "Master sent unexpected ACK/NACK for %d", j);
199-
transfer_start <= 1'b0;
200-
transfer_continues <= 1'(j + 1 != 7);
201-
if (j != 7)
202-
begin
203-
TEST3 <= {8'd0, TEST3[63:8]};
204-
data_tx <= TEST3[15:8];
205-
end
206-
end
207-
208-
wait(transfer_ready && !clk_in);
209-
210-
$finish;
211-
end
4+
master_tb #(.INPUT_CLK_RATE(INPUT_CLK_RATE)) master_tb();
2125

2136
endmodule

test/master_tb.sv

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
module master_tb();
2-
3-
localparam INPUT_CLK_RATE = 400000;
4-
localparam TARGET_SCL_RATE = 100000;
5-
localparam SLOWEST_DEVICE_RATE = 10000;
6-
1+
module master_tb #(
2+
parameter INPUT_CLK_RATE,
3+
parameter TARGET_SCL_RATE = 100000,
4+
parameter SLOWEST_DEVICE_RATE = 10000
5+
) ();
76
logic sda_in = 1'bz;
87
logic inoutmode = 1'b0;
98
wire scl;
@@ -126,8 +125,8 @@ begin
126125
assert (master.transaction_progress == 4'(i + 2)) else $fatal(1, "Unexpected TX progress: %d should be ", master.transaction_progress, i + 2);
127126
assert (master.latched_data[7 - i] == TEST1[7 - i]) else $fatal(1, "Loop %d RX progress %d expected %b but was %b", i, master.transaction_progress, TEST1[7 - i], master.latched_data[7 - i]);
128127
end
129-
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
130128
inoutmode <= 1'b0;
129+
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
131130
wait (interrupt && !clk_in);
132131
assert (transaction_complete) else $fatal(1, "Transaction did not complete successfully");
133132
assert (nack) else $fatal(1, "Master should've sent NACK");
@@ -191,8 +190,8 @@ begin
191190
wait (master.counter == (master.COUNTER_RECEIVE + 1) % (master.COUNTER_END + 1) && !clk_in);
192191
assert (master.latched_data[7 - i] == TEST3[7 - i]) else $fatal(1, "Loop %d RX progress %d expected %b but was %b", i, master.transaction_progress, TEST3[7 - i], master.latched_data[7 - i]);
193192
end
194-
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
195193
inoutmode <= 1'b0;
194+
wait (master.counter == master.COUNTER_TRANSMIT + 1 && !clk_in);
196195
wait (interrupt && !clk_in);
197196
assert (transaction_complete) else $fatal(1, "Transaction did not complete successfully");
198197
assert (j == 7 ? nack : !nack) else $fatal(1, "Master sent unexpected ACK/NACK for %d", j);

test/slow_master_tb.sv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module slow_master_tb();
2+
3+
localparam INPUT_CLK_RATE = 400000;
4+
master_tb #(.INPUT_CLK_RATE(INPUT_CLK_RATE)) master_tb();
5+
6+
endmodule

0 commit comments

Comments
 (0)