verilator/test_regress/t/t_math_signed.v
2022-05-01 10:10:00 -04:00

207 lines
6.2 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2004 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
by_width #(1) w1 (.clk(clk));
by_width #(31) w31 (.clk(clk));
by_width #(32) w32 (.clk(clk));
by_width #(33) w33 (.clk(clk));
by_width #(63) w63 (.clk(clk));
by_width #(64) w64 (.clk(clk));
by_width #(65) w65 (.clk(clk));
by_width #(95) w95 (.clk(clk));
by_width #(96) w96 (.clk(clk));
by_width #(97) w97 (.clk(clk));
reg signed [15:0] a;
reg signed [4:0] b;
reg signed [15:0] sr,srs,sl,sls;
reg [15:0] b_s;
reg [15:0] b_us;
task check_s(input signed [7:0] i, input [7:0] expval);
//$display("check_s %x\n", i);
if (i !== expval) $stop;
endtask
task check_us(input signed [7:0] i, input [7:0] expval);
//$display("check_us %x\n", i);
if (i !== expval) $stop;
endtask
always @* begin
sr = a>>b;
srs = copy_signed(a)>>>b;
sl = a<<b;
sls = a<<<b;
// verilator lint_off WIDTH
b_s = b>>>4; // Signed
b_us = b[4:0]>>>4; // Unsigned, due to extract
check_s ( 3'b111, 8'h07);
check_s (3'sb111, 8'hff);
check_us( 3'b111, 8'h07);
check_us(3'sb111, 8'hff); // Note we sign extend ignoring function's input requirements
// verilator lint_on WIDTH
end
reg signed [32:0] bug349;
initial
begin
end
integer i;
initial begin
if ((-1 >>> 3) != -1) $stop; // Decimals are signed
// verilator lint_off WIDTH
if ((3'b111 >>> 3) != 0) $stop; // Based numbers are unsigned
if ((3'sb111 >>> 3) != -1) $stop; // Signed based numbers
// verilator lint_on WIDTH
if ( (3'sb000 > 3'sb000)) $stop;
if (!(3'sb000 > 3'sb111)) $stop;
if ( (3'sb111 > 3'sb000)) $stop;
if ( (3'sb000 < 3'sb000)) $stop;
if ( (3'sb000 < 3'sb111)) $stop;
if (!(3'sb111 < 3'sb000)) $stop;
if (!(3'sb000 >= 3'sb000)) $stop;
if (!(3'sb000 >= 3'sb111)) $stop;
if ( (3'sb111 >= 3'sb000)) $stop;
if (!(3'sb000 <= 3'sb000)) $stop;
if ( (3'sb000 <= 3'sb111)) $stop;
if (!(3'sb111 <= 3'sb000)) $stop;
// When we multiply overflow, the sign bit stays correct.
if ( (4'sd2*4'sd8) != 4'd0) $stop;
// From the spec:
// verilator lint_off WIDTH
i = -12 /3; if (i !== 32'hfffffffc) $stop;
i = -'d12 /3; if (i !== 32'h55555551) $stop;
i = -'sd12 /3; if (i !== 32'hfffffffc) $stop;
i = -4'sd12 /3; if (i !== 32'h00000001) $stop;
// verilator lint_on WIDTH
// verilator lint_off WIDTH
bug349 = 4'sb1111 - 1'b1;
if (bug349 != 32'he) $stop;
end
function signed [15:0] copy_signed;
input [15:0] ai;
copy_signed = ai;
endfunction
integer cyc; initial cyc = 0;
wire [31:0] ucyc = cyc;
always @ (posedge clk) begin
cyc <= cyc + 1;
`ifdef TEST_VERBOSE
$write("%x %x %x %x %x %x %x\n", cyc, sr,srs,sl,sls, b_s,b_us);
`endif
case (cyc)
0: begin
a <= 16'sh8b1b; b <= 5'sh1f; // -1
end
1: begin
// Check spaces in constants
a <= 16 'sh 8b1b; b <= 5'sh01; // -1
end
2: begin
a <= 16'sh8b1b; b <= 5'sh1e; // shift AMOUNT is really unsigned
if (ucyc / 1 != 32'd2) $stop;
if (ucyc / 2 != 32'd1) $stop;
if (ucyc * 1 != 32'd2) $stop;
if (ucyc * 2 != 32'd4) $stop;
if (ucyc * 3 != 32'd6) $stop;
if (cyc * 32'sd1 != 32'sd2) $stop;
if (cyc * 32'sd2 != 32'sd4) $stop;
if (cyc * 32'sd3 != 32'sd6) $stop;
end
3: begin
a <= 16'sh0048; b <= 5'sh1f;
if (ucyc * 1 != 32'd3) $stop;
if (ucyc * 2 != 32'd6) $stop;
if (ucyc * 3 != 32'd9) $stop;
if (ucyc * 4 != 32'd12) $stop;
if (cyc * 32'sd1 != 32'sd3) $stop;
if (cyc * 32'sd2 != 32'sd6) $stop;
if (cyc * 32'sd3 != 32'sd9) $stop;
end
4: begin
a <= 16'sh4154; b <= 5'sh02;
end
5: begin
a <= 16'shc3e8; b <= 5'sh12;
end
6: begin
a <= 16'sh488b; b <= 5'sh02;
end
9: begin
$write("*-* All Finished *-*\n");
$finish;
end
default: ;
endcase
case (cyc)
0: ;
1: if ({sr,srs,sl,sls,b_s,b_us}!==96'sh0000_ffff_0000_0000_ffff_0001) $stop;
2: if ({sr,srs,sl,sls,b_s,b_us}!==96'sh458d_c58d_1636_1636_0000_0000) $stop;
3: if ({sr,srs,sl,sls,b_s,b_us}!==96'sh0000_ffff_0000_0000_ffff_0001) $stop;
4: if ({sr,srs,sl,sls,b_s,b_us}!==96'sh0000_0000_0000_0000_ffff_0001) $stop;
5: if ({sr,srs,sl,sls,b_s,b_us}!==96'sh1055_1055_0550_0550_0000_0000) $stop;
6: if ({sr,srs,sl,sls,b_s,b_us}!==96'sh0000_ffff_0000_0000_ffff_0001) $stop;
7: if ({sr,srs,sl,sls,b_s,b_us}!==96'sh1222_1222_222c_222c_0000_0000) $stop;
8: ;
9: ;
endcase
end
endmodule
module by_width (
input clk
);
parameter WIDTH=1;
reg signed i1;
reg signed [62:0] i63;
reg signed [64:0] i65;
// verilator lint_off WIDTH
wire signed [WIDTH-1:0] i1extp /*verilator public*/ = i1;
wire signed [WIDTH-1:0] i1ext = i1;
wire signed [WIDTH-1:0] i63ext = i63;
wire signed [WIDTH-1:0] i65ext = i65;
// verilator lint_on WIDTH
integer cyc; initial cyc = 0;
always @ (posedge clk) begin
cyc <= cyc + 1;
i1 <= cyc[0];
i63 <= {63{cyc[0]}};
i65 <= {65{cyc[0]}};
case (cyc)
1: begin
if (i1extp != {WIDTH{1'b0}}) $stop;
if (i1ext != {WIDTH{1'b0}}) $stop;
if (i63ext != {WIDTH{1'b0}}) $stop;
if (i65ext != {WIDTH{1'b0}}) $stop;
end
2: begin
if (i1extp != {WIDTH{1'b1}}) $stop;
if (i1ext != {WIDTH{1'b1}}) $stop;
if (i63ext != {WIDTH{1'b1}}) $stop;
if (i65ext != {WIDTH{1'b1}}) $stop;
end
default: ;
endcase
end
endmodule