Quote:

> I think this is only possible with the new signed data type defined in

> Verilog 2000. Some tools already support them, so you might want to

> give it a try. But be careful, arithmetic types have been defined in

> Verilog 2000 in the most unlogical way. Whenever signed and unsigned

> vectors are mixed in an expression, everything becomes unsigned, which

> is obviously wrong for signed vectors (the only meaningful conversion is

> from unsigned to signed with a 1-bit zero-extension, as done in VHDL's

> numeric_std). Also, part-selects of signed vectors become unsigned,

> even if part-select specifies the whole vector. Example:

> reg signed [15:0] a;

> reg signed [7:0] b;

> a = b; // b is signed and therefore sign-extended

> a = b[7:0]; // b[7:0] is unsigned and therefore zero-extended

> This severely limits the usefulness of signed types in Verilog again.

Well my way is probably extremely retarded, but I couldn't think of any

other easy way.

Basically, whenever I need to do (simple) arithmetic on signed 2's C

data types, I converted the input values (from input ports) into

integers.

So far, this works in Verilog-XL, NC-Verilog. Synthesis-output from

Synopsys Design_Compiler (standard cell ASIC, ARtisan TSMC library), and

from Synopsys FPGA-Express (Xilinx Student Edition 2.1i) agree with

the simulated results.

One word of caution, a right-shift (>>) on a verilog-integer (which

is signed) is performed UNsigned! This is NOT what you would expect...

.......

module stupid_adder( i_a, i_b, o_sum);

parameter I_W = 8; // Input width (#bits), user-adjustable (1..32)

// don't change these two params

parameter O_W = I_W+1; // output width (#bits), DO NOT MODIFY!

parameter VINT_W = 32; // CONSTANT, Verilog integer width, DO NOT

MODIFY!

input [(I_W-1):0] i_a; // signed input A

input [(I_W-1):0] i_b; // signed input B

output [(O_W-1):0] o_sum; // signed output sum = i_a + i+b

integer int_a, int_b; // intermediate integer variables

integer int_sum; // intermediate sum

// sign-extend from (I_W) to 32-bit signed integer.

function [ (VINT_W-1):0 ] sign_extend;

input [ (VINT_W-1):0 ] input_a;

input [ 5:0 ] input_width;

reg [5:0] i;

begin

// 1) copy lower-bits to output

for ( i = 0; i < input_width; i = i + 1 )

sign_extend[ i ] = input_a[ i ];

// 2) replicate sign-bit to upper output bits

for ( i = input_width; i < VINT_W; i = i + 1 )

sign_extend[ i ] = input_a[ input_width - 1 ];

end

endfunction // function [ (VINT_W-1):0 ] sign_extend;

// here's some *real* work being done, sort of...

begin

// sign-extend from (I_W) to 32-bit signed integer.

int_a = sign_extend( i_a, I_W );

int_b = sign_extend( i_b, I_W );

int_sum = int_a + int_b;

end

assign o_sum = int_sum; // auto-truncate the upper bits

endmodule

/////////////////////////////////////////////////

module test_the_stupid_adder; // ahahahahahahahahahahahahahahahahahahah

parameter I_W = 8; // Input width (#bits), user-adjustable (1..32)

// derived parameters, don't change these two params

parameter O_W = I_W+1; // output width (#bits), DO NOT MODIFY!

parameter VINT_W = 32; // CONSTANT, Verilog integer width, DO NOT

MODIFY!

// derived parameters, don't change these two params

parameter T_LOW = (-1) << (O_W-2);

parameter T_HIGH = ((1) << (O_W-2)) - 1;

wire [(I_W-1):0] i_a; // signed input A

wire [(I_W-1):0] i_b; // signed input B

wire [(O_W-1):0] o_sum; // signed output sum = i_a + i+b

integer int_a; // stimulus generator

integer int_b; // stimulus generator

integer int_sum; // device-under-test's output

integer loop_i, loop_j; // testbench variables

integer exp_sum; // expected output (calculated by testbench)

// sign-extend from (I_W) to 32-bit signed integer.

function [ (VINT_W-1):0 ] sign_extend;

input [ (VINT_W-1):0 ] input_a;

input [ 5:0 ] input_width;

reg [5:0] i;

begin

// 1) copy lower-bits to output

for ( i = 0; i < input_width; i = i + 1 )

sign_extend[ i ] = input_a[ i ];

// 2) replicate sign-bit to upper output bits

for ( i = input_width; i < VINT_W; i = i + 1 )

sign_extend[ i ] = input_a[ input_width - 1 ];

end

endfunction // function [ (VINT_W-1):0 ] sign_extend;

// drive inputs, convert integers into 8-bit bus

assign i_a = int_a;

assign i_b = int_b;

// capture the device output, convert to 32-bit signed integer

begin

int_sum = sign_extend( o_sum, O_W );

end

// the device under test

stupid_adder adder1( .i_a(i_a), .i_b(i_b), .o_sum(o_sum) );

initial

begin

int_a = 0; int_b = 0;

$display("WILL TEST %d through %d", T_LOW, T_HIGH );

for ( loop_i = T_LOW; loop_i <= T_HIGH; loop_i = loop_i + 1 )

begin

for ( loop_j = T_LOW; loop_j <= T_HIGH; loop_j = loop_j + 1 )

begin

int_a = loop_i;

int_b = loop_j;

exp_sum = int_a + int_b; // calculate expected value

#100;

if ( int_sum != exp_sum )

$display( "'%d' + '%d' = '%d', but got '%d'!", int_a,

int_b, exp_sum, int_sum );

end // for ( loop_j = 0 ...

$display("...working on %d of %d", loop_i, T_HIGH );

end // for ( loop_i = 0 ...

#1000 $finish;

end

endmodule