module video_mnist_seg_cls
        #(
            parameter   DATA_WIDTH         = 1,
            parameter   MAX_X_NUM          = 1024,
            parameter   RAM_TYPE           = "block",
            
            parameter   NUM_CALSS          = 11,
            parameter   CHANNEL_WIDTH      = 7,
            
            parameter   IMG_Y_NUM          = 480,
            parameter   IMG_Y_WIDTH        = 12,
            
            parameter   TUSER_WIDTH        = 1,
            parameter   S_TDATA_WIDTH      = DATA_WIDTH,
            parameter   M_TNUMBER_WIDTH    = 4,
            parameter   M_TCOUNT_WIDTH     = 4,
            parameter   M_CLUSTERING_WIDTH = NUM_CALSS * CHANNEL_WIDTH,
            
            parameter   DEVICE             = "rtl",
            
            parameter   WB_ADR_WIDTH       = 8,
            parameter   WB_DAT_WIDTH       = 32,
            parameter   WB_SEL_WIDTH       = (WB_DAT_WIDTH / 8),
            parameter   INIT_PARAM_TH      = 127,
            parameter   INIT_PARAM_INV     = 1'b0
        )
        (
            input   wire                                aresetn,
            input   wire                                aclk,
            
            input   wire    [TUSER_WIDTH-1:0]           s_axi4s_tuser,
            input   wire                                s_axi4s_tlast,
            input   wire    [S_TDATA_WIDTH-1:0]         s_axi4s_tdata,
            input   wire                                s_axi4s_tvalid,
            output  wire                                s_axi4s_tready,
            
            output  wire    [TUSER_WIDTH-1:0]           m_axi4s_tuser,
            output  wire                                m_axi4s_tlast,
            output  wire    [M_TNUMBER_WIDTH-1:0]       m_axi4s_tnumber,
            output  wire    [M_TCOUNT_WIDTH-1:0]        m_axi4s_tcount,
            output  wire    [M_CLUSTERING_WIDTH-1:0]    m_axi4s_tclustering,
            output  wire                                m_axi4s_tvalid,
            input   wire                                m_axi4s_tready,
            
            input   wire                                s_wb_rst_i,
            input   wire                                s_wb_clk_i,
            input   wire    [WB_ADR_WIDTH-1:0]          s_wb_adr_i,
            input   wire    [WB_DAT_WIDTH-1:0]          s_wb_dat_i,
            output  wire    [WB_DAT_WIDTH-1:0]          s_wb_dat_o,
            input   wire                                s_wb_we_i,
            input   wire    [WB_SEL_WIDTH-1:0]          s_wb_sel_i,
            input   wire                                s_wb_stb_i,
            output  wire                                s_wb_ack_o
        );
    
    
    /*
    // binarizer
    wire    [TUSER_WIDTH-1:0]   axi4s_bin_tuser;
    wire                        axi4s_bin_tlast;
    wire    [0:0]               axi4s_bin_tbinary;
    wire    [DATA_WIDTH-1:0]    axi4s_bin_tdata;
    wire                        axi4s_bin_tvalid;
    wire                        axi4s_bin_tready;
    
    jelly_video_binarizer_core
            #(
                .TUSER_WIDTH        (TUSER_WIDTH),
                .TDATA_WIDTH        (S_TDATA_WIDTH)
            )
        i_video_binarizer_core
            (
                .aresetn            (aresetn),
                .aclk               (aclk),
                
                .param_th           (8'd127),
                .param_inv          (1'b0),
                
                .s_axi4s_tuser      (s_axi4s_tuser),
                .s_axi4s_tlast      (s_axi4s_tlast),
                .s_axi4s_tdata      (s_axi4s_tdata),
                .s_axi4s_tvalid     (s_axi4s_tvalid),
                .s_axi4s_tready     (s_axi4s_tready),
                
                .m_axi4s_tuser      (axi4s_bin_tuser),
                .m_axi4s_tlast      (axi4s_bin_tlast),
                .m_axi4s_tbinary    (axi4s_bin_tbinary),
                .m_axi4s_tdata      (axi4s_bin_tdata),
                .m_axi4s_tvalid     (axi4s_bin_tvalid),
                .m_axi4s_tready     (axi4s_bin_tready)
            );
    */
    
    assign s_wb_ack_o = s_wb_stb_i;
    
    
    
    // DNN
    wire    [TUSER_WIDTH-1:0]           axi4s_cnv_tuser;
    wire                                axi4s_cnv_tlast;
    wire    [35:0]                      axi4s_cnv_tdata;
    wire                                axi4s_cnv_tvalid;
    wire                                axi4s_cnv_tready;
    
    MnistConv
            #(
                .MAX_X_NUM          (MAX_X_NUM),
                .RAM_TYPE           (RAM_TYPE),
                
                .IMG_Y_NUM          (IMG_Y_NUM),
                .IMG_Y_WIDTH        (IMG_Y_WIDTH),
                
