`default_nettype none
module nn4x4
#( int wa = 10, ww = 5 )
( output uwire [wa-1:0] ao[4],
input uwire [wa-1:0] ai[4],
input uwire [ww-1:0] wht[4][4] );
assign ao[0] = ai[0] * wht[0][0] + ai[1] * wht[0][1]
+ ai[2] * wht[0][2] + ai[3] * wht[0][3];
assign ao[1] = ai[0] * wht[1][0] + ai[1] * wht[1][1]
+ ai[2] * wht[1][2] + ai[3] * wht[1][3];
assign ao[2] = ai[0] * wht[2][0] + ai[1] * wht[2][1]
+ ai[2] * wht[2][2] + ai[3] * wht[2][3];
assign ao[3] = ai[0] * wht[3][0] + ai[1] * wht[3][1]
+ ai[2] * wht[3][2] + ai[3] * wht[3][3];
endmodule
module nn4x4b
#( int wa = 10, ww = 5 )
( output uwire [wa-1:0] ao[4],
input uwire [wa-1:0] ai[4],
input uwire [ww-1:0] wht[4][4] );
nn1x4b #(wa,ww) n0( ao[0], ai, wht[0] );
nn1x4b #(wa,ww) n1( ao[1], ai, wht[1] );
nn1x4b #(wa,ww) n2( ao[2], ai, wht[2] );
nn1x4b #(wa,ww) n3( ao[3], ai, wht[3] );
endmodule
module nn1x4b
#( int wa = 10, ww = 5 )
( output uwire [wa-1:0] ao,
input uwire [wa-1:0] ai[4],
input uwire [ww-1:0] wht[4] );
uwire [wa-1:0] aoa, aob;
nn1x2b #(wa,ww) n0(aoa, ai[0:1], wht[0:1] );
nn1x2b #(wa,ww) n1(aob, ai[2:3], wht[2:3] );
assign ao = aoa + aob;
endmodule
module nn1x2b
#( int wa = 10, ww = 5 )
( output uwire [wa-1:0] ao,
input uwire [wa-1:0] ai[2],
input uwire [ww-1:0] wht[2] );
assign ao = ai[0] * wht[0] + ai[1] * wht[1];
endmodule
module nnOxI
#( int no = 4, ni = 4, wa = 10, ww = 5 )
( output logic [wa-1:0] ao[no],
input uwire [wa-1:0] ai[ni],
input uwire [ww-1:0] wht[no][ni] );
always_comb
for ( int o = 0; o < no; o++ ) begin
ao[o] = 0;
for ( int i=0; i<ni; i++ ) ao[o] += ai[i] * wht[o][i];
end
endmodule
cadence
module testbench;
localparam int wa = 16;
localparam int ww = 8;
localparam int ni = 4; localparam int no = 4; localparam int nmut = 3;
localparam int ntests = 10;
logic [wa-1:0] ai[ni];
uwire [wa-1:0] ao[nmut][no];
logic [ww-1:0] wht[no][ni];
string mname[] = { "Behav", "Flat", "Sol" };
typedef struct { string name; int no, ni; } Test_Set;
Test_Set ts[] = '{ '{ "n12", 1, 2 }, '{ "n14", 1, 4 }, '{ "n44", 4, 4 } };
nnOxI #(no,ni,wa,ww) nn1i(ao[0],ai,wht);
nn4x4 #(wa,ww) nn2i(ao[1],ai,wht);
nn4x4b #(wa,ww) nn3i(ao[2],ai,wht);
initial begin
automatic int mut = 2;
automatic string test_summary = "";
$write("Testing module %s\n", mname[mut]);
foreach ( ts[ti] ) begin
automatic Test_Set tinfo = ts[ti];
automatic int n_err = 0;
$write("\n** Starting test set %s (%0d outputs, %0d inputs) **\n",
tinfo.name, tinfo.no, tinfo.ni );
for ( int tnum=0; tnum < ntests; tnum++ ) begin
for ( int io=0; io<no; io++ )
for ( int ii=0; ii<ni; ii++ )
wht[io][ii] = io < tinfo.no && ii < tinfo.ni ? {$random} : 0;
for ( int ii=0; ii<ni; ii++ )
ai[ii] = ii < tinfo.ni ? {$random} : 0;
#1;
for ( int io=0; io<tinfo.no; io++ ) begin
if ( ao[0][io] !== ao[mut][io] ) begin
n_err++;
if ( n_err < 4 )
$write
("Error test # %0d, output %0d: %0d != %0d (correct)\n",
tnum, io, ao[mut][io], ao[0][io] );
end
end
end
begin
automatic string msg =
$sformatf("%0d %s tests on %s: %0d errors found.",
ntests, tinfo.name, mname[mut], n_err);
$write("Done with %s\n",msg);
test_summary = { test_summary, $sformatf("Results of %s\n", msg) };
end
end
$write("\n** Summary of Results **\n%s", test_summary);
end
endmodule
cadence