Gowin Vol.3 第2部第3章 リスト5

class UdpLoopback(config: EthernetServiceConfig = EthernetServiceConfig.default(), streamWidth: Int = 1) extends Module {
val io = IO(new Bundle {
val port = new UdpServicePort(streamWidth)
})

object State extends ChiselEnum {
val Idle, Sending = Value
}

val state = RegInit(State.Idle)
val udpContext = Reg(new UdpContext)

val udpReceiveContextReady = WireDefault(false.B)
io.port.udpReceiveContext.ready := udpReceiveContextReady

val udpSendContextValid = RegInit(false.B)
io.port.udpSendContext.valid := udpSendContextValid
io.port.udpSendContext.bits := udpContext

// データのキュー (2048オクテット分)
val queue = Module(new PacketQueue(Flushable((streamWidth*8).W), 2048))
queue.io.write.valid <> io.port.udpReceiveData.valid
queue.io.write.ready <> io.port.udpReceiveData.ready
queue.io.write.bits.data <> io.port.udpReceiveData.bits.data
queue.io.write.bits.last <> io.port.udpReceiveData.bits.last
queue.io.read.valid <> io.port.udpSendData.valid
queue.io.read.ready <> io.port.udpSendData.ready
queue.io.read.bits.data <> io.port.udpSendData.bits.data
queue.io.read.bits.last <> io.port.udpSendData.bits.last
io.port.udpSendData.bits.keep := 1.U

when(udpSendContextValid && io.port.udpSendContext.ready) {
udpSendContextValid := false.B
}

udpReceiveContextReady := !udpSendContextValid
when( io.port.udpReceiveContext.valid && udpReceiveContextReady ) {
// Store UDP context with swapping source <-> destination
udpContext.dataLength := io.port.udpReceiveContext.bits.dataLength
udpContext.sourceAddress := io.port.udpReceiveContext.bits.destinationAddress
udpContext.sourcePort := io.port.udpReceiveContext.bits.destinationPort
udpContext.sourceMacAddress := io.port.udpReceiveContext.bits.destinationMacAddress
udpContext.destinationAddress := io.port.udpReceiveContext.bits.sourceAddress
udpContext.destinationPort := io.port.udpReceiveContext.bits.sourcePort
udpContext.destinationMacAddress := io.port.udpReceiveContext.bits.sourceMacAddress
udpSendContextValid := true.B
state := State.Sending
}
}