data/full_repos/permissive/217441787/fpga/mig/ddr_cache.v
[Errno 2] No such file or directory: 'preprocess.output'
1: b'%Error: data/full_repos/permissive/217441787/fpga/mig/ddr_cache.v:101: Cannot find file containing module: \'bram_256_72\'\n    bram_256_72 cache_way_0_high(clk, rst, addr_line_mux, ~rst, cache_way_we_0, {cache_way_rd_0[143: 136], cache_way_rd_0[127:64]}, {cache_way_wr_0[143: 136], cache_way_wr_0[127:64]});\n    ^~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/217441787/fpga/mig,data/full_repos/permissive/217441787/bram_256_72\n             data/full_repos/permissive/217441787/fpga/mig,data/full_repos/permissive/217441787/bram_256_72.v\n             data/full_repos/permissive/217441787/fpga/mig,data/full_repos/permissive/217441787/bram_256_72.sv\n             bram_256_72\n             bram_256_72.v\n             bram_256_72.sv\n             obj_dir/bram_256_72\n             obj_dir/bram_256_72.v\n             obj_dir/bram_256_72.sv\n%Error: data/full_repos/permissive/217441787/fpga/mig/ddr_cache.v:102: Cannot find file containing module: \'bram_256_72\'\n    bram_256_72 cache_way_0_low (clk, rst, addr_line_mux, ~rst, cache_way_we_0, {cache_way_rd_0[135: 128], cache_way_rd_0[63:0]},   {cache_way_wr_0[135: 128], cache_way_wr_0[63:0]});\n    ^~~~~~~~~~~\n%Error: data/full_repos/permissive/217441787/fpga/mig/ddr_cache.v:103: Cannot find file containing module: \'bram_256_72\'\n    bram_256_72 cache_way_1_high(clk, rst, addr_line_mux, ~rst, cache_way_we_1, {cache_way_rd_1[143: 136], cache_way_rd_1[127:64]}, {cache_way_wr_1[143: 136], cache_way_wr_1[127:64]});\n    ^~~~~~~~~~~\n%Error: data/full_repos/permissive/217441787/fpga/mig/ddr_cache.v:104: Cannot find file containing module: \'bram_256_72\'\n    bram_256_72 cache_way_1_low (clk, rst, addr_line_mux, ~rst, cache_way_we_1, {cache_way_rd_1[135: 128], cache_way_rd_1[63:0]},   {cache_way_wr_1[135: 128], cache_way_wr_1[63:0]});\n    ^~~~~~~~~~~\n%Warning-WIDTH: data/full_repos/permissive/217441787/fpga/mig/ddr_cache.v:138: Operator ASSIGNW expects 128 bits on the Assign RHS, but Assign RHS\'s COND generates 144 bits.\n                                                                             : ... In instance ddr_cache\n    wire [127:0] mem_wdata_comb = (mem_w_src == 1\'b0) ? (cache_way_rd_0) : (cache_way_rd_1);\n                                ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/217441787/fpga/mig/ddr_cache.v:167: Operator EQ expects 32 bits on the LHS, but LHS\'s VARREF \'addr_word\' generates 2 bits.\n                                                                             : ... In instance ddr_cache\n                sys_byte_strobe[i * 4 + j] = (addr_word == i) && (sys_wstrb[j]);\n                                                        ^~\n%Error: Exiting due to 4 error(s), 2 warning(s)\n'
module ddr_cache(
    input wire clk,
    input wire rst, 
    input wire [24:0] sys_addr,
    input wire [31:0] sys_wdata,
    output reg [31:0] sys_rdata,
    input wire [3:0] sys_wstrb,
    input wire sys_valid,
    output reg sys_ready,
    output reg [20:0] mem_addr,
    output wire [127:0] mem_wdata,
    input wire [127:0] mem_rdata,
    output reg mem_wstrb,
    output reg mem_valid,
    input wire mem_ready
    );












    







    

    
    `define USE_3_CYCLE_CACHE 1
    

    localparam CACHE_WAY = 2; 
    localparam CACHE_WAY_BITS = 1;
    localparam CACHE_LINE = 256;
    localparam CACHE_LINE_BITS = 8;
    localparam CACHE_LEN = 4;
    localparam CACHE_LEN_ABITS = 2;
    localparam CACHE_LEN_DBITS = 128;
    localparam CACHE_ADDR_BITS = 23;
    localparam CACHE_TAG_BITS = CACHE_ADDR_BITS - CACHE_LINE_BITS - CACHE_LEN_ABITS;
    localparam CACHE_VALID_BITS = 1;
    localparam CACHE_DIRTY_BITS = 1;
    localparam CACHE_LRU_BITS = 1;
    localparam CACHE_LEN_TOTAL = CACHE_LEN_DBITS + CACHE_TAG_BITS + CACHE_VALID_BITS + CACHE_DIRTY_BITS + CACHE_LRU_BITS;
    
    localparam BIT_TAG_START = 128;
    localparam BIT_TAG_END = 128 + 13 - 1;
    localparam BIT_LRU = 143;
    localparam BIT_VALID = 142;
    localparam BIT_DIRTY = 141;
    
    wire [CACHE_ADDR_BITS - 1: 0] sys_word_addr = sys_addr[CACHE_ADDR_BITS + 1: 2];
    
    wire [CACHE_LEN_ABITS - 1: 0] addr_word = sys_word_addr[CACHE_LEN_ABITS - 1: 0];
    wire [CACHE_LINE_BITS - 1: 0] addr_line = sys_word_addr[CACHE_LINE_BITS + CACHE_LEN_ABITS - 1: CACHE_LEN_ABITS];
    wire [CACHE_TAG_BITS - 1: 0]  addr_tag  = sys_word_addr[CACHE_ADDR_BITS - 1: CACHE_LINE_BITS + CACHE_LEN_ABITS];
    
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_rd_0;
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_rd_1;
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_wr_0;
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_wr_1;
    reg                           cache_way_we_0;
    reg                           cache_way_we_1;
    
    wire [CACHE_LINE_BITS - 1: 0] addr_line_mux;
    reg addr_line_sel;
    

    bram_256_72 cache_way_0_high(clk, rst, addr_line_mux, ~rst, cache_way_we_0, {cache_way_rd_0[143: 136], cache_way_rd_0[127:64]}, {cache_way_wr_0[143: 136], cache_way_wr_0[127:64]});
    bram_256_72 cache_way_0_low (clk, rst, addr_line_mux, ~rst, cache_way_we_0, {cache_way_rd_0[135: 128], cache_way_rd_0[63:0]},   {cache_way_wr_0[135: 128], cache_way_wr_0[63:0]});
    bram_256_72 cache_way_1_high(clk, rst, addr_line_mux, ~rst, cache_way_we_1, {cache_way_rd_1[143: 136], cache_way_rd_1[127:64]}, {cache_way_wr_1[143: 136], cache_way_wr_1[127:64]});
    bram_256_72 cache_way_1_low (clk, rst, addr_line_mux, ~rst, cache_way_we_1, {cache_way_rd_1[135: 128], cache_way_rd_1[63:0]},   {cache_way_wr_1[135: 128], cache_way_wr_1[63:0]});
    
    wire cache_comparator_0_comb = ((addr_tag == cache_way_rd_0[BIT_TAG_END: BIT_TAG_START]) && (cache_way_rd_0[BIT_VALID])) ? 1'b1 : 1'b0;
    wire cache_comparator_1_comb = ((addr_tag == cache_way_rd_1[BIT_TAG_END: BIT_TAG_START]) && (cache_way_rd_1[BIT_VALID])) ? 1'b1 : 1'b0;
`ifdef USE_3_CYCLE_CACHE
    reg cache_comparator_0;
    reg cache_comparator_1;
    
    always@(posedge clk) begin
        cache_comparator_0 <= cache_comparator_0_comb;
        cache_comparator_1 <= cache_comparator_1_comb;
    end
