ninputs = 4
noutputs = 4
-oreg = description.Register("o")
-ofield = description.Field(oreg, "val", noutputs)
-ireg = description.Register("i")
-ifield = description.Field(ireg, "val", ninputs, description.READ_ONLY, description.WRITE_ONLY)
+oreg = description.RegisterField("o", noutputs)
+ireg = description.RegisterRaw("i", ninputs)
# input path
gpio_in = Signal(BV(ninputs))
gpio_in_s = Signal(BV(ninputs)) # synchronizer
-incomb = [ifield.dev_we.eq(1)]
-insync = [gpio_in_s.eq(gpio_in), ifield.dev_w.eq(gpio_in_s)]
-inf = Fragment(incomb, insync)
+insync = [gpio_in_s.eq(gpio_in), ireg.w.eq(gpio_in_s)]
+inf = Fragment(sync=insync)
bank = csrgen.Bank([oreg, ireg])
f = bank.get_fragment() + inf
+oreg.field.r.name_override = "gpio_out"
i = bank.interface
-ofield.dev_r.name_override = "gpio_out"
-v = verilog.convert(f, {i.d_o, ofield.dev_r, i.a_i, i.we_i, i.d_i, gpio_in})
+v = verilog.convert(f, {i.d_o, oreg.field.r, i.a_i, i.we_i, i.d_i, gpio_in})
print(v)
# Bus writes
bwcases = []
for i, reg in enumerate(self.description):
- if reg.raw is None:
+ if isinstance(reg, RegisterRaw):
+ comb.append(reg.r.eq(self.interface.d_i[:reg.size]))
+ comb.append(reg.re.eq(sel & \
+ self.interface.we_i & \
+ (self.interface.a_i[:nbits] == Constant(i, BV(nbits)))))
+ elif isinstance(reg, RegisterFields):
bwra = [Constant(i, BV(nbits))]
for j, field in enumerate(reg.fields):
if field.access_bus == WRITE_ONLY or field.access_bus == READ_WRITE:
if len(bwra) > 1:
bwcases.append(bwra)
else:
- comb.append(reg.dev_r.eq(self.interface.d_i[:reg.raw.width]))
- comb.append(reg.dev_re.eq(sel & \
- self.interface.we_i & \
- (self.interface.a_i[:nbits] == Constant(i, BV(nbits)))))
+ raise TypeError
if bwcases:
sync.append(If(sel & self.interface.we_i, Case(self.interface.a_i[:nbits], *bwcases)))
# Bus reads
brcases = []
for i, reg in enumerate(self.description):
- if reg.raw is None:
+ if isinstance(reg, RegisterRaw):
+ brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(reg.w)])
+ elif isinstance(reg, RegisterFields):
brs = []
reg_readable = False
for j, field in enumerate(reg.fields):
else:
brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(brs[0])])
else:
- brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(reg.dev_w)])
+ raise TypeError
if brcases:
sync.append(self.interface.d_o.eq(Constant(0, BV(8))))
sync.append(If(sel, Case(self.interface.a_i[:nbits], *brcases)))
# Device access
for reg in self.description:
- if reg.raw is None:
+ if isinstance(reg, RegisterFields):
for field in reg.fields:
if field.access_dev == READ_ONLY or field.access_dev == READ_WRITE:
- comb.append(field.dev_r.eq(field.storage))
+ comb.append(field.r.eq(field.storage))
if field.access_dev == WRITE_ONLY or field.access_dev == READ_WRITE:
- sync.append(If(field.dev_we, field.storage.eq(field.dev_w)))
+ sync.append(If(field.we, field.storage.eq(field.w)))
return Fragment(comb, sync)
from migen.fhdl.structure import *
-class Register:
- def __init__(self, name, raw=None):
+class RegisterRaw:
+ def __init__(self, name, size=1):
self.name = name
- self.raw = raw
- if raw is not None:
- self.dev_re = Signal(name=name + "_re")
- self.dev_r = Signal(raw, name + "_r")
- self.dev_w = Signal(raw, name + "_w")
- else:
- self.fields = []
-
- def add_field(self, f):
- self.fields.append(f)
+ self.size = size
+ self.re = Signal()
+ self.r = Signal(BV(self.size))
+ self.w = Signal(BV(self.size))
(READ_ONLY, WRITE_ONLY, READ_WRITE) = range(3)
class Field:
- def __init__(self, parent, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0):
- self.parent = parent
+ def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0):
self.name = name
self.size = size
self.access_bus = access_bus
self.access_dev = access_dev
- self.reset = reset
- fullname = parent.name + "_" + name
- self.storage = Signal(BV(self.size), fullname)
+ self.storage = Signal(BV(self.size), reset=reset)
if self.access_dev == READ_ONLY or self.access_dev == READ_WRITE:
- self.dev_r = Signal(BV(self.size), fullname + "_r")
+ self.r = Signal(BV(self.size))
if self.access_dev == WRITE_ONLY or self.access_dev == READ_WRITE:
- self.dev_w = Signal(BV(self.size), fullname + "_w")
- self.dev_we = Signal(name=fullname + "_we")
- self.parent.add_field(self)
+ self.w = Signal(BV(self.size))
+ self.we = Signal()
+
+class RegisterFields:
+ def __init__(self, name, fields):
+ self.name = name
+ self.fields = fields
+
+class RegisterField(RegisterFields):
+ def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0):
+ self.field = Field(name, size, access_bus, access_dev, reset)
+ RegisterFields.__init__(self, name, [self.field])