data/full_repos/permissive/430337995/systolic_tb/src/systolic.v
1: b'%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:1: Cannot find include file: define.v\n`include "define.v" \n         ^~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/430337995/systolic_tb/src,data/full_repos/permissive/430337995/define.v\n             data/full_repos/permissive/430337995/systolic_tb/src,data/full_repos/permissive/430337995/define.v.v\n             data/full_repos/permissive/430337995/systolic_tb/src,data/full_repos/permissive/430337995/define.v.sv\n             define.v\n             define.v.v\n             define.v.sv\n             obj_dir/define.v\n             obj_dir/define.v.v\n             obj_dir/define.v.sv\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:42: Define or directive not defined: \'`WORD_ADDR_BITS\'\ninput       [`WORD_ADDR_BITS-1:0]   uni_src_addr;\n             ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:43: Define or directive not defined: \'`WORD_ADDR_BITS\'\ninput       [`WORD_ADDR_BITS-1:0]   wei_src_addr;\n             ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:46: Define or directive not defined: \'`DATA_MAX_BITS\'\ninput       [`DATA_MAX_BITS-1:0]    uni_channel;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:47: Define or directive not defined: \'`DATA_MAX_BITS\'\ninput       [`DATA_MAX_BITS-1:0]    wei_channel;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:50: Define or directive not defined: \'`DATA_MAX_BITS\'\ninput       [`DATA_MAX_BITS-1:0]    uni_row;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:51: Define or directive not defined: \'`DATA_MAX_BITS\'\ninput       [`DATA_MAX_BITS-1:0]    wei_row;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:54: Define or directive not defined: \'`DATA_MAX_BITS\'\ninput       [`DATA_MAX_BITS-1:0]    uni_col;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:55: Define or directive not defined: \'`DATA_MAX_BITS\'\ninput       [`DATA_MAX_BITS-1:0]    wei_col;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:64: Define or directive not defined: \'`WORD_ADDR_BITS\'\noutput      [`WORD_ADDR_BITS-1:0]   uni_addr;\n             ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:65: Define or directive not defined: \'`WORD_SIZE\'\ninput       [`WORD_SIZE-1:0]        uni_data;\n             ^~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:70: Define or directive not defined: \'`WORD_ADDR_BITS\'\noutput      [`WORD_ADDR_BITS-1:0]   wei_addr;\n             ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:71: Define or directive not defined: \'`WORD_SIZE\'\ninput       [`WORD_SIZE-1:0]        wei_data;\n             ^~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:75: Define or directive not defined: \'`WORD_SIZE\'\noutput      [`WORD_SIZE-1:0]        DO_uni;\n             ^~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:76: Define or directive not defined: \'`WORD_SIZE\'\noutput      [`WORD_SIZE-1:0]        DO_wei;\n             ^~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:80: Define or directive not defined: \'`WORD_SIZE\'\nreg [`WORD_SIZE-1:0]                uni_data_buf;\n     ^~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:90: Define or directive not defined: \'`WORD_ADDR_BITS\'\nreg  [`WORD_ADDR_BITS-1:0]          uni_src_addr_reg;\n      ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:91: Define or directive not defined: \'`WORD_ADDR_BITS\'\nreg  [`WORD_ADDR_BITS-1:0]          wei_src_addr_reg;\n      ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:92: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg  [`DATA_MAX_BITS-1:0]           uni_channel_reg;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:93: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg  [`DATA_MAX_BITS-1:0]           wei_channel_reg;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:95: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg  [`DATA_MAX_BITS-1:0]           uni_row_reg;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:96: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg  [`DATA_MAX_BITS-1:0]           wei_row_reg;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:98: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg  [`DATA_MAX_BITS-1:0]           uni_col_reg;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:99: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg  [`DATA_MAX_BITS-1:0]           wei_col_reg;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:102: Define or directive not defined: \'`DATA_MAX_BITS\'\nwire [`DATA_MAX_BITS-1:0]            uni_channel_index;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:103: Define or directive not defined: \'`DATA_MAX_BITS\'\nwire [`DATA_MAX_BITS-1:0]            uni_row_index;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:104: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg [`DATA_MAX_BITS-1:0]             uni_col_index;\n     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:107: Define or directive not defined: \'`DATA_MAX_BITS\'\nwire [`DATA_MAX_BITS-1:0]            wei_channel_index;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:108: Define or directive not defined: \'`DATA_MAX_BITS\'\nwire [`DATA_MAX_BITS-1:0]            wei_row_index;\n      ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:109: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg [`DATA_MAX_BITS-1:0]             wei_col_index;\n     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:116: Define or directive not defined: \'`WORD_SIZE\'\nwire [`WORD_SIZE-1:0]               uni_zero_pad_DO;\n      ^~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:117: Define or directive not defined: \'`WORD_SIZE\'\nwire [`WORD_SIZE-1:0]               uni_zero_pad_DI;\n      ^~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:130: Define or directive not defined: \'`DATA_MAX_BITS\'\nreg [`DATA_MAX_BITS-1:0]            kernel_size;\n     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/430337995/systolic_tb/src/systolic.v:131: Define or directive not defined: \'`WORD_SIZE\'\nreg [`WORD_SIZE-1:0]                uni_zero_pad_DO_reg;\n     ^~~~~~~~~~\n%Error: Exiting due to 34 error(s)\n'
module Systolic(
    clk,
    rst,
    op,
    config_valid,
    uni_src_addr,
    uni_channel,
    uni_row,
    uni_col,
    wei_src_addr,
    wei_channel,
    wei_row,
    wei_col,
    ack,
    done,
    uni_ready,
    uni_wen,
    uni_addr,
    uni_data,
    wei_ready,
    wei_wen,
    wei_addr,
    wei_data,
    DO_valid,
    DO_uni,
    DO_wei
);



