Source

Boolean Bit Reducer

This module generalizes the usual 2-input Boolean functions to their n-input reductions, which are interesting and useful:

Beginners can use this module to implement any combinational logic while knowing a minimum of Verilog (no always blocks, no blocking/non-blocking statements, only wires, etc...).

Experts generally would not use this module. It's far simpler to express the desired conditions directly in Verilog. However, there are a few reasons to use it:

There's no clean way to stop the CAD tools if the OPERATION parameter is missing or incorrect. Here, the logic doesn't get generated, which will fail pretty fast...

The OPERATION parameter also reveals how strings are implemented in Verilog: just a sequence of 8-bit bytes. Thus, if we give OPERATION a value of "OR" (16 bits), it must first get compared against "AND" (24 bits) and "NAND" (32 bits). The Verilator linter throws a width mismatch warning at those first two comaprisons, of course. Width warnings are important to spot bugs, so to keep them relevant we carefully disable width checks only during the parameter tests.

`default_nettype none

module Bit_Reducer
#(
    parameter OPERATION     = "",
    parameter INPUT_COUNT   = 0
)
(
    input   wire    [INPUT_COUNT-1:0]   bits_in,
    output  reg                         bit_out
);

    initial begin
        bit_out = 1'b0;
    end

    generate

        // verilator lint_off WIDTH
        if (OPERATION == "AND") begin
        // verilator lint_off WIDTH
            always @(*) begin
                bit_out = &bits_in;
            end
        end
        else
        // verilator lint_off WIDTH
        if (OPERATION == "NAND") begin
        // verilator lint_off WIDTH
            always @(*) begin
                bit_out = ~&bits_in;
            end
        end
        else
        // verilator lint_off WIDTH
        if (OPERATION == "OR") begin
        // verilator lint_off WIDTH
            always @(*) begin
                bit_out = |bits_in;
            end
        end
        else
        // verilator lint_off WIDTH
        if (OPERATION == "NOR") begin
        // verilator lint_off WIDTH
            always @(*) begin
                bit_out = ~|bits_in;
            end
        end
        else
        // verilator lint_off WIDTH
        if (OPERATION == "XOR") begin
        // verilator lint_off WIDTH
            always @(*) begin
                bit_out = ^bits_in;
            end
        end
        else
        // verilator lint_off WIDTH
        if (OPERATION == "XNOR") begin
        // verilator lint_off WIDTH
            always @(*) begin
                bit_out = ~^bits_in;
            end
        end

    endgenerate
endmodule

back to FPGA Design Elements

fpgacpu.ca