Case support + register bank generator
This commit is contained in:
parent
458cfc8623
commit
ec51f09c98
|
@ -46,5 +46,5 @@ class Divider:
|
|||
|
||||
d = Divider(32)
|
||||
f = d.GetFragment()
|
||||
o = verilog.Convert(f, {d.start_i, d.dividend_i, d.divisor_i}, {d.ready_o, d.quotient_o, d.remainder_o})
|
||||
o = verilog.Convert(f, {d.ready_o, d.quotient_o, d.remainder_o}, {d.start_i, d.dividend_i, d.divisor_i})
|
||||
print(o)
|
|
@ -0,0 +1,25 @@
|
|||
from migen.fhdl import structure as f
|
||||
from migen.fhdl import verilog
|
||||
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)
|
||||
|
||||
# input path
|
||||
gpio_in = f.Signal(f.BV(ninputs), name="gpio_in")
|
||||
gpio_in_s = f.Signal(f.BV(ninputs), name="gpio_in_s") # synchronizer
|
||||
incomb = [f.Assign(ifield.dev_we, 1)]
|
||||
insync = [f.Assign(gpio_in_s, gpio_in), f.Assign(ifield.dev_w, gpio_in_s)]
|
||||
inf = f.Fragment(incomb, insync)
|
||||
|
||||
bank = csrgen.Bank([oreg, ireg])
|
||||
f = bank.GetFragment() + inf
|
||||
i = bank.interface
|
||||
ofield.dev_r.name = "gpio_out"
|
||||
v = verilog.Convert(f, {i.d_o, ofield.dev_r}, {i.a_i, i.we_i, i.d_i, gpio_in})
|
||||
print(v)
|
|
@ -0,0 +1,72 @@
|
|||
from ..fhdl import structure as f
|
||||
from ..bus.csr import *
|
||||
from .description import *
|
||||
from functools import partial
|
||||
|
||||
class Bank:
|
||||
def __init__(self, description, address=0):
|
||||
self.description = description
|
||||
self.address = address
|
||||
self.interface = Slave()
|
||||
d = partial(f.Declare, self)
|
||||
d("_sel")
|
||||
|
||||
def GetFragment(self):
|
||||
a = f.Assign
|
||||
comb = []
|
||||
sync = []
|
||||
|
||||
comb.append(a(self._sel, self.interface.a_i[12:] == f.Constant(self.address, f.BV(4))))
|
||||
|
||||
nregs = len(self.description)
|
||||
nbits = f.BitsFor(nregs-1)
|
||||
|
||||
# Bus writes
|
||||
bwcases = []
|
||||
for i in range(nregs):
|
||||
reg = self.description[i]
|
||||
nfields = len(reg.fields)
|
||||
bwra = []
|
||||
for j in range(nfields):
|
||||
field = reg.fields[j]
|
||||
if field.access_bus == WRITE_ONLY or field.access_bus == READ_WRITE:
|
||||
bwra.append(a(field.storage, self.interface.d_i[j]))
|
||||
if bwra:
|
||||
bwcases.append((f.Constant(i, f.BV(nbits)), bwra))
|
||||
if bwcases:
|
||||
sync.append(f.If(self._sel & self.interface.we_i, [f.Case(self.interface.a_i[:nbits], bwcases)]))
|
||||
|
||||
# Bus reads
|
||||
brcases = []
|
||||
for i in range(nregs):
|
||||
reg = self.description[i]
|
||||
nfields = len(reg.fields)
|
||||
brs = []
|
||||
reg_readable = False
|
||||
for j in range(nfields):
|
||||
field = reg.fields[j]
|
||||
if field.access_bus == READ_ONLY or field.access_bus == READ_WRITE:
|
||||
brs.append(field.storage)
|
||||
reg_readable = True
|
||||
else:
|
||||
brs.append(f.Constant(0, f.bv(field.size)))
|
||||
if reg_readable:
|
||||
if len(brs) > 1:
|
||||
brcases.append((f.Constant(i, f.BV(nbits)), [a(self.interface.d_o, f.Cat(*brs))]))
|
||||
else:
|
||||
brcases.append((f.Constant(i, f.BV(nbits)), [a(self.interface.d_o, brs[0])]))
|
||||
if brcases:
|
||||
sync.append(a(self.interface.d_o, f.Constant(0, f.BV(32))))
|
||||
sync.append(f.If(self._sel, [f.Case(self.interface.a_i[:nbits], brcases)]))
|
||||
else:
|
||||
comb.append(a(self.interface.d_o, f.Constant(0, f.BV(32))))
|
||||
|
||||
# Device access
|
||||
for reg in self.description:
|
||||
for field in reg.fields:
|
||||
if field.access_dev == READ_ONLY or field.access_dev == READ_WRITE:
|
||||
comb.append(a(field.dev_r, field.storage))
|
||||
if field.access_dev == WRITE_ONLY or field.access_dev == READ_WRITE:
|
||||
sync.append(f.If(field.dev_we, [a(field.storage, field.dev_w)]))
|
||||
|
||||
return f.Fragment(comb, sync)
|
|
@ -0,0 +1,28 @@
|
|||
from ..fhdl import structure as f
|
||||
|
||||
class Register:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.fields = []
|
||||
|
||||
def AddField(self, f):
|
||||
self.fields.append(f)
|
||||
|
||||
(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
|
||||
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 = f.Signal(f.BV(self.size), fullname)
|
||||
if self.access_dev == READ_ONLY or self.access_dev == READ_WRITE:
|
||||
self.dev_r = f.Signal(f.BV(self.size), fullname + "_r")
|
||||
if self.access_dev == WRITE_ONLY or self.access_dev == READ_WRITE:
|
||||
self.dev_w = f.Signal(f.BV(self.size), fullname + "_w")
|
||||
self.dev_we = f.Signal(name=fullname + "_we")
|
||||
self.parent.AddField(self)
|
|
@ -44,6 +44,9 @@ def ListSignals(node):
|
|||
return set().union(*l)
|
||||
elif isinstance(node, If):
|
||||
return ListSignals(node.cond) | ListSignals(node.t) | ListSignals(node.f)
|
||||
elif isinstance(node, Case):
|
||||
l = list(map(lambda x: ListSignals(x[1]), node.cases))
|
||||
return ListSignals(node.test).union(*l).union(ListSignals(node.default))
|
||||
elif isinstance(node, Fragment):
|
||||
return ListSignals(node.comb) | ListSignals(node.sync)
|
||||
else:
|
||||
|
@ -64,6 +67,9 @@ def ListTargets(node):
|
|||
return set().union(*l)
|
||||
elif isinstance(node, If):
|
||||
return ListTargets(node.t) | ListTargets(node.f)
|
||||
elif isinstance(node, Case):
|
||||
l = list(map(lambda x: ListTargets(x[1]), node.cases))
|
||||
return ListTargets(node.default).union(*l)
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
|
@ -73,4 +79,4 @@ def InsertReset(rst, sl):
|
|||
for t in targets:
|
||||
if not t.variable:
|
||||
resetcode.append(Assign(t, t.reset))
|
||||
return If(rst == 1, resetcode, sl)
|
||||
return If(rst, resetcode, sl)
|
|
@ -195,9 +195,10 @@ class If:
|
|||
return r
|
||||
|
||||
class Case:
|
||||
def __init__(self, test, cases=[]):
|
||||
def __init__(self, test, cases=[], default=StatementList()):
|
||||
self.test = test
|
||||
self.cases = cases
|
||||
self.cases = [(c[0], _sl(c[1])) for c in cases]
|
||||
self.default = _sl(default)
|
||||
|
||||
#
|
||||
|
||||
|
@ -208,3 +209,6 @@ class Fragment:
|
|||
|
||||
def __str__(self):
|
||||
return "Comb:\n" + _indent(str(self.comb)) + "\nSync:\n" + _indent(str(self.sync))
|
||||
|
||||
def __add__(self, other):
|
||||
return Fragment(self.comb.l + other.comb.l, self.sync.l + other.sync.l)
|
|
@ -2,7 +2,7 @@ from .structure import *
|
|||
from .convtools import *
|
||||
from functools import partial
|
||||
|
||||
def Convert(f, ins, outs, name="top", clkname="sys_clk", rstname="sys_rst"):
|
||||
def Convert(f, outs=set(), ins=set(), name="top", clkname="sys_clk", rstname="sys_rst"):
|
||||
ns = Namespace()
|
||||
|
||||
clks = Signal(name=clkname)
|
||||
|
@ -50,13 +50,21 @@ def Convert(f, ins, outs, name="top", clkname="sys_clk", rstname="sys_rst"):
|
|||
elif isinstance(node, StatementList):
|
||||
return "".join(list(map(partial(printnode, level), node.l)))
|
||||
elif isinstance(node, If):
|
||||
r = "\t"*level + "if " + printnode(level, node.cond) + " begin\n"
|
||||
r = "\t"*level + "if (" + printnode(level, node.cond) + ") begin\n"
|
||||
r += printnode(level + 1, node.t)
|
||||
if node.f.l:
|
||||
r += "\t"*level + "end else begin\n"
|
||||
r += printnode(level + 1, node.f)
|
||||
r += "\t"*level + "end\n"
|
||||
return r
|
||||
elif isinstance(node, Case):
|
||||
r = "\t"*level + "case (" + printnode(level, node.test) + ")\n"
|
||||
for case in node.cases:
|
||||
r += "\t"*(level + 1) + printnode(level, case[0]) + ": begin\n"
|
||||
r += printnode(level + 2, case[1])
|
||||
r += "\t"*(level + 1) + "end\n"
|
||||
r += "\t"*level + "endcase\n"
|
||||
return r
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
|
|
Loading…
Reference in New Issue