@@ -249,7 +249,12 @@ case class Axi4Master(axi: Axi4, clockDomain: ClockDomain, name: String = "unnam
249
249
case _ => data.take(bytes)
250
250
}
251
251
val remaining = data.drop(slice.length)
252
- writeSingle(addr, slice, id, burst, len, size)(handleTransaction(addr, transactionId, remaining))
252
+ val thisLen = if (remaining.length == 0 ) {
253
+ ((slice.length / bytePerBeat.toFloat).ceil.toInt - 1 ) min len
254
+ } else {
255
+ len
256
+ }
257
+ writeSingle(addr, slice, id, burst, thisLen, size)(handleTransaction(addr, transactionId, remaining))
253
258
}
254
259
255
260
def handleTransaction (addr : BigInt , transactionId : Int , remaining : List [Byte ])() = {
@@ -273,40 +278,38 @@ case class Axi4Master(axi: Axi4, clockDomain: ClockDomain, name: String = "unnam
273
278
}
274
279
assert(len <= 255 , s " max burst in one transaction is 256 " )
275
280
val bytePerBeat = 1 << size
276
- val actualLen = ((data.length / bytePerBeat.toFloat).ceil.toInt - 1 ) min len
277
- val bytes = (actualLen + 1 ) * bytePerBeat
281
+ val bytes = (len + 1 ) * bytePerBeat
278
282
val bytePerBus = 1 << log2Up(busConfig.dataWidth / 8 )
279
283
280
284
val (roundedAddress, padFront, padBack, paddedData) = padData(address, data)
281
- assert(
282
- paddedData.length <= bytes,
283
- s " requested length ${data.length} ( ${paddedData.length} with padding) could not be completed in one transaction "
284
- )
285
+ assert(data.length <= (len + 1 ) * bytePerBeat, " data is too long and cannot be sent in one transaction" )
286
+ assert(data.length >= len * bytePerBeat, f " data is too short ( ${data.length}) for len= $len (would result in erroneous zero transfers) " )
287
+ assert(paddedData.length <= bytes, s " requested length ${data.length} ( ${paddedData.length} with padding) could not be completed in one transaction " )
285
288
286
289
awQueue += { aw =>
287
290
aw.addr #= roundedAddress
288
291
if (busConfig.useId) aw.id #= id
289
- if (busConfig.useLen) aw.len #= actualLen
292
+ if (busConfig.useLen) aw.len #= len
290
293
if (busConfig.useSize) aw.size #= size
291
294
if (busConfig.useBurst) aw.burst #= burst.id
292
- log(" AW" , f " addr $roundedAddress%#x size $size len $actualLen burst $burst" )
295
+ log(" AW" , f " addr $roundedAddress%#x size $size len $len burst $burst" )
293
296
294
- for (beat <- 0 to actualLen ) {
297
+ for (beat <- 0 to len ) {
295
298
wQueue += { w =>
296
299
val data = paddedData.slice(beat * bytePerBeat, (beat + 1 ) * bytePerBeat)
297
300
w.data #= data.toArray
298
301
val fullStrb = (BigInt (1 ) << bytePerBeat) - 1
299
- val strb = (if (actualLen == 0 ) {
302
+ val strb = (if (len == 0 ) {
300
303
((BigInt (1 ) << data.length) - 1 ) << padFront
301
304
} else
302
305
beat match {
303
- case 0 => fullStrb << padFront
304
- case `actualLen ` => fullStrb >> padBack
305
- case _ => fullStrb
306
+ case 0 => fullStrb << padFront
307
+ case `len ` => fullStrb >> padBack
308
+ case _ => fullStrb
306
309
}) & fullStrb
307
310
if (busConfig.useStrb) w.strb #= strb
308
- if (busConfig.useLast) w.last #= beat == actualLen
309
- log(" W" , f " data ${data.reverse.bytesToHex} strb $strb%#x last ${beat == actualLen }" )
311
+ if (busConfig.useLast) w.last #= beat == len
312
+ log(" W" , f " data ${data.reverse.bytesToHex} strb $strb%#x last ${beat == len }" )
310
313
}
311
314
}
312
315
0 commit comments