module config_ctrl(clk,
                   rst,
                   entry,
                   o_tag,
                   writedata,
                   byte_en,
                   word_en,
                   write,
                   readdata0,
                   readdata1,
                   readdata2,
                   readdata3,
                   readdata4,
                   readdata5,
                   readdata6,
                   readdata7,
                   wb_addr0,
                   wb_addr1,
                   wb_addr2,
                   wb_addr3,
                   wb_addr4,
                   wb_addr5,
                   wb_addr6,
                   wb_addr7,
                   hit,
                   miss,
                   dirty,
                   valid,
                   read_miss,
                   flash,
                   c_fig);

    parameter cache_entry = 14;
    
    input wire                    clk, rst;
    input wire [cache_entry-1:0]  entry;
    input wire [22-cache_entry:0] o_tag;
    input wire [127:0] 		      writedata;
    input wire [3:0] 		      byte_en;
    input wire [3:0]              word_en;
    input wire [7:0]   	          write;
    input wire 			          read_miss;
    input wire [1:0]	          flash;
    input wire [3:0]              c_fig;       

    output wire [127:0] 		  readdata0, readdata1, readdata2, readdata3;
    output wire [127:0] 		  readdata4, readdata5, readdata6, readdata7;
    output wire [22:0] 		      wb_addr0, wb_addr1, wb_addr2, wb_addr3;
    output wire [22:0] 		      wb_addr4, wb_addr5, wb_addr6, wb_addr7;
    output wire [7:0]    	      hit, miss, dirty, valid;

    wire [7:0] s_hit;
    wire [7:0] s_miss;
    wire [7:0] s_dirty;
    wire [7:0] s_valid;

    wire [127:0]     		  s_readdata0, s_readdata1, s_readdata2, s_readdata3;
    wire [127:0]     		  s_readdata4, s_readdata5, s_readdata6, s_readdata7;
    wire [22:0] 		      s_wb_addr0, s_wb_addr1, s_wb_addr2, s_wb_addr3;
    wire [22:0] 		      s_wb_addr4, s_wb_addr5, s_wb_addr6, s_wb_addr7;

    assign hit = (c_fig == 0) ? s_hit : 
                 (c_fig == 4'b0001) ? ((o_tag[0]) ? {4'b0000, s_hit[7], s_hit[5], s_hit[3], s_hit[1]} : 
                                                    {4'b0000, s_hit[6], s_hit[4], s_hit[2], s_hit[0]}) :
                 (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? {6'b000000, s_hit[4], s_hit[0]} :
                                       (o_tag[1:0] == 2'b01) ? {6'b000000, s_hit[5], s_hit[1]} :
                                       (o_tag[1:0] == 2'b10) ? {6'b000000, s_hit[6], s_hit[2]} : 
                                                               {6'b000000, s_hit[7], s_hit[3]}) : 8'b00000000;
    assign miss = (c_fig == 0) ? s_miss : 
                 (c_fig == 4'b0001) ? ((o_tag[0]) ? {4'b0000, s_miss[7], s_miss[5], s_miss[3], s_miss[1]} : 
                                                    {4'b0000, s_miss[6], s_miss[4], s_miss[2], s_miss[0]}) :
                 (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? {6'b000000, s_miss[4], s_miss[0]} :
                                       (o_tag[1:0] == 2'b01) ? {6'b000000, s_miss[5], s_miss[1]} :
                                       (o_tag[1:0] == 2'b10) ? {6'b000000, s_miss[6], s_miss[2]} : 
                                                                 {6'b000000, s_miss[7], s_miss[3]}) : 8'b00000000;
    assign dirty = s_dirty;
    assign valid = (c_fig == 0) ? s_valid : 
                 (c_fig == 4'b0001) ? ((o_tag[0]) ? {4'b1111, s_valid[7], s_valid[5], s_valid[3], s_valid[1]} : 
                                                    {4'b1111, s_valid[6], s_valid[4], s_valid[2], s_valid[0]}) :
                 (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? {6'b111111, s_valid[4], s_valid[0]} :
                                       (o_tag[1:0] == 2'b01) ? {6'b111111, s_valid[5], s_valid[1]} :
                                       (o_tag[1:0] == 2'b10) ? {6'b111111, s_valid[6], s_valid[2]} : 
                                                               {6'b111111, s_valid[7], s_valid[3]}) : 8'b00000000;
    assign readdata0 = ((c_fig == 0) || flash[1]) ? s_readdata0 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_readdata1 : s_readdata0) :
                       (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? s_readdata0 :
                                             (o_tag[1:0] == 2'b01) ? s_readdata1 :
                                             (o_tag[1:0] == 2'b10) ? s_readdata2 : s_readdata3) : s_readdata0;
    assign readdata1 = ((c_fig == 0) || flash[1]) ? s_readdata1 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_readdata3 : s_readdata2) :
                       (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? s_readdata4 :
                                             (o_tag[1:0] == 2'b01) ? s_readdata5 :
                                             (o_tag[1:0] == 2'b10) ? s_readdata6 : s_readdata7) : s_readdata1;
    assign readdata2 = ((c_fig == 0) || flash[1]) ? s_readdata2 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_readdata5 : s_readdata4) : readdata2;
    assign readdata3 = ((c_fig == 0) || flash[1]) ? s_readdata3 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_readdata7 : s_readdata6) : readdata3;
    assign readdata4 = s_readdata4;
    assign readdata5 = s_readdata5;
    assign readdata6 = s_readdata6;
    assign readdata7 = s_readdata7;

    assign wb_addr0 = ((c_fig == 0) || flash[1]) ? s_wb_addr0 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_wb_addr1 : s_wb_addr0) :
                       (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? s_wb_addr0 :
                                             (o_tag[1:0] == 2'b01) ? s_wb_addr1 :
                                             (o_tag[1:0] == 2'b10) ? s_wb_addr2 : s_wb_addr3) : s_wb_addr0;
    assign wb_addr1 = ((c_fig == 0) || flash[1]) ? s_wb_addr1 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_wb_addr3 : s_wb_addr2) :
                       (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? s_wb_addr4 :
                                             (o_tag[1:0] == 2'b01) ? s_wb_addr5 :
                                             (o_tag[1:0] == 2'b10) ? s_wb_addr6 : s_wb_addr7) : s_wb_addr1;
    assign wb_addr2 = ((c_fig == 0) || flash[1]) ? s_wb_addr2 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_wb_addr5 : s_wb_addr4) : wb_addr2;
    assign wb_addr3 = ((c_fig == 0) || flash[1]) ? s_wb_addr3 :
                       (c_fig == 4'b0001) ? ((o_tag[0]) ? s_wb_addr7 : s_wb_addr6) : wb_addr3;
    assign wb_addr4 = s_wb_addr4;
    assign wb_addr5 = s_wb_addr5;
    assign wb_addr6 = s_wb_addr6;
    assign wb_addr7 = s_wb_addr7;

    wire [7:0] s_write;
    assign s_write = (c_fig == 0) ? write :
                     (c_fig == 4'b0001) ? ((o_tag[0]) ? {write[3], 1'b0, write[2], 1'b0, write[1], 1'b0, write[0], 1'b0} :
                                                       {1'b0, write[3], 1'b0, write[2], 1'b0, write[1], 1'b0, write[0]}) :
                     (c_fig == 4'b0010) ? ((o_tag[1:0] == 2'b00) ? {3'b000, write[1], 3'b000, write[0]} :
                                           (o_tag[1:0] == 2'b01) ? {2'b00, write[1], 3'b000, write[0], 1'b0} :
                                           (o_tag[1:0] == 2'b10) ? {1'b0, write[1], 3'b000, write[0], 2'b00} : {write[1], 3'b000, write[0], 3'b000}) : 8'b00000000;

    set #(.cache_entry(cache_entry))
    set0(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[0]),
         .readdata(s_readdata0),
         .wb_addr(s_wb_addr0),
         .hit(s_hit[0]),
         .miss(s_miss[0]),
         .dirty(s_dirty[0]),
         .valid(s_valid[0]),
         .read_miss(read_miss),
         .flash(flash[0]));

    set #(.cache_entry(cache_entry))
    set1(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[1]),
         .readdata(s_readdata1),
         .wb_addr(s_wb_addr1),
         .hit(s_hit[1]),
         .miss(s_miss[1]),
         .dirty(s_dirty[1]),
         .valid(s_valid[1]),
         .read_miss(read_miss),
         .flash(flash[0]));

    set #(.cache_entry(cache_entry))
    set2(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[2]),
         .readdata(s_readdata2),
         .wb_addr(s_wb_addr2),
         .hit(s_hit[2]),
         .miss(s_miss[2]),
         .dirty(s_dirty[2]),
         .valid(s_valid[2]),
         .read_miss(read_miss),
         .flash(flash[0]));

    set #(.cache_entry(cache_entry))
    set3(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[3]),
         .readdata(s_readdata3),
         .wb_addr(s_wb_addr3),
         .hit(s_hit[3]),
         .miss(s_miss[3]),
         .dirty(s_dirty[3]),
         .valid(s_valid[3]),
         .read_miss(read_miss),
         .flash(flash[0]));

    set #(.cache_entry(cache_entry))
    set4(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[4]),
         .readdata(s_readdata4),
         .wb_addr(s_wb_addr4),
         .hit(s_hit[4]),
         .miss(s_miss[4]),
         .dirty(s_dirty[4]),
         .valid(s_valid[4]),
         .read_miss(read_miss),
         .flash(flash[0]));

    set #(.cache_entry(cache_entry))
    set5(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[5]),
         .readdata(s_readdata5),
         .wb_addr(s_wb_addr5),
         .hit(s_hit[5]),
         .miss(s_miss[5]),
         .dirty(s_dirty[5]),
         .valid(s_valid[5]),
         .read_miss(read_miss),
         .flash(flash[0]));

    set #(.cache_entry(cache_entry))
    set6(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[6]),
         .readdata(s_readdata6),
         .wb_addr(s_wb_addr6),
         .hit(s_hit[6]),
         .miss(s_miss[6]),
         .dirty(s_dirty[6]),
         .valid(s_valid[6]),
         .read_miss(read_miss),
         .flash(flash[0]));

    set #(.cache_entry(cache_entry))
    set7(.clk(clk),
         .rst(rst),
         .entry(entry),
         .o_tag(o_tag),
         .writedata(writedata),
         .byte_en(byte_en),
         .word_en(word_en), // 4word r/w change 
         .write(s_write[7]),
         .readdata(s_readdata7),
         .wb_addr(s_wb_addr7),
         .hit(s_hit[7]),
         .miss(s_miss[7]),
         .dirty(s_dirty[7]),
         .valid(s_valid[7]),
         .read_miss(read_miss),
         .flash(flash[0]));


endmodule // config_ctrl