@@ -49,25 +49,26 @@ module master #(
4949localparam MODE = $unsigned (TARGET_SCL_RATE ) <= 100000 ? 0 : $unsigned (TARGET_SCL_RATE ) <= 400000 ? 1 : $unsigned (TARGET_SCL_RATE ) <= 1000000 ? 2 : - 1 ;
5050
5151localparam COUNTER_WIDTH = $clog2 ($unsigned (INPUT_CLK_RATE ) / $unsigned (TARGET_SCL_RATE ));
52- localparam COUNTER_END = COUNTER_WIDTH ' ($unsigned (INPUT_CLK_RATE ) / $unsigned (TARGET_SCL_RATE ) - 1 );
52+ localparam COUNTER_END = COUNTER_WIDTH ' ($ceil ( $ unsigned (INPUT_CLK_RATE ) / $unsigned (TARGET_SCL_RATE ) ) - 1 );
5353// Conforms to Table 10 tLOW, tHIGH for SCL clock.
5454localparam COUNTER_HIGH = COUNTER_WIDTH ' (MODE == 0 ? ( (COUNTER_WIDTH + 1 )'(COUNTER_END ) + 1 ) / 2 : (( (COUNTER_WIDTH + 2 )'(COUNTER_END ) + 1 ) * 2 ) / 3 );
5555// Conforms to Table 10 tr (rise time) for SCL clock.
5656localparam COUNTER_RISE = COUNTER_WIDTH ' ($ceil ($unsigned (INPUT_CLK_RATE ) / 1 .0E9 * $unsigned (MODE == 0 ? 1000 : MODE == 1 ? 300 : MODE == 2 ? 120 : 0 )));
5757
5858// Bus clear event counter
59- localparam WAIT_WIDTH = $clog2 (2 * $unsigned (INPUT_CLK_RATE ) / $unsigned (SLOWEST_DEVICE_RATE ));
60- localparam WAIT_END = WAIT_WIDTH ' (2 * $ unsigned (INPUT_CLK_RATE ) / $unsigned (SLOWEST_DEVICE_RATE ) - 1 );
59+ localparam WAIT_WIDTH = $clog2 ($unsigned (INPUT_CLK_RATE ) / $unsigned (SLOWEST_DEVICE_RATE ));
60+ localparam WAIT_END = WAIT_WIDTH ' ($ceil ( $ unsigned (INPUT_CLK_RATE ) / $unsigned (SLOWEST_DEVICE_RATE ) ) - 1 );
6161
6262logic [COUNTER_WIDTH - 1 : 0 ] counter;
63- // stick counter
63+ // stick counter used to meet timing requirements
6464logic [COUNTER_WIDTH - 1 : 0 ] countdown = COUNTER_WIDTH ' (0 );
65+
6566// assume bus is free
6667logic busy = 1'b0 ;
6768logic [3 : 0 ] transaction_progress = 4'd0 ;
6869
6970logic release_line;
70- assign release_line = ( ! busy && transaction_progress == 4'd0 ) || countdown > 0 || (busy && transaction_progress == 4'd0 && MULTI_MASTER ) ;
71+ assign release_line = transaction_progress == 4'd0 || countdown > 0 ;
7172
7273clock # (
7374 .COUNTER_WIDTH (COUNTER_WIDTH ),
@@ -120,13 +121,13 @@ end
120121// Conforms to Table 10 minimum setup/hold/bus free times.
121122localparam TLOW_MIN = MODE == 0 ? 4 .7 : MODE == 1 ? 1 .3 : MODE == 2 ? 0 .5 : 0 ; // in microseconds
122123localparam THIGH_MIN = MODE == 0 ? 4 .0 : MODE == 1 ? 0 .6 : MODE == 2 ? 0 .26 : 0 ; // in microseconds
123- localparam COUNTER_SETUP_REPEATED_START = COUNTER_WIDTH ' ($ceil ($unsigned (INPUT_CLK_RATE )/ 1E6 * TLOW_MIN ));
124- localparam COUNTER_HOLD_REPEATED_START = COUNTER_WIDTH ' ($ceil ($unsigned (INPUT_CLK_RATE )/ 1E6 * THIGH_MIN ));
125- localparam COUNTER_SETUP_STOP = COUNTER_HOLD_REPEATED_START ;
124+ localparam COUNTER_SETUP_REPEATED_START = COUNTER_WIDTH ' ($floor ($unsigned (INPUT_CLK_RATE ) / 1 .0E6 * TLOW_MIN ));
126125localparam COUNTER_BUS_FREE = COUNTER_SETUP_REPEATED_START ;
126+ localparam COUNTER_HOLD_REPEATED_START = COUNTER_WIDTH ' ($floor ($unsigned (INPUT_CLK_RATE ) / 1 .0E6 * THIGH_MIN ));
127+ localparam COUNTER_SETUP_STOP = COUNTER_HOLD_REPEATED_START ;
127128
128129localparam COUNTER_TRANSMIT = COUNTER_WIDTH ' (COUNTER_HIGH / 2 );
129- localparam COUNTER_RECEIVE = COUNTER_WIDTH ' (( COUNTER_END - COUNTER_HIGH + 1 ) / 2 + COUNTER_HIGH );
130+ localparam COUNTER_RECEIVE = COUNTER_WIDTH ' (COUNTER_HIGH + COUNTER_RISE );
130131
131132logic latched_mode;
132133logic [7 : 0 ] latched_data;
@@ -140,11 +141,13 @@ always @(posedge clk_in)
140141begin
141142 start_err = start_by_another_master;
142143
143- // transmitter listens for loss of arbitration on receive
144- // treats a start by another master as no loss of arbitration
145- arbitration_err = counter == COUNTER_RECEIVE && busy && transaction_progress >= 4'd2 && transaction_progress < 4'd10 && ! latched_mode && MULTI_MASTER && sda != latched_data[4'd9 - transaction_progress] && ! start_by_another_master;
144+ // transmitter listens for loss of arbitration
145+ // either another master won during a tranmission
146+ // or another master issued a start condition before this master could
147+ 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_by_another_master)
148+ || (counter == COUNTER_RECEIVE && countdown == COUNTER_WIDTH ' (0 ) && transaction_progress == 4'd1 && busy && transfer_start));
146149
147- transaction_complete = counter == COUNTER_RECEIVE - 1 && busy && transaction_progress == 4'd10 && ! start_by_another_master;
150+ transaction_complete = counter == COUNTER_RECEIVE - 1 && transaction_progress == 4'd10 && ! start_by_another_master;
148151 // transmitter notes whether ACK/NACK was received
149152 // receiver notes whether ACK/NACK was sent
150153 // treats a start by another master as as an ACK
@@ -161,20 +164,21 @@ begin
161164 begin
162165 sda_internal <= 1'b1 ; // release line
163166 transaction_progress <= 4'd0 ;
164- start_by_another_master <= 1'b0 ; // synchronous reset
167+ start_by_another_master <= 1'b0 ; // synchronous reset of flag
165168 countdown <= COUNTER_WIDTH ' (0 );
166169 end
167- // Keep current state to meet setup/hold constraints
168- else if (countdown > 0 )
170+ // Keep current state to meet setup/hold constraints in Table 10.
171+ else if (countdown != COUNTER_WIDTH ' ( 0 ) )
169172 begin
170173 countdown <= countdown - 1'b1 ;
171174 end
172175 else if (counter == COUNTER_HIGH )
173176 begin
174- // TODO: what if the user saw transfer_ready and put in some stuff, but then busy went high before COUNTER_RECEIVE and now the transaction can't start? user thinks transaction began but it didn't, and there should be an arbitration error later on
175- if (((! busy && transaction_progress == 4'd0 ) || (busy && transaction_progress == 4'd11 )) && transfer_start)
177+ if ((transaction_progress == 4'd0 || transaction_progress == 4'd11 ) && transfer_start)
176178 begin
177- transaction_progress <= 4'd1 ;
179+ if (transaction_progress == 4'd0 )
180+ transaction_progress <= 4'd1 ;
181+
178182 latched_mode <= mode;
179183 // if (!mode) // Mode doesn't matter, save some logic cells
180184 latched_data <= data_tx;
@@ -191,29 +195,30 @@ begin
191195 // "The data on the SDA line must be stable during the HIGH period of the clock."
192196 else if (counter == COUNTER_RECEIVE )
193197 begin
194- if (transaction_progress > 0 )
198+ // Another master is doing a transaction (void messages tolerated, see Note 5 in Section 3.1.10)
199+ if (transaction_progress == 4'd0 && MULTI_MASTER )
200+ sda_internal <= 1'b1 ;
195201 // START or repeated START condition
196- if (! busy && (transaction_progress == 4'd1 || transaction_progress == 4'd11 ))
202+ else if ((transaction_progress == 4'd1 || transaction_progress == 4'd11 ) && transfer_start )
197203 begin
198204 sda_internal <= 1'b0 ;
199205 if (transaction_progress == 4'd11 ) // Hold time padding
200206 countdown <= COUNTER_HOLD_REPEATED_START - (COUNTER_END - COUNTER_RECEIVE );
201207 end
202208 // See Section 3.1.5. Shift in data.
203- else if (busy && transaction_progress >= 4'd2 && transaction_progress < 4'd10 && latched_mode)
209+ else if (transaction_progress >= 4'd2 && transaction_progress < 4'd10 && latched_mode)
204210 begin
205211 `ifdef MODEL_TECH
206212 latched_data[4'd9 - transaction_progress] <= sda === 1'bz ;
207213 `else
208214 latched_data[4'd9 - transaction_progress] <= sda;
209215 `endif
210- sda_internal <= 1'b1 ; // Helps reduce slave rise time
216+ sda_internal <= 1'b1 ; // Should help reduce slave rise time
211217 end
212218 // See Section 3.1.6. Transmitter got an acknowledge bit or receiver sent it.
213- // sda value must be ACK, agnostic of transmit/receive
214219 // transaction continues immediately in the next LOW, latch now
215220 // delayed by a clock here so that user input after transaction_complete can be ready
216- else if (busy && transaction_progress == 4'd10 && latched_transfer_continue && ! sda )
221+ else if (transaction_progress == 4'd10 && latched_transfer_continue)
217222 begin
218223 transaction_progress <= 4'd1 ;
219224 latched_mode <= mode;
@@ -222,18 +227,15 @@ begin
222227 latched_transfer_continue <= transfer_continue;
223228 end
224229 // STOP condition
225- else if (busy && transaction_progress == 4'd11 && ! sda )
230+ else if (transaction_progress == 4'd11 && ! transfer_start )
226231 begin
227232 sda_internal <= 1'b1 ;
228233 transaction_progress <= 4'd0 ;
229234 countdown <= COUNTER_BUS_FREE - (COUNTER_END - COUNTER_RECEIVE );
230235 end
231- // Another master is doing a transaction (void messages tolerated, see Note 5 in Section 3.1.10)
232- else if (busy && transaction_progress == 4'd0 && MULTI_MASTER )
233- sda_internal <= 1'b1 ;
234236 end
235237 // "The HIGH or LOW state of the data line can only change when the clock signal on the SCL line is LOW"
236- else if (counter == COUNTER_TRANSMIT && busy && transaction_progress != 4'd0 )
238+ else if (counter == COUNTER_TRANSMIT && transaction_progress != 4'd0 )
237239 begin
238240 transaction_progress <= transaction_progress + 4'd1 ;
239241 // See Section 3.1.5. Shift out data.
@@ -246,12 +248,10 @@ begin
246248 end
247249 // See Section 3.1.6. Expecting an acknowledge bit transfer in the next HIGH.
248250 else if (transaction_progress == 4'd9 )
249- sda_internal <= ! ( latched_mode && latched_transfer_continue) ; // receiver sends ACK / NACK, transmitter releases line
251+ sda_internal <= ! latched_mode || ! latched_transfer_continue; // receiver sends ACK / NACK, transmitter releases line
250252 // See Section 3.1.4
251253 else if (transaction_progress == 4'd10 )
252- begin
253254 sda_internal <= transfer_start; // prepare for repeated START condition or STOP condition
254- end
255255 end
256256end
257257
0 commit comments