input                               clk;
input                               rst;


input [2:0]                         op;


input                               config_valid;


input       [`WORD_ADDR_BITS-1:0]   uni_src_addr;
input       [`WORD_ADDR_BITS-1:0]   wei_src_addr;


input       [`DATA_MAX_BITS-1:0]    uni_channel;
input       [`DATA_MAX_BITS-1:0]    wei_channel;


input       [`DATA_MAX_BITS-1:0]    uni_row;
input       [`DATA_MAX_BITS-1:0]    wei_row;


input       [`DATA_MAX_BITS-1:0]    uni_col;
input       [`DATA_MAX_BITS-1:0]    wei_col;


output      reg                     ack;
output      reg                     done;


input                               uni_ready;
output                              uni_wen;
output      [`WORD_ADDR_BITS-1:0]   uni_addr;
input       [`WORD_SIZE-1:0]        uni_data;


input                               wei_ready;
output                              wei_wen;
output      [`WORD_ADDR_BITS-1:0]   wei_addr;
input       [`WORD_SIZE-1:0]        wei_data;


output                              DO_valid;
output      [`WORD_SIZE-1:0]        DO_uni;
output      [`WORD_SIZE-1:0]        DO_wei;



reg [`WORD_SIZE-1:0]                uni_data_buf;
reg                                 uni_data_buf_valid;

reg [4:0]                           cur_st;
wire                                conf_op;
wire                                conv_op;
wire                                mat_op;
reg                                 op_reg;


reg  [`WORD_ADDR_BITS-1:0]          uni_src_addr_reg;
reg  [`WORD_ADDR_BITS-1:0]          wei_src_addr_reg;
reg  [`DATA_MAX_BITS-1:0]           uni_channel_reg;
reg  [`DATA_MAX_BITS-1:0]           wei_channel_reg;

reg  [`DATA_MAX_BITS-1:0]           uni_row_reg;
reg  [`DATA_MAX_BITS-1:0]           wei_row_reg;

reg  [`DATA_MAX_BITS-1:0]           uni_col_reg;
reg  [`DATA_MAX_BITS-1:0]           wei_col_reg;


wire [`DATA_MAX_BITS-1:0]            uni_channel_index;
wire [`DATA_MAX_BITS-1:0]            uni_row_index;
reg [`DATA_MAX_BITS-1:0]             uni_col_index;