`else
    wire cache_comparator_0 = cache_comparator_0_comb;
    wire cache_comparator_1 = cache_comparator_1_comb;
`endif

    wire [31: 0] cache_way_0_output_mux = 
        (addr_word == 2'b00) ? (cache_way_rd_0[31:0]) :
        (addr_word == 2'b01) ? (cache_way_rd_0[63:32]) :
        (addr_word == 2'b10) ? (cache_way_rd_0[95:64]) :
                               (cache_way_rd_0[127:96]);
    wire [31: 0] cache_way_1_output_mux = 
        (addr_word == 2'b00) ? (cache_way_rd_1[31:0]) :
        (addr_word == 2'b01) ? (cache_way_rd_1[63:32]) :
        (addr_word == 2'b10) ? (cache_way_rd_1[95:64]) :
                               (cache_way_rd_1[127:96]);
    wire [31: 0] mem_rd_output_mux = 
        (addr_word == 2'b00) ? (mem_rdata[31:0]) :
        (addr_word == 2'b01) ? (mem_rdata[63:32]) :
        (addr_word == 2'b10) ? (mem_rdata[95:64]) :
                               (mem_rdata[127:96]);
    
    reg mem_w_src;
    wire [127:0] mem_wdata_comb = (mem_w_src == 1'b0) ? (cache_way_rd_0) : (cache_way_rd_1);
    

    assign mem_wdata = mem_wdata_comb;
    










    
    wire cache_lru_bit_0 = cache_way_rd_0[BIT_LRU];
    wire cache_lru_bit_1 = cache_way_rd_1[BIT_LRU];
    wire cache_lru_way_0_newer = (cache_lru_bit_0 == cache_lru_bit_1) ? 1 : 0;
    wire cache_lru_way_1_newer = !cache_lru_way_0_newer;
    
    reg sys_byte_strobe [0: 15];
    integer i;
    integer j;
    always @(*) begin
        for (i = 0; i < 4; i = i + 1) begin
            for (j = 0; j < 4; j = j + 1) begin
                sys_byte_strobe[i * 4 + j] = (addr_word == i) && (sys_wstrb[j]);
            end
        end
    end
    

    wire [143: 0] cache_way_0_input_overlay;
    wire [143: 0] cache_way_1_input_overlay;

    assign cache_way_0_input_overlay[8 - 1: 0] = (sys_byte_strobe[0]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[8 - 1: 0]);
    assign cache_way_1_input_overlay[8 - 1: 0] = (sys_byte_strobe[0]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[8 - 1: 0]);
    assign cache_way_0_input_overlay[16 - 1: 8] = (sys_byte_strobe[1]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[16 - 1: 8]);
    assign cache_way_1_input_overlay[16 - 1: 8] = (sys_byte_strobe[1]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[16 - 1: 8]);
    assign cache_way_0_input_overlay[24 - 1: 16] = (sys_byte_strobe[2]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[24 - 1: 16]);
    assign cache_way_1_input_overlay[24 - 1: 16] = (sys_byte_strobe[2]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[24 - 1: 16]);
    assign cache_way_0_input_overlay[32 - 1: 24] = (sys_byte_strobe[3]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[32 - 1: 24]);
    assign cache_way_1_input_overlay[32 - 1: 24] = (sys_byte_strobe[3]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[32 - 1: 24]);
    assign cache_way_0_input_overlay[40 - 1: 32] = (sys_byte_strobe[4]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[40 - 1: 32]);
    assign cache_way_1_input_overlay[40 - 1: 32] = (sys_byte_strobe[4]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[40 - 1: 32]);
    assign cache_way_0_input_overlay[48 - 1: 40] = (sys_byte_strobe[5]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[48 - 1: 40]);
    assign cache_way_1_input_overlay[48 - 1: 40] = (sys_byte_strobe[5]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[48 - 1: 40]);
    assign cache_way_0_input_overlay[56 - 1: 48] = (sys_byte_strobe[6]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[56 - 1: 48]);
    assign cache_way_1_input_overlay[56 - 1: 48] = (sys_byte_strobe[6]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[56 - 1: 48]);
    assign cache_way_0_input_overlay[64 - 1: 56] = (sys_byte_strobe[7]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[64 - 1: 56]);
    assign cache_way_1_input_overlay[64 - 1: 56] = (sys_byte_strobe[7]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[64 - 1: 56]);
    assign cache_way_0_input_overlay[72 - 1: 64] = (sys_byte_strobe[8]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[72 - 1: 64]);
    assign cache_way_1_input_overlay[72 - 1: 64] = (sys_byte_strobe[8]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[72 - 1: 64]);
    assign cache_way_0_input_overlay[80 - 1: 72] = (sys_byte_strobe[9]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[80 - 1: 72]);
    assign cache_way_1_input_overlay[80 - 1: 72] = (sys_byte_strobe[9]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[80 - 1: 72]);
    assign cache_way_0_input_overlay[88 - 1: 80] = (sys_byte_strobe[10]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[88 - 1: 80]);
    assign cache_way_1_input_overlay[88 - 1: 80] = (sys_byte_strobe[10]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[88 - 1: 80]);
    assign cache_way_0_input_overlay[96 - 1: 88] = (sys_byte_strobe[11]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[96 - 1: 88]);
    assign cache_way_1_input_overlay[96 - 1: 88] = (sys_byte_strobe[11]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[96 - 1: 88]);
    assign cache_way_0_input_overlay[104 - 1: 96] = (sys_byte_strobe[12]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[104 - 1: 96]);
    assign cache_way_1_input_overlay[104 - 1: 96] = (sys_byte_strobe[12]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[104 - 1: 96]);
    assign cache_way_0_input_overlay[112 - 1: 104] = (sys_byte_strobe[13]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[112 - 1: 104]);
    assign cache_way_1_input_overlay[112 - 1: 104] = (sys_byte_strobe[13]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[112 - 1: 104]);
    assign cache_way_0_input_overlay[120 - 1: 112] = (sys_byte_strobe[14]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[120 - 1: 112]);
    assign cache_way_1_input_overlay[120 - 1: 112] = (sys_byte_strobe[14]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[120 - 1: 112]);
    assign cache_way_0_input_overlay[128 - 1: 120] = (sys_byte_strobe[15]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[128 - 1: 120]);
    assign cache_way_1_input_overlay[128 - 1: 120] = (sys_byte_strobe[15]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[128 - 1: 120]);
    

    assign cache_way_0_input_overlay[140: 128] = cache_way_rd_0[BIT_TAG_END: BIT_TAG_START];
    assign cache_way_1_input_overlay[140: 128] = cache_way_rd_1[BIT_TAG_END: BIT_TAG_START];
    assign cache_way_0_input_overlay[143: 141] = {cache_way_rd_1[BIT_LRU], 1'b1, ((sys_wstrb != 0) || (cache_way_rd_0[BIT_DIRTY])) ? 1'b1 : 1'b0};
    assign cache_way_1_input_overlay[143: 141] = {!cache_way_rd_0[BIT_LRU], 1'b1, ((sys_wstrb != 0) || (cache_way_rd_1[BIT_DIRTY])) ? 1'b1 : 1'b0};
                             
    reg [1:0] cache_line_wb_src;
    assign cache_way_wr_0 = 
        (cache_line_wb_src == 2'b01) ? ({cache_way_rd_1[143], 2'b10, addr_tag, mem_rdata}) : 
        (cache_line_wb_src == 2'b00) ? (cache_way_0_input_overlay) : ({!cache_way_rd_1[BIT_LRU], 143'd0});
    assign cache_way_wr_1 = 
        (cache_line_wb_src == 2'b01) ? ({!cache_way_rd_0[143], 2'b10, addr_tag, mem_rdata}) : 
        (cache_line_wb_src == 2'b00) ? (cache_way_1_input_overlay) : ({cache_way_rd_0[BIT_LRU], 143'd0});
    
    reg [3: 0] cache_state;
    

    localparam STATE_RESET = 4'd0;
    localparam STATE_IDLE = 4'd1;
    localparam STATE_RW_COMPARE = 4'd2;
    localparam STATE_RW_CHECK = 4'd3;
    localparam STATE_RW_MISS = 4'd4;
    localparam STATE_RW_DONE = 4'd5;
    localparam STATE_RW_FLUSH = 4'd6;
    localparam STATE_RW_FLUSH_WAIT = 4'd7;
    localparam STATE_WRITE_MISS_APPLY = 4'd8;
    localparam STATE_WAIT = 4'd15;
    
    reg [CACHE_LINE_BITS - 1: 0] invalidate_counter;
    assign addr_line_mux = (addr_line_sel) ? invalidate_counter : addr_line;
    
    always@(posedge clk) begin
        if (rst) begin
            cache_state <= STATE_RESET;
            sys_ready <= 1'b0;
            mem_valid <= 1'b0;
            cache_way_we_0 <= 1'b0;
            cache_way_we_1 <= 1'b0;
            cache_line_wb_src <= 2'b10;
            invalidate_counter <= 8'hFF;
            addr_line_sel <= 1'b1;
        end
        else begin
            case (cache_state)
                STATE_RESET: begin
                    cache_way_we_0 <= 1'b1;
                    cache_way_we_1 <= 1'b1;
                    invalidate_counter <= invalidate_counter - 1;
                    if (invalidate_counter == 8'd0)
                        cache_state <= STATE_IDLE;
                end
                STATE_IDLE: begin
                    addr_line_sel <= 1'b0;
                    cache_way_we_0 <= 1'b0;
                    cache_way_we_1 <= 1'b0;
                    if (sys_valid) begin
                    `ifdef USE_3_CYCLE_CACHE
                        cache_state <= STATE_RW_COMPARE;
                    `else
                        cache_state <= STATE_RW_CHECK;
                    `endif
                    end
                end
                STATE_RW_COMPARE: begin

                    cache_state <= STATE_RW_CHECK;
                end
                STATE_RW_CHECK: begin
                    if (cache_comparator_0) begin

                        sys_rdata <= cache_way_0_output_mux;
                        sys_ready <= 1'b1;


                        cache_way_we_0 <= 1'b1;
                        cache_way_we_1 <= 1'b0;
                        cache_line_wb_src <= 2'b00;
                        cache_state <= STATE_WAIT;

                    end
                    else if (cache_comparator_1) begin
                        sys_rdata <= cache_way_1_output_mux;
                        sys_ready <= 1'b1;
                        cache_way_we_0 <= 1'b0;
                        cache_way_we_1 <= 1'b1;
                        cache_line_wb_src <= 2'b00;
                        cache_state <= STATE_WAIT;

                    end
                    else begin


                        if (cache_lru_way_1_newer) begin
                            if (cache_way_rd_0[BIT_VALID] && cache_way_rd_0[BIT_DIRTY]) begin

                                mem_addr <= {cache_way_rd_0[BIT_TAG_END: BIT_TAG_START], addr_line};
                                mem_w_src <= 1'b0;
                                mem_wstrb <= 1'b1;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_FLUSH;


                            end
                            else begin

                                mem_addr <= sys_addr[24:4];
                                mem_wstrb <= 1'b0;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_MISS;

                            end
                        end
                        else begin
                            if (cache_way_rd_1[BIT_VALID] && cache_way_rd_1[BIT_DIRTY]) begin

                                mem_addr <= {cache_way_rd_1[BIT_TAG_END: BIT_TAG_START], addr_line};
                                mem_w_src <= 1'b1;
                                mem_wstrb <= 1'b1;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_FLUSH;


                            end
                            else begin

                                mem_addr <= sys_addr[24:4];
                                mem_wstrb <= 1'b0;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_MISS;

                            end
                        end
                    end
                end
                STATE_RW_MISS: begin
                    if (mem_ready) begin

                        cache_line_wb_src <= 2'b01;
                        if (cache_lru_way_1_newer) begin
                            cache_way_we_0 <= 1'b1;
                        end
                        else begin
                            cache_way_we_1 <= 1'b1;
                        end
                        if (sys_wstrb == 0) begin
                            sys_rdata <= mem_rd_output_mux;
                            sys_ready <= 1'b1;
                            cache_state <= STATE_WAIT;
                        end
                        else begin

                            cache_state <= STATE_WRITE_MISS_APPLY;
                        end
                    end
                end
                STATE_RW_FLUSH: begin
                    if (mem_ready) begin
                        mem_valid <= 1'b0;
                        cache_line_wb_src <= 2'b10;
                        if (cache_lru_way_1_newer) begin
                            cache_way_we_0 <= 1'b1;
                        end
                        else begin
                            cache_way_we_1 <= 1'b1;
                        end
                        cache_state <= STATE_RW_FLUSH_WAIT;
                    end
                end
                STATE_RW_FLUSH_WAIT: begin
                    cache_way_we_0 <= 1'b0;
                    cache_way_we_1 <= 1'b0;
                    if (!mem_ready) begin
                        cache_state <= STATE_RW_CHECK;
                    end
                end
                STATE_WRITE_MISS_APPLY: begin
                    cache_line_wb_src <= 2'b00;
                    sys_ready <= 1'b1;
                    cache_state <= STATE_WAIT;
                end
                STATE_WAIT: begin
                    cache_way_we_0 <= 1'b0;
                    cache_way_we_1 <= 1'b0;
                    mem_valid <= 1'b0;
                    sys_ready <= 1'b0;
                    if (!sys_valid) begin
                        cache_state <= STATE_IDLE;
                    end
                end
            endcase
        end
    end
    

endmodule
module ddr_cache(
    input wire clk,
    input wire rst, 
    input wire [24:0] sys_addr,
    input wire [31:0] sys_wdata,
    output reg [31:0] sys_rdata,
    input wire [3:0] sys_wstrb,
    input wire sys_valid,
    output reg sys_ready,
    output reg [20:0] mem_addr,
    output wire [127:0] mem_wdata,
    input wire [127:0] mem_rdata,
    output reg mem_wstrb,
    output reg mem_valid,
    input wire mem_ready
    );













    







    

    
    `define USE_3_CYCLE_CACHE 1
    

    localparam CACHE_WAY = 2; 
    localparam CACHE_WAY_BITS = 1;
    localparam CACHE_LINE = 256;
    localparam CACHE_LINE_BITS = 8;
    localparam CACHE_LEN = 4;
    localparam CACHE_LEN_ABITS = 2;
    localparam CACHE_LEN_DBITS = 128;
    localparam CACHE_ADDR_BITS = 23;
    localparam CACHE_TAG_BITS = CACHE_ADDR_BITS - CACHE_LINE_BITS - CACHE_LEN_ABITS;
    localparam CACHE_VALID_BITS = 1;
    localparam CACHE_DIRTY_BITS = 1;
    localparam CACHE_LRU_BITS = 1;
    localparam CACHE_LEN_TOTAL = CACHE_LEN_DBITS + CACHE_TAG_BITS + CACHE_VALID_BITS + CACHE_DIRTY_BITS + CACHE_LRU_BITS;
    
    localparam BIT_TAG_START = 128;
    localparam BIT_TAG_END = 128 + 13 - 1;
    localparam BIT_LRU = 143;
    localparam BIT_VALID = 142;
    localparam BIT_DIRTY = 141;
    
    wire [CACHE_ADDR_BITS - 1: 0] sys_word_addr = sys_addr[CACHE_ADDR_BITS + 1: 2];
    
    wire [CACHE_LEN_ABITS - 1: 0] addr_word = sys_word_addr[CACHE_LEN_ABITS - 1: 0];
    wire [CACHE_LINE_BITS - 1: 0] addr_line = sys_word_addr[CACHE_LINE_BITS + CACHE_LEN_ABITS - 1: CACHE_LEN_ABITS];
    wire [CACHE_TAG_BITS - 1: 0]  addr_tag  = sys_word_addr[CACHE_ADDR_BITS - 1: CACHE_LINE_BITS + CACHE_LEN_ABITS];
    
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_rd_0;
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_rd_1;
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_wr_0;
    wire [CACHE_LEN_TOTAL - 1: 0] cache_way_wr_1;
    reg                           cache_way_we_0;
    reg                           cache_way_we_1;
    
    wire [CACHE_LINE_BITS - 1: 0] addr_line_mux;
    reg addr_line_sel;
    

    bram_256_72 cache_way_0_high(clk, rst, addr_line_mux, ~rst, cache_way_we_0, {cache_way_rd_0[143: 136], cache_way_rd_0[127:64]}, {cache_way_wr_0[143: 136], cache_way_wr_0[127:64]});
    bram_256_72 cache_way_0_low (clk, rst, addr_line_mux, ~rst, cache_way_we_0, {cache_way_rd_0[135: 128], cache_way_rd_0[63:0]},   {cache_way_wr_0[135: 128], cache_way_wr_0[63:0]});
    bram_256_72 cache_way_1_high(clk, rst, addr_line_mux, ~rst, cache_way_we_1, {cache_way_rd_1[143: 136], cache_way_rd_1[127:64]}, {cache_way_wr_1[143: 136], cache_way_wr_1[127:64]});
    bram_256_72 cache_way_1_low (clk, rst, addr_line_mux, ~rst, cache_way_we_1, {cache_way_rd_1[135: 128], cache_way_rd_1[63:0]},   {cache_way_wr_1[135: 128], cache_way_wr_1[63:0]});
    
    wire cache_comparator_0_comb = ((addr_tag == cache_way_rd_0[BIT_TAG_END: BIT_TAG_START]) && (cache_way_rd_0[BIT_VALID])) ? 1'b1 : 1'b0;
    wire cache_comparator_1_comb = ((addr_tag == cache_way_rd_1[BIT_TAG_END: BIT_TAG_START]) && (cache_way_rd_1[BIT_VALID])) ? 1'b1 : 1'b0;
`ifdef USE_3_CYCLE_CACHE
    reg cache_comparator_0;
    reg cache_comparator_1;
    
    always@(posedge clk) begin
        cache_comparator_0 <= cache_comparator_0_comb;
        cache_comparator_1 <= cache_comparator_1_comb;
    end
`else
    wire cache_comparator_0 = cache_comparator_0_comb;
    wire cache_comparator_1 = cache_comparator_1_comb;
`endif

    wire [31: 0] cache_way_0_output_mux = 
        (addr_word == 2'b00) ? (cache_way_rd_0[31:0]) :
        (addr_word == 2'b01) ? (cache_way_rd_0[63:32]) :
        (addr_word == 2'b10) ? (cache_way_rd_0[95:64]) :
                               (cache_way_rd_0[127:96]);
    wire [31: 0] cache_way_1_output_mux = 
        (addr_word == 2'b00) ? (cache_way_rd_1[31:0]) :
        (addr_word == 2'b01) ? (cache_way_rd_1[63:32]) :
        (addr_word == 2'b10) ? (cache_way_rd_1[95:64]) :
                               (cache_way_rd_1[127:96]);
    wire [31: 0] mem_rd_output_mux = 
        (addr_word == 2'b00) ? (mem_rdata[31:0]) :
        (addr_word == 2'b01) ? (mem_rdata[63:32]) :
        (addr_word == 2'b10) ? (mem_rdata[95:64]) :
                               (mem_rdata[127:96]);
    
    reg mem_w_src;
    wire [127:0] mem_wdata_comb = (mem_w_src == 1'b0) ? (cache_way_rd_0) : (cache_way_rd_1);
    

    assign mem_wdata = mem_wdata_comb;
    










    
    wire cache_lru_bit_0 = cache_way_rd_0[BIT_LRU];
    wire cache_lru_bit_1 = cache_way_rd_1[BIT_LRU];
    wire cache_lru_way_0_newer = (cache_lru_bit_0 == cache_lru_bit_1) ? 1 : 0;
    wire cache_lru_way_1_newer = !cache_lru_way_0_newer;
    
    reg sys_byte_strobe [0: 15];
    integer i;
    integer j;
    always @(*) begin
        for (i = 0; i < 4; i = i + 1) begin
            for (j = 0; j < 4; j = j + 1) begin
                sys_byte_strobe[i * 4 + j] = (addr_word == i) && (sys_wstrb[j]);
            end
        end
    end
    

    wire [143: 0] cache_way_0_input_overlay;
    wire [143: 0] cache_way_1_input_overlay;

    assign cache_way_0_input_overlay[8 - 1: 0] = (sys_byte_strobe[0]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[8 - 1: 0]);
    assign cache_way_1_input_overlay[8 - 1: 0] = (sys_byte_strobe[0]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[8 - 1: 0]);
    assign cache_way_0_input_overlay[16 - 1: 8] = (sys_byte_strobe[1]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[16 - 1: 8]);
    assign cache_way_1_input_overlay[16 - 1: 8] = (sys_byte_strobe[1]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[16 - 1: 8]);
    assign cache_way_0_input_overlay[24 - 1: 16] = (sys_byte_strobe[2]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[24 - 1: 16]);
    assign cache_way_1_input_overlay[24 - 1: 16] = (sys_byte_strobe[2]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[24 - 1: 16]);
    assign cache_way_0_input_overlay[32 - 1: 24] = (sys_byte_strobe[3]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[32 - 1: 24]);
    assign cache_way_1_input_overlay[32 - 1: 24] = (sys_byte_strobe[3]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[32 - 1: 24]);
    assign cache_way_0_input_overlay[40 - 1: 32] = (sys_byte_strobe[4]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[40 - 1: 32]);
    assign cache_way_1_input_overlay[40 - 1: 32] = (sys_byte_strobe[4]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[40 - 1: 32]);
    assign cache_way_0_input_overlay[48 - 1: 40] = (sys_byte_strobe[5]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[48 - 1: 40]);
    assign cache_way_1_input_overlay[48 - 1: 40] = (sys_byte_strobe[5]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[48 - 1: 40]);
    assign cache_way_0_input_overlay[56 - 1: 48] = (sys_byte_strobe[6]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[56 - 1: 48]);
    assign cache_way_1_input_overlay[56 - 1: 48] = (sys_byte_strobe[6]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[56 - 1: 48]);
    assign cache_way_0_input_overlay[64 - 1: 56] = (sys_byte_strobe[7]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[64 - 1: 56]);
    assign cache_way_1_input_overlay[64 - 1: 56] = (sys_byte_strobe[7]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[64 - 1: 56]);
    assign cache_way_0_input_overlay[72 - 1: 64] = (sys_byte_strobe[8]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[72 - 1: 64]);
    assign cache_way_1_input_overlay[72 - 1: 64] = (sys_byte_strobe[8]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[72 - 1: 64]);
    assign cache_way_0_input_overlay[80 - 1: 72] = (sys_byte_strobe[9]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[80 - 1: 72]);
    assign cache_way_1_input_overlay[80 - 1: 72] = (sys_byte_strobe[9]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[80 - 1: 72]);
    assign cache_way_0_input_overlay[88 - 1: 80] = (sys_byte_strobe[10]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[88 - 1: 80]);
    assign cache_way_1_input_overlay[88 - 1: 80] = (sys_byte_strobe[10]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[88 - 1: 80]);
    assign cache_way_0_input_overlay[96 - 1: 88] = (sys_byte_strobe[11]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[96 - 1: 88]);
    assign cache_way_1_input_overlay[96 - 1: 88] = (sys_byte_strobe[11]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[96 - 1: 88]);
    assign cache_way_0_input_overlay[104 - 1: 96] = (sys_byte_strobe[12]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_0[104 - 1: 96]);
    assign cache_way_1_input_overlay[104 - 1: 96] = (sys_byte_strobe[12]) ? (sys_wdata[8 - 1: 0]) : (cache_way_rd_1[104 - 1: 96]);
    assign cache_way_0_input_overlay[112 - 1: 104] = (sys_byte_strobe[13]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_0[112 - 1: 104]);
    assign cache_way_1_input_overlay[112 - 1: 104] = (sys_byte_strobe[13]) ? (sys_wdata[16 - 1: 8]) : (cache_way_rd_1[112 - 1: 104]);
    assign cache_way_0_input_overlay[120 - 1: 112] = (sys_byte_strobe[14]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_0[120 - 1: 112]);
    assign cache_way_1_input_overlay[120 - 1: 112] = (sys_byte_strobe[14]) ? (sys_wdata[24 - 1: 16]) : (cache_way_rd_1[120 - 1: 112]);
    assign cache_way_0_input_overlay[128 - 1: 120] = (sys_byte_strobe[15]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_0[128 - 1: 120]);
    assign cache_way_1_input_overlay[128 - 1: 120] = (sys_byte_strobe[15]) ? (sys_wdata[32 - 1: 24]) : (cache_way_rd_1[128 - 1: 120]);
    

    assign cache_way_0_input_overlay[140: 128] = cache_way_rd_0[BIT_TAG_END: BIT_TAG_START];
    assign cache_way_1_input_overlay[140: 128] = cache_way_rd_1[BIT_TAG_END: BIT_TAG_START];
    assign cache_way_0_input_overlay[143: 141] = {cache_way_rd_1[BIT_LRU], 1'b1, ((sys_wstrb != 0) || (cache_way_rd_0[BIT_DIRTY])) ? 1'b1 : 1'b0};
    assign cache_way_1_input_overlay[143: 141] = {!cache_way_rd_0[BIT_LRU], 1'b1, ((sys_wstrb != 0) || (cache_way_rd_1[BIT_DIRTY])) ? 1'b1 : 1'b0};
                             
    reg [1:0] cache_line_wb_src;
    assign cache_way_wr_0 = 
        (cache_line_wb_src == 2'b01) ? ({cache_way_rd_1[143], 2'b10, addr_tag, mem_rdata}) : 
        (cache_line_wb_src == 2'b00) ? (cache_way_0_input_overlay) : ({!cache_way_rd_1[BIT_LRU], 143'd0});
    assign cache_way_wr_1 = 
        (cache_line_wb_src == 2'b01) ? ({!cache_way_rd_0[143], 2'b10, addr_tag, mem_rdata}) : 
        (cache_line_wb_src == 2'b00) ? (cache_way_1_input_overlay) : ({cache_way_rd_0[BIT_LRU], 143'd0});
    
    reg [3: 0] cache_state;
    

    localparam STATE_RESET = 4'd0;
    localparam STATE_IDLE = 4'd1;
    localparam STATE_RW_COMPARE = 4'd2;
    localparam STATE_RW_CHECK = 4'd3;
    localparam STATE_RW_MISS = 4'd4;
    localparam STATE_RW_DONE = 4'd5;
    localparam STATE_RW_FLUSH = 4'd6;
    localparam STATE_RW_FLUSH_WAIT = 4'd7;
    localparam STATE_WRITE_MISS_APPLY = 4'd8;
    localparam STATE_WAIT = 4'd15;
    
    reg [CACHE_LINE_BITS - 1: 0] invalidate_counter;
    assign addr_line_mux = (addr_line_sel) ? invalidate_counter : addr_line;
    
    always@(posedge clk) begin
        if (rst) begin
            cache_state <= STATE_RESET;
            sys_ready <= 1'b0;
            mem_valid <= 1'b0;
            cache_way_we_0 <= 1'b0;
            cache_way_we_1 <= 1'b0;
            cache_line_wb_src <= 2'b10;
            invalidate_counter <= 8'hFF;
            addr_line_sel <= 1'b1;
        end
        else begin
            case (cache_state)
                STATE_RESET: begin
                    cache_way_we_0 <= 1'b1;
                    cache_way_we_1 <= 1'b1;
                    invalidate_counter <= invalidate_counter - 1;
                    if (invalidate_counter == 8'd0)
                        cache_state <= STATE_IDLE;
                end
                STATE_IDLE: begin
                    addr_line_sel <= 1'b0;
                    cache_way_we_0 <= 1'b0;
                    cache_way_we_1 <= 1'b0;
                    if (sys_valid) begin
                    `ifdef USE_3_CYCLE_CACHE
                        cache_state <= STATE_RW_COMPARE;
                    `else
                        cache_state <= STATE_RW_CHECK;
                    `endif
                    end
                end
                STATE_RW_COMPARE: begin

                    cache_state <= STATE_RW_CHECK;
                end
                STATE_RW_CHECK: begin
                    if (cache_comparator_0) begin

                        sys_rdata <= cache_way_0_output_mux;
                        sys_ready <= 1'b1;


                        cache_way_we_0 <= 1'b1;
                        cache_way_we_1 <= 1'b0;
                        cache_line_wb_src <= 2'b00;
                        cache_state <= STATE_WAIT;

                    end
                    else if (cache_comparator_1) begin
                        sys_rdata <= cache_way_1_output_mux;
                        sys_ready <= 1'b1;
                        cache_way_we_0 <= 1'b0;
                        cache_way_we_1 <= 1'b1;
                        cache_line_wb_src <= 2'b00;
                        cache_state <= STATE_WAIT;

                    end
                    else begin


                        if (cache_lru_way_1_newer) begin
                            if (cache_way_rd_0[BIT_VALID] && cache_way_rd_0[BIT_DIRTY]) begin

                                mem_addr <= {cache_way_rd_0[BIT_TAG_END: BIT_TAG_START], addr_line};
                                mem_w_src <= 1'b0;
                                mem_wstrb <= 1'b1;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_FLUSH;


                            end
                            else begin

                                mem_addr <= sys_addr[24:4];
                                mem_wstrb <= 1'b0;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_MISS;

                            end
                        end
                        else begin
                            if (cache_way_rd_1[BIT_VALID] && cache_way_rd_1[BIT_DIRTY]) begin

                                mem_addr <= {cache_way_rd_1[BIT_TAG_END: BIT_TAG_START], addr_line};
                                mem_w_src <= 1'b1;
                                mem_wstrb <= 1'b1;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_FLUSH;


                            end
                            else begin

                                mem_addr <= sys_addr[24:4];
                                mem_wstrb <= 1'b0;
                                mem_valid <= 1'b1;
                                cache_state <= STATE_RW_MISS;

                            end
                        end
                    end
                end
                STATE_RW_MISS: begin
                    if (mem_ready) begin

                        cache_line_wb_src <= 2'b01;
                        if (cache_lru_way_1_newer) begin
                            cache_way_we_0 <= 1'b1;
                        end
                        else begin
                            cache_way_we_1 <= 1'b1;
                        end
                        if (sys_wstrb == 0) begin
                            sys_rdata <= mem_rd_output_mux;
                            sys_ready <= 1'b1;
                            cache_state <= STATE_WAIT;
                        end
                        else begin

                            cache_state <= STATE_WRITE_MISS_APPLY;
                        end
                    end
                end
                STATE_RW_FLUSH: begin
                    if (mem_ready) begin
                        mem_valid <= 1'b0;
                        cache_line_wb_src <= 2'b10;
                        if (cache_lru_way_1_newer) begin
                            cache_way_we_0 <= 1'b1;
                        end
                        else begin
                            cache_way_we_1 <= 1'b1;
                        end
                        cache_state <= STATE_RW_FLUSH_WAIT;
                    end
                end
                STATE_RW_FLUSH_WAIT: begin
                    cache_way_we_0 <= 1'b0;
                    cache_way_we_1 <= 1'b0;
                    if (!mem_ready) begin
                        cache_state <= STATE_RW_CHECK;
                    end
                end
                STATE_WRITE_MISS_APPLY: begin
                    cache_line_wb_src <= 2'b00;
                    sys_ready <= 1'b1;
                    cache_state <= STATE_WAIT;
                end
                STATE_WAIT: begin
                    cache_way_we_0 <= 1'b0;
                    cache_way_we_1 <= 1'b0;
                    mem_valid <= 1'b0;
                    sys_ready <= 1'b0;
                    if (!sys_valid) begin
                        cache_state <= STATE_IDLE;
                    end
                end
            endcase
        end
    end
    

endmodule