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: fe8cb552041c
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: 528747703d8f
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on Dec 26, 2018

  1. lib.coding: port from Migen.

    whitequark committed Dec 26, 2018
    Copy the full SHA
    5287477 View commit details
Showing with 205 additions and 5 deletions.
  1. +5 −5 doc/COMPAT_SUMMARY.md
  2. +4 −0 nmigen/compat/genlib/coding.py
  3. +118 −0 nmigen/lib/coding.py
  4. +78 −0 nmigen/test/test_lib_coding.py
10 changes: 5 additions & 5 deletions doc/COMPAT_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -130,11 +130,11 @@ Compatibility summary
- (−) `ElasticBuffer` ?
- (−) `lcm` ?
- (−) `Gearbox` ?
- () `coding` ?
- () `Encoder` ?
- () `PriorityEncoder` ?
- () `Decoder` ?
- () `PriorityDecoder` ?
- () `coding` id
- () `Encoder` id
- () `PriorityEncoder` id
- () `Decoder` id
- () `PriorityDecoder` id
- (−) `divider` ?
- (−) `Divider` ?
- (−) `fifo` ?
4 changes: 4 additions & 0 deletions nmigen/compat/genlib/coding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from ...lib.cdc import *


__all__ = ["Encoder", "PriorityEncoder", "Decoder", "PriorityDecoder"]
118 changes: 118 additions & 0 deletions nmigen/lib/coding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
"""Encoders and decoders between binary and one-hot representation."""

from .. import *


class Encoder:
"""Encode one-hot to binary.
If one bit in ``i`` is asserted, ``n`` is low and ``o`` indicates the asserted bit.
Otherwise, ``n`` is high and ``o`` is ``0``.
Parameters
----------
width : int
Bit width of the input
Attributes
----------
i : Signal(width), in
One-hot input.
o : Signal(max=width), out
Encoded binary.
n : Signal, out
Invalid: either none or multiple input bits are asserted.
"""
def __init__(self, width):
self.i = Signal(width)
self.o = Signal(max=max(2, width))
self.n = Signal()

def get_fragment(self, platform):
m = Module()
with m.Switch(self.i):
for j in range(len(self.i)):
with m.Case(1 << j):
m.d.comb += self.o.eq(j)
with m.Case():
m.d.comb += self.n.eq(1)
return m.lower(platform)


class PriorityEncoder:
"""Priority encode requests to binary.
If any bit in ``i`` is asserted, ``n`` is low and ``o`` indicates the least significant
asserted bit.
Otherwise, ``n`` is high and ``o`` is ``0``.
Parameters
----------
width : int
Bit width of the input.
Attributes
----------
i : Signal(width), in
Input requests.
o : Signal(max=width), out
Encoded binary.
n : Signal, out
Invalid: no input bits are asserted.
"""
def __init__(self, width):
self.i = Signal(width)
self.o = Signal(max=max(2, width))
self.n = Signal()

def get_fragment(self, platform):
m = Module()
for j, b in enumerate(reversed(self.i)):
with m.If(b):
m.d.comb += self.o.eq(j)
m.d.comb += self.n.eq(self.i == 0)
return m.lower(platform)


class Decoder:
"""Decode binary to one-hot.
If ``n`` is low, only the ``i``th bit in ``o`` is asserted.
If ``n`` is high, ``o`` is ``0``.
Parameters
----------
width : int
Bit width of the output.
Attributes
----------
i : Signal(max=width), in
Input binary.
o : Signal(width), out
Decoded one-hot.
n : Signal, in
Invalid, no output bits are to be asserted.
"""
def __init__(self, width):
self.i = Signal(max=max(2, width))
self.n = Signal()
self.o = Signal(width)

def get_fragment(self, platform):
m = Module()
with m.Switch(self.i):
for j in range(len(self.o)):
with m.Case(j):
m.d.comb += self.o.eq(1 << j)
with m.Case():
with m.If(self.n):
m.d.comb += self.o.eq(0)
return m.lower(platform)


class PriorityDecoder(Decoder):
"""Decode binary to priority request.
Identical to :class:`Decoder`.
"""
78 changes: 78 additions & 0 deletions nmigen/test/test_lib_coding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from .tools import *
from ..hdl.ast import *
from ..back.pysim import *
from ..lib.coding import *


class EncoderTestCase(FHDLTestCase):
def test_basic(self):
enc = Encoder(4)
with Simulator(enc) as sim:
def process():
self.assertEqual((yield enc.n), 1)
self.assertEqual((yield enc.o), 0)

yield enc.i.eq(0b0001)
yield Delay()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 0)

yield enc.i.eq(0b0100)
yield Delay()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 2)

yield enc.i.eq(0b0110)
yield Delay()
self.assertEqual((yield enc.n), 1)
self.assertEqual((yield enc.o), 0)

sim.add_process(process)


class PriorityEncoderTestCase(FHDLTestCase):
def test_basic(self):
enc = PriorityEncoder(4)
with Simulator(enc) as sim:
def process():
self.assertEqual((yield enc.n), 1)
self.assertEqual((yield enc.o), 0)

yield enc.i.eq(0b0001)
yield Delay()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 0)

yield enc.i.eq(0b0100)
yield Delay()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 2)

yield enc.i.eq(0b0110)
yield Delay()
self.assertEqual((yield enc.n), 0)
self.assertEqual((yield enc.o), 1)

sim.add_process(process)


class DecoderTestCase(FHDLTestCase):
def test_basic(self):
dec = Decoder(4)
with Simulator(dec) as sim:
def process():
self.assertEqual((yield enc.o), 0b0001)

yield enc.i.eq(1)
yield Delay()
self.assertEqual((yield enc.o), 0b0010)

yield enc.i.eq(3)
yield Delay()
self.assertEqual((yield enc.o), 0b1000)

yield enc.n.eq(1)
yield Delay()
self.assertEqual((yield enc.o), 0b0000)

sim.add_process(process)