Hello, everybody. I have been trying to create a bus arbiter module to externally set an “access granted” flag for each device in a list. I ended up writing following code:
#bus.py
from myhdl import *
# Grants access to a device with lowest index in a list if it's request flag is set
def arbiter(clk, devices):
request_list = [ device.request for device in devices ]
request_vector = ConcatSignal(*reversed(request_list))
grant_list = [ device.grant for device in devices ]
grant_vector = ConcatSignal(*reversed(grant_list))
@always(clk.posedge)
def logic():
grant_vector.next = request_vector & (-request_vector)
# Also tried this:
# for i, device in enumerate(devices):
# device.grant.next = grant_vector[i]
return instances(), grant_vector
#test module
from myhdl import *
from bus import arbiter
# Device template, should increment it's counter if allowed by an arbiter.
# Implementation only tests the arbiter, nothing useful yet
class Device:
def __init__(self):
self.request = Signal(bool())
self.grant = Signal(bool())
def instance(self, clk):
counter = Signal(intbv())
@always(clk.posedge)
def logic():
if self.grant == 1:
counter.next = counter + 2
self.request.next = 1
return instances()
clk = Signal(bool())
devices = [ Device(), Device() ]
def top(clk):
a = arbiter(clk, devices)
di = [ device.instance(clk) for device in devices ]
return instances()
toVerilog(top, clk)
This results in an invalid conversion to Verilog:
// File: top.v
// Generated by MyHDL 0.9.0
// Date: Tue Jan 2 21:14:46 2018
`timescale 1ns/10ps
module top (
clk
);
input clk;
always @(posedge clk) begin: MYHDL1_BLOCK
if ((False == 1)) begin
0 <= (0 + 1);
end
False <= 1;
end
always @(posedge clk) begin: MYHDL2_BLOCK
if ((False == 1)) begin
0 <= (0 + 1);
end
False <= 1;
end
endmodule
I wanted grant to be a wire that is set by the arbiter on the same cycle, so the device can understand if it is allowed to use a shared resource. It should scale up to any reasonable number of devices. However, it doesn’t seem to work. Maybe because of indirect access to a signal? If it is the cause, then it will be hard to build scaleable hardware designs. Nobody would want their arbiter code to merge with a “Device” logic, so some kind of abstraction is needed.
I’ve got following response:
grant_vector = ConcatSignal(*reversed(grant_list))
grant_vector is a ShadowSignal and cannot be assigned to.
use a Signal(intbv()) insteadgrant_vector = Signal(intbv(0)[len(request_list):])
You then still have to assign each bit of this vector to the grant-bit in its respective Device.
Then I changed arbiter code as follows:
from myhdl import *
def arbiter(clk, devices):
request_list = [ device.request for device in devices ]
request_vector = ConcatSignal(*reversed(request_list))
grant_vector = Signal(intbv(0)[len(request_vector):])
grant_list = [ device.grant for device in reversed(devices) ]
@always(clk.posedge)
def logic():
grant_vector.next = request_vector & (-request_vector)
for i, grant in enumerate(grant_list):
grant.next = grant_vector[i]
return instances()
Unfortunaltely, this doesn’t seem to work and I don’t really know how to set bits in devices properly.
myhdl.ConversionError: in file D:\Projects\CPU\bus.py, line 12:
Not supported: tuple assignment
Thanks in advance.