wire [`DATA_MAX_BITS-1:0]            wei_channel_index;
wire [`DATA_MAX_BITS-1:0]            wei_row_index;
reg [`DATA_MAX_BITS-1:0]             wei_col_index;

reg  [3:0]                          padding_size_reg;

wire                                uni_data_NA;
wire                                wei_data_NA;

wire [`WORD_SIZE-1:0]               uni_zero_pad_DO;
wire [`WORD_SIZE-1:0]               uni_zero_pad_DI;
reg  [3:0]                          stall_cnt;

reg                                 uni_data_fetch;
reg                                 wei_data_fetch;
reg                                 uni_out_valid;
reg                                 wei_out_valid;

wire                                wei_channel_index_rst;
reg                                 wei_row_index_rst;
wire                                uni_channel_index_rst;
wire                                uni_row_index_rst;

reg [`DATA_MAX_BITS-1:0]            kernel_size;
reg [`WORD_SIZE-1:0]                uni_zero_pad_DO_reg;
reg [9:0]                           DO_cnt;
wire [9:0]                          mat_total;
wire [9:0]                          DO_total;

integer i;


always@(posedge clk or negedge rst) begin
    if(!rst) begin
        cur_st <= 5'd0;
        stall_cnt <= 0;
        uni_src_addr_reg <= 0;
        wei_src_addr_reg <= 0;
        uni_channel_reg <= 0;
        wei_channel_reg <= 0;
        uni_row_reg <= 0;
        wei_row_reg <= 0;
        uni_col_reg <= 0;
        wei_col_reg <= 0;
        uni_col_index <= 0;
        wei_col_index <= 0;
        op_reg <= 0;
        uni_data_fetch <= 1'b0;
        wei_data_fetch <= 1'b0;
        uni_out_valid <= 1'b0;
        wei_out_valid <= 1'b0;
        wei_row_index_rst <= 1'b0;
        done <= 1'b0;
        ack <= 1'b0;
        uni_data_buf_valid <= 1'b0;
        uni_data_buf <= 0;
        kernel_size <= 8'd3;
        DO_cnt <= 0;
    end else begin
        case(cur_st)
            5'd0: begin
                if(config_valid & conf_op) begin
                    uni_src_addr_reg    <= uni_src_addr;
                    wei_src_addr_reg    <= wei_src_addr;
                    uni_channel_reg     <= uni_channel;
                    wei_channel_reg     <= wei_channel;
                    uni_row_reg         <= uni_row;
                    wei_row_reg         <= wei_row;
                    uni_col_reg         <= uni_col;
                    wei_col_reg         <= wei_col;
                    ack                 <= 1'b1;
                    cur_st <= 5'd0;
                end else if(config_valid & conv_op) begin
                    op_reg  <= 1'b1;
                    cur_st  <= 5'd1;
                    ack     <= 1'b1;
                end else if(config_valid & mat_op) begin
                    op_reg  <= 1'b0;
                    cur_st  <= 5'd1;
                    ack     <= 1'b1;
                end else begin
                    ack     <= 1'b0;
                    cur_st  <= 5'd0;
                    op_reg  <= 1'b0;
                    done <= 1'b0;
                    uni_col_index <= 0;
                    wei_col_index <= 0;
                    op_reg <= 0;
                    uni_data_fetch <= 1'b0;
                    wei_data_fetch <= 1'b0;
                    uni_out_valid <= 1'b0;
                    wei_out_valid <= 1'b0;
                    wei_row_index_rst <= 1'b0;
                    uni_data_buf_valid <= 1'b0;
                    uni_data_buf <= 0;
                    kernel_size <= 8'd3;
                    DO_cnt <= 0;
                end
            end
            5'd1: begin
                ack <= 1'b0;
                cur_st <= (uni_ready & wei_ready) ? ((op_reg == 1'b1) ? 5'd2 : 5'd3) : 5'd1;
            end
            5'd2: begin
                uni_data_fetch <= (stall_cnt < 4'd1) ? 1'b1 : 1'b0;
                wei_data_fetch <= (stall_cnt == 4'd2) ? 1'b1 : 1'b0;
                stall_cnt <= (stall_cnt == 4'd2) ? 4'd0 : stall_cnt + 4'd1;
                cur_st     <=  (stall_cnt == 4'd2) ? 5'd5 : 5'd2;
            end
            5'd3: begin
                uni_data_fetch <= 1'b1;
                wei_data_fetch <= 1'b1;
                stall_cnt <= (stall_cnt == 4'd1) ? 4'd0 : stall_cnt + 4'd1;
                cur_st <= (stall_cnt == 4'd1) ? 5'd4 : 5'd3;
                DO_cnt <= 10'h3ff;
            end
            5'd4: begin
                uni_out_valid <= (DO_cnt == DO_total - 1) ? 1'b0 : 1'b1;
                wei_out_valid <= (DO_cnt == DO_total - 1) ? 1'b0 : 1'b1;
                DO_cnt <= (DO_cnt == DO_total - 1) ? 0 : DO_cnt + 10'd1;
                cur_st <= (DO_cnt == DO_total - 1) ? 5'd0 : 5'd4;
                done <= (DO_cnt == DO_total - 1) ? 1'b1 : 1'b0;
            end
            5'd5: begin
                uni_data_fetch <= 1'b1;
                uni_data_buf <= uni_data;
                uni_data_buf_valid <= 1'b1;
                cur_st <= 5'd6;
                wei_col_index <= 8'd0;
                padding_size_reg <= 4'h0;
                DO_cnt <= 10'h3ff;
            end
            5'd6: begin
                uni_out_valid <= (DO_cnt == DO_total -1) ? 1'b0 : 1'b1;
                wei_out_valid <= (DO_cnt == DO_total -1) ? 1'b0 : 1'b1;
                uni_data_fetch <= (!uni_data_NA) && (wei_col_index == kernel_size-1) ? 1'b1 : 1'b0; 
                uni_data_buf <= (wei_col_index == kernel_size -1) ? uni_data : uni_data_buf;
                wei_data_fetch <= (uni_data_NA & wei_data_NA) ? 1'b0 : 1'b1;
                wei_row_index_rst <=  ((!uni_data_NA) && (wei_row_index == wei_row_reg-2)) ? 1'b1 : 1'b0;
                DO_cnt <= (DO_cnt == DO_total -1) ? 0 : DO_cnt + 10'd1;
                wei_col_index <= (wei_col_index == kernel_size -1) ? 8'd0 : wei_col_index + 8'd1;
                cur_st <= (DO_cnt == DO_total -1) ? 5'd0 : 5'd6;
                done <= (DO_cnt == DO_total -1) ? 1'b1 : 1'b0;
            end
        endcase
        uni_zero_pad_DO_reg <= uni_zero_pad_DO;
    end
end

always@(*) begin
    if(!rst) begin
        padding_size_reg = 4'd0;
    end else begin
        case(wei_col_index)
            8'd0: padding_size_reg = 4'h0;
            8'd1: padding_size_reg = 4'h1;
            8'd2: padding_size_reg = 4'hf;
            8'd3: padding_size_reg = 4'h2;
            4'd4: padding_size_reg = 4'he;
        endcase
    end
end




assign conf_op = op == 3'b000 ? 1'b1 : 1'b0;
assign conv_op = op == 3'b001 ? 1'b1 : 1'b0;
assign  mat_op = op == 3'b010 ? 1'b1 : 1'b0;



assign uni_zero_pad_DI = (uni_data_buf_valid) ? uni_data_buf : 0;
assign mat_total = uni_channel_reg * uni_row_reg;
assign DO_total = (op_reg == 1'b1) ? mat_total * 3 : mat_total;
assign DO_valid = (uni_out_valid & wei_out_valid) ? 1'b1 : 1'b0;
assign DO_uni   =  (op_reg == 1'b1) ? uni_zero_pad_DO_reg : uni_data;
assign DO_wei   =  wei_data;

assign uni_channel_index_rst = 0;
assign uni_row_index_rst    = 0;
assign wei_channel_index_rst = 0;

    DataFetch uni_fetcher(
        .clk                (clk                    ),
        .rst                (rst                    ),
        .data_ready         (uni_ready              ),
        .fetch              (uni_data_fetch         ),
        .src_addr           (uni_src_addr_reg       ),
        .channel            (uni_channel_reg        ),
        .channel_index_rst  (uni_channel_index_rst  ),
        .channel_index      (uni_channel_index      ),
        .row                (uni_row_reg            ),
        .row_index_rst      (uni_row_index_rst      ),
        .row_index          (uni_row_index          ),
        .wen                (uni_wen                ),
        .addr_out           (uni_addr               ),
        .data_NA            (uni_data_NA            )
    );

    DataFetch wei_fetcher(
        .clk                (clk                    ),
        .rst                (rst                    ),
        .data_ready         (wei_ready              ),
        .fetch              (wei_data_fetch         ),
        .src_addr           (wei_src_addr_reg       ),
        .channel            (wei_channel_reg        ),
        .channel_index_rst  (wei_channel_index_rst  ),
        .channel_index      (wei_channel_index      ),
        .row                (wei_row_reg            ),
        .row_index_rst      (wei_row_index_rst      ),
        .row_index          (wei_row_index          ),
        .wen                (wei_wen                ),
        .addr_out           (wei_addr               ),
        .data_NA            (wei_data_NA            )
    );

    ZeroPadding zp_i(
        .rst                (rst                    ),
        .padding_size       (padding_size_reg       ),
        .col_size           (uni_col_reg[3:0]       ),
        .DI                 (uni_zero_pad_DI        ),
        .DO                 (uni_zero_pad_DO        )
    );


endmodule
module Systolic(
    clk,
    rst,
    op,
    config_valid,
    uni_src_addr,
    uni_channel,
    uni_row,
    uni_col,
    wei_src_addr,
    wei_channel,
    wei_row,
    wei_col,
    ack,
    done,
    uni_ready,
    uni_wen,
    uni_addr,
    uni_data,
    wei_ready,
    wei_wen,
    wei_addr,
    wei_data,
    DO_valid,
    DO_uni,
    DO_wei
);




input                               clk;
input                               rst;


input [2:0]                         op;


input                               config_valid;


input       [`WORD_ADDR_BITS-1:0]   uni_src_addr;
input       [`WORD_ADDR_BITS-1:0]   wei_src_addr;


input       [`DATA_MAX_BITS-1:0]    uni_channel;
input       [`DATA_MAX_BITS-1:0]    wei_channel;


input       [`DATA_MAX_BITS-1:0]    uni_row;
input       [`DATA_MAX_BITS-1:0]    wei_row;


input       [`DATA_MAX_BITS-1:0]    uni_col;
input       [`DATA_MAX_BITS-1:0]    wei_col;


output      reg                     ack;
output      reg                     done;


input                               uni_ready;
output                              uni_wen;
output      [`WORD_ADDR_BITS-1:0]   uni_addr;
input       [`WORD_SIZE-1:0]        uni_data;


input                               wei_ready;
output                              wei_wen;
output      [`WORD_ADDR_BITS-1:0]   wei_addr;
input       [`WORD_SIZE-1:0]        wei_data;


output                              DO_valid;
output      [`WORD_SIZE-1:0]        DO_uni;
output      [`WORD_SIZE-1:0]        DO_wei;



reg [`WORD_SIZE-1:0]                uni_data_buf;
reg                                 uni_data_buf_valid;

