Skip to content

Arbiter

Muhammad Hadir Khan edited this page Aug 31, 2020 · 2 revisions

This page is dedicated for the implementation of a fixed priority arbiter. The host connected with the lowest index port of the Arbiter is given the priority.

class Arbiter(M: Int)(implicit val conf: TLConfiguration) extends Module {
  val io = IO(new Bundle {
    val req_i = Input(Vec(M, Bool())) // a_valid signals coming from all the hosts
    val data_i = Vec(M, Flipped(new TL_H2D))  // Channel A data coming from all the hosts
    val gnt_o = Output(Vec(M, Bool()))  // The grant output used for indicating the host that the device is ready to accept the request
    val valid_o = Output(Bool())  // The valid signal from the host to the device
    val data_o = new TL_H2D // The Channel A data of selected host forwarded to the device
    val ready_i = Input(Bool()) // The ready signal coming from the device
  })

As discussed in the M:1 Socket description where this module is actually used, the Arbiter takes:

  • req_i input which is a bundle of wires that contain a_valid signals coming from M hosts.
  • data_i input which is bundle of Channel A bundles (TL_H2D) coming from M hosts.
  • gnt_o output which is a bundle of wires connected to M hosts indicating them whether the device is ready to accept their request or not.
  • valid_o output connected with the device which indicates a valid request is being sent from the host.
  • data_o output which is a Channel A bundle of the selected host.
  • ready_i input which is a signal coming in from the device indicating it is ready to accept a request.
// by default setting the arbiter to pass the request of last host
io.data_o <> io.data_i(M-1)
io.valid_o := io.req_i(M-1)
io.gnt_o(M-1) := Mux(io.ready_i, Mux(io.req_i(M-1), true.B, false.B), false.B)

Here we are by default setting up the last host with the output of the Arbiter to be connected with the device. The data_o is wired with the last host's TL_H2D bundle with data_i(M-1). Similarly, the valid_o of the Arbiter is connected with the valid request of the last host req_i(M-1) by default and the gnt_o of the last host gnt_o(M-1) is connected with the following logic:

Mux(io.ready_i, Mux(io.req_i(M-1), true.B, false.B), false.B)

This first checks if the ready_i is high indicating that device is ready to accept the request:

If true:
  Checks if the valid of last host `req_i(M-1)` is high:
    If true:
      Sets the `gnt_o` to true
    else:
      Sets the `gnt_o` to false

else:
  It means the device is not ready to accept the request so wire the `gnt_o` with false.

This concludes the default setup of the Arbiter which sets the connections of the last host with the device.

for(i <- M-2 to 0 by -1) {
    when(io.req_i(i)) {
      io.gnt_o(i) := Mux(io.ready_i, true.B, false.B)
      io.data_o := io.data_i(i)
      io.valid_o := io.req_i(i)
    } .otherwise {
      io.gnt_o(i) := false.B
    }
  }

Then we loop over the remaining hosts M-2 and see if their valid signals coming in to req_i are high or not:

If true:
  Connect the `data_o` of the Arbiter with the `data_i` of that specific host.
  Connect the `valid_o` of the Arbiter with the `req_i` of that specific host.
  Check whether device is ready to accept the request with `ready_i`:
    If true:
      Set the `gnt_o` of that specific host to true.
    else:
      Set the `gnt_o` of that specific host to false.
else:
  Set the `gnt_o` of that specific host to false.

So what happens is that let's assume we have 4 hosts: host(0), host(1), host(2) and host(3). By default the Arbiter connects host(3) with the device. Then we loop over from host(2) till host(0) and see if their valid signals req_i are high. So if host(2) has it's valid signal set which means it wants to access the device then the when block gets executed and we connect the host(2) with the Arbiter's output and eventually with the device. Next we again loop and assume if host(1) also wants to send a request to the device and it's req_i is also high. Again the when block gets executed and we connect the Arbiter's output with the host(1) signals. The same process goes on if the host(0)'s valid signal is also high which means in the end when the for loop ends the host with the lowest index is given the highest priority.

Clone this wiki locally