-
Hi @jerryz123, Re #1380: I'm going through the RoCC-to-NoC example, since I need to do something similar, and I'm writing down my own notes for each line of code to make sure I understand it. Looking at this section: for ((hartId, index) <- hartMappings.keys.zipWithIndex) {
val beat = RegInit(0.U(1.W))
val ingress = ingresses(index)
val source = Queue(ron_io.from_source(index), 2)
ingress.flit.valid := source.valid
ingress.flit.bits.payload := source.bits.wdata >> (beat << 5)
ingress.flit.bits.head := beat === 0.U
ingress.flit.bits.tail := beat === 1.U
ingress.flit.bits.egress_id := source.bits.sink_hartid
source.ready := ingress.flit.ready && beat === 1.U
when (ingress.flit.fire()) { beat := Mux(beat === 1.U, 0.U, beat + 1.U) }
} Most of it makes sense to me, but I'm stuck on
EDIT: second question: Why is there a 2-long Queue for the ingress/source logic, but no Queue for the egress/sink logic? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The example assumes packets have fixed size of 2 flits. So a packet can only be dequeued from the source queue when the seconf flit fires This bit of logic is converting each source message into a 2-flit packet, so each source.fire has to generate 2 ingress.flit.fire.
On the ingress side, the packet-to-flit conversion requires that the input is actually a Irrevocable decoupled interface, which means that once source.valid is asserted, source.bits cannot change. The 2 entry queue acts like a latch on the source bits. I think the minimal implementation would actually make it a 1-entry Queue with flow=true and pipe=true. |
Beta Was this translation helpful? Give feedback.
The example assumes packets have fixed size of 2 flits. So a packet can only be dequeued from the source queue when the seconf flit fires
(ingress.flit.ready && beat === 1.U)
.This bit of logic is converting each source message into a 2-flit packet, so each source.fire has to generate 2 ingress.flit.fire.