reg [4:0]                           cur_st;
wire                                conf_op;
wire                                conv_op;
wire                                mat_op;
reg                                 op_reg;


reg  [`WORD_ADDR_BITS-1:0]          uni_src_addr_reg;
reg  [`WORD_ADDR_BITS-1:0]          wei_src_addr_reg;
reg  [`DATA_MAX_BITS-1:0]           uni_channel_reg;
reg  [`DATA_MAX_BITS-1:0]           wei_channel_reg;

reg  [`DATA_MAX_BITS-1:0]           uni_row_reg;
reg  [`DATA_MAX_BITS-1:0]           wei_row_reg;

reg  [`DATA_MAX_BITS-1:0]           uni_col_reg;
reg  [`DATA_MAX_BITS-1:0]           wei_col_reg;


wire [`DATA_MAX_BITS-1:0]            uni_channel_index;
wire [`DATA_MAX_BITS-1:0]            uni_row_index;
reg [`DATA_MAX_BITS-1:0]             uni_col_index;


wire [`DATA_MAX_BITS-1:0]            wei_channel_index;
wire [`DATA_MAX_BITS-1:0]            wei_row_index;
reg [`DATA_MAX_BITS-1:0]             wei_col_index;

reg  [3:0]                          padding_size_reg;

wire                                uni_data_NA;
wire                                wei_data_NA;

