Created
May 16, 2018 17:52
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It does not convert into VHDL:
It needed a SIgnal for
arbiter_position
.I would try to make such an arbiter using barrel rotate and shift.