Source

Width Adjuster

Takes in a vector of a given input width, a flag denoting if it is a signed/unsigned value, and an output width. Outputs the same vector extended or truncated to the output width, with signed/unsigned extension. There is no guard against truncating so much you lose significant bits.

You would use this to normalize binary integers to the same constant width before doing arithmetic or Boolean operations upon them. The max function is handy for this when you don't know the widths ahead of time (e.g.: when they depend on another module parameter).

`default_nettype none

module Width_Adjuster
#(
    parameter WORD_WIDTH_IN     = 0,
    parameter SIGNED            = 0,
    parameter WORD_WIDTH_OUT    = 0
)
(
    // It's possible some input bits are truncated away
    // verilator lint_off UNUSED
    input   wire    [WORD_WIDTH_IN-1:0]     original_input,
    // verilator lint_on  UNUSED
    output  reg     [WORD_WIDTH_OUT-1:0]    adjusted_output
);

Calculate the width difference and handle each possible case:

    localparam PAD_WIDTH = WORD_WIDTH_OUT - WORD_WIDTH_IN;

    generate
        if (PAD_WIDTH == 0) begin: zero
            always @(*) begin
                adjusted_output = original_input;
            end
        end

        if (PAD_WIDTH > 0) begin: sign_extend
            localparam PAD_ZERO = {PAD_WIDTH{1'b0}};
            localparam PAD_ONES = {PAD_WIDTH{1'b1}};
            always @(*) begin
                adjusted_output = ((SIGNED != 0) && (original_input[WORD_WIDTH_IN-1] == 1'b1)) ? {PAD_ONES, original_input} : {PAD_ZERO, original_input};
            end
        end

        if (PAD_WIDTH < 0) begin: truncate
            always @(*) begin
                adjusted_output = original_input [WORD_WIDTH_OUT-1:0];
            end
        end
    endgenerate

endmodule

back to FPGA Design Elements

fpgacpu.ca