lib.coding: port from Migen.
This commit is contained in:
parent
fe8cb55204
commit
528747703d
|
@ -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
nmigen/compat/genlib/coding.py
Normal file
4
nmigen/compat/genlib/coding.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
from ...lib.cdc import *
|
||||
|
||||
|
||||
__all__ = ["Encoder", "PriorityEncoder", "Decoder", "PriorityDecoder"]
|
118
nmigen/lib/coding.py
Normal file
118
nmigen/lib/coding.py
Normal file
|
@ -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
nmigen/test/test_lib_coding.py
Normal file
78
nmigen/test/test_lib_coding.py
Normal file
|
@ -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)
|
Loading…
Reference in a new issue