dakies/OSS_Verilog huggingface dataset:
module NODE_1(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b101010100;
   weights[1]<=9'b000001001;
   weights[2]<=9'b111011010;
   weights[3]<=9'b000000111;
   weights[4]<=9'b000111111;
   weights[5]<=9'b111001011;
   weights[6]<=9'b111001101;
   weights[7]<=9'b110101100;
   weights[8]<=9'b000000011;
   weights[9]<=9'b000001111;
   weights[10]<=9'b000000101;
   weights[11]<=9'b001011001;
   weights[12]<=9'b000100101;
   weights[13]<=9'b111000001;
   weights[14]<=9'b111101101;
   weights[15]<=9'b111011100;
   weights[16]<=9'b111100111;
   weights[17]<=9'b111011011;
   weights[18]<=9'b000111111;
   weights[19]<=9'b000101000;
   weights[20]<=9'b000001110;
   weights[21]<=9'b111000110;
   weights[22]<=9'b000100100;
   weights[23]<=9'b110101001;
   weights[24]<=9'b000000110;
   weights[25]<=9'b111000011;
   weights[26]<=9'b000111100;
   weights[27]<=9'b000111001;
   weights[28]<=9'b000010101;
   weights[29]<=9'b000100001;
   weights[30]<=9'b111100011;
   weights[31]<=9'b111000001;
   weights[32]<=9'b111111010;
   weights[33]<=9'b110111010;
   weights[34]<=9'b000000111;
   weights[35]<=9'b111110111;
   weights[36]<=9'b000000110;
   weights[37]<=9'b111010001;
   weights[38]<=9'b111111010;
   weights[39]<=9'b000001010;
   weights[40]<=9'b111110000;
   weights[41]<=9'b000010010;
   weights[42]<=9'b000000000;
   weights[43]<=9'b111101011;
   weights[44]<=9'b111110101;
   weights[45]<=9'b110111111;
   weights[46]<=9'b111111010;
   weights[47]<=9'b111111001;
   weights[48]<=9'b000010111;
   weights[49]<=9'b000001011;
   weights[50]<=9'b111101110;
   weights[51]<=9'b000001100;
   weights[52]<=9'b111111100;
   weights[53]<=9'b111000011;
   weights[54]<=9'b000010100;
   weights[55]<=9'b111100011;
   weights[56]<=9'b111111111;
   weights[57]<=9'b000010000;
   weights[58]<=9'b111101001;
   weights[59]<=9'b000011000;
   weights[60]<=9'b000010101;
   weights[61]<=9'b111011000;
   weights[62]<=9'b000001010;
   weights[63]<=9'b000101101;
   bias<=8'b00001101;
 end

 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module NODE_14(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b111010001;
   weights[1]<=9'b000001100;
   weights[2]<=9'b000001001;
   weights[3]<=9'b000010110;
   weights[4]<=9'b000000001;
   weights[5]<=9'b000101011;
   weights[6]<=9'b000110100;
   weights[7]<=9'b000011100;
   weights[8]<=9'b111111111;
   weights[9]<=9'b000001100;
   weights[10]<=9'b111101100;
   weights[11]<=9'b000010001;
   weights[12]<=9'b000011001;
   weights[13]<=9'b110110000;
   weights[14]<=9'b111111011;
   weights[15]<=9'b111100010;
   weights[16]<=9'b000010101;
   weights[17]<=9'b000110011;
   weights[18]<=9'b000010000;
   weights[19]<=9'b000110111;
   weights[20]<=9'b000100111;
   weights[21]<=9'b000101001;
   weights[22]<=9'b000000100;
   weights[23]<=9'b000011010;
   weights[24]<=9'b111011110;
   weights[25]<=9'b111101001;
   weights[26]<=9'b000010101;
   weights[27]<=9'b111101101;
   weights[28]<=9'b000000001;
   weights[29]<=9'b111100000;
   weights[30]<=9'b000100001;
   weights[31]<=9'b111011001;
   weights[32]<=9'b111101101;
   weights[33]<=9'b111100011;
   weights[34]<=9'b000011101;
   weights[35]<=9'b111111110;
   weights[36]<=9'b000000101;
   weights[37]<=9'b111101100;
   weights[38]<=9'b000010110;
   weights[39]<=9'b111111100;
   weights[40]<=9'b111100101;
   weights[41]<=9'b111001011;
   weights[42]<=9'b000000111;
   weights[43]<=9'b111101000;
   weights[44]<=9'b000100101;
   weights[45]<=9'b000010110;
   weights[46]<=9'b000100101;
   weights[47]<=9'b111110101;
   weights[48]<=9'b111100000;
   weights[49]<=9'b111010101;
   weights[50]<=9'b111010100;
   weights[51]<=9'b000011101;
   weights[52]<=9'b111011011;
   weights[53]<=9'b111100010;
   weights[54]<=9'b000111110;
   weights[55]<=9'b000000111;
   weights[56]<=9'b111111011;
   weights[57]<=9'b111011010;
   weights[58]<=9'b111110000;
   weights[59]<=9'b000000010;
   weights[60]<=9'b000100011;
   weights[61]<=9'b000001000;
   weights[62]<=9'b111111111;
   weights[63]<=9'b000001010;
   bias<=8'b11101101;
 end
 
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module TB_MAXPOOL2;

	// Inputs
	reg [35:0] y;
	reg clk;
	reg start;
	reg reset;

	// Outputs
	wire [1:0] mx2_done;
	wire [3:0] mx2_count;
	wire [35:0] mx2_output;

	// Instantiate the Unit Under Test (UUT)
	MAXPOOL2 uut (
		.mx2_input(y), 
		.clk(clk), 
		.start(start), 
		.reset(reset), 
		.mx2_done(mx2_done), 
		.mx2_count(mx2_count), 
		.mx2_output(mx2_output)
	);

	initial begin
		// Initialize Inputs
		y = 0;
		clk = 0;
		start = 0;
		reset = 0;

		#50;
        reset = 1; 
        
        // Add stimulus here
        #100 reset = 0; start = 1; 
            y = 15;  #50  y = 20;  #50  y = 25;  #50  y = 30; #50 y = 35; #50 y = 40; #50 y = 45;  #50 y = 50; 
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50  y = 70; #50 y = 75; #50 y = 80; #50 y = 15;  #50 y = 90; 
        #50 y = 100; #50  y = 120; #50  y = 125; #50 y = 30;  #50 y = 35; #50 y = 40; #50 y = 45;  #50 y = 50; 
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50 y = 70;  #50 y = 75; #50 y = 80; #50 y = 85;  #50 y = 90; 
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50  y = 70; #50 y = 75; #50 y = 80; #50 y = 15;  #50 y = 90; 
        #50 y = 100; #50  y = 120; #50  y = 125; #50 y = 30;  #50 y = 35; #50 y = 40; #50 y = 45;  #50 y = 50; 
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50 y = 70;  #50 y = 75; #50 y = 80; #50 y = 85;  #50 y = 90;
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50  y = 70; #50 y = 75; #50 y = 80; #50 y = 15;  #50 y = 90; 
        #50 y = 100; #50  y = 120; #50  y = 125; #50 y = 30;  #50 y = 35; #50 y = 40; #50 y = 45;  #50 y = 1000; 
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50 y = 70;  #50 y = 75; #50 y = 80; #50 y = 85;  #50 y = 90;
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50  y = 150; #50 y = 75; #50 y = 80; #50 y = 15; #50 y = 90; 
        #50 y = 100; #50  y = 120; #50  y = 125; #50 y = 30;  #50 y = 35; #50 y = 40; #50 y = 45;  #50 y = 50; 
        #50 y = 55;  #50  y = 60;  #50  y = 65;  #50 y = 70;  #50 y = 75; #50 y = 80; #50 y = 85;  #50 y = 90; //#10000 start = 0;
                
	end
      
     always #25 clk = ~clk;
     
endmodule
module TB_CNN;
    reg clk;
    reg reset;
    wire signed [39:0] CNN_output;
    wire write_strobe;
    
    CNN uut( .clk(clk), .reset(reset), .CNN_output(CNN_output), .write_strobe(write_strobe));
    
    always #5 clk = ~clk;
    
    initial begin
    clk = 0;
    reset = 0;
    #50;
    reset = 1;
    #10;
    reset = 0;
    
    #400000;
    reset = 1;
    #10;
    reset = 0;
    end
    

endmodule
module Counter_ws(
    input clk,
    input start,
    input reset,
    output reg done=1'b0,
    output reg ws
    );
    parameter fill = 212; //213 clock XXXX
    //parameter mod = fill + 67*64;
    reg [8:0] count; //ws_count
    reg [5:0] count2; //64 rows
    always @ ( posedge clk )
    begin
        if( reset || ~start )
        begin
            count <= 0;
            ws <= 0;
            count2 <= 0;
            done <= 0;
        end else if ( start )
        begin
            if( count < fill )
            begin
				count <= count + 1;
				ws <= 0;
				done <= 0;
            end else if ( count2 == 63 && count == 279)
            begin
                count <= 12;
                count2 <= 0;
                ws <= 0;
                done <= 0;
            end else if ( count < 276 )
            begin
                count <= count + 1;
				ws <= 1;
				done <= 1;
            end else if ( count < 279 )
			begin
				count <= count + 1;
				ws <= 0;
				done <= 1;
			end
			else if ( count == 279 )
			begin
			     count <= 213;
			     ws <= 1;
			     count2 <= count2 + 1;
			     done <= 1;
			end
        end
    end
	
endmodule
module TB_RELU;

reg [21:0] a_t;
reg clk;
reg enable_t;
reg read_strobe_t;
wire [21:0] out_t;
wire write_strobe_t;


RELU1 uut(
 .a(a_t),
 .clk(clk),
 .enable(enable_t),
 .read_strobe(read_strobe_t),
 .out(out_t),
 .write_strobe(write_strobe_t)
   );

always #5 clk=~clk;
initial begin
            
           enable_t = 1;
           clk = 0;
           read_strobe_t=1;
           #10;
           a_t = -22'd869;
           #10;
           a_t = 22'd869;
           #10;
           a_t = -22'd877;
   end
endmodule
module NODE_4(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b111110000;
   weights[1]<=9'b110101111;
   weights[2]<=9'b000001110;
   weights[3]<=9'b111001001;
   weights[4]<=9'b000001100;
   weights[5]<=9'b000011000;
   weights[6]<=9'b111111000;
   weights[7]<=9'b101100111;
   weights[8]<=9'b000100101;
   weights[9]<=9'b000100111;
   weights[10]<=9'b111111111;
   weights[11]<=9'b111001101;
   weights[12]<=9'b000000010;
   weights[13]<=9'b111010111;
   weights[14]<=9'b111100000;
   weights[15]<=9'b000010011;
   weights[16]<=9'b000011111;
   weights[17]<=9'b110111101;
   weights[18]<=9'b000100001;
   weights[19]<=9'b101101101;
   weights[20]<=9'b111011000;
   weights[21]<=9'b000100110;
   weights[22]<=9'b111101110;
   weights[23]<=9'b000001010;
   weights[24]<=9'b111101010;
   weights[25]<=9'b111101001;
   weights[26]<=9'b110011011;
   weights[27]<=9'b111101101;
   weights[28]<=9'b111100000;
   weights[29]<=9'b000011001;
   weights[30]<=9'b111111101;
   weights[31]<=9'b111111010;
   weights[32]<=9'b111110011;
   weights[33]<=9'b111111011;
   weights[34]<=9'b111101000;
   weights[35]<=9'b000011011;
   weights[36]<=9'b111101100;
   weights[37]<=9'b111110111;
   weights[38]<=9'b000010100;
   weights[39]<=9'b111111101;
   weights[40]<=9'b000011010;
   weights[41]<=9'b111011101;
   weights[42]<=9'b000101011;
   weights[43]<=9'b000001110;
   weights[44]<=9'b111100010;
   weights[45]<=9'b111101010;
   weights[46]<=9'b000010010;
   weights[47]<=9'b111001100;
   weights[48]<=9'b000101111;
   weights[49]<=9'b110011100;
   weights[50]<=9'b111101111;
   weights[51]<=9'b111000111;
   weights[52]<=9'b000001100;
   weights[53]<=9'b000110001;
   weights[54]<=9'b110101110;
   weights[55]<=9'b111111101;
   weights[56]<=9'b111111111;
   weights[57]<=9'b000011100;
   weights[58]<=9'b111110001;
   weights[59]<=9'b000001111;
   weights[60]<=9'b111110010;
   weights[61]<=9'b000010011;
   weights[62]<=9'b000001011;
   weights[63]<=9'b111010111;
   bias<=8'b00010000;
 end
 
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module NODE_11(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b001000010;
   weights[1]<=9'b000111100;
   weights[2]<=9'b000000010;
   weights[3]<=9'b000000111;
   weights[4]<=9'b000011011;
   weights[5]<=9'b111110001;
   weights[6]<=9'b000001000;
   weights[7]<=9'b110110011;
   weights[8]<=9'b000011010;
   weights[9]<=9'b111110100;
   weights[10]<=9'b111111000;
   weights[11]<=9'b000001011;
   weights[12]<=9'b000000111;
   weights[13]<=9'b111111001;
   weights[14]<=9'b000110011;
   weights[15]<=9'b000101110;
   weights[16]<=9'b000011110;
   weights[17]<=9'b000010110;
   weights[18]<=9'b000100010;
   weights[19]<=9'b110101101;
   weights[20]<=9'b111010111;
   weights[21]<=9'b110111111;
   weights[22]<=9'b111111000;
   weights[23]<=9'b000011101;
   weights[24]<=9'b000001110;
   weights[25]<=9'b110110011;
   weights[26]<=9'b000011001;
   weights[27]<=9'b111011111;
   weights[28]<=9'b000001001;
   weights[29]<=9'b000001100;
   weights[30]<=9'b111111000;
   weights[31]<=9'b000001100;
   weights[32]<=9'b111110111;
   weights[33]<=9'b111010011;
   weights[34]<=9'b111010110;
   weights[35]<=9'b111110010;
   weights[36]<=9'b111111111;
   weights[37]<=9'b111011110;
   weights[38]<=9'b111010110;
   weights[39]<=9'b000010111;
   weights[40]<=9'b000010000;
   weights[41]<=9'b000010111;
   weights[42]<=9'b111101100;
   weights[43]<=9'b000100000;
   weights[44]<=9'b111111100;
   weights[45]<=9'b111101000;
   weights[46]<=9'b000000010;
   weights[47]<=9'b111101001;
   weights[48]<=9'b111111001;
   weights[49]<=9'b110000011;
   weights[50]<=9'b000100101;
   weights[51]<=9'b111111011;
   weights[52]<=9'b111011010;
   weights[53]<=9'b000000011;
   weights[54]<=9'b000000101;
   weights[55]<=9'b111101110;
   weights[56]<=9'b111110100;
   weights[57]<=9'b111101100;
   weights[58]<=9'b111111101;
   weights[59]<=9'b111100101;
   weights[60]<=9'b111100100;
   weights[61]<=9'b000001010;
   weights[62]<=9'b111010101;
   weights[63]<=9'b111110111;
   bias<=8'b11110101;
 end
 
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module NODE_2(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b110100111;
   weights[1]<=9'b111110100;
   weights[2]<=9'b111110010;
   weights[3]<=9'b001000011;
   weights[4]<=9'b000011010;
   weights[5]<=9'b111101111;
   weights[6]<=9'b111010100;
   weights[7]<=9'b000011000;
   weights[8]<=9'b000010000;
   weights[9]<=9'b111011111;
   weights[10]<=9'b111111000;
   weights[11]<=9'b111110001;
   weights[12]<=9'b111111100;
   weights[13]<=9'b000000110;
   weights[14]<=9'b000000101;
   weights[15]<=9'b000000101;
   weights[16]<=9'b111111100;
   weights[17]<=9'b111101000;
   weights[18]<=9'b000000010;
   weights[19]<=9'b000001011;
   weights[20]<=9'b000010010;
   weights[21]<=9'b110011010;
   weights[22]<=9'b000010101;
   weights[23]<=9'b110111110;
   weights[24]<=9'b111110111;
   weights[25]<=9'b000110100;
   weights[26]<=9'b000001001;
   weights[27]<=9'b111111001;
   weights[28]<=9'b111100000;
   weights[29]<=9'b000010010;
   weights[30]<=9'b000011011;
   weights[31]<=9'b000100001;
   weights[32]<=9'b000101011;
   weights[33]<=9'b000110011;
   weights[34]<=9'b110100110;
   weights[35]<=9'b111101111;
   weights[36]<=9'b000011000;
   weights[37]<=9'b111011110;
   weights[38]<=9'b111001110;
   weights[39]<=9'b000001000;
   weights[40]<=9'b000000111;
   weights[41]<=9'b000010000;
   weights[42]<=9'b000001000;
   weights[43]<=9'b000011111;
   weights[44]<=9'b111001100;
   weights[45]<=9'b111001110;
   weights[46]<=9'b111101101;
   weights[47]<=9'b000011111;
   weights[48]<=9'b000000110;
   weights[49]<=9'b000001110;
   weights[50]<=9'b000001011;
   weights[51]<=9'b111111110;
   weights[52]<=9'b111101110;
   weights[53]<=9'b111101011;
   weights[54]<=9'b000100111;
   weights[55]<=9'b000001011;
   weights[56]<=9'b111110010;
   weights[57]<=9'b111110010;
   weights[58]<=9'b000001111;
   weights[59]<=9'b111101001;
   weights[60]<=9'b111111100;
   weights[61]<=9'b111100010;
   weights[62]<=9'b000000111;
   weights[63]<=9'b110111000;
   bias<=8'b00001101;
 end
 
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module NODE_13(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b111100010;
   weights[1]<=9'b000000000;
   weights[2]<=9'b000001101;
   weights[3]<=9'b111100001;
   weights[4]<=9'b111010101;
   weights[5]<=9'b000000111;
   weights[6]<=9'b001100101;
   weights[7]<=9'b110011011;
   weights[8]<=9'b111100101;
   weights[9]<=9'b111110011;
   weights[10]<=9'b111111001;
   weights[11]<=9'b110101011;
   weights[12]<=9'b000001110;
   weights[13]<=9'b111000100;
   weights[14]<=9'b111110100;
   weights[15]<=9'b111111100;
   weights[16]<=9'b000100101;
   weights[17]<=9'b110000100;
   weights[18]<=9'b111011010;
   weights[19]<=9'b111011011;
   weights[20]<=9'b111001101;
   weights[21]<=9'b000110100;
   weights[22]<=9'b111110100;
   weights[23]<=9'b111010110;
   weights[24]<=9'b000100010;
   weights[25]<=9'b101001010;
   weights[26]<=9'b110111100;
   weights[27]<=9'b000011101;
   weights[28]<=9'b111000111;
   weights[29]<=9'b111111000;
   weights[30]<=9'b111100111;
   weights[31]<=9'b000111101;
   weights[32]<=9'b000010010;
   weights[33]<=9'b000100111;
   weights[34]<=9'b000011101;
   weights[35]<=9'b000001001;
   weights[36]<=9'b000001010;
   weights[37]<=9'b000001001;
   weights[38]<=9'b000101001;
   weights[39]<=9'b000010011;
   weights[40]<=9'b111101100;
   weights[41]<=9'b111110011;
   weights[42]<=9'b000001000;
   weights[43]<=9'b000001100;
   weights[44]<=9'b000001101;
   weights[45]<=9'b000111100;
   weights[46]<=9'b111111110;
   weights[47]<=9'b000000011;
   weights[48]<=9'b111110110;
   weights[49]<=9'b000100110;
   weights[50]<=9'b101001101;
   weights[51]<=9'b110101001;
   weights[52]<=9'b111111010;
   weights[53]<=9'b001001000;
   weights[54]<=9'b110010111;
   weights[55]<=9'b000000110;
   weights[56]<=9'b111111010;
   weights[57]<=9'b111111010;
   weights[58]<=9'b111010100;
   weights[59]<=9'b111100110;
   weights[60]<=9'b000000010;
   weights[61]<=9'b000111111;
   weights[62]<=9'b111101000;
   weights[63]<=9'b001011001;
   bias<=8'b00010000;
 end
 
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module RELU1(
input [22:0] a,
input clk,
input enable,
input read_strobe,
output reg [21:0] out,
output reg write_strobe,
output reg done
    );

always@(posedge clk) begin
    done <= enable;
  if (enable && read_strobe) begin
    if (a[22] == 1) begin
      out <= 0;
      write_strobe <= 1;
    end
    else begin
      out <= a[21:0];
      write_strobe <= 1;
    end
  end else write_strobe <= 0;
end
endmodule
module TB_Counter;
    reg clk;
    reg reset;
    reg start;
    
    wire [6:0] count1,count2;
    
    Counter uut( .clk(clk), .start(start), .reset(reset), .count1(count1), .count2(count2));
    
    always #5 clk = ~clk;
    initial begin
        clk = 0;
        reset = 0;
        start = 0;
        #22;
        start = 1;
    end
endmodule
module TB_WeightsRAM;
    reg clk;
    reg [2:0] addr;
    wire [127:0] weights;
    
    WeightsRAM_R uut( .clk(clk), .addr(addr), .weights(weights));
    
    always #5 clk = ~clk;
    
    initial begin
        clk = 0;
        addr = 3'd0;
        #10;
        addr = 3'd1;
        #10;
        addr = 3'd5;
        #10;
        addr = 3'd7;
        #10;
    end
    
    
endmodule
module TB_AdderTree;
    reg signed [7:0] w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16;
    reg clk;
    reg start;
    reg reset;
    wire count_done;
    wire signed [19:0] result;
    
    AdderTree_R uut( .clk(clk), .count_done(count_done), .result(result), .w1(w1), .w2(w2), .w3(w3), .w4(w4), .w5(w5),
    .w6(w6), .w7(w7), .w8(w8), .w9(w9), .w10(w10), .w11(w11), .w12(w12), .w13(w13), .w14(w14), .w15(w15), .w16(w16));
    
    Counter counter( .clk(clk), .start(start), .reset(reset), /*.count1(count1), .count2(count2),*/ .done(count_done));
    always #5 clk = ~clk;
    
    initial begin
        clk = 0;
        reset = 1;
        start = 0;
        #12;
        start = 1;
        reset = 0;
        w1 = 1;
        w2 = 1;
        w3 = 1;
        w4 = 1;
        w5 = 1;
        w6 = 1;
        w7 = 1;
        w8 = 1;
        w9 = 1;
        w10 = 1;
        w11 = 1;
        w12 = 1;
        w13 = 1;
        w14 = 1;
        w15 = 1;
        w16 = 1;
    end

endmodule
module TB_ShiftReg;
    reg clk;
    reg [7:0] x;
    
    wire [7:0] o1,o2,o3,o4,o5,o6,o7,o8,o9,o10,o11,o12,o13,o14,o15,o16;
    
    ShiftReg uut(.clk(clk), .x(x), .o1(o1), .o2(o2), .o3(o3), .o4(o4), .o5(o5), .o6(o6), .o7(o7), .o8(o8),
         .o9(o9), .o10(o10), .o11(o11), .o12(o12), .o13(o13), .o14(o14), .o15(o15), .o16(o16));
     
     always #5 clk = ~clk;
     
     integer input_File;
         
     initial begin
         clk = 0;
         input_File=$fopen("image.txt","r");  
     end
     
     always @ (posedge clk)
     begin
 
         $fscanf(input_File,"%d\n",x);
         if($feof(input_File))
         begin
             $fclose(input_File);
             $finish;
         end
     end
       

endmodule
module NODE_7(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b111110010;
   weights[1]<=9'b000011000;
   weights[2]<=9'b000011000;
   weights[3]<=9'b111110110;
   weights[4]<=9'b110110010;
   weights[5]<=9'b111100100;
   weights[6]<=9'b000001100;
   weights[7]<=9'b111111110;
   weights[8]<=9'b111111111;
   weights[9]<=9'b111010100;
   weights[10]<=9'b000010101;
   weights[11]<=9'b111010110;
   weights[12]<=9'b000001000;
   weights[13]<=9'b000010001;
   weights[14]<=9'b000001011;
   weights[15]<=9'b111110110;
   weights[16]<=9'b111101010;
   weights[17]<=9'b001010110;
   weights[18]<=9'b111011001;
   weights[19]<=9'b000010000;
   weights[20]<=9'b111100001;
   weights[21]<=9'b000100101;
   weights[22]<=9'b000111000;
   weights[23]<=9'b000011100;
   weights[24]<=9'b000110011;
   weights[25]<=9'b000000111;
   weights[26]<=9'b111000110;
   weights[27]<=9'b111101010;
   weights[28]<=9'b111100001;
   weights[29]<=9'b000100011;
   weights[30]<=9'b110100010;
   weights[31]<=9'b110101110;
   weights[32]<=9'b111111000;
   weights[33]<=9'b000101011;
   weights[34]<=9'b111101110;
   weights[35]<=9'b111101001;
   weights[36]<=9'b111111111;
   weights[37]<=9'b000111110;
   weights[38]<=9'b000011010;
   weights[39]<=9'b000001111;
   weights[40]<=9'b000101000;
   weights[41]<=9'b000000001;
   weights[42]<=9'b000010100;
   weights[43]<=9'b000001100;
   weights[44]<=9'b111010111;
   weights[45]<=9'b111101010;
   weights[46]<=9'b111101110;
   weights[47]<=9'b000000100;
   weights[48]<=9'b111111000;
   weights[49]<=9'b000000011;
   weights[50]<=9'b001001001;
   weights[51]<=9'b000001110;
   weights[52]<=9'b111101101;
   weights[53]<=9'b000100110;
   weights[54]<=9'b111000100;
   weights[55]<=9'b111111010;
   weights[56]<=9'b110110111;
   weights[57]<=9'b000010000;
   weights[58]<=9'b000000110;
   weights[59]<=9'b111110001;
   weights[60]<=9'b000011100;
   weights[61]<=9'b111011101;
   weights[62]<=9'b000010011;
   weights[63]<=9'b000000010;
   bias<=8'b00011001;
 end
 
 //MAIN SYNCHRONOUS ACCUMULATION BLOCK
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end
 
endmodule
module Counter_64(
    input clk,
    input start,
    input reset,
    output reg [6:0] count1,
    output reg [6:0] count2,
    output reg done
    );
    
    parameter mod = 64;
    
    always @ ( posedge clk )
    begin
        if( reset || ~start )
        begin
            count1 <= 0;
            count2 <= 0;
            done <= 0;
        end else if ( start )
        begin
            if( count2 < mod-1 )
            begin
                if( count1 < mod-1+3 )
                begin
                    count1 <= count1 + 1;
                    done <= 0;
                end else
                begin
                    count1 <= 0;
                    count2 <= count2 + 1;
                    done <= 0;
                end
            end else if ( count2 == mod-1 )
            begin
                if( count1 < mod - 2+3 )
                    begin
                        count1 <= count1 + 1;
                        done <= 0;
                    end else if ( count1 == mod - 2+3 )
                    begin
                        count1 <= count1 + 1;
                        done <= 1;
                    end
                    else
                    begin
                        count1 <= 0;
                        count2 <= 0;
                        done <= 0;
                    end
            end
        end
    end
endmodule
module NODE_3(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

 initial begin
   weights[0]<=9'b000111001;
   weights[1]<=9'b000011010;
   weights[2]<=9'b111111101;
   weights[3]<=9'b000111110;
   weights[4]<=9'b000001011;
   weights[5]<=9'b110000001;
   weights[6]<=9'b000001001;
   weights[7]<=9'b111111000;
   weights[8]<=9'b111010001;
   weights[9]<=9'b111111100;
   weights[10]<=9'b000001101;
   weights[11]<=9'b111101010;
   weights[12]<=9'b000001010;
   weights[13]<=9'b111011000;
   weights[14]<=9'b000011100;
   weights[15]<=9'b000011100;
   weights[16]<=9'b111101110;
   weights[17]<=9'b111100100;
   weights[18]<=9'b111101100;
   weights[19]<=9'b111110101;
   weights[20]<=9'b111101100;
   weights[21]<=9'b110000001;
   weights[22]<=9'b111101100;
   weights[23]<=9'b001101110;
   weights[24]<=9'b111100101;
   weights[25]<=9'b001001010;
   weights[26]<=9'b001000011;
   weights[27]<=9'b111110111;
   weights[28]<=9'b001000011;
   weights[29]<=9'b000001000;
   weights[30]<=9'b000000010;
   weights[31]<=9'b111110111;
   weights[32]<=9'b111101001;
   weights[33]<=9'b000011110;
   weights[34]<=9'b000010101;
   weights[35]<=9'b111001010;
   weights[36]<=9'b000000001;
   weights[37]<=9'b000010000;
   weights[38]<=9'b000001011;
   weights[39]<=9'b000000101;
   weights[40]<=9'b111111001;
   weights[41]<=9'b000001110;
   weights[42]<=9'b111001101;
   weights[43]<=9'b111101011;
   weights[44]<=9'b111011101;
   weights[45]<=9'b111101111;
   weights[46]<=9'b000000001;
   weights[47]<=9'b000100001;
   weights[48]<=9'b000000100;
   weights[49]<=9'b111110100;
   weights[50]<=9'b000100101;
   weights[51]<=9'b000110001;
   weights[52]<=9'b000011001;
   weights[53]<=9'b000001011;
   weights[54]<=9'b111100100;
   weights[55]<=9'b111111001;
   weights[56]<=9'b000011010;
   weights[57]<=9'b111100000;
   weights[58]<=9'b000101111;
   weights[59]<=9'b000000101;
   weights[60]<=9'b000000111;
   weights[61]<=9'b000000000;
   weights[62]<=9'b111111001;
   weights[63]<=9'b111100001;
   bias<=8'b00001010;
 end
 
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module NODE_12(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b110101110;
   weights[1]<=9'b000001110;
   weights[2]<=9'b000010101;
   weights[3]<=9'b111001010;
   weights[4]<=9'b111110100;
   weights[5]<=9'b001000001;
   weights[6]<=9'b000110111;
   weights[7]<=9'b001011100;
   weights[8]<=9'b111100110;
   weights[9]<=9'b000100100;
   weights[10]<=9'b111111010;
   weights[11]<=9'b111001110;
   weights[12]<=9'b000000011;
   weights[13]<=9'b111011010;
   weights[14]<=9'b111111011;
   weights[15]<=9'b111101100;
   weights[16]<=9'b000000000;
   weights[17]<=9'b111111111;
   weights[18]<=9'b000010101;
   weights[19]<=9'b111001111;
   weights[20]<=9'b000010111;
   weights[21]<=9'b111111111;
   weights[22]<=9'b111100011;
   weights[23]<=9'b111110010;
   weights[24]<=9'b111101110;
   weights[25]<=9'b111010011;
   weights[26]<=9'b111100000;
   weights[27]<=9'b111101010;
   weights[28]<=9'b000011000;
   weights[29]<=9'b111111011;
   weights[30]<=9'b111101110;
   weights[31]<=9'b000111000;
   weights[32]<=9'b000101001;
   weights[33]<=9'b000001000;
   weights[34]<=9'b000000000;
   weights[35]<=9'b000101011;
   weights[36]<=9'b000001101;
   weights[37]<=9'b000001000;
   weights[38]<=9'b000001011;
   weights[39]<=9'b111101110;
   weights[40]<=9'b111100110;
   weights[41]<=9'b111010011;
   weights[42]<=9'b000000100;
   weights[43]<=9'b000001101;
   weights[44]<=9'b000101011;
   weights[45]<=9'b000101100;
   weights[46]<=9'b111100010;
   weights[47]<=9'b000010011;
   weights[48]<=9'b000001000;
   weights[49]<=9'b000010000;
   weights[50]<=9'b111100100;
   weights[51]<=9'b110001011;
   weights[52]<=9'b000001011;
   weights[53]<=9'b000001011;
   weights[54]<=9'b111101011;
   weights[55]<=9'b000010001;
   weights[56]<=9'b000010001;
   weights[57]<=9'b111011110;
   weights[58]<=9'b111110000;
   weights[59]<=9'b000000010;
   weights[60]<=9'b111110011;
   weights[61]<=9'b000001101;
   weights[62]<=9'b000000011;
   weights[63]<=9'b111111011;
   bias<=8'b11101100;
 end
 
 //MAIN SYNCHRONOUS ACCUMULATION BLOCK
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end
 
endmodule
module NODE_5(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b111101001;
   weights[1]<=9'b111110010;
   weights[2]<=9'b111101001;
   weights[3]<=9'b000000010;
   weights[4]<=9'b000001000;
   weights[5]<=9'b111101101;
   weights[6]<=9'b000011110;
   weights[7]<=9'b111010000;
   weights[8]<=9'b111111111;
   weights[9]<=9'b000010000;
   weights[10]<=9'b000010110;
   weights[11]<=9'b111010100;
   weights[12]<=9'b111100111;
   weights[13]<=9'b001000010;
   weights[14]<=9'b000100110;
   weights[15]<=9'b000000001;
   weights[16]<=9'b000001010;
   weights[17]<=9'b111000100;
   weights[18]<=9'b111010111;
   weights[19]<=9'b110000101;
   weights[20]<=9'b111101101;
   weights[21]<=9'b000001110;
   weights[22]<=9'b000011001;
   weights[23]<=9'b000111000;
   weights[24]<=9'b110111110;
   weights[25]<=9'b000011010;
   weights[26]<=9'b000010010;
   weights[27]<=9'b111110011;
   weights[28]<=9'b110111111;
   weights[29]<=9'b111000110;
   weights[30]<=9'b111101101;
   weights[31]<=9'b000101100;
   weights[32]<=9'b111011110;
   weights[33]<=9'b111011000;
   weights[34]<=9'b000010101;
   weights[35]<=9'b111101111;
   weights[36]<=9'b000010001;
   weights[37]<=9'b000100000;
   weights[38]<=9'b111101011;
   weights[39]<=9'b000011100;
   weights[40]<=9'b000001110;
   weights[41]<=9'b000100010;
   weights[42]<=9'b000010001;
   weights[43]<=9'b111110101;
   weights[44]<=9'b111111101;
   weights[45]<=9'b111110100;
   weights[46]<=9'b111011100;
   weights[47]<=9'b000101011;
   weights[48]<=9'b000011101;
   weights[49]<=9'b111100101;
   weights[50]<=9'b111010110;
   weights[51]<=9'b111110101;
   weights[52]<=9'b111101011;
   weights[53]<=9'b000000110;
   weights[54]<=9'b111101100;
   weights[55]<=9'b000010001;
   weights[56]<=9'b111110100;
   weights[57]<=9'b000101100;
   weights[58]<=9'b111110010;
   weights[59]<=9'b111110010;
   weights[60]<=9'b000010101;
   weights[61]<=9'b110100010;
   weights[62]<=9'b000011110;
   weights[63]<=9'b111100101;
   bias<=8'b00010101;
 end

 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end
 
endmodule
module RELU2(
input [35:0] a,
input clk,
input enable,
input read_strobe,
output reg [35:0] out,
output reg write_strobe,
output reg done
    );

always@(posedge clk) begin
    done <= enable;
  if (enable && read_strobe) begin
    if (a[35] == 1) begin
      out <= 0;
      write_strobe <= 1;
    end
    else begin
      out <= a;
      write_strobe <= 1;
    end
  end else write_strobe <= 0;
end
endmodule
module NODE_9(
input signed [35:0] A,
input [5:0] step,
input CLK,
input ENABLE,
input RST,
output reg signed [39:0] OUT //16-bit output
    );
    
reg signed [39:0] accumulator = 40'd0; //store the matrix mult here
reg signed [8:0] weights [63:0]; //store the weights here
reg signed [7:0] bias; //store node bias here

initial begin
   weights[0]<=9'b000010011;
   weights[1]<=9'b000111100;
   weights[2]<=9'b111110110;
   weights[3]<=9'b111011101;
   weights[4]<=9'b111011110;
   weights[5]<=9'b111000010;
   weights[6]<=9'b000000000;
   weights[7]<=9'b110100101;
   weights[8]<=9'b111101000;
   weights[9]<=9'b111110101;
   weights[10]<=9'b111111011;
   weights[11]<=9'b000001010;
   weights[12]<=9'b000010000;
   weights[13]<=9'b111101100;
   weights[14]<=9'b000010111;
   weights[15]<=9'b111001010;
   weights[16]<=9'b000100000;
   weights[17]<=9'b000010110;
   weights[18]<=9'b111111001;
   weights[19]<=9'b110101101;
   weights[20]<=9'b111101001;
   weights[21]<=9'b000100101;
   weights[22]<=9'b111010101;
   weights[23]<=9'b110011111;
   weights[24]<=9'b101111111;
   weights[25]<=9'b111010010;
   weights[26]<=9'b111100101;
   weights[27]<=9'b000101001;
   weights[28]<=9'b111101011;
   weights[29]<=9'b111100101;
   weights[30]<=9'b000000001;
   weights[31]<=9'b110110011;
   weights[32]<=9'b000001011;
   weights[33]<=9'b000000010;
   weights[34]<=9'b000000111;
   weights[35]<=9'b000100111;
   weights[36]<=9'b000000101;
   weights[37]<=9'b111111001;
   weights[38]<=9'b111101101;
   weights[39]<=9'b000010010;
   weights[40]<=9'b111100010;
   weights[41]<=9'b110111011;
   weights[42]<=9'b000011111;
   weights[43]<=9'b000010011;
   weights[44]<=9'b111011110;
   weights[45]<=9'b000101011;
   weights[46]<=9'b000000010;
   weights[47]<=9'b111100110;
   weights[48]<=9'b000010100;
   weights[49]<=9'b000111000;
   weights[50]<=9'b111001001;
   weights[51]<=9'b111011010;
   weights[52]<=9'b000010100;
   weights[53]<=9'b000001011;
   weights[54]<=9'b110010000;
   weights[55]<=9'b111111110;
   weights[56]<=9'b111010110;
   weights[57]<=9'b000000111;
   weights[58]<=9'b111101001;
   weights[59]<=9'b111111000;
   weights[60]<=9'b000000011;
   weights[61]<=9'b111110010;
   weights[62]<=9'b000100101;
   weights[63]<=9'b111011001;
   bias<=8'b11110001;
 end
 
 //MAIN SYNCHRONOUS ACCUMULATION BLOCK
 always @ ( posedge CLK )
 begin
    if( ENABLE == 1 && RST == 0 )
    begin
        if ( step == 0 )
        begin
            accumulator <=  A * weights[step];
        end
        else if( step == 63 )
        begin
            OUT <= accumulator + bias + A * weights[step];
        end else accumulator <=  A * weights[step] + accumulator;
    end
 end

endmodule
module MAXPOOL2(
    input  [35:0] mx2_input,
    input  clk,
    input  enable,
    input  reset,
    input  read_strobe,
	output reg [1:0]  mx2_done,
	output reg [3:0]  mx2_count =1'b0, // muhtemelen degismesi gerekecek
    output reg [35:0] mx2_output
    );
    
	wire [35:0] mx2_input_reg;
    wire [3:0] count1, count2; //bitleri degisecek
    wire done;
    reg [35:0] temp1 = 35'd0, temp2 = 35'd0;
    //reg start = 1'b0;
	 
	assign mx2_input_reg = mx2_input;
	 
    counter_8 counter8 ( // 8 e çevirilecek
        .clk(clk), 
        .start(enable), 
        .reset(reset), 
        .count1(count1), 
        .count2(count2), 
        .done(done)
        );
        
    //always @ ( posedge read_strobe ) if(enable) start <= 1;
    //always @ ( posedge clk ) begin if ( done ) start <= 0; end

    always @(posedge clk)
    begin
    if(reset)
        mx2_count <= 0;
    else if (done)
        mx2_count <= mx2_count + 1;
    else if((mx2_count % 4) == 0 )
        mx2_count <= 0;
    end    
      
    always @(posedge clk)
    begin 
        if(enable && (( count2 == 3 )|( count2 == 7 )))
			begin
			if(count1 == 4)
				begin mx2_output <= temp1; mx2_done <= 1; end
			else if(count1 == 8)
				begin mx2_output <= temp2; mx2_done <= 2; end
			else 
				begin mx2_output <= -1;    mx2_done <= 0; end
			end
		else  mx2_done <= 0;
    end  
    
    always @ (posedge clk)
    begin
		 if(reset || (mx2_done == 2))
		 begin 
			//mx_done <= 0;
            temp1 <= 0; temp2 <= 0;  
		 end
		 else if(read_strobe && enable) begin
           if(count1 <  4 && temp1 < mx2_input_reg)
                temp1 <= mx2_input_reg;
           if(count1 >= 4 && count1  < 8 && temp2 < mx2_input_reg)
                temp2 <= mx2_input_reg;
		 end
    end     
        
endmodule
module DualPortBRAM #(
    parameter DATA = 72,
    parameter ADDR = 10
) (
    input   wire               clk,

    // Port A
    input   wire                a_wr,
    input   wire    [ADDR-1:0]  a_addr,
    input   wire    [DATA-1:0]  a_din,
    output  reg     [DATA-1:0]  a_dout,

    // Port B
    input   wire                b_wr,
    input   wire    [ADDR-1:0]  b_addr,
    input   wire    [DATA-1:0]  b_din,
    output  reg     [DATA-1:0]  b_dout
);

// Shared memory
reg [DATA-1:0] mem [(2**ADDR)-1:0];

// Port A
always @(posedge clk) begin
    a_dout      <= mem[a_addr];
    if(a_wr) begin
        a_dout      <= a_din;
        mem[a_addr] <= a_din;
    end
end

// Port B
always @(posedge clk) begin
    b_dout      <= mem[b_addr];
    if(b_wr) begin
        b_dout      <= b_din;
        mem[b_addr] <= b_din;
    end
end

endmodule
module singleKeyExpansion( 
  input  [127:0] keyInput ,
	input clk,
	input enable,
	input reset,
	input [3:0] keyNum,
  output  reg [127:0] keyOutput
  );
    wire [31:0] stp1 ;
  wire [31:0] stp2 ;
  wire [31:0]Rcon ;
    

 	 rcon uut1 (.r(keyNum),.rcon(Rcon));
   subByte uut2 (.state(stp1) , .state_out(stp2));
	 
    assign stp1 = { keyInput[23:0] , keyInput[31:24] }; 
	
    initial keyOutput = 0;
    always @(posedge clk) 
     begin
        if ( reset == 1 )
        begin 
        keyOutput = 0;
            /* donothing */
        end 
        else 
        begin 
            if(enable)
                begin 
                    keyOutput[127:96] = keyInput[127:96] ^ stp2 ^ Rcon; 	
                    keyOutput[95:64] = keyInput[95:64] ^ keyOutput[127:96];
                    keyOutput[63:32] = keyInput[63:32] ^ keyOutput[95:64];
                    keyOutput[31:0] = keyInput[31:0] ^ keyOutput[63:32];
                end
        end 
    end

/* 
// This requires two cycles for the output to be settled 

    wire [127:0] keyOutComb;
    assign keyOutComb[127:96] = keyInput[127:96] ^ stp2 ^ Rcon; 	
    assign keyOutComb[95:64] = keyInput[95:64] ^ keyOutput[127:96];
    assign keyOutComb[63:32] = keyInput[63:32] ^ keyOutput[95:64];
    assign keyOutComb[31:0] = keyInput[31:0] ^ keyOutput[63:32];

    initial keyOutput = 0;
    
    always @(posedge clk) 
     begin
        if ( reset == 1 )
        begin 
        keyOutput= 0;
            // donothing 
        end 
        else 
            if(enable)
                keyOutput <= keyOutComb;
    end
*/

`ifdef FORMAL

    reg f_past_valid; // to know if the $past value is valid to process
    initial f_past_valid = 0;

    initial assume(reset);


    always @(posedge clk)
        f_past_valid = 1;

    // sync reset
    // the design starts at reset state so if no f_past_valid it should be on reset
    // if the past cycle had reset then it should be in reset state
    always @(posedge clk)
        if(!f_past_valid || $past(reset))
            assert(keyOutput == 128'd0);


    // sync enable

    // if enable is valid 
    // assume stable input key == $past(key) and state == $past(state) 
    always @(posedge clk)
        if(enable || $past(enable))
            assume($stable(keyInput));
    always @(posedge clk)
        if(enable || $past(enable))
            assume($stable(keyNum));


`endif

endmodule
module rcon(
input [3:0] r,
output reg [31:0] rcon // output reg [3:0]  rcon [7:0] // can't do that ._. 
);

always @(*)
 case(r)
    4'h1: rcon=32'h01000000;
    4'h2: rcon=32'h02000000;
    4'h3: rcon=32'h04000000;
    4'h4: rcon=32'h08000000;
    4'h5: rcon=32'h10000000;
    4'h6: rcon=32'h20000000;
    4'h7: rcon=32'h40000000;
    4'h8: rcon=32'h80000000;
    4'h9: rcon=32'h1b000000;
    4'ha: rcon=32'h36000000;
    default: rcon=32'h00000000;
  endcase
endmodule
module subByte
	(
	input wire [31:0] state,
	output wire  [31:0]state_out
	);



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


/* cannot instantiate instances inisde initial block. */

genvar itr;
genvar jtr;
generate
		for (itr = 0 ; itr <= 31; itr = itr+8)
					s_box sbox (state[itr +:8] , state_out[itr +:8]);
endgenerate


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



endmodule
module addRoundKey(
	input wire [127:0] key ,
	input wire [127:0] state,
	input  clk,enable, reset,
	output reg  [127:0]state_out,
	output reg done);

//	integer i;

    // separating the combinational from the sequential 
    wire [127:0] state_out_comb; 
    genvar ii;
    for (ii=0 ;ii<=15; ii=ii+1)
        assign state_out_comb[ii*8 +: 8] = key[ii*8  +:  8] ^ state[ii*8  +:  8];

    initial state_out <= 0;
    initial done <= 0;

    always@(posedge clk)
    begin
        if (reset) begin
            state_out<=128'd0;
            done <= 0;
        end 
        else if (enable) begin 
            //	for ( i=0; i<=15; i=i+1)
            //		state_out[i*8  +:  8] <= key[i*8  +:  8] ^ state[i*8  +:  8];
            state_out <= state_out_comb;
            done <= 1;
        end 
        else done <= 0;
    end



`ifdef FORMAL

    reg f_past_valid; // to know if the $past value is valid to process
    initial f_past_valid = 0;

    initial assume(reset);


    always @(posedge clk)
        f_past_valid = 1;

    // sync reset
    // the design starts at reset state so if no f_past_valid it should be on reset
    // if the past cycle had reset then it should be in reset state
    always @(posedge clk)
        if(!f_past_valid || $past(reset))
        begin
            assert(state_out == 128'd0);
            assert(done == 1'b0);
        end


    // sync enable

    // if enable is valid 
    // assume stable input key == $past(key) and state == $past(state) 
    always @(posedge clk)
        if(enable || $past(enable))
            assume($stable(state));
    always @(posedge clk)
        if(enable || $past(enable))
            assume($stable(key));
        
    always @(posedge clk)
        if(done)
            assert(state_out == key^state);

`endif
endmodule
module singleKeyExpansion( 
  input  [127:0] keyInput ,
	input clk,
	input enable,
	input reset,
	input [3:0] keyNum,
  output  reg [127:0] keyOutput);
  
	reg [31:0] stp1 ;
  wire [31:0] stp2 ;
  wire [31:0]Rcon ;

 	 rcon uut1 (.r(keyNum),.rcon(Rcon));
   subByte uut2 (.state(stp1) , .state_out(stp2));
	 
	 always @(negedge clk)
	 begin 
		if(enable)
			stp1 	<= { keyInput[25:0] , keyInput[31:24] }; 
	 end 

always @(posedge clk) 
 begin
	if ( reset == 1 )
	begin 
	keyOutput = 0;
		/* donothing */
	end 
	else 
	begin 
		if(enable)
			begin 
				keyOutput[127:96] = keyInput[127:96] ^ stp2 ^ Rcon; 	
				keyOutput[95:64] = keyInput[95:64] ^ keyOutput[127:96];
				keyOutput[63:32] = keyInput[63:32] ^ keyOutput[95:64];
				keyOutput[31:0] = keyInput[31:0] ^ keyOutput[63:32];
			end
	end 
end
 endmodule
module Inv_Shift_Rows 
 #(parameter word_size =8 ,array_size =16)(
  input en,clk,rst,
  input  wire [0:word_size*array_size-1] Shifted_Data,
	output reg  [0:word_size*array_size-1] Inv_Shifted_Data );
  
  reg [word_size-1:0] shifted_data [0:3] [0:3];
  reg [word_size-1:0] inv_shifted_data[0:3] [0:3];
 
 integer i,j,ij;	 
  
always @(posedge clk)
  begin
    if (rst)
	       Inv_Shifted_Data = 128'b0;
  else if (en) begin
    for ( i=0; i<=3; i=i+1)
	   for ( j=0; j<=3; j=j+1)
	      begin 
	        ij =((4*i)+j);
		      shifted_data[j][i]=Shifted_Data[ij*word_size  +:  word_size];
		    end	
		    
		 for ( i=0; i<=3; i=i+1)
	    for ( j=0; j<=3; j=j+1)
	     begin
	      if (i ==0)
	         inv_shifted_data[i][j] = shifted_data[i][j];
	      else if (i ==1)
	        begin
	         inv_shifted_data[1][0] = shifted_data[1][3];
           inv_shifted_data[1][1] = shifted_data[1][0];
           inv_shifted_data[1][2] = shifted_data[1][1];
           inv_shifted_data[1][3] = shifted_data[1][2];
          end
         else if (i ==2)
           begin
	          inv_shifted_data[2][0] = shifted_data[2][2];
	          inv_shifted_data[2][1] = shifted_data[2][3];
            inv_shifted_data[2][2] = shifted_data[2][0];
            inv_shifted_data[2][3] = shifted_data[2][1];
           end
          else if (i ==3) 
           begin
		        inv_shifted_data[3][0] = shifted_data[3][1];
            inv_shifted_data[3][1] = shifted_data[3][2];
            inv_shifted_data[3][2] = shifted_data[3][3];
            inv_shifted_data[3][3] = shifted_data[3][0];
           end
        end 
 
    for ( i=0; i<=3; i=i+1)
	    for ( j=0; j<=3; j=j+1)
	      begin 
	        ij =((4*i)+j);
	       	Inv_Shifted_Data[ij*word_size  +:  word_size]=inv_shifted_data[j][i];
		    end	
		    end
	 end
		   
  
endmodule