Skip to content

Instantly share code, notes, and snippets.

@hgomersall
Created May 16, 2018 17:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hgomersall/ed0f553e3020507e0d554ab161514c29 to your computer and use it in GitHub Desktop.
Save hgomersall/ed0f553e3020507e0d554ab161514c29 to your computer and use it in GitHub Desktop.
A quick and dirty round robin arbiter in myhdl for demonstrating myhdls meta-programming capability. It's not tested, but shows the principles.
from myhdl import *
@block
def grant_selector(request, grant, request_bit):
if request_bit == 0:
@always_comb
def selector():
grant.next = request[request_bit]
else:
@always_comb
def selector():
if request[request_bit:] != 0:
grant.next = False
else:
grant.next = request[request_bit]
return selector
@block
def request_rotate(request, reordered_request, rotate):
bits = len(request)
if rotate > 0:
@always_comb
def reorder():
reordered_request.next[:rotate] = request[bits-rotate:]
reordered_request.next[rotate:] = request[:bits-rotate]
else:
@always_comb
def reorder():
reordered_request.next = request
return reorder
@block
def grant_derotate(grant, rotated_grant, rotate):
bits = len(grant)
if rotate > 0:
@always_comb
def reorder():
grant.next[bits-rotate:] = rotated_grant[:rotate]
grant.next[:bits-rotate] = rotated_grant[rotate:]
else:
@always_comb
def reorder():
grant.next = rotated_grant
return reorder
@block
def rr_arbiter(clk, req, grant):
'''The architecture here is we generate a list of rotated requests
(with associated block to do the rotation). The specific rotated request
is set by the arbiter_position index.
The grant bit is then set if all the lower bits than it in the rotated
request are not set, and that bit is.
Of course, that means the resultant grant bit vector is rotated, so we
need to derotate it. This is done by broadcasting to a set of signals
that are then each derotated, and the correct derotated signal is
selected using the arbiter_position index.
The policy is for arbiter_position index to increment on every cycle.
'''
n = len(req)
assert len(req) == len(grant)
arbiter_position = intbv(0, min=0, max=n)
rotated_reqs = [Signal(intbv(0)[n:]) for each in range(n)]
sel_rotators = []
for p, rotated_req in enumerate(rotated_reqs):
sel_rotators.append(request_rotate(req, rotated_req, p))
rot_grant_bits = [Signal(False) for each in range(n)]
current_rotated_req = Signal(intbv(0)[n:])
grant_selectors = []
for p, grant_bit in enumerate(rot_grant_bits):
grant_selectors.append(
grant_selector(current_rotated_req, grant_bit, p))
rotated_grant = Signal(intbv(0)[n:])
# We need to clone this to all the output rotations
rotated_grants = [Signal(intbv(0)[n:]) for each in range(n)]
# This maps to a set of grants which the multiplexor selects
grants = [Signal(intbv(0)[n:]) for each in range(n)]
grant_derotators = []
for p, (each_grant, each_rotated_grant) in enumerate(
zip(grants, rotated_grants)):
grant_derotators.append(
grant_derotate(each_grant, each_rotated_grant, p))
@always_comb
def assign_grant_bits():
for i in range(n):
rotated_grant[i].next = rot_grant_bits[i]
@always_comb
def assign_rotated_grants():
for i in range(n):
rotated_grants[i].next = rotated_grant
@always(clk.posedge)
def assign_req():
arbiter_position.next = arbiter_position + 1 % n
grant.next = grants[arbiter_position]
current_rotated_req.next = rotated_reqs[arbiter_position]
return (sel_rotators, grant_selectors, grant_derotators,
assign_grant_bits, assign_rotated_grants, assign_req)
def convert():
clk = Signal(False)
req = Signal(intbv(0)[4:])
grant = Signal(intbv(0)[4:])
inst = rr_arbiter(clk, req, grant)
inst.convert()
if __name__ == '__main__':
convert()
@josyb
Copy link

josyb commented May 31, 2018

It does not convert into VHDL:

  File "C:\Users\josy\myhdlsupport\issues\myhdl\conversion\_toVHDL.py", line 882, in setAttr
    self.SigAss = sig._name
AttributeError: 'intbv' object has no attribute '_name'

It needed a SIgnal for arbiter_position.

    arbiter_position = Signal(intbv(0, min=0, max=n))

I would try to make such an arbiter using barrel rotate and shift.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment