bus/csr: add SRAM
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 6 Dec 2012 16:16:17 +0000 (17:16 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 6 Dec 2012 16:16:17 +0000 (17:16 +0100)
migen/bus/csr.py

index df2543482af08916fb5ab0b66a1ecd9ec0087190..3200fb5e66f5c57a0fdb74ee24ea837766914072 100644 (file)
@@ -2,6 +2,7 @@ from migen.fhdl.structure import *
 from migen.bus.simple import *
 from migen.bus.transactions import *
 from migen.sim.generic import PureSimulable
+from migen.bank.description import RegisterField
 
 data_width = 8
 
@@ -40,3 +41,56 @@ class Initiator(PureSimulable):
                                if isinstance(self.transaction, TWrite):
                                        s.wr(self.bus.we, 1)
                                        s.wr(self.bus.dat_w, self.transaction.data)
+
+def _compute_page_bits(nwords):
+       npages = (nwords - 1)//512
+       if npages > 0:
+               return bits_for(npages-1)
+       else:
+               return 0
+
+class SRAM:
+       def __init__(self, mem_or_size, address, bus=Interface()):
+               if isinstance(mem_or_size, Memory):
+                       assert(mem_or_size.width <= data_width)
+                       self.mem = mem_or_size
+               else:
+                       self.mem = Memory(data_width, mem_or_size//(data_width//8))
+               self.address = address
+               page_bits = _compute_page_bits(self.mem.depth)
+               if page_bits:
+                       self._page = RegisterField("page", page_bits)
+               else:
+                       self._page = None
+               self.bus = bus
+       
+       def get_registers(self):
+               if self._page is None:
+                       return []
+               else:
+                       return [self._page]
+       
+       def get_fragment(self):
+               port = self.mem.get_port(write_capable=True)
+               
+               sel = Signal()
+               sel_r = Signal()
+               sync = [sel_r.eq(sel)]
+               
+               comb = [
+                       sel.eq(self.bus.adr[9:] == self.address),
+                       port.we.eq(sel & self.bus.we),
+                       
+                       port.dat_w.eq(self.bus.dat_w),
+                       If(sel_r,
+                               self.bus.dat_r.eq(port.dat_r)
+                       )
+               ]
+               
+               if self._page is None:
+                       comb.append(port.adr.eq(self.bus.adr[:len(port.adr)]))
+               else:
+                       pv = self._page.field.r
+                       comb.append(port.adr.eq(Cat(self.bus.adr[:len(port.adr)-len(pv)], pv)))
+               
+               return Fragment(comb, sync, memories=[self.mem])