How to sign-extend a number in Verilog

77,709

Solution 1

You nearly got it...

always @( posedge clk ) begin
    extended[15:0] <= { {8{extend[7]}}, extend[7:0] };
end

You're also missing a clock edge for the '40' test. Try this, & let me know how you get on...

Solution 2

We can use the syntax $signed to sign extend

module signextender(
  input [7:0] unextended,//the msb bit is the sign bit
  input clk,
  output reg [15:0] extended 
);
[email protected](posedge clk)
  begin 
    extended <= $signed(unextended);
  end
endmodule

Solution 3

By the way your module assign is pure combinational so it should not contain a clk, this is another way of doing your module:

module sign_ext
             (
              unextend,
              extended
             );
input  [15:0] unextend;
output [31:0] extended;
assign extended = {{16{unextend[15]}}, unextend};
endmodule
//TB
module tb_sign_ext;
reg  [15:0] unex;
wire   [31:0] ext;
sign_ext TBSIGNEXT
                  (
                   .unextend(unex),
                   .extended(ext)
                  );
initial
begin
   unex = 16'd0;
end
initial 
begin
   #10 unex = 16'b0000_0000_1111_1111;
   #20 unex = 16'b1000_0000_1111_1111;
end
endmodule
;)
Share:
77,709

Related videos on Youtube

Alex Mullans
Author by

Alex Mullans

Product Manager on GitHub Package Registry.

Updated on December 10, 2020

Comments

  • Alex Mullans
    Alex Mullans almost 2 years

    I'm working on a simple sign-extender in Verilog for a processor I'm creating for Computer Architecture.

    Here's what I've got so far: [EDIT: Changed the selection statement slightly]

    `timescale 1ns / 1ps
    module SignExtender( CLK, extend, extended );
    input[7:0] extend;
    input CLK;
    output[15:0] extended;
    reg[15:0] extended;
    wire[7:0] extend;
    always
    begin
        while (CLK == 1)
        extended[7:0] = extend[7:0];
        extended[15:8] = {8{extend[7]}};
    end
    endmodule
    

    I added the while (CLK == 1) thinking that would solve my problem, which I believe is an infinite loop. When I try to test this in iSim, the circuit never initializes.

    I also tried removing the copying syntax and just doing extended[8] = extend[7] etc. for [8]-[15], but the same result occurs, so I'm pretty sure that the innermost syntax is correct.

    Here's the test file:

    `timescale 1ns / 1ps
    module SignExtender_testbench0;
        // Inputs
        reg [7:0] extend;
        reg CLK;
        // Outputs
        wire [15:0] extended;
        // Instantiate the Unit Under Test (UUT)
        SignExtender uut (
            .extend(extend), 
            .extended(extended)
        );
        initial begin
            // Initialize Inputs
            extend = 0;
            #100; // Wait 100 ns for global reset to finish
            extend = -30;
            CLK = 1;
            #10;
            CLK = 0;
            if (extended == -30)
                $display("okay 1");
            else
                $display("fail 1");
            extend = 40;
            #10;
            if (extended == 40)
                $display("okay 2");
            else
                $display("fail 2");
        end
    endmodule
    

    Any ideas how I can do this successfully?

  • minexew
    minexew almost 5 years
    Note that some tools will raise a warning about width mismatch, because $signed(unextended) is still just 8 bits before it's assiged to extended

Related