Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f75a0163f9ed
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 94e8f479a5ac
Choose a head ref
  • 1 commit
  • 5 files changed
  • 1 contributor

Commits on Jul 1, 2019

  1. hdl.mem: use read_port(domain="comb") for asynchronous read ports.

    This avoids the absurdity of the combination of arguments that is
    read_port(domain="sync", synchronous=True).
    
    Fixes #116.
    whitequark committed Jul 1, 2019
    Copy the full SHA
    94e8f47 View commit details
Showing with 20 additions and 23 deletions.
  1. +13 −14 nmigen/hdl/mem.py
  2. +1 −1 nmigen/lib/fifo.py
  3. +3 −6 nmigen/test/test_hdl_mem.py
  4. +1 −1 nmigen/test/test_lib_fifo.py
  5. +2 −1 nmigen/test/test_sim.py
27 changes: 13 additions & 14 deletions nmigen/hdl/mem.py
Original file line number Diff line number Diff line change
@@ -52,10 +52,10 @@ def init(self, new_init):
raise TypeError("Memory initialization value at address {:x}: {}"
.format(addr, e)) from None

def read_port(self, domain="sync", synchronous=True, transparent=True):
if not synchronous and not transparent:
def read_port(self, domain="sync", transparent=True):
if domain == "comb" and not transparent:
raise ValueError("Read port cannot be simultaneously asynchronous and non-transparent")
return ReadPort(self, domain, synchronous, transparent)
return ReadPort(self, domain, transparent)

def write_port(self, domain="sync", priority=0, granularity=None):
if granularity is None:
@@ -77,17 +77,16 @@ def __getitem__(self, index):


class ReadPort(Elaboratable):
def __init__(self, memory, domain, synchronous, transparent):
def __init__(self, memory, domain, transparent):
self.memory = memory
self.domain = domain
self.synchronous = synchronous
self.transparent = transparent

self.addr = Signal(max=memory.depth,
name="{}_r_addr".format(memory.name))
self.data = Signal(memory.width,
name="{}_r_data".format(memory.name))
if synchronous and not transparent:
if self.domain != "comb" and not transparent:
self.en = Signal(name="{}_r_en".format(memory.name))
else:
self.en = Const(1)
@@ -97,23 +96,27 @@ def elaborate(self, platform):
p_MEMID=self.memory,
p_ABITS=self.addr.nbits,
p_WIDTH=self.data.nbits,
p_CLK_ENABLE=self.synchronous,
p_CLK_ENABLE=self.domain != "comb",
p_CLK_POLARITY=1,
p_TRANSPARENT=self.transparent,
i_CLK=ClockSignal(self.domain) if self.synchronous else Const(0),
i_CLK=ClockSignal(self.domain) if self.domain != "comb" else Const(0),
i_EN=self.en,
i_ADDR=self.addr,
o_DATA=self.data,
)
if self.synchronous and not self.transparent:
if self.domain == "comb":
# Asynchronous port
f.add_statements(self.data.eq(self.memory._array[self.addr]))
f.add_driver(self.data)
elif not self.transparent:
# Synchronous, read-before-write port
f.add_statements(
Switch(self.en, {
1: self.data.eq(self.memory._array[self.addr])
})
)
f.add_driver(self.data, self.domain)
elif self.synchronous:
else:
# Synchronous, write-through port
# This model is a bit unconventional. We model transparent ports as asynchronous ports
# that are latched when the clock is high. This isn't exactly correct, but it is very
@@ -134,10 +137,6 @@ def elaborate(self, platform):
)
f.add_driver(latch_addr, self.domain)
f.add_driver(self.data)
else:
# Asynchronous port
f.add_statements(self.data.eq(self.memory._array[self.addr]))
f.add_driver(self.data)
return f


2 changes: 1 addition & 1 deletion nmigen/lib/fifo.py
Original file line number Diff line number Diff line change
@@ -151,7 +151,7 @@ def elaborate(self, platform):
storage = Memory(self.width, self.depth)
wrport = m.submodules.wrport = storage.write_port()
rdport = m.submodules.rdport = storage.read_port(
synchronous=not self.fwft, transparent=self.fwft)
domain="comb" if self.fwft else "sync", transparent=self.fwft)
produce = Signal(max=self.depth)
consume = Signal(max=self.depth)

9 changes: 3 additions & 6 deletions nmigen/test/test_hdl_mem.py
Original file line number Diff line number Diff line change
@@ -45,7 +45,6 @@ def test_read_port_transparent(self):
rdport = mem.read_port()
self.assertEqual(rdport.memory, mem)
self.assertEqual(rdport.domain, "sync")
self.assertEqual(rdport.synchronous, True)
self.assertEqual(rdport.transparent, True)
self.assertEqual(len(rdport.addr), 2)
self.assertEqual(len(rdport.data), 8)
@@ -58,17 +57,15 @@ def test_read_port_non_transparent(self):
rdport = mem.read_port(transparent=False)
self.assertEqual(rdport.memory, mem)
self.assertEqual(rdport.domain, "sync")
self.assertEqual(rdport.synchronous, True)
self.assertEqual(rdport.transparent, False)
self.assertEqual(len(rdport.en), 1)
self.assertIsInstance(rdport.en, Signal)

def test_read_port_asynchronous(self):
mem = Memory(width=8, depth=4)
rdport = mem.read_port(synchronous=False)
rdport = mem.read_port(domain="comb")
self.assertEqual(rdport.memory, mem)
self.assertEqual(rdport.domain, "sync")
self.assertEqual(rdport.synchronous, False)
self.assertEqual(rdport.domain, "comb")
self.assertEqual(rdport.transparent, True)
self.assertEqual(len(rdport.en), 1)
self.assertIsInstance(rdport.en, Const)
@@ -78,7 +75,7 @@ def test_read_port_wrong(self):
mem = Memory(width=8, depth=4)
with self.assertRaises(ValueError,
msg="Read port cannot be simultaneously asynchronous and non-transparent"):
mem.read_port(synchronous=False, transparent=False)
mem.read_port(domain="comb", transparent=False)

def test_write_port(self):
mem = Memory(width=8, depth=4)
2 changes: 1 addition & 1 deletion nmigen/test/test_lib_fifo.py
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ def elaborate(self, platform):

storage = Memory(self.width, self.depth)
wrport = m.submodules.wrport = storage.write_port(domain=self.wdomain)
rdport = m.submodules.rdport = storage.read_port (synchronous=False)
rdport = m.submodules.rdport = storage.read_port (domain="comb")

produce = Signal(max=self.depth)
consume = Signal(max=self.depth)
3 changes: 2 additions & 1 deletion nmigen/test/test_sim.py
Original file line number Diff line number Diff line change
@@ -431,7 +431,8 @@ def setUp_memory(self, rd_synchronous=True, rd_transparent=True, wr_granularity=
self.m = Module()
self.memory = Memory(width=8, depth=4, init=[0xaa, 0x55])
self.m.submodules.rdport = self.rdport = \
self.memory.read_port(synchronous=rd_synchronous, transparent=rd_transparent)
self.memory.read_port(domain="sync" if rd_synchronous else "comb",
transparent=rd_transparent)
self.m.submodules.wrport = self.wrport = \
self.memory.write_port(granularity=wr_granularity)