`default_nettype none
typedef enum
{ Char_space = 32, Char_0 = 48, Char_9 = 57,
Char_A = 65, Char_Z = 90, Char_a = 97, Char_z = 122 }
Chars_Special;
module mux2
#( int w = 3 )
( output uwire [w-1:0] x,
input uwire s,
input uwire [w-1:0] a0, a1 );
assign x = s ? a1 : a0;
endmodule
module char_to_uc( output uwire [7:0] uc, input uwire [7:0] c );
uwire is_lc = c >= Char_a && c <= Char_z;
uwire [7:0] uc_if_lc = c - Char_a + Char_A;
mux2 #(8) m( uc, is_lc, c, uc_if_lc );
endmodule
module digit_valid_az
#( int r = 11, vw = $clog2(r) )
( output uwire valid, output uwire [vw-1:0] val, input uwire [7:0] char );
assign val = 10 + char - Char_A;
assign valid = char >= Char_A && char < Char_A + r - 10;
endmodule
module atoi1
#( int r = 32, w = $clog2(r) )
( output logic [w-1:0] val,
output logic is_digit,
input uwire [7:0] char );
logic [w-1:0] val_09, val_az, val_n;
logic is_09, is_az;
digit_valid_09 #(r,w) v09( is_09, val_09, char );
uwire [7:0] char_uc;
char_to_uc tuc(char_uc,char);
digit_valid_az #(r,w) vaz( is_az, val_az, char_uc );
uwire [w-1:0] z = 0;
mux2 #(w) mval(val_n,is_09,val_az,val_09);
mux2 #(w) mval0(val,is_digit,z,val_n);
assign is_digit = is_09 || is_az;
endmodule
module digit_valid_09
#( int r = 9, vw = $clog2(r) )
( output uwire valid, output uwire [vw-1:0] val, input uwire [7:0] char );
assign val = char - Char_0;
assign valid = char >= Char_0 && char <= Char_9 && char < Char_0 + r;
endmodule
module atoi1_behavioral
#( int r = 32, w = $clog2(r) )
( output logic [w-1:0] val,
output logic is_digit,
input uwire [7:0] char );
logic [7:0] char_uc;
logic [w-1:0] val_09, val_az;
logic is_09, is_az;
always_comb begin
char_uc = char >= Char_a && char <= Char_z
? char - Char_a + Char_A : char;
val_09 = char - Char_0;
val_az = 10 + char_uc - Char_A;
is_09 = char >= Char_0 && char <= Char_9 && char < Char_0 + r;
is_az = char_uc >= Char_A && char_uc < Char_A + r - 10;
is_digit = is_09 || is_az;
if ( is_09 ) val = val_09;
else if ( is_az ) val = val_az;
else val = 0;
end
endmodule
cadence
module testbench;
localparam int nradices = 6;
localparam int radices[nradices] =
'{ 4, 8, 10, 14, 16, 19 };
int t_errs; initial t_errs = 0;
final $write("Total number of errors: %0d\n",t_errs);
uwire d[nradices:-1]; assign d[-1] = 1;
for ( genvar i=0; i<nradices; i++ )
testbench_r #(radices[i]) t2( .done(d[i]), .tstart(d[i-1]) );
endmodule
module testbench_r
#( int r = 16 )
( output logic done, input uwire tstart );
localparam int wd = 8;
localparam int w = $clog2(r**wd);
localparam int w1 = 2 * $clog2(r);
localparam int ntests = 500;
logic [1:0][7:0] str;
uwire [w1-1:0] val1;
uwire is_digit1;
atoi1 #(r,w1) a1( val1, is_digit1, str[0] );
logic [7:0] non_digit[256];
function string to_string(input logic [w1-1:0] val);
automatic string result = "";
if ( val == 0 ) result = "0";
while ( val ) begin
automatic int d = val % r;
automatic int v = d < 10 ? d + Char_0 : d - 10 + Char_A;
val = val / r;
result = { string'(v), result };
end
to_string = result;
endfunction
initial begin
automatic int nd_size = 0;
automatic int rm10 = r > 10 ? 10 : r;
automatic bit err_silent = 0;
for ( int i=32; i<128; i++ ) begin
if ( i >= Char_0 && i < Char_0 + rm10 ) continue;
if ( i >= Char_A && i < Char_A + r - 10 ) continue;
if ( i >= Char_a && i < Char_a + r - 10 ) continue;
non_digit[nd_size++] = i;
end
str[1] = Char_space;
wait( tstart );
for ( int tt=0; tt<1; tt++ ) begin
automatic bit single_char = tt == 0;
automatic bit space_pad = single_char || tt == 1;
automatic int nttests = single_char ? 256 : ntests;
automatic int n_err = 0, n_lerr = 0;
automatic string ttype =
single_char ? "Single_Char (SC)"
: space_pad ? "Space_Pad (SP)" : "General (GE)";
automatic string abbrev =
single_char ? "SC" : space_pad ? "SP" : "GE";
for ( int i=0; i<nttests; i++ ) begin
automatic int len = single_char ? 1 : 1 + {$random} % wd;
automatic logic [w1-1:0] sval = 0;
automatic bit is_09 = i >= Char_0 && i <= Char_9 && i < Char_0 + r;
automatic int iuc =
i >= Char_a && i <= Char_z ? i - Char_a + Char_A : i;
automatic bit is_az = iuc >= Char_A && iuc < Char_A + r - 10;
automatic bit sis_digit = is_09 || is_az;
str[0] = i;
sval = is_09 ? i - Char_0 : is_az ? 10 + iuc - Char_A : 0;
#1;
if ( sval !== val1 ) begin
n_err++;
if ( !err_silent && n_err < 5 )
$write("R %2d Error val 'h%h or %s != %s (correct) for string \"%s\"\n",
r, val1, to_string(val1), to_string(sval),
string'(str));
end
if ( sis_digit !== is_digit1 ) begin
n_lerr++;
if ( !err_silent && n_lerr < 5 )
$write("R %2d Error is_digit %h != %0d (correct) for string \"%s\"\n",
r, is_digit1, sis_digit, string'(str) );
end
#1;
end
$write("Radix %2d, done with %0d tests, %0d val errors, %0d is_digit errors.\n",
r, nttests, n_err, n_lerr);
testbench.t_errs += n_err + n_lerr;
if ( n_err + n_lerr ) err_silent = 1;
end
done = 1;
end
endmodule