From 3399f284b2f70036408f094926f0ca823bbad5b1 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 12 Nov 2014 23:59:02 -0800 Subject: [PATCH] Add priority encoder --- rtl/priority_encoder.v | 82 ++++++++++++++++++++ tb/test_priority_encoder.py | 147 ++++++++++++++++++++++++++++++++++++ tb/test_priority_encoder.v | 71 +++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 rtl/priority_encoder.v create mode 100755 tb/test_priority_encoder.py create mode 100644 tb/test_priority_encoder.v diff --git a/rtl/priority_encoder.v b/rtl/priority_encoder.v new file mode 100644 index 000000000..03af53fe9 --- /dev/null +++ b/rtl/priority_encoder.v @@ -0,0 +1,82 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * Priority encoder module + */ +module priority_encoder # +( + parameter WIDTH = 4 +) +( + input wire [WIDTH-1:0] input_unencoded, + output wire output_valid, + output wire [$clog2(WIDTH)-1:0] output_encoded, + output wire [WIDTH-1:0] output_unencoded +); + +// power-of-two width +localparam W1 = 2**$clog2(WIDTH); +localparam W2 = W1/2; + +generate + if (WIDTH == 2) begin + // two inputs - just an OR gate + assign output_valid = |input_unencoded; + assign output_encoded = input_unencoded[1]; + end else begin + // more than two inputs - split into two parts and recurse + // also pad input to correct power-of-two width + wire [$clog2(W2)-1:0] out1, out2; + wire valid1, valid2; + priority_encoder #( + .WIDTH(W2) + ) + priority_encoder_inst1 ( + .input_unencoded(input_unencoded[W2-1:0]), + .output_valid(valid1), + .output_encoded(out1) + ); + priority_encoder #( + .WIDTH(W2) + ) + priority_encoder_inst2 ( + .input_unencoded({{W1-WIDTH{1'b0}}, input_unencoded[WIDTH-1:W2]}), + .output_valid(valid2), + .output_encoded(out2) + ); + // multiplexer to select part + assign output_valid = valid1 | valid2; + assign output_encoded = valid2 ? {1'b1, out2} : {1'b0, out1}; + end +endgenerate + +// unencoded output +assign output_unencoded = 1 << output_encoded; + +endmodule diff --git a/tb/test_priority_encoder.py b/tb/test_priority_encoder.py new file mode 100755 index 000000000..143aa9bb6 --- /dev/null +++ b/tb/test_priority_encoder.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python2 +""" + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +from myhdl import * +import os + +module = 'priority_encoder' + +srcs = [] + +srcs.append("../rtl/%s.v" % module) +srcs.append("test_%s.v" % module) + +src = ' '.join(srcs) + +build_cmd = "iverilog -o test_%s.vvp %s" % (module, src) + +def dut_priority_encoder(clk, + rst, + current_test, + + input_unencoded, + + output_valid, + output_encoded, + output_unencoded): + + if os.system(build_cmd): + raise Exception("Error running build command") + return Cosimulation("vvp -m myhdl test_%s.vvp -lxt2" % module, + clk=clk, + rst=rst, + current_test=current_test, + + input_unencoded=input_unencoded, + + output_valid=output_valid, + output_encoded=output_encoded, + output_unencoded=output_unencoded) + +def bench(): + + # Inputs + clk = Signal(bool(0)) + rst = Signal(bool(0)) + current_test = Signal(intbv(0)[8:]) + + input_unencoded = Signal(intbv(0)[32:]) + + # Outputs + output_valid = Signal(bool(0)) + output_encoded = Signal(intbv(0)[5:]) + output_unencoded = Signal(intbv(0)[32:]) + + # DUT + dut = dut_priority_encoder(clk, + rst, + current_test, + + input_unencoded, + + output_valid, + output_encoded, + output_unencoded) + + @always(delay(4)) + def clkgen(): + clk.next = not clk + + @instance + def check(): + yield delay(100) + yield clk.posedge + rst.next = 1 + yield clk.posedge + rst.next = 0 + yield clk.posedge + yield delay(100) + yield clk.posedge + + yield clk.posedge + + print("test 1: one bit") + current_test.next = 1 + + for i in range(32): + input_unencoded.next = 1 << i + + yield clk.posedge + + assert output_encoded == i + assert output_unencoded == 1 << i + + yield delay(100) + + yield clk.posedge + + print("test 2: two bits") + current_test.next = 2 + + for i in range(32): + for j in range(32): + + input_unencoded.next = (1 << i) | (1 << j) + + yield clk.posedge + + assert output_encoded == max(i,j) + assert output_unencoded == 1 << max(i,j) + + yield delay(100) + + raise StopSimulation + + return dut, clkgen, check + +def test_bench(): + os.chdir(os.path.dirname(os.path.abspath(__file__))) + sim = Simulation(bench()) + sim.run() + +if __name__ == '__main__': + print("Running test...") + test_bench() + diff --git a/tb/test_priority_encoder.v b/tb/test_priority_encoder.v new file mode 100644 index 000000000..af7f07882 --- /dev/null +++ b/tb/test_priority_encoder.v @@ -0,0 +1,71 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1 ns / 1 ps + +module test_priority_encoder; + +// parameters +localparam WIDTH = 32; + +// Inputs +reg clk = 0; +reg rst = 0; +reg [7:0] current_test = 0; + +reg [WIDTH-1:0] input_unencoded = 0; + +// Outputs +wire output_valid; +wire [$clog2(WIDTH)-1:0] output_encoded; +wire [WIDTH-1:0] output_unencoded; + +initial begin + // myhdl integration + $from_myhdl(clk, + rst, + current_test, + input_unencoded); + $to_myhdl(output_valid, + output_encoded, + output_unencoded); + + // dump file + $dumpfile("test_priority_encoder.lxt"); + $dumpvars(0, test_priority_encoder); +end + +priority_encoder #( + .WIDTH(WIDTH) +) +UUT ( + .input_unencoded(input_unencoded), + .output_valid(output_valid), + .output_encoded(output_encoded), + .output_unencoded(output_unencoded) +); + +endmodule