data/full_repos/permissive/494353034/rtl/src_top/CNN.v
1: b'%Warning-IMPLICIT: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:117: Signal definition not found, creating implicitly: \'weight_rerd\'\n                                                                             : ... Suggested alternative: \'weight_ready\'\n assign weight_rerd = weight_rerd_r;\n        ^~~~~~~~~~~\n                   ... Use "/* verilator lint_off IMPLICIT */" and lint_on around source to disable this message.\n%Warning-IMPLICIT: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:1206: Signal definition not found, creating implicitly: \'conv_start\'\n                                                                              : ... Suggested alternative: \'conv_cnt\'\nassign conv_start = start_conv;\n       ^~~~~~~~~~\n%Warning-IMPLICIT: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:1207: Signal definition not found, creating implicitly: \'window_start\'\nassign window_start = start_window;\n       ^~~~~~~~~~~~\n%Warning-IMPLICIT: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:1208: Signal definition not found, creating implicitly: \'done_conv\'\nassign done_conv = conv_done;\n       ^~~~~~~~~\n%Warning-WIDTH: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:343: Operator LTE expects 11 bits on the RHS, but RHS\'s CONST \'10\'h181\' generates 10 bits.\n                                                                          : ... In instance CNN\nelse if(cnt_fc <= 10\'d385)\n               ^~\n%Warning-WIDTH: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:339: Operator LTE expects 11 bits on the RHS, but RHS\'s CONST \'10\'h1\' generates 10 bits.\n                                                                          : ... In instance CNN\nif(cnt_fc <= 10\'d1)\n          ^~\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:727: Cannot find file containing module: \'window\'\nwindow window_inst(.clk(clk),.rstn(resetn),.start(start_window),.state(state),.din(image_in),.taps(taps));\n^~~~~~\n        ... Looked in:\n             data/full_repos/permissive/494353034/rtl/src_top,data/full_repos/permissive/494353034/window\n             data/full_repos/permissive/494353034/rtl/src_top,data/full_repos/permissive/494353034/window.v\n             data/full_repos/permissive/494353034/rtl/src_top,data/full_repos/permissive/494353034/window.sv\n             window\n             window.v\n             window.sv\n             obj_dir/window\n             obj_dir/window.v\n             obj_dir/window.sv\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:821: Cannot find file containing module: \'conv\'\n            conv u_conv(.clk(clk),\n            ^~~~\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:916: Cannot find file containing module: \'user_fifo_ip\'\n            user_fifo_ip your_instance_name(\n            ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:942: Cannot find file containing module: \'add\'\n            add u_add(\n            ^~~\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:982: Cannot find file containing module: \'relu\'\n            relu u_relu(\n            ^~~~\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:1010: Cannot find file containing module: \'maxpooling\'\n    maxpooling u_pooling(\n    ^~~~~~~~~~\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:1044: Cannot find file containing module: \'FIFO_fmap\'\n            FIFO_fmap u_FIFO_fmap (\n            ^~~~~~~~~\n%Error: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:1071: Cannot find file containing module: \'fc\'\n            fc u_fullconnect(\n            ^~\n%Warning-WIDTH: data/full_repos/permissive/494353034/rtl/src_top/CNN.v:1208: Operator ASSIGNW expects 1 bits on the Assign RHS, but Assign RHS\'s VARREF \'conv_done\' generates 6 bits.\n                                                                           : ... In instance CNN\nassign done_conv = conv_done;\n                 ^\n%Error: Exiting due to 8 error(s), 7 warning(s)\n'
module CNN
(
    input wire clk,
    input wire resetn,
    
    input wire start_cnn,
    
    input wire image_tvalid,
    output wire image_tready,
    input wire signed [7:0] image_tdata,
    
    input wire weight_tvalid,
    output wire weight_tready,
    input wire signed [7:0] weight_tdata,
    
    input wire weightfc_tvalid,
    output wire weightfc_tready,
    input wire signed [7:0] weightfc_tdata,
    
    output wire cnn_done,
   
    input wire result_tready,
    output wire result_tvalid,
    output wire signed [31:0] result_tdata,

    output wire [3:0] conv_cnt

);
	reg image_ready;
	reg weight_ready;
	reg weightfc_ready;
	reg result_valid_r;
	reg weight_rerd_r;
	reg cnn_done_r;
	reg signed [31:0] result_data;
	assign image_tready = image_ready;
	assign weight_tready = weight_ready;
	assign weightfc_tready = weightfc_ready;
	assign result_tvalid = result_valid_r;
	assign cnn_done = cnn_done_r;
	assign weight_rerd = weight_rerd_r;
	
	assign result_tdata = result_data;



	reg start_window;
	reg start_conv;


	wire [5:0] conv_wren;
	wire [5:0] add_wren;
	wire [5:0] relu_wren;
	wire [5:0] pooling_wren;
	wire [9:0] fc_wren;


	wire [5:0] conv_done;


	wire [39:0] taps;
	reg signed [31:0] add_data [0:5];
	reg signed [31:0] relu_data [0:5];
	

	wire signed [31:0] conv_result [0:5];
	wire signed [31:0] add_result [0:5];
	wire signed [7:0] relu_result [0:5];
	wire signed [7:0] pooling_result [0:5];
	wire signed [31:0] fc_result [0:9];
	reg signed [31:0] result_r0 [0:9];
	reg signed [31:0] result_r1 [0:9];




reg [3:0] conv_counter = 4'd0;


reg [5:0] fmap_rdrst;
reg [5:0] fmap_rden;


reg [7:0] image_in;                      


reg state; 


reg [10:0] weight_counter;


reg signed [7:0] weight_c [0:5];
reg signed [7:0] weight_fc [0:9];


reg [9:0] cnt;


reg [5:0] fmap_wren;
wire signed [7:0] fmap_dout [0:5];


reg [11:0] s_fifo_valid;
reg signed [31:0] s_fifo_data [0:11];
wire [11:0] s_fifo_ready;
wire [11:0] m_fifo_valid;
wire signed [31:0] m_fifo_data [0:11];
reg [11:0] m_fifo_ready;

reg start_conv_ff_0;
reg start_conv_ff_1;
reg start_conv_ff_2;

wire start_conv_r;



reg [10:0] cnt_fc;
reg [9:0] weight_fc_en;

assign conv_cnt = conv_counter;

reg start_cnn_delay;

always@(posedge clk or negedge resetn)
if(!resetn)
    start_cnn_delay <= 0;
else
    start_cnn_delay <= start_cnn;



reg [9:0] conv_result_cnt;
always@(posedge clk)
if(!start_conv)
    conv_result_cnt <= 0;
