187 lines
4.2 KiB
Python
187 lines
4.2 KiB
Python
"""Encoders and decoders between binary and one-hot representation."""
|
|
|
|
from .. import *
|
|
|
|
|
|
__all__ = [
|
|
"Encoder", "Decoder",
|
|
"PriorityEncoder", "PriorityDecoder",
|
|
"GrayEncoder", "GrayDecoder",
|
|
]
|
|
|
|
|
|
class Encoder(Elaboratable):
|
|
"""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(range(width)), out
|
|
Encoded binary.
|
|
n : Signal, out
|
|
Invalid: either none or multiple input bits are asserted.
|
|
"""
|
|
def __init__(self, width):
|
|
self.width = width
|
|
|
|
self.i = Signal(width)
|
|
self.o = Signal(range(width))
|
|
self.n = Signal()
|
|
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
with m.Switch(self.i):
|
|
for j in range(self.width):
|
|
with m.Case(1 << j):
|
|
m.d.comb += self.o.eq(j)
|
|
with m.Case():
|
|
m.d.comb += self.n.eq(1)
|
|
return m
|
|
|
|
|
|
class PriorityEncoder(Elaboratable):
|
|
"""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(range(width)), out
|
|
Encoded binary.
|
|
n : Signal, out
|
|
Invalid: no input bits are asserted.
|
|
"""
|
|
def __init__(self, width):
|
|
self.width = width
|
|
|
|
self.i = Signal(width)
|
|
self.o = Signal(range(width))
|
|
self.n = Signal()
|
|
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
for j in reversed(range(self.width)):
|
|
with m.If(self.i[j]):
|
|
m.d.comb += self.o.eq(j)
|
|
m.d.comb += self.n.eq(self.i == 0)
|
|
return m
|
|
|
|
|
|
class Decoder(Elaboratable):
|
|
"""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(range(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.width = width
|
|
|
|
self.i = Signal(range(width))
|
|
self.n = Signal()
|
|
self.o = Signal(width)
|
|
|
|
def elaborate(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.If(self.n):
|
|
m.d.comb += self.o.eq(0)
|
|
return m
|
|
|
|
|
|
class PriorityDecoder(Decoder):
|
|
"""Decode binary to priority request.
|
|
|
|
Identical to :class:`Decoder`.
|
|
"""
|
|
|
|
|
|
class GrayEncoder(Elaboratable):
|
|
"""Encode binary to Gray code.
|
|
|
|
Parameters
|
|
----------
|
|
width : int
|
|
Bit width.
|
|
|
|
Attributes
|
|
----------
|
|
i : Signal(width), in
|
|
Input natural binary.
|
|
o : Signal(width), out
|
|
Encoded Gray code.
|
|
"""
|
|
def __init__(self, width):
|
|
self.width = width
|
|
|
|
self.i = Signal(width)
|
|
self.o = Signal(width)
|
|
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
m.d.comb += self.o.eq(self.i ^ self.i[1:])
|
|
return m
|
|
|
|
|
|
class GrayDecoder(Elaboratable):
|
|
"""Decode Gray code to binary.
|
|
|
|
Parameters
|
|
----------
|
|
width : int
|
|
Bit width.
|
|
|
|
Attributes
|
|
----------
|
|
i : Signal(width), in
|
|
Input Gray code.
|
|
o : Signal(width), out
|
|
Decoded natural binary.
|
|
"""
|
|
def __init__(self, width):
|
|
self.width = width
|
|
|
|
self.i = Signal(width)
|
|
self.o = Signal(width)
|
|
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
m.d.comb += self.o[-1].eq(self.i[-1])
|
|
for i in reversed(range(self.width - 1)):
|
|
m.d.comb += self.o[i].eq(self.o[i + 1] ^ self.i[i])
|
|
return m
|