wire [`WORD_SIZE-1:0]               uni_zero_pad_DO;
wire [`WORD_SIZE-1:0]               uni_zero_pad_DI;
reg  [3:0]                          stall_cnt;

reg                                 uni_data_fetch;
reg                                 wei_data_fetch;
reg                                 uni_out_valid;
reg                                 wei_out_valid;

wire                                wei_channel_index_rst;
reg                                 wei_row_index_rst;
wire                                uni_channel_index_rst;
wire                                uni_row_index_rst;

reg [`DATA_MAX_BITS-1:0]            kernel_size;
reg [`WORD_SIZE-1:0]                uni_zero_pad_DO_reg;
reg [9:0]                           DO_cnt;
wire [9:0]                          mat_total;
wire [9:0]                          DO_total;

integer i;


always@(posedge clk or negedge rst) begin
    if(!rst) begin
        cur_st <= 5'd0;
        stall_cnt <= 0;
        uni_src_addr_reg <= 0;
        wei_src_addr_reg <= 0;
        uni_channel_reg <= 0;
        wei_channel_reg <= 0;
        uni_row_reg <= 0;
        wei_row_reg <= 0;
        uni_col_reg <= 0;
        wei_col_reg <= 0;
        uni_col_index <= 0;
        wei_col_index <= 0;
        op_reg <= 0;
        uni_data_fetch <= 1'b0;
        wei_data_fetch <= 1'b0;
        uni_out_valid <= 1'b0;
        wei_out_valid <= 1'b0;
        wei_row_index_rst <= 1'b0;
        done <= 1'b0;
        ack <= 1'b0;
        uni_data_buf_valid <= 1'b0;
        uni_data_buf <= 0;
        kernel_size <= 8'd3;
        DO_cnt <= 0;
    end else begin
        case(cur_st)
            5'd0: begin
                if(config_valid & conf_op) begin
                    uni_src_addr_reg    <= uni_src_addr;
                    wei_src_addr_reg    <= wei_src_addr;
                    uni_channel_reg     <= uni_channel;
                    wei_channel_reg     <= wei_channel;
                    uni_row_reg         <= uni_row;
                    wei_row_reg         <= wei_row;
                    uni_col_reg         <= uni_col;
                    wei_col_reg         <= wei_col;
                    ack                 <= 1'b1;
                    cur_st <= 5'd0;
                end else if(config_valid & conv_op) begin
                    op_reg  <= 1'b1;
                    cur_st  <= 5'd1;
                    ack     <= 1'b1;
                end else if(config_valid & mat_op) begin
                    op_reg  <= 1'b0;
                    cur_st  <= 5'd1;
                    ack     <= 1'b1;
                end else begin
                    ack     <= 1'b0;
                    cur_st  <= 5'd0;
                    op_reg  <= 1'b0;
                    done <= 1'b0;
                    uni_col_index <= 0;
                    wei_col_index <= 0;
                    op_reg <= 0;
                    uni_data_fetch <= 1'b0;
                    wei_data_fetch <= 1'b0;
                    uni_out_valid <= 1'b0;
                    wei_out_valid <= 1'b0;
                    wei_row_index_rst <= 1'b0;
                    uni_data_buf_valid <= 1'b0;
                    uni_data_buf <= 0;
                    kernel_size <= 8'd3;
                    DO_cnt <= 0;
                end
            end
            5'd1: begin
                ack <= 1'b0;
                cur_st <= (uni_ready & wei_ready) ? ((op_reg == 1'b1) ? 5'd2 : 5'd3) : 5'd1;
            end
            5'd2: begin
                uni_data_fetch <= (stall_cnt < 4'd1) ? 1'b1 : 1'b0;
                wei_data_fetch <= (stall_cnt == 4'd2) ? 1'b1 : 1'b0;
                stall_cnt <= (stall_cnt == 4'd2) ? 4'd0 : stall_cnt + 4'd1;
                cur_st     <=  (stall_cnt == 4'd2) ? 5'd5 : 5'd2;
            end
            5'd3: begin
                uni_data_fetch <= 1'b1;
                wei_data_fetch <= 1'b1;
                stall_cnt <= (stall_cnt == 4'd1) ? 4'd0 : stall_cnt + 4'd1;
                cur_st <= (stall_cnt == 4'd1) ? 5'd4 : 5'd3;
                DO_cnt <= 10'h3ff;
            end
            5'd4: begin
                uni_out_valid <= (DO_cnt == DO_total - 1) ? 1'b0 : 1'b1;
                wei_out_valid <= (DO_cnt == DO_total - 1) ? 1'b0 : 1'b1;
                DO_cnt <= (DO_cnt == DO_total - 1) ? 0 : DO_cnt + 10'd1;
                cur_st <= (DO_cnt == DO_total - 1) ? 5'd0 : 5'd4;
                done <= (DO_cnt == DO_total - 1) ? 1'b1 : 1'b0;
            end
            5'd5: begin
                uni_data_fetch <= 1'b1;
                uni_data_buf <= uni_data;
                uni_data_buf_valid <= 1'b1;
                cur_st <= 5'd6;
                wei_col_index <= 8'd0;
                padding_size_reg <= 4'h0;
                DO_cnt <= 10'h3ff;
            end
            5'd6: begin
                uni_out_valid <= (DO_cnt == DO_total -1) ? 1'b0 : 1'b1;
                wei_out_valid <= (DO_cnt == DO_total -1) ? 1'b0 : 1'b1;
                uni_data_fetch <= (!uni_data_NA) && (wei_col_index == kernel_size-1) ? 1'b1 : 1'b0; 
                uni_data_buf <= (wei_col_index == kernel_size -1) ? uni_data : uni_data_buf;
                wei_data_fetch <= (uni_data_NA & wei_data_NA) ? 1'b0 : 1'b1;
                wei_row_index_rst <=  ((!uni_data_NA) && (wei_row_index == wei_row_reg-2)) ? 1'b1 : 1'b0;
                DO_cnt <= (DO_cnt == DO_total -1) ? 0 : DO_cnt + 10'd1;
                wei_col_index <= (wei_col_index == kernel_size -1) ? 8'd0 : wei_col_index + 8'd1;
                cur_st <= (DO_cnt == DO_total -1) ? 5'd0 : 5'd6;
                done <= (DO_cnt == DO_total -1) ? 1'b1 : 1'b0;
            end
        endcase
        uni_zero_pad_DO_reg <= uni_zero_pad_DO;
    end
end

always@(*) begin
    if(!rst) begin
        padding_size_reg = 4'd0;
    end else begin
        case(wei_col_index)
            8'd0: padding_size_reg = 4'h0;
            8'd1: padding_size_reg = 4'h1;
            8'd2: padding_size_reg = 4'hf;
            8'd3: padding_size_reg = 4'h2;
            4'd4: padding_size_reg = 4'he;
        endcase
    end
end




assign conf_op = op == 3'b000 ? 1'b1 : 1'b0;
assign conv_op = op == 3'b001 ? 1'b1 : 1'b0;
assign  mat_op = op == 3'b010 ? 1'b1 : 1'b0;



assign uni_zero_pad_DI = (uni_data_buf_valid) ? uni_data_buf : 0;
assign mat_total = uni_channel_reg * uni_row_reg;
assign DO_total = (op_reg == 1'b1) ? mat_total * 3 : mat_total;
assign DO_valid = (uni_out_valid & wei_out_valid) ? 1'b1 : 1'b0;
assign DO_uni   =  (op_reg == 1'b1) ? uni_zero_pad_DO_reg : uni_data;
assign DO_wei   =  wei_data;

assign uni_channel_index_rst = 0;
assign uni_row_index_rst    = 0;
assign wei_channel_index_rst = 0;

    DataFetch uni_fetcher(
        .clk                (clk                    ),
        .rst                (rst                    ),
        .data_ready         (uni_ready              ),
        .fetch              (uni_data_fetch         ),
        .src_addr           (uni_src_addr_reg       ),
        .channel            (uni_channel_reg        ),
        .channel_index_rst  (uni_channel_index_rst  ),
        .channel_index      (uni_channel_index      ),
        .row                (uni_row_reg            ),
        .row_index_rst      (uni_row_index_rst      ),
        .row_index          (uni_row_index          ),
        .wen                (uni_wen                ),
        .addr_out           (uni_addr               ),
        .data_NA            (uni_data_NA            )
    );

    DataFetch wei_fetcher(
        .clk                (clk                    ),
        .rst                (rst                    ),
        .data_ready         (wei_ready              ),
        .fetch              (wei_data_fetch         ),
        .src_addr           (wei_src_addr_reg       ),
        .channel            (wei_channel_reg        ),
        .channel_index_rst  (wei_channel_index_rst  ),
        .channel_index      (wei_channel_index      ),
        .row                (wei_row_reg            ),
        .row_index_rst      (wei_row_index_rst      ),
        .row_index          (wei_row_index          ),
        .wen                (wei_wen                ),
        .addr_out           (wei_addr               ),
        .data_NA            (wei_data_NA            )
    );

    ZeroPadding zp_i(
        .rst                (rst                    ),
        .padding_size       (padding_size_reg       ),
        .col_size           (uni_col_reg[3:0]       ),
        .DI                 (uni_zero_pad_DI        ),
        .DO                 (uni_zero_pad_DO        )
    );


endmodule