else
    if(conv_wren == 6'b111111)
        conv_result_cnt <= conv_result_cnt + 1;
    else
        conv_result_cnt <= conv_result_cnt;

reg [6:0] add_result_cnt;
always@(posedge clk)
begin
    case(conv_counter)
    4'd4,4'd5,4'd6,4'd7,4'd8,4'd9,4'd10,4'd11,4'd12,4'd13:begin
        if(add_result_cnt == 7'd64)
            add_result_cnt <= 7'd0;
        else
            if(add_wren == 6'b111111)
                add_result_cnt <= add_result_cnt + 7'd1;
            else
                add_result_cnt <= add_result_cnt;
          end
    default:add_result_cnt <= 7'd0;
    endcase
end

reg [7:0] pooling_result_cnt;
always@(posedge clk)
begin
    case(conv_counter)
    4'd1:begin
        if(pooling_result_cnt == 8'd144)
            pooling_result_cnt <= 8'd0;
        else
            if(pooling_wren == 6'b111111)
                pooling_result_cnt <= pooling_result_cnt + 8'd1;
            else
                pooling_result_cnt <= pooling_result_cnt;
         end
    4'd12,4'd13:begin
        if(pooling_result_cnt == 8'd16)
            pooling_result_cnt <= 8'd0;
        else
            if(pooling_wren == 6'b111111)
                pooling_result_cnt <= pooling_result_cnt + 8'd1;
            else
                pooling_result_cnt <= pooling_result_cnt;
          end
    default:pooling_result_cnt <= 8'd0;
    endcase
end


always@(posedge clk or negedge resetn)
begin
    if(!resetn)
        cnt_fc <= 0;
    else
    begin
        if(cnt_fc == 11'd1923)
            cnt_fc <= cnt_fc;
        else if(start_cnn_delay)
            cnt_fc <= cnt_fc + 1'b1;
    end
end

always@(*)
if(cnt_fc <= 10'd1)
    weight_fc_en <= 10'b0000000000;
else if(cnt_fc <= 11'd193)
    weight_fc_en <= 10'b0000000001;
else if(cnt_fc <= 10'd385)
    weight_fc_en <= 10'b0000000010;
else if(cnt_fc <= 11'd577)
    weight_fc_en <= 10'b0000000100;
else if(cnt_fc <= 11'd769)
    weight_fc_en <= 10'b0000001000;
else if(cnt_fc <= 11'd961)
    weight_fc_en <= 10'b0000010000;
else if(cnt_fc <= 11'd1153)
    weight_fc_en <= 10'b0000100000;
else if(cnt_fc <= 11'd1345)
    weight_fc_en <= 10'b0001000000;
else if(cnt_fc <= 11'd1537)
    weight_fc_en <= 10'b0010000000;
else if(cnt_fc <= 11'd1729)
    weight_fc_en <= 10'b0100000000;
else if(cnt_fc <= 11'd1921)
    weight_fc_en <= 10'b1000000000;
else
    weight_fc_en <= 10'b0000000000;

always@(posedge clk or negedge resetn)
if(!resetn)
    weightfc_ready <= 1'b0;
else
    begin
        if(cnt_fc >= 11'd1921)
            weightfc_ready <= 1'b0;
        else if(cnt_fc == 11'd0)
            weightfc_ready <= 1'b0;
        else
            weightfc_ready <= 1'b1;
    end


reg start_conv_delay;
   
always@(posedge clk or negedge resetn)
if(!resetn)
    start_conv_delay <= 0;
else
    start_conv_delay <= start_conv;

assign start_conv_r = start_conv && (~start_conv_delay);
 
always@(posedge clk) 
if(cnn_done)
    conv_counter <= 4'd0;
else if(start_conv_r)
    conv_counter <= conv_counter + 1;


	always@(*)
		case(conv_counter)
		4'd0,4'd1:state <= 0;
		default:state <= 1;
	endcase


always@(posedge clk or negedge resetn)
if(!resetn)
    weight_ready <= 1'b0;
else
    begin
        if(!start_conv || cnt >= 10'd150)
            weight_ready <= 1'b0;
        else
            weight_ready <= 1'b1;
    end                      
    
always@(posedge clk or negedge resetn)
if(!resetn)
    weight_rerd_r <= 0;
else
    if(cnn_done)
        weight_rerd_r <= 1;
    else
        weight_rerd_r <= 0;   

always@(posedge clk or negedge resetn)
if(!resetn)
    weight_counter <= 0;
else if(cnn_done)
    weight_counter <= 0;
else if(weight_tvalid && weight_tready)
    weight_counter <= weight_counter + 1;  
    

	always@(*)
	begin

		if(weight_counter <= 11'd24)                                    
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd49)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd74)
			weight_c[2] <= weight_tdata;    
		else if(weight_counter <= 11'd99)
			weight_c[3] <= weight_tdata;
		else if(weight_counter <= 11'd124)
			weight_c[4] <= weight_tdata;
		else if(weight_counter <= 11'd149)
			weight_c[5] <= weight_tdata;

		else if(weight_counter <= 11'd174)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd199)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd224)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd249)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd274)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd299)
			weight_c[5] <= weight_tdata;             

		else if(weight_counter <= 11'd324)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd349)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd374)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd399)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd424)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd449)
			weight_c[5] <= weight_tdata;                 

		else if(weight_counter <= 11'd474)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd499)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd524)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd549)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd574)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd599)
			weight_c[5] <= weight_tdata;         

		else if(weight_counter <= 11'd624)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd649)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd674)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd699)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd724)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd749)
			weight_c[5] <= weight_tdata;        

		else if(weight_counter <= 11'd774)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd799)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd824)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd849)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd874)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd899)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd924)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd949)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd974)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd999)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1024)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1049)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1074)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1099)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1124)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1149)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1174)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1199)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1224)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1249)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1274)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1299)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1324)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1349)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1374)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1399)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1424)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1449)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1474)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1499)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1524)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1549)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1574)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1599)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1624)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1649)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1674)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1699)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1724)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1749)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1774)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1799)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1824)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1849)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1874)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1899)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1924)
			weight_c[4] <= weight_tdata; 
		else
			weight_c[5] <= weight_tdata;
	end


always@(*)
begin

    if(cnt_fc <= 11'd1)
        begin
            weight_fc[0] <= 0;
            weight_fc[1] <= 0;
            weight_fc[2] <= 0;
            weight_fc[3] <= 0;
            weight_fc[4] <= 0;
            weight_fc[5] <= 0;
            weight_fc[6] <= 0;
            weight_fc[7] <= 0;
            weight_fc[8] <= 0;
            weight_fc[9] <= 0;
        end    

    else if(cnt_fc <= 11'd193)
        weight_fc[0] <= weightfc_tdata;
    else if(cnt_fc <= 11'd385)
        weight_fc[1] <= weightfc_tdata;
    else if(cnt_fc <= 11'd577)
        weight_fc[2] <= weightfc_tdata;
    else if(cnt_fc <= 11'd769)
        weight_fc[3] <= weightfc_tdata;
    else if(cnt_fc <= 11'd961)
        weight_fc[4] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1153)
        weight_fc[5] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1345)
        weight_fc[6] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1537)
        weight_fc[7] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1729)
        weight_fc[8] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1921)
        weight_fc[9] <= weightfc_tdata;
end   


always@(posedge clk)
    case(conv_counter)
        4'd1:if(!start_window) image_ready <= 1'b0;
             else image_ready <= 1'b1;
        4'd2,4'd3:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b000001;              
        4'd4,4'd5:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b000010;
        4'd6,4'd7:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b000100;
        4'd8,4'd9:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b001000;
        4'd10,4'd11:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b010000;
        4'd12,4'd13:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b100000;
        default:begin
                image_ready <= 1'b0;
                fmap_rden <= 6'b000000;
                end
    endcase

always@(posedge clk)
    begin
        case(conv_counter)
            4'd2:if(conv_done == 6'b111111) fmap_rdrst <= 6'b000001;
                 else fmap_rdrst <= 6'b000000;            
            4'd4:if(conv_done == 6'b111111) fmap_rdrst <= 6'b000010;
                 else fmap_rdrst <= 6'b000000;
            4'd6:if(conv_done == 6'b111111) fmap_rdrst <= 6'b000100;
                 else fmap_rdrst <= 6'b000000;
            4'd8:if(conv_done == 6'b111111) fmap_rdrst <= 6'b001000;
                 else fmap_rdrst <= 6'b000000;
            4'd10:if(conv_done == 6'b111111) fmap_rdrst <= 6'b010000;
                 else fmap_rdrst <= 6'b000000;
            4'd12:if(conv_done == 6'b111111) fmap_rdrst <= 6'b100000;
                 else fmap_rdrst <= 6'b000000;
            default:fmap_rdrst <= 6'b000000;
        endcase
end


always@(*)
begin
    case(conv_counter)
        4'd1:image_in <= image_tdata; 
        4'd2,4'd3:image_in <= fmap_dout[0];
        4'd4,4'd5:image_in <= fmap_dout[1];
        4'd6,4'd7:image_in <= fmap_dout[2];
        4'd8,4'd9:image_in <= fmap_dout[3];
        4'd10,4'd11:image_in <= fmap_dout[4];
        4'd12,4'd13:image_in <= fmap_dout[5];
        default:image_in <= 8'b00000000;
    endcase
end

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    cnt <= 10'd0;
else
    if(!start_conv)
        cnt <= 10'd0;
    else 
        cnt <= cnt + 10'd1;
end


always@(posedge clk or negedge resetn)
begin
    if(!resetn)
        start_window <= 0;
    else
        if(conv_done == 6'b111111)
            start_window <= 0;
        else
            case(state)
            1'b0:if(cnt == 10'd11) start_window <= 1;
            1'b1:if(cnt == 10'd91) start_window <= 1;
            endcase
end

window window_inst(.clk(clk),.rstn(resetn),.start(start_window),.state(state),.din(image_in),.taps(taps));



always@(posedge clk or negedge resetn)
begin
if(!resetn)
    start_conv <= 0;
else
    case(conv_counter)
        4'd0:begin
             if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                start_conv <= 0;
             else 
                if(start_cnn_delay && ~cnn_done)
                    start_conv <= 1;
                else
                    start_conv <= start_conv;
             end
        4'd1:begin
             if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                 start_conv <= 0;
             else 
                 if(pooling_result_cnt == 8'd144)
                     start_conv <= 1;
                 else
                     start_conv <= start_conv;
             end
        4'd2,4'd3:begin
                  if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                      start_conv <= 0;
                  else
                      if(conv_result_cnt == 10'd64)
                          start_conv <= 1;
                      else
                          start_conv <= start_conv;
                  end
        4'd4,4'd5,4'd6,4'd7,4'd8,4'd9,4'd10,4'd11:begin
                                                  if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                                                      start_conv <= 0;
                                                  else
                                                      if(add_result_cnt == 7'd64)
                                                          start_conv <= 1;
                                                      else
                                                          start_conv <= start_conv;
                                                  end
        4'd12:begin
              if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                  start_conv <= 0; 
              else
                  if(fc_wren == 10'b1111111111)
                      start_conv <= 1;
                  else
                      start_conv <= start_conv;
              end
        4'd13:begin
              if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                  start_conv <= 0;
              else
                  if(fc_wren == 10'b1111111111)
                      start_conv <= start_conv;
              end
        default:start_conv <= 0;      
    endcase
end

reg [5:0] weight_en = 6'b000000;

always@(*)
begin
    if(cnt == 10'd0)
        weight_en <= 6'b000000;
    else if(cnt <= 10'd25)
        weight_en <= 6'b000001;
    else if(cnt <= 10'd50)
        weight_en <= 6'b000010;
    else if(cnt <= 10'd75)
        weight_en <= 6'b000100;
    else if(cnt <= 10'd100)
        weight_en <= 6'b001000;
    else if(cnt <= 10'd125)
        weight_en <= 6'b010000;
    else if(cnt <= 10'd150)
        weight_en <= 6'b100000;
    else
        weight_en <= 6'b000000;
    end



genvar i;
generate
    for(i=0;i<=5;i=i+1)
        begin:conv_inst
            conv u_conv(.clk(clk),
                        .rstn(resetn),
                        .start(start_conv),
                        .weight_en(weight_en[i]),
                        .weight(weight_c[i]),
                        .taps(taps),
                        .state(state),
                        .dout(conv_result[i]),
                        .ovalid(conv_wren[i]),
                        .done(conv_done[i]));
            end
endgenerate


always@(*)
case(conv_counter)
    4'd2:if(conv_wren == 6'b111111) s_fifo_valid <= 12'b000000111111;
         else s_fifo_valid <= 12'b000000000000;
    4'd3:if(conv_wren == 6'b111111) s_fifo_valid <= 12'b111111000000;
         else s_fifo_valid <= 12'b000000000000;
    4'd4,4'd6,4'd8,4'd10:if(add_wren == 6'b111111) s_fifo_valid <= 12'b000000111111;
         else s_fifo_valid <= 12'b000000000000;
    4'd5,4'd7,4'd9,4'd11:if(add_wren == 6'b111111) s_fifo_valid <= 12'b111111000000;
         else s_fifo_valid <= 12'b000000000000;
    default:s_fifo_valid <= 12'b000000000000;     
endcase

integer j;

always@(*)
case(conv_counter)
    4'd2:for(j=0;j<=5;j=j+1)
                 s_fifo_data[j] <= conv_result[j];
    4'd3:for(j=0;j<=5;j=j+1)
                 s_fifo_data[j+6] <= conv_result[j];                     
    4'd4,4'd6,4'd8,4'd10:for(j=0;j<=5;j=j+1)
                             s_fifo_data[j] <= add_result[j]; 
    4'd5,4'd7,4'd9,4'd11:for(j=0;j<=5;j=j+1)
                             s_fifo_data[j+6] <= add_result[j];                                                      
    default:for(j=0;j<=11;j=j+1)
                s_fifo_data[j] <= 0;
           
endcase

always@(*)
case(conv_counter)
    4'd4,4'd6,4'd8,4'd10,4'd12:if(conv_wren == 6'b111111) m_fifo_ready <= 12'b000000111111;
         else if(conv_wren == 6'b000000) m_fifo_ready <= 12'b000000000000;
    4'd5,4'd7,4'd9,4'd11,4'd13:if(conv_wren == 6'b111111) m_fifo_ready <= 12'b111111000000;
         else if(conv_wren == 6'b000000) m_fifo_ready <= 12'b000000000000;
    default:m_fifo_ready <= 12'b000000000000;     
endcase


integer k;
always@(posedge clk)
begin
    case(conv_counter)
    4'd4,4'd6,4'd8,4'd10,4'd12:begin
         for(k=0;k<=5;k=k+1)
             if(m_fifo_valid[k] && m_fifo_ready[k])
                 add_data[k] <= m_fifo_data[k];
             else 
                 add_data[k] <= 0;
         end
    4'd5,4'd7,4'd9,4'd11,4'd13:begin
         for(k=0;k<=5;k=k+1)
             if(m_fifo_valid[k+6] && m_fifo_ready[k+6])
                 add_data[k] <= m_fifo_data[k+6];
             else 
                 add_data[k] <= 0;
         end
    default:begin
            for(k=0;k<=5;k=k+1)
                add_data[k] <= 0;
            end
    endcase
end

reg reset_fifo;

always@(posedge clk or negedge resetn)
if(!resetn)
    reset_fifo <= 0;
else
    if(cnn_done)
        reset_fifo <= 0;
    else
        reset_fifo <= 1;
   

genvar a;
generate
    for(a=0;a<=11;a=a+1)
        begin:fifo_inst
            user_fifo_ip your_instance_name(
              .s_axis_aresetn(reset_fifo),
              .s_axis_aclk(clk),
              .s_axis_tvalid(s_fifo_valid[a]),
              .s_axis_tready(s_fifo_ready[a]),
              .s_axis_tdata(s_fifo_data[a]),
              .m_axis_tvalid(m_fifo_valid[a]),
              .m_axis_tready(m_fifo_ready[a]),
              .m_axis_tdata(m_fifo_data[a])
            );
        end
endgenerate


reg ivalid_add;
always@(*)
case(conv_counter)
4'd4,4'd5,4'd6,4'd7,4'd8,4'd9,4'd10,4'd11,4'd12,4'd13:if(conv_wren == 6'b111111) ivalid_add <= 1'b1;
                                                        else ivalid_add <= 1'b0;
default:ivalid_add <= 1'b0;
endcase

genvar b;
generate
    for(b=0;b<=5;b=b+1)
        begin:add_inst 
            add u_add(
                .clk(clk),
                .ivalid(ivalid_add),
                .din_0(conv_result[b]),
                .din_1(add_data[b]),
                .ovalid(add_wren[b]),
                .dout(add_result[b])
            );    
        end
endgenerate
    

reg ivalid_relu;
always@(*)
case(conv_counter)
4'd1:if(conv_wren == 6'b111111) ivalid_relu <= 1'b1;
     else ivalid_relu <= 1'b0;
4'd12,4'd13:if(add_wren == 6'b111111) ivalid_relu <= 1'b1;
     else ivalid_relu <= 1'b0;
default:ivalid_relu <= 1'b0;
endcase


integer m;
always@(*)
case(conv_counter)
    4'd1:for(m=0;m<=5;m=m+1)
             relu_data[m] <= conv_result[m];
    4'd12,4'd13:for(m=0;m<=5;m=m+1)
             relu_data[m] <= add_result[m];    
    default:for(m=0;m<=5;m=m+1)
             relu_data[m] <= 0;
           
endcase


genvar c;
generate
    for(c=0;c<=5;c=c+1)
        begin:relu_inst 
            relu u_relu(
                .clk(clk),
                .ivalid(ivalid_relu),
                .state(state),
                .din(relu_data[c]),
                .ovalid(relu_wren[c]),
                .dout(relu_result[c])
            );    
        end
endgenerate


	reg ivalid_pooling;
	always@(*)begin
		case(conv_counter)
			4'd1,4'd12,4'd13:
				if(relu_wren == 6'b111111) 
					ivalid_pooling <= 1'b1;
				else 
					ivalid_pooling <= 1'b0;
			default:ivalid_pooling <= 1'b0;
			endcase
	end
	
	genvar d;
	generate
		for(d=0;d<=5;d=d+1)
			begin:pooling_inst
				maxpooling u_pooling(
					.clk(clk),
					.rstn(resetn),
					.ivalid(ivalid_pooling),
					.state(state),
					.din(relu_result[d]),
					.ovalid(pooling_wren[d]),
					.dout(pooling_result[d])                                     
				);
			end
	endgenerate


always@(*)
if(conv_counter == 4'd1 && pooling_wren == 6'b111111)
    fmap_wren <= 6'b111111;
else
    fmap_wren <= 6'b000000;

reg reset_fmap;

always@(posedge clk or negedge resetn)
if(!resetn)
    reset_fmap <= 0;
else
    if(cnn_done)
        reset_fmap <= 0;
    else
        reset_fmap <= 1;

genvar e;
generate
    for(e=0;e<=5;e=e+1)
        begin:fmap_inst
            FIFO_fmap u_FIFO_fmap (
              .clk(clk),
              .rstn(reset_fmap),
              .din(pooling_result[e]),
              .wr_en(fmap_wren[e]),
              .rd_en(fmap_rden[e]),
              .rd_rst(fmap_rdrst[e]),
              .dout(fmap_dout[e]),
              .full(),
              .empty()
            );
        end
endgenerate


reg ivalid_fc;
always@(*)
case(conv_counter)
4'd12,4'd13:if(pooling_wren == 6'b111111) ivalid_fc <= 1;
      else ivalid_fc <= 0;
default:ivalid_fc <= 0;
endcase

genvar f;
generate
    for(f=0;f<10;f=f+1)
        begin:fullconnect_inst
            fc u_fullconnect(
                .clk(clk),
                .rstn(resetn),
                .ivalid(ivalid_fc),
                .din_0(pooling_result[0]),
                .din_1(pooling_result[1]),
                .din_2(pooling_result[2]),
                .din_3(pooling_result[3]),
                .din_4(pooling_result[4]),
                .din_5(pooling_result[5]),
                .weight(weight_fc[f]),
                .weight_en(weight_fc_en[f]),
                .ovalid(fc_wren[f]),
                .dout(fc_result[f])
            );
        end
endgenerate


integer r;
always@(posedge clk)
case(conv_counter)
4'd12:if(fc_wren == 10'b1111111111)
      begin
          result_r0[0] <= fc_result[0];
          result_r0[1] <= fc_result[1];
          result_r0[2] <= fc_result[2];
          result_r0[3] <= fc_result[3];
          result_r0[4] <= fc_result[4];
          result_r0[5] <= fc_result[5];
          result_r0[6] <= fc_result[6];
          result_r0[7] <= fc_result[7];
          result_r0[8] <= fc_result[8];
          result_r0[9] <= fc_result[9];
      end
4'd13:if(fc_wren == 10'b1111111111)
      begin
          result_r1[0] <= fc_result[0] + result_r0[0];
          result_r1[1] <= fc_result[1] + result_r0[1];
          result_r1[2] <= fc_result[2] + result_r0[2];
          result_r1[3] <= fc_result[3] + result_r0[3];
          result_r1[4] <= fc_result[4] + result_r0[4];
          result_r1[5] <= fc_result[5] + result_r0[5];
          result_r1[6] <= fc_result[6] + result_r0[6];
          result_r1[7] <= fc_result[7] + result_r0[7];
          result_r1[8] <= fc_result[8] + result_r0[8];
          result_r1[9] <= fc_result[9] + result_r0[9];
      end
default:begin
          result_r0[0] <= 0;
          result_r0[1] <= 0;
          result_r0[2] <= 0;
          result_r0[3] <= 0;
          result_r0[4] <= 0;
          result_r0[5] <= 0;
          result_r0[6] <= 0;
          result_r0[7] <= 0;
          result_r0[8] <= 0;
          result_r0[9] <= 0;
          result_r1[0] <= 0;
          result_r1[1] <= 0;
          result_r1[2] <= 0;
          result_r1[3] <= 0;
          result_r1[4] <= 0;
          result_r1[5] <= 0;
          result_r1[6] <= 0;
          result_r1[7] <= 0;
          result_r1[8] <= 0;
          result_r1[9] <= 0;
        end
endcase

reg result_valid;
reg [3:0] cnt4;

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    result_valid <= 0;
else
    if(!start_cnn_delay)
        result_valid <= 0;
    else if(cnt4 > 4'd10)
        result_valid <= 0; 
    else if(conv_counter == 4'd13 && fc_wren == 10'b1111111111)
        result_valid <= 1;    
end

wire start_cnn_r;

assign start_cnn_r = start_cnn && ~start_cnn_delay;

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    cnn_done_r <= 0;
else
    if(start_cnn_r)
        cnn_done_r <= 0;
    else if(cnt4 == 4'd10)
        cnn_done_r <= 1;
end
   
always@(posedge clk or negedge resetn)
begin
if(!resetn)
    cnt4 <= 0;
else
    if(!result_valid)
        cnt4 <= 0;
    else
        cnt4 <= cnt4 + 1;
end

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    result_valid_r <= 1'b0;
else    
    if(cnt4 == 4'd0)
        result_valid_r <= 1'b0;
    else if(cnt4 <= 4'd10)
        result_valid_r <= 1'b1;
    else
        result_valid_r <= 1'b0;
end

always@(posedge clk)
begin
if(cnt4 > 4'd0 && cnt4 <= 4'd10)
    result_data <= result_r1[cnt4-1];
else
    result_data <= 0;
end

assign conv_start = start_conv;
assign window_start = start_window;
assign done_conv = conv_done;

endmodule
module CNN
(
    input wire clk,
    input wire resetn,
    
    input wire start_cnn,
    
    input wire image_tvalid,
    output wire image_tready,
    input wire signed [7:0] image_tdata,
    
    input wire weight_tvalid,
    output wire weight_tready,
    input wire signed [7:0] weight_tdata,
    
    input wire weightfc_tvalid,
    output wire weightfc_tready,
    input wire signed [7:0] weightfc_tdata,
    
    output wire cnn_done,
   
    input wire result_tready,
    output wire result_tvalid,
    output wire signed [31:0] result_tdata,

    output wire [3:0] conv_cnt

);

	reg image_ready;
	reg weight_ready;
	reg weightfc_ready;
	reg result_valid_r;
	reg weight_rerd_r;
	reg cnn_done_r;
	reg signed [31:0] result_data;
	assign image_tready = image_ready;
	assign weight_tready = weight_ready;
	assign weightfc_tready = weightfc_ready;
	assign result_tvalid = result_valid_r;
	assign cnn_done = cnn_done_r;
	assign weight_rerd = weight_rerd_r;
	
	assign result_tdata = result_data;



	reg start_window;
	reg start_conv;


	wire [5:0] conv_wren;
	wire [5:0] add_wren;
	wire [5:0] relu_wren;
	wire [5:0] pooling_wren;
	wire [9:0] fc_wren;


	wire [5:0] conv_done;


	wire [39:0] taps;
	reg signed [31:0] add_data [0:5];
	reg signed [31:0] relu_data [0:5];
	

	wire signed [31:0] conv_result [0:5];
	wire signed [31:0] add_result [0:5];
	wire signed [7:0] relu_result [0:5];
	wire signed [7:0] pooling_result [0:5];
	wire signed [31:0] fc_result [0:9];
	reg signed [31:0] result_r0 [0:9];
	reg signed [31:0] result_r1 [0:9];




reg [3:0] conv_counter = 4'd0;


reg [5:0] fmap_rdrst;
reg [5:0] fmap_rden;


reg [7:0] image_in;                      


reg state; 


reg [10:0] weight_counter;


reg signed [7:0] weight_c [0:5];
reg signed [7:0] weight_fc [0:9];


reg [9:0] cnt;


reg [5:0] fmap_wren;
wire signed [7:0] fmap_dout [0:5];


reg [11:0] s_fifo_valid;
reg signed [31:0] s_fifo_data [0:11];
wire [11:0] s_fifo_ready;
wire [11:0] m_fifo_valid;
wire signed [31:0] m_fifo_data [0:11];
reg [11:0] m_fifo_ready;

reg start_conv_ff_0;
reg start_conv_ff_1;
reg start_conv_ff_2;

wire start_conv_r;



reg [10:0] cnt_fc;
reg [9:0] weight_fc_en;

assign conv_cnt = conv_counter;

reg start_cnn_delay;

always@(posedge clk or negedge resetn)
if(!resetn)
    start_cnn_delay <= 0;
else
    start_cnn_delay <= start_cnn;



reg [9:0] conv_result_cnt;
always@(posedge clk)
if(!start_conv)
    conv_result_cnt <= 0;
else
    if(conv_wren == 6'b111111)
        conv_result_cnt <= conv_result_cnt + 1;
    else
        conv_result_cnt <= conv_result_cnt;

reg [6:0] add_result_cnt;
always@(posedge clk)
begin
    case(conv_counter)
    4'd4,4'd5,4'd6,4'd7,4'd8,4'd9,4'd10,4'd11,4'd12,4'd13:begin
        if(add_result_cnt == 7'd64)
            add_result_cnt <= 7'd0;
        else
            if(add_wren == 6'b111111)
                add_result_cnt <= add_result_cnt + 7'd1;
            else
                add_result_cnt <= add_result_cnt;
          end
    default:add_result_cnt <= 7'd0;
    endcase
end

reg [7:0] pooling_result_cnt;
always@(posedge clk)
begin
    case(conv_counter)
    4'd1:begin
        if(pooling_result_cnt == 8'd144)
            pooling_result_cnt <= 8'd0;
        else
            if(pooling_wren == 6'b111111)
                pooling_result_cnt <= pooling_result_cnt + 8'd1;
            else
                pooling_result_cnt <= pooling_result_cnt;
         end
    4'd12,4'd13:begin
        if(pooling_result_cnt == 8'd16)
            pooling_result_cnt <= 8'd0;
        else
            if(pooling_wren == 6'b111111)
                pooling_result_cnt <= pooling_result_cnt + 8'd1;
            else
                pooling_result_cnt <= pooling_result_cnt;
          end
    default:pooling_result_cnt <= 8'd0;
    endcase
end


always@(posedge clk or negedge resetn)
begin
    if(!resetn)
        cnt_fc <= 0;
    else
    begin
        if(cnt_fc == 11'd1923)
            cnt_fc <= cnt_fc;
        else if(start_cnn_delay)
            cnt_fc <= cnt_fc + 1'b1;
    end
end

always@(*)
if(cnt_fc <= 10'd1)
    weight_fc_en <= 10'b0000000000;
else if(cnt_fc <= 11'd193)
    weight_fc_en <= 10'b0000000001;
else if(cnt_fc <= 10'd385)
    weight_fc_en <= 10'b0000000010;
else if(cnt_fc <= 11'd577)
    weight_fc_en <= 10'b0000000100;
else if(cnt_fc <= 11'd769)
    weight_fc_en <= 10'b0000001000;
else if(cnt_fc <= 11'd961)
    weight_fc_en <= 10'b0000010000;
else if(cnt_fc <= 11'd1153)
    weight_fc_en <= 10'b0000100000;
else if(cnt_fc <= 11'd1345)
    weight_fc_en <= 10'b0001000000;
else if(cnt_fc <= 11'd1537)
    weight_fc_en <= 10'b0010000000;
else if(cnt_fc <= 11'd1729)
    weight_fc_en <= 10'b0100000000;
else if(cnt_fc <= 11'd1921)
    weight_fc_en <= 10'b1000000000;
else
    weight_fc_en <= 10'b0000000000;

always@(posedge clk or negedge resetn)
if(!resetn)
    weightfc_ready <= 1'b0;
else
    begin
        if(cnt_fc >= 11'd1921)
            weightfc_ready <= 1'b0;
        else if(cnt_fc == 11'd0)
            weightfc_ready <= 1'b0;
        else
            weightfc_ready <= 1'b1;
    end


reg start_conv_delay;
   
always@(posedge clk or negedge resetn)
if(!resetn)
    start_conv_delay <= 0;
else
    start_conv_delay <= start_conv;

assign start_conv_r = start_conv && (~start_conv_delay);
 
always@(posedge clk) 
if(cnn_done)
    conv_counter <= 4'd0;
else if(start_conv_r)
    conv_counter <= conv_counter + 1;


	always@(*)
		case(conv_counter)
		4'd0,4'd1:state <= 0;
		default:state <= 1;
	endcase


always@(posedge clk or negedge resetn)
if(!resetn)
    weight_ready <= 1'b0;
else
    begin
        if(!start_conv || cnt >= 10'd150)
            weight_ready <= 1'b0;
        else
            weight_ready <= 1'b1;
    end                      
    
always@(posedge clk or negedge resetn)
if(!resetn)
    weight_rerd_r <= 0;
else
    if(cnn_done)
        weight_rerd_r <= 1;
    else
        weight_rerd_r <= 0;   

always@(posedge clk or negedge resetn)
if(!resetn)
    weight_counter <= 0;
else if(cnn_done)
    weight_counter <= 0;
else if(weight_tvalid && weight_tready)
    weight_counter <= weight_counter + 1;  
    

	always@(*)
	begin

		if(weight_counter <= 11'd24)                                    
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd49)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd74)
			weight_c[2] <= weight_tdata;    
		else if(weight_counter <= 11'd99)
			weight_c[3] <= weight_tdata;
		else if(weight_counter <= 11'd124)
			weight_c[4] <= weight_tdata;
		else if(weight_counter <= 11'd149)
			weight_c[5] <= weight_tdata;

		else if(weight_counter <= 11'd174)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd199)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd224)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd249)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd274)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd299)
			weight_c[5] <= weight_tdata;             

		else if(weight_counter <= 11'd324)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd349)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd374)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd399)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd424)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd449)
			weight_c[5] <= weight_tdata;                 

		else if(weight_counter <= 11'd474)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd499)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd524)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd549)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd574)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd599)
			weight_c[5] <= weight_tdata;         

		else if(weight_counter <= 11'd624)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd649)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd674)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd699)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd724)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd749)
			weight_c[5] <= weight_tdata;        

		else if(weight_counter <= 11'd774)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd799)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd824)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd849)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd874)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd899)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd924)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd949)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd974)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd999)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1024)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1049)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1074)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1099)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1124)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1149)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1174)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1199)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1224)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1249)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1274)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1299)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1324)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1349)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1374)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1399)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1424)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1449)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1474)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1499)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1524)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1549)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1574)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1599)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1624)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1649)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1674)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1699)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1724)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1749)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1774)
			weight_c[4] <= weight_tdata; 
		else if(weight_counter <= 11'd1799)
			weight_c[5] <= weight_tdata; 

		else if(weight_counter <= 11'd1824)
			weight_c[0] <= weight_tdata;
		else if(weight_counter <= 11'd1849)
			weight_c[1] <= weight_tdata;
		else if(weight_counter <= 11'd1874)
			weight_c[2] <= weight_tdata;        
		else if(weight_counter <= 11'd1899)
			weight_c[3] <= weight_tdata;        
		else if(weight_counter <= 11'd1924)
			weight_c[4] <= weight_tdata; 
		else
			weight_c[5] <= weight_tdata;
	end


always@(*)
begin

    if(cnt_fc <= 11'd1)
        begin
            weight_fc[0] <= 0;
            weight_fc[1] <= 0;
            weight_fc[2] <= 0;
            weight_fc[3] <= 0;
            weight_fc[4] <= 0;
            weight_fc[5] <= 0;
            weight_fc[6] <= 0;
            weight_fc[7] <= 0;
            weight_fc[8] <= 0;
            weight_fc[9] <= 0;
        end    

    else if(cnt_fc <= 11'd193)
        weight_fc[0] <= weightfc_tdata;
    else if(cnt_fc <= 11'd385)
        weight_fc[1] <= weightfc_tdata;
    else if(cnt_fc <= 11'd577)
        weight_fc[2] <= weightfc_tdata;
    else if(cnt_fc <= 11'd769)
        weight_fc[3] <= weightfc_tdata;
    else if(cnt_fc <= 11'd961)
        weight_fc[4] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1153)
        weight_fc[5] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1345)
        weight_fc[6] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1537)
        weight_fc[7] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1729)
        weight_fc[8] <= weightfc_tdata;
    else if(cnt_fc <= 11'd1921)
        weight_fc[9] <= weightfc_tdata;
end   


always@(posedge clk)
    case(conv_counter)
        4'd1:if(!start_window) image_ready <= 1'b0;
             else image_ready <= 1'b1;
        4'd2,4'd3:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b000001;              
        4'd4,4'd5:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b000010;
        4'd6,4'd7:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b000100;
        4'd8,4'd9:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b001000;
        4'd10,4'd11:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b010000;
        4'd12,4'd13:if(!start_window) fmap_rden <= 6'b000000;
             else fmap_rden <= 6'b100000;
        default:begin
                image_ready <= 1'b0;
                fmap_rden <= 6'b000000;
                end
    endcase

always@(posedge clk)
    begin
        case(conv_counter)
            4'd2:if(conv_done == 6'b111111) fmap_rdrst <= 6'b000001;
                 else fmap_rdrst <= 6'b000000;            
            4'd4:if(conv_done == 6'b111111) fmap_rdrst <= 6'b000010;
                 else fmap_rdrst <= 6'b000000;
            4'd6:if(conv_done == 6'b111111) fmap_rdrst <= 6'b000100;
                 else fmap_rdrst <= 6'b000000;
            4'd8:if(conv_done == 6'b111111) fmap_rdrst <= 6'b001000;
                 else fmap_rdrst <= 6'b000000;
            4'd10:if(conv_done == 6'b111111) fmap_rdrst <= 6'b010000;
                 else fmap_rdrst <= 6'b000000;
            4'd12:if(conv_done == 6'b111111) fmap_rdrst <= 6'b100000;
                 else fmap_rdrst <= 6'b000000;
            default:fmap_rdrst <= 6'b000000;
        endcase
end


always@(*)
begin
    case(conv_counter)
        4'd1:image_in <= image_tdata; 
        4'd2,4'd3:image_in <= fmap_dout[0];
        4'd4,4'd5:image_in <= fmap_dout[1];
        4'd6,4'd7:image_in <= fmap_dout[2];
        4'd8,4'd9:image_in <= fmap_dout[3];
        4'd10,4'd11:image_in <= fmap_dout[4];
        4'd12,4'd13:image_in <= fmap_dout[5];
        default:image_in <= 8'b00000000;
    endcase
end

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    cnt <= 10'd0;
else
    if(!start_conv)
        cnt <= 10'd0;
    else 
        cnt <= cnt + 10'd1;
end


always@(posedge clk or negedge resetn)
begin
    if(!resetn)
        start_window <= 0;
    else
        if(conv_done == 6'b111111)
            start_window <= 0;
        else
            case(state)
            1'b0:if(cnt == 10'd11) start_window <= 1;
            1'b1:if(cnt == 10'd91) start_window <= 1;
            endcase
end

window window_inst(.clk(clk),.rstn(resetn),.start(start_window),.state(state),.din(image_in),.taps(taps));



always@(posedge clk or negedge resetn)
begin
if(!resetn)
    start_conv <= 0;
else
    case(conv_counter)
        4'd0:begin
             if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                start_conv <= 0;
             else 
                if(start_cnn_delay && ~cnn_done)
                    start_conv <= 1;
                else
                    start_conv <= start_conv;
             end
        4'd1:begin
             if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                 start_conv <= 0;
             else 
                 if(pooling_result_cnt == 8'd144)
                     start_conv <= 1;
                 else
                     start_conv <= start_conv;
             end
        4'd2,4'd3:begin
                  if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                      start_conv <= 0;
                  else
                      if(conv_result_cnt == 10'd64)
                          start_conv <= 1;
                      else
                          start_conv <= start_conv;
                  end
        4'd4,4'd5,4'd6,4'd7,4'd8,4'd9,4'd10,4'd11:begin
                                                  if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                                                      start_conv <= 0;
                                                  else
                                                      if(add_result_cnt == 7'd64)
                                                          start_conv <= 1;
                                                      else
                                                          start_conv <= start_conv;
                                                  end
        4'd12:begin
              if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                  start_conv <= 0; 
              else
                  if(fc_wren == 10'b1111111111)
                      start_conv <= 1;
                  else
                      start_conv <= start_conv;
              end
        4'd13:begin
              if(conv_done[0] && conv_done[1] && conv_done[2] && conv_done[3] && conv_done[4] && conv_done[5])
                  start_conv <= 0;
              else
                  if(fc_wren == 10'b1111111111)
                      start_conv <= start_conv;
              end
        default:start_conv <= 0;      
    endcase
end

reg [5:0] weight_en = 6'b000000;

always@(*)
begin
    if(cnt == 10'd0)
        weight_en <= 6'b000000;
    else if(cnt <= 10'd25)
        weight_en <= 6'b000001;
    else if(cnt <= 10'd50)
        weight_en <= 6'b000010;
    else if(cnt <= 10'd75)
        weight_en <= 6'b000100;
    else if(cnt <= 10'd100)
        weight_en <= 6'b001000;
    else if(cnt <= 10'd125)
        weight_en <= 6'b010000;
    else if(cnt <= 10'd150)
        weight_en <= 6'b100000;
    else
        weight_en <= 6'b000000;
    end



genvar i;
generate
    for(i=0;i<=5;i=i+1)
        begin:conv_inst
            conv u_conv(.clk(clk),
                        .rstn(resetn),
                        .start(start_conv),
                        .weight_en(weight_en[i]),
                        .weight(weight_c[i]),
                        .taps(taps),
                        .state(state),
                        .dout(conv_result[i]),
                        .ovalid(conv_wren[i]),
                        .done(conv_done[i]));
            end
endgenerate


always@(*)
case(conv_counter)
    4'd2:if(conv_wren == 6'b111111) s_fifo_valid <= 12'b000000111111;
         else s_fifo_valid <= 12'b000000000000;
    4'd3:if(conv_wren == 6'b111111) s_fifo_valid <= 12'b111111000000;
         else s_fifo_valid <= 12'b000000000000;
    4'd4,4'd6,4'd8,4'd10:if(add_wren == 6'b111111) s_fifo_valid <= 12'b000000111111;
         else s_fifo_valid <= 12'b000000000000;
    4'd5,4'd7,4'd9,4'd11:if(add_wren == 6'b111111) s_fifo_valid <= 12'b111111000000;
         else s_fifo_valid <= 12'b000000000000;
    default:s_fifo_valid <= 12'b000000000000;     
endcase

integer j;

always@(*)
case(conv_counter)
    4'd2:for(j=0;j<=5;j=j+1)
                 s_fifo_data[j] <= conv_result[j];
    4'd3:for(j=0;j<=5;j=j+1)
                 s_fifo_data[j+6] <= conv_result[j];                     
    4'd4,4'd6,4'd8,4'd10:for(j=0;j<=5;j=j+1)
                             s_fifo_data[j] <= add_result[j]; 
    4'd5,4'd7,4'd9,4'd11:for(j=0;j<=5;j=j+1)
                             s_fifo_data[j+6] <= add_result[j];                                                      
    default:for(j=0;j<=11;j=j+1)
                s_fifo_data[j] <= 0;
           
endcase

always@(*)
case(conv_counter)
    4'd4,4'd6,4'd8,4'd10,4'd12:if(conv_wren == 6'b111111) m_fifo_ready <= 12'b000000111111;
         else if(conv_wren == 6'b000000) m_fifo_ready <= 12'b000000000000;
    4'd5,4'd7,4'd9,4'd11,4'd13:if(conv_wren == 6'b111111) m_fifo_ready <= 12'b111111000000;
         else if(conv_wren == 6'b000000) m_fifo_ready <= 12'b000000000000;
    default:m_fifo_ready <= 12'b000000000000;     
endcase


integer k;
always@(posedge clk)
begin
    case(conv_counter)
    4'd4,4'd6,4'd8,4'd10,4'd12:begin
         for(k=0;k<=5;k=k+1)
             if(m_fifo_valid[k] && m_fifo_ready[k])
                 add_data[k] <= m_fifo_data[k];
             else 
                 add_data[k] <= 0;
         end
    4'd5,4'd7,4'd9,4'd11,4'd13:begin
         for(k=0;k<=5;k=k+1)
             if(m_fifo_valid[k+6] && m_fifo_ready[k+6])
                 add_data[k] <= m_fifo_data[k+6];
             else 
                 add_data[k] <= 0;
         end
    default:begin
            for(k=0;k<=5;k=k+1)
                add_data[k] <= 0;
            end
    endcase
end

reg reset_fifo;

always@(posedge clk or negedge resetn)
if(!resetn)
    reset_fifo <= 0;
else
    if(cnn_done)
        reset_fifo <= 0;
    else
        reset_fifo <= 1;
   

genvar a;
generate
    for(a=0;a<=11;a=a+1)
        begin:fifo_inst
            user_fifo_ip your_instance_name(
              .s_axis_aresetn(reset_fifo),
              .s_axis_aclk(clk),
              .s_axis_tvalid(s_fifo_valid[a]),
              .s_axis_tready(s_fifo_ready[a]),
              .s_axis_tdata(s_fifo_data[a]),
              .m_axis_tvalid(m_fifo_valid[a]),
              .m_axis_tready(m_fifo_ready[a]),
              .m_axis_tdata(m_fifo_data[a])
            );
        end
endgenerate


reg ivalid_add;
always@(*)
case(conv_counter)
4'd4,4'd5,4'd6,4'd7,4'd8,4'd9,4'd10,4'd11,4'd12,4'd13:if(conv_wren == 6'b111111) ivalid_add <= 1'b1;
                                                        else ivalid_add <= 1'b0;
default:ivalid_add <= 1'b0;
endcase

genvar b;
generate
    for(b=0;b<=5;b=b+1)
        begin:add_inst 
            add u_add(
                .clk(clk),
                .ivalid(ivalid_add),
                .din_0(conv_result[b]),
                .din_1(add_data[b]),
                .ovalid(add_wren[b]),
                .dout(add_result[b])
            );    
        end
endgenerate
    

reg ivalid_relu;
always@(*)
case(conv_counter)
4'd1:if(conv_wren == 6'b111111) ivalid_relu <= 1'b1;
     else ivalid_relu <= 1'b0;
4'd12,4'd13:if(add_wren == 6'b111111) ivalid_relu <= 1'b1;
     else ivalid_relu <= 1'b0;
default:ivalid_relu <= 1'b0;
endcase


integer m;
always@(*)
case(conv_counter)
    4'd1:for(m=0;m<=5;m=m+1)
             relu_data[m] <= conv_result[m];
    4'd12,4'd13:for(m=0;m<=5;m=m+1)
             relu_data[m] <= add_result[m];    
    default:for(m=0;m<=5;m=m+1)
             relu_data[m] <= 0;
           
endcase


genvar c;
generate
    for(c=0;c<=5;c=c+1)
        begin:relu_inst 
            relu u_relu(
                .clk(clk),
                .ivalid(ivalid_relu),
                .state(state),
                .din(relu_data[c]),
                .ovalid(relu_wren[c]),
                .dout(relu_result[c])
            );    
        end
endgenerate


	reg ivalid_pooling;
	always@(*)begin
		case(conv_counter)
			4'd1,4'd12,4'd13:
				if(relu_wren == 6'b111111) 
					ivalid_pooling <= 1'b1;
				else 
					ivalid_pooling <= 1'b0;
			default:ivalid_pooling <= 1'b0;
			endcase
	end
	
	genvar d;
	generate
		for(d=0;d<=5;d=d+1)
			begin:pooling_inst
				maxpooling u_pooling(
					.clk(clk),
					.rstn(resetn),
					.ivalid(ivalid_pooling),
					.state(state),
					.din(relu_result[d]),
					.ovalid(pooling_wren[d]),
					.dout(pooling_result[d])                                     
				);
			end
	endgenerate


always@(*)
if(conv_counter == 4'd1 && pooling_wren == 6'b111111)
    fmap_wren <= 6'b111111;
else
    fmap_wren <= 6'b000000;

reg reset_fmap;

always@(posedge clk or negedge resetn)
if(!resetn)
    reset_fmap <= 0;
else
    if(cnn_done)
        reset_fmap <= 0;
    else
        reset_fmap <= 1;

genvar e;
generate
    for(e=0;e<=5;e=e+1)
        begin:fmap_inst
            FIFO_fmap u_FIFO_fmap (
              .clk(clk),
              .rstn(reset_fmap),
              .din(pooling_result[e]),
              .wr_en(fmap_wren[e]),
              .rd_en(fmap_rden[e]),
              .rd_rst(fmap_rdrst[e]),
              .dout(fmap_dout[e]),
              .full(),
              .empty()
            );
        end
endgenerate


reg ivalid_fc;
always@(*)
case(conv_counter)
4'd12,4'd13:if(pooling_wren == 6'b111111) ivalid_fc <= 1;
      else ivalid_fc <= 0;
default:ivalid_fc <= 0;
endcase

genvar f;
generate
    for(f=0;f<10;f=f+1)
        begin:fullconnect_inst
            fc u_fullconnect(
                .clk(clk),
                .rstn(resetn),
                .ivalid(ivalid_fc),
                .din_0(pooling_result[0]),
                .din_1(pooling_result[1]),
                .din_2(pooling_result[2]),
                .din_3(pooling_result[3]),
                .din_4(pooling_result[4]),
                .din_5(pooling_result[5]),
                .weight(weight_fc[f]),
                .weight_en(weight_fc_en[f]),
                .ovalid(fc_wren[f]),
                .dout(fc_result[f])
            );
        end
endgenerate


integer r;
always@(posedge clk)
case(conv_counter)
4'd12:if(fc_wren == 10'b1111111111)
      begin
          result_r0[0] <= fc_result[0];
          result_r0[1] <= fc_result[1];
          result_r0[2] <= fc_result[2];
          result_r0[3] <= fc_result[3];
          result_r0[4] <= fc_result[4];
          result_r0[5] <= fc_result[5];
          result_r0[6] <= fc_result[6];
          result_r0[7] <= fc_result[7];
          result_r0[8] <= fc_result[8];
          result_r0[9] <= fc_result[9];
      end
4'd13:if(fc_wren == 10'b1111111111)
      begin
          result_r1[0] <= fc_result[0] + result_r0[0];
          result_r1[1] <= fc_result[1] + result_r0[1];
          result_r1[2] <= fc_result[2] + result_r0[2];
          result_r1[3] <= fc_result[3] + result_r0[3];
          result_r1[4] <= fc_result[4] + result_r0[4];
          result_r1[5] <= fc_result[5] + result_r0[5];
          result_r1[6] <= fc_result[6] + result_r0[6];
          result_r1[7] <= fc_result[7] + result_r0[7];
          result_r1[8] <= fc_result[8] + result_r0[8];
          result_r1[9] <= fc_result[9] + result_r0[9];
      end
default:begin
          result_r0[0] <= 0;
          result_r0[1] <= 0;
          result_r0[2] <= 0;
          result_r0[3] <= 0;
          result_r0[4] <= 0;
          result_r0[5] <= 0;
          result_r0[6] <= 0;
          result_r0[7] <= 0;
          result_r0[8] <= 0;
          result_r0[9] <= 0;
          result_r1[0] <= 0;
          result_r1[1] <= 0;
          result_r1[2] <= 0;
          result_r1[3] <= 0;
          result_r1[4] <= 0;
          result_r1[5] <= 0;
          result_r1[6] <= 0;
          result_r1[7] <= 0;
          result_r1[8] <= 0;
          result_r1[9] <= 0;
        end
endcase

reg result_valid;
reg [3:0] cnt4;

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    result_valid <= 0;
else
    if(!start_cnn_delay)
        result_valid <= 0;
    else if(cnt4 > 4'd10)
        result_valid <= 0; 
    else if(conv_counter == 4'd13 && fc_wren == 10'b1111111111)
        result_valid <= 1;    
end

wire start_cnn_r;

assign start_cnn_r = start_cnn && ~start_cnn_delay;

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    cnn_done_r <= 0;
else
    if(start_cnn_r)
        cnn_done_r <= 0;
    else if(cnt4 == 4'd10)
        cnn_done_r <= 1;
end
   
always@(posedge clk or negedge resetn)
begin
if(!resetn)
    cnt4 <= 0;
else
    if(!result_valid)
        cnt4 <= 0;
    else
        cnt4 <= cnt4 + 1;
end

always@(posedge clk or negedge resetn)
begin
if(!resetn)
    result_valid_r <= 1'b0;
else    
    if(cnt4 == 4'd0)
        result_valid_r <= 1'b0;
    else if(cnt4 <= 4'd10)
        result_valid_r <= 1'b1;
    else
        result_valid_r <= 1'b0;
end

always@(posedge clk)
begin
if(cnt4 > 4'd0 && cnt4 <= 4'd10)
    result_data <= result_r1[cnt4-1];
else
    result_data <= 0;
end

assign conv_start = start_conv;
assign window_start = start_window;
assign done_conv = conv_done;

endmodule