From ae31be3fcc64a382ecf9d081c83890d08c9ac9a2 Mon Sep 17 00:00:00 2001 From: Daniel Benusovich Date: Fri, 8 Mar 2019 18:59:27 -0800 Subject: [PATCH] Add AddressEncoder to consolidate encoder modules and hide ugliness --- TLB/src/AddressEncoder.py | 54 +++++++++++++++++++++ TLB/test/test_address_encoder.py | 80 ++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 TLB/src/AddressEncoder.py create mode 100644 TLB/test/test_address_encoder.py diff --git a/TLB/src/AddressEncoder.py b/TLB/src/AddressEncoder.py new file mode 100644 index 00000000..c6437fc8 --- /dev/null +++ b/TLB/src/AddressEncoder.py @@ -0,0 +1,54 @@ +from nmigen import Module, Signal +from nmigen.lib.coding import Encoder, PriorityEncoder + +class AddressEncoder(): + def __init__(self, width): + # Internal + self.encoder = Encoder(width) + self.p_encoder = PriorityEncoder(width) + + # Input + self.i = Signal(width) + + # Output + self.single_match = Signal(1) + self.multiple_match = Signal(1) + self.o = Signal(width) + + def elaborate(self, platform=None): + m = Module() + + # Add internal submodules + m.submodules.encoder = self.encoder + m.submodules.p_encoder = self.p_encoder + + m.d.comb += [ + self.encoder.i.eq(self.i), + self.p_encoder.i.eq(self.i) + ] + + # If the priority encoder recieves an input of 0 + # If n is 1 then the output is not valid + with m.If(self.p_encoder.n): + m.d.comb += [ + self.single_match.eq(0), + self.multiple_match.eq(0), + self.o.eq(0) + ] + # If the priority encoder recieves an input > 0 + with m.Else(): + # Multiple Match if encoder n is invalid + with m.If(self.encoder.n): + m.d.comb += [ + self.single_match.eq(0), + self.multiple_match.eq(1) + ] + # Single Match if encoder n is valid + with m.Else(): + m.d.comb += [ + self.single_match.eq(1), + self.multiple_match.eq(0) + ] + # Always set output based on priority encoder output + m.d.comb += self.o.eq(self.p_encoder.o) + return m \ No newline at end of file diff --git a/TLB/test/test_address_encoder.py b/TLB/test/test_address_encoder.py new file mode 100644 index 00000000..db555e12 --- /dev/null +++ b/TLB/test/test_address_encoder.py @@ -0,0 +1,80 @@ +import sys +sys.path.append("../src") +sys.path.append("../../TestUtil") + +from nmigen.compat.sim import run_simulation + +from AddressEncoder import AddressEncoder + +from test_helper import assert_eq, assert_ne, assert_op + +def set_encoder(dut, i): + yield dut.i.eq(i) + yield + +def check_single_match(dut, sm, op): + out_sm = yield dut.single_match + assert_op("Single Match", out_sm, sm, op) + +def check_multiple_match(dut, mm, op): + out_mm = yield dut.multiple_match + assert_op("Multiple Match", out_mm, mm, op) + +def check_output(dut, o, op): + out_o = yield dut.o + assert_op("Output", out_o, o, op) + +def check_all(dut, sm, mm, o, sm_op, mm_op, o_op): + yield from check_single_match(dut, sm, sm_op) + yield from check_multiple_match(dut, mm, mm_op) + yield from check_output(dut, o, o_op) + +def testbench(dut): + # Check invalid input + input = 0 + single_match = 0 + multiple_match = 0 + output = 0 + yield from set_encoder(dut, input) + yield from check_all(dut, single_match, multiple_match, output, 0, 0, 0) + + # Check single bit + input = 1 + single_match = 1 + multiple_match = 0 + output = 0 + yield from set_encoder(dut, input) + yield from check_all(dut, single_match, multiple_match, output, 0, 0, 0) + + # Check another single bit + input = 4 + single_match = 1 + multiple_match = 0 + output = 2 + yield from set_encoder(dut, input) + yield from check_all(dut, single_match, multiple_match, output, 0, 0, 0) + + # Check multiple match + # We expected the lowest bit to be returned which is address 0 + input = 5 + single_match = 0 + multiple_match = 1 + output = 0 + yield from set_encoder(dut, input) + yield from check_all(dut, single_match, multiple_match, output, 0, 0, 0) + + # Check another multiple match + # We expected the lowest bit to be returned which is address 1 + input = 6 + single_match = 0 + multiple_match = 1 + output = 1 + yield from set_encoder(dut, input) + yield from check_all(dut, single_match, multiple_match, output, 0, 0, 0) + + + +if __name__ == "__main__": + dut = AddressEncoder(4) + run_simulation(dut, testbench(dut), vcd_name="Waveforms/test_address_encoder.vcd") + print("AddressEncoder Unit Test Success") \ No newline at end of file -- 2.30.2