diff --git a/examples/simple_gpio.py b/examples/simple_gpio.py index e0d1c6b8d..426df02cc 100644 --- a/examples/simple_gpio.py +++ b/examples/simple_gpio.py @@ -5,21 +5,18 @@ from migen.bank import description, csrgen 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) diff --git a/migen/bank/csrgen.py b/migen/bank/csrgen.py index b732e162a..894579350 100644 --- a/migen/bank/csrgen.py +++ b/migen/bank/csrgen.py @@ -20,7 +20,12 @@ class Bank: # 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: @@ -28,17 +33,16 @@ class Bank: 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): @@ -53,7 +57,7 @@ class Bank: 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))) @@ -62,11 +66,11 @@ class Bank: # 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) diff --git a/migen/bank/description.py b/migen/bank/description.py index 102deff01..14d2d136d 100644 --- a/migen/bank/description.py +++ b/migen/bank/description.py @@ -1,34 +1,34 @@ 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])