Skip to content

Commit

Permalink
bank: support direct mapping of CSRs on Wishbone
Browse files Browse the repository at this point in the history
sbourdeauducq committed Nov 30, 2014
1 parent ee928a8 commit ae770c0
Showing 3 changed files with 60 additions and 30 deletions.
23 changes: 23 additions & 0 deletions migen/bank/bank.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from migen.fhdl.std import Module, bits_for
from migen.bank.description import CSR

class GenericBank(Module):
def __init__(self, description, busword):
# Turn description into simple CSRs and claim ownership of compound CSR modules
self.simple_csrs = []
for c in description:
if isinstance(c, CSR):
self.simple_csrs.append(c)
else:
c.finalize(busword)
self.simple_csrs += c.get_simple_csrs()
self.submodules += c
self.decode_bits = bits_for(len(self.simple_csrs)-1)

def get_offset(description, name, busword):
offset = 0
for c in description:
if c.name == name:
return offset
offset += (c.size + busword - 1)//busword
raise KeyError("CSR not found: "+name)
41 changes: 11 additions & 30 deletions migen/bank/csrgen.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,33 @@
from migen.util.misc import xdir
from migen.fhdl.std import *
from migen.bus import csr
from migen.bank.description import *
from migen.bank.bank import GenericBank

def get_offset(description, name, csr_data_width=8):
offset = 0
for c in description:
if c.name == name:
return offset
offset += (c.size + csr_data_width - 1)//csr_data_width
raise KeyError("CSR not found: "+name)

class Bank(Module):
class Bank(GenericBank):
def __init__(self, description, address=0, bus=None):
if bus is None:
bus = csr.Interface()
self.bus = bus

###

if not description:
return

# Turn description into simple CSRs and claim ownership of compound CSR modules
simple_csrs = []
for c in description:
if isinstance(c, CSR):
simple_csrs.append(c)
else:
c.finalize(flen(self.bus.dat_w))
simple_csrs += c.get_simple_csrs()
self.submodules += c
nbits = bits_for(len(simple_csrs)-1)
GenericBank.__init__(self, description, flen(self.bus.dat_w))

# Decode selection
sel = Signal()
self.comb += sel.eq(self.bus.adr[9:] == address)

# Bus writes
for i, c in enumerate(simple_csrs):
for i, c in enumerate(self.simple_csrs):
self.comb += [
c.r.eq(self.bus.dat_w[:c.size]),
c.re.eq(sel & \
self.bus.we & \
(self.bus.adr[:nbits] == i))
(self.bus.adr[:self.decode_bits] == i))
]

# Bus reads
brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(simple_csrs))
brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs))
self.sync += [
self.bus.dat_r.eq(0),
If(sel, Case(self.bus.adr[:nbits], brcases))
If(sel, Case(self.bus.adr[:self.decode_bits], brcases))
]

# address_map(name, memory) returns the CSR offset at which to map
@@ -77,13 +54,17 @@ def scan(self, ifargs, ifkwargs):
memories = obj.get_memories()
for memory in memories:
mapaddr = self.address_map(name, memory)
if mapaddr is None:
continue
sram_bus = csr.Interface(*ifargs, **ifkwargs)
mmap = csr.SRAM(memory, mapaddr, bus=sram_bus)
self.submodules += mmap
csrs += mmap.get_csrs()
self.srams.append((name, memory, mapaddr, mmap))
if csrs:
mapaddr = self.address_map(name, None)
if mapaddr is None:
continue
bank_bus = csr.Interface(*ifargs, **ifkwargs)
rmap = Bank(csrs, mapaddr, bus=bank_bus)
self.submodules += rmap
26 changes: 26 additions & 0 deletions migen/bank/wbgen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from migen.fhdl.std import *
from migen.bus import wishbone
from migen.bank.bank import GenericBank

class Bank(GenericBank):
def __init__(self, description, bus=None):
if bus is None:
bus = wishbone.Interface()
self.bus = bus

###

GenericBank.__init__(self, description, flen(self.bus.dat_w))

for i, c in enumerate(self.simple_csrs):
self.comb += [
c.r.eq(self.bus.dat_w[:c.size]),
c.re.eq(self.bus.cyc & self.bus.stb & ~self.bus.ack & self.bus.we & \
(self.bus.adr[:self.decode_bits] == i))
]

brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs))
self.sync += [
Case(self.bus.adr[:self.decode_bits], brcases),
If(bus.ack, bus.ack.eq(0)).Elif(bus.cyc & bus.stb, bus.ack.eq(1))
]

0 comments on commit ae770c0

Please sign in to comment.