//                .S_TDATA_WIDTH      (1),
//                .M_TDATA_WIDTH      (11),
                .TUSER_WIDTH        (TUSER_WIDTH),
                
                .DEVICE             (DEVICE)
            )
        i_MnistConv
            (
                .reset              (~aresetn),
                .clk                (aclk),
                
                .param_blank_num    (8'd30),
                
                .s_axi4s_tuser      (s_axi4s_tuser),
                .s_axi4s_tlast      (s_axi4s_tlast),
                .s_axi4s_tdata      (s_axi4s_tdata),
                .s_axi4s_tvalid     (s_axi4s_tvalid),
                .s_axi4s_tready     (s_axi4s_tready),
                
                .m_axi4s_tuser      (axi4s_cnv_tuser),
                .m_axi4s_tlast      (axi4s_cnv_tlast),
                .m_axi4s_tdata      (axi4s_cnv_tdata),
                .m_axi4s_tvalid     (axi4s_cnv_tvalid),
                .m_axi4s_tready     (axi4s_cnv_tready)
            );
    
    
    wire    [TUSER_WIDTH-1:0]           axi4s_cls_tuser;
    wire                                axi4s_cls_tlast;
    wire    [70-1:0]                    axi4s_cls_tdata;
    wire                                axi4s_cls_tvalid;
    wire                                axi4s_cls_tready;
    MnistClassification
            #(
                .MAX_X_NUM          (MAX_X_NUM),
                .RAM_TYPE           (RAM_TYPE),
                
                .IMG_Y_NUM          (IMG_Y_NUM),
                .IMG_Y_WIDTH        (IMG_Y_WIDTH),
                
                .TUSER_WIDTH        (TUSER_WIDTH),
                
                .DEVICE             (DEVICE)
            )
        i_MnistClassification
            (
                .reset              (~aresetn),
                .clk                (aclk),
                
                .param_blank_num    (8'd30),
                
                .s_axi4s_tuser      (axi4s_cnv_tuser),
                .s_axi4s_tlast      (axi4s_cnv_tlast),
                .s_axi4s_tdata      (axi4s_cnv_tdata),
                .s_axi4s_tvalid     (axi4s_cnv_tvalid),
                .s_axi4s_tready     (axi4s_cnv_tready),
                
                .m_axi4s_tuser      (axi4s_cls_tuser),
                .m_axi4s_tlast      (axi4s_cls_tlast),
                .m_axi4s_tdata      (axi4s_cls_tdata),
                .m_axi4s_tvalid     (axi4s_cls_tvalid),
                .m_axi4s_tready     (axi4s_cls_tready)
            );
    
    
    wire    [TUSER_WIDTH-1:0]           axi4s_seg_tuser;
    wire                                axi4s_seg_tlast;
    wire    [CHANNEL_WIDTH-1:0]         axi4s_seg_tdata;
    wire                                axi4s_seg_tvalid;
    
    MnistSegmentation
            #(
                .MAX_X_NUM          (MAX_X_NUM),
                .RAM_TYPE           (RAM_TYPE),
                
                .IMG_Y_NUM          (IMG_Y_NUM),
                .IMG_Y_WIDTH        (IMG_Y_WIDTH),
                
                .TUSER_WIDTH        (TUSER_WIDTH),
                
                .DEVICE             (DEVICE)
            )
        i_MnistSegmentation
            (
                .reset              (~aresetn),
                .clk                (aclk),
                
                .param_blank_num    (8'd30),
                
                .s_axi4s_tuser      (axi4s_cnv_tuser),
                .s_axi4s_tlast      (axi4s_cnv_tlast),
                .s_axi4s_tdata      (axi4s_cnv_tdata),
                .s_axi4s_tvalid     (axi4s_cnv_tvalid),
                .s_axi4s_tready     (axi4s_cnv_tready),
                
                .m_axi4s_tuser      (axi4s_seg_tuser),
                .m_axi4s_tlast      (axi4s_seg_tlast),
                .m_axi4s_tdata      (axi4s_seg_tdata),
                .m_axi4s_tvalid     (axi4s_seg_tvalid),
                .m_axi4s_tready     (axi4s_cls_tready)
            );
    
    
    
    wire    [77-1:0]    axi4s_cls_tclustering;
    genvar  i;
    generate
    for (i = 0; i < 7; i = i+1 ) begin : loop_tclustering
        assign axi4s_cls_tclustering[i*11 +: 10] = axi4s_seg_tdata > 3 ? axi4s_cls_tdata[i*10 +: 10] : 0;
        assign axi4s_cls_tclustering[i*11 +  10] = axi4s_seg_tdata[i];
    end
    endgenerate
    
    video_dnn_max_count
            #(
                .NUM_CALSS          (NUM_CALSS),
                .CHANNEL_WIDTH      (CHANNEL_WIDTH),
                .TUSER_WIDTH        (TUSER_WIDTH),
                .TNUMBER_WIDTH      (4),
                .TCOUNT_WIDTH       (4)
            )
        i_video_dnn_max_count
            (
                .aresetn            (aresetn),
                .aclk               (aclk),
                
                .s_axi4s_tuser      (axi4s_cls_tuser),
                .s_axi4s_tlast      (axi4s_cls_tlast),
                .s_axi4s_tdata      (axi4s_cls_tclustering),
                .s_axi4s_tvalid     (axi4s_cls_tvalid),
                .s_axi4s_tready     (axi4s_cls_tready),
                
                .m_axi4s_tuser      (m_axi4s_tuser),
                .m_axi4s_tlast      (m_axi4s_tlast),
                .m_axi4s_tnumber    (m_axi4s_tnumber),
                .m_axi4s_tcount     (m_axi4s_tcount),
                .m_axi4s_tdata      (m_axi4s_tclustering),
                .m_axi4s_tvalid     (m_axi4s_tvalid),
                .m_axi4s_tready     (m_axi4s_tready)
            );
    
    
endmodule