아래 코드에서 중복되거나 합칠 수 있는 부분이 있으면 합치거나 정리해줘.

reg       ar_state;
reg       ar_state_n;
reg       read_state;
reg       read_state_n;
reg [1:0] write_state;
reg [1:0] write_state_n;
reg [2:0] Aread_count;
reg [2:0] Aread_count_n;
reg [2:0] matrix_width;
reg [3:0] write_counter;
reg [3:0] write_count_n;
reg [6:0] read_count;
reg [6:0] read_count_n;

reg         rready;
reg         arvalid;
reg         awvalid;
reg         wvalid;
reg         wlast;
reg [31:0]  araddr;
reg [31:0]  wdata;
reg [127:0] rdata;

localparam S_IDLE = 2'b00;
localparam S_PROC = 2'b01;
localparam W_ADDR = 2'b01;
localparam W_DATA = 2'b10;
localparam W_RESP = 2'b11;

always_ff @(posedge clk) begin
    if (!rst_n) begin
        ar_state      <= S_IDLE;
        read_state    <= S_IDLE;
        write_state   <= S_IDLE;
        read_count    <= 7'd0;
        write_counter <= 4'd0;
        Aread_count   <= 3'd0;
        matrix_width  <= 3'd0;
    end else begin
        ar_state      <= ar_state_n;
        read_state    <= read_state_n;
        write_state   <= write_state_n;
        read_count    <= read_count_n;
        write_counter <= write_count_n;
        Aread_count   <= Aread_count_n;
        matrix_width  <= mat_width_i[4:2];
    end
end

always_comb begin
    set_defaults();

    case (ar_state)
        S_IDLE:
            if (start_i)
                handle_ar_idle();
        S_PROC:
            handle_ar_proc();
    endcase

    case (read_state)
        S_IDLE:
            if (axi_ar_if.arready)
                read_state_n = S_PROC;
        S_PROC: begin
            rready = 1'b1;
            if (axi_r_if.rvalid) begin
                if (read_count[6:4] < matrix_width) 
                    buf_a_wren_o = 1'b1;
                else 
                    buf_b_wren_o = 1'b1;

                if ((read_count[6:4] == mat_width_i[4:1] - 1'd1) & axi_r_if.rlast) begin
                    read_count_n = 7'd0;
                    read_state_n = S_IDLE;
                    mm_start_o = 1'b1;
                end else 
                    read_count_n = read_count + 7'd1;
            end
        end
    endcase

    case (write_state)
        S_IDLE:
            if (mm_start_o)
                write_state_n = W_ADDR;
        W_ADDR: begin
            awvalid = mm_done_i;
            if (axi_aw_if.awready)
                write_state_n = W_DATA;
        end
        W_DATA: begin
            wvalid = 1'b1;
            if (write_counter == 4'hF)
                wlast = 1'b1;
            if (axi_w_if.wready) begin
                if (write_counter != 4'hF) 
                    write_count_n = write_counter + 4'd1;
                else begin
                    write_count_n = 4'd0;
                    write_state_n = W_RESP;
                end
            end
        end
        W_RESP:
            if (axi_b_if.bvalid)
                write_state_n = S_IDLE;
    endcase
end

task set_defaults();
    begin
        ar_state_n = ar_state;
        read_state_n = read_state;
        write_state_n = write_state;

        read_count_n = read_count;
        write_count_n = write_counter;
        Aread_count_n = Aread_count;

        buf_a_wren_o = 1'b0;
        buf_b_wren_o = 1'b0;

        araddr = 32'b0;
        arvalid = 1'b0;
        rready = 1'b0;
        awvalid = 1'b0;
        wvalid = 1'b0;
        wlast = 1'b0;
        mm_start_o = 1'b0;
    end
endtask

task handle_ar_idle();
    begin
        ar_state_n = S_PROC;
        arvalid = 1'b1;
        araddr = mat_a_addr_i;
    end
endtask

task handle_ar_proc();
    arvalid = 1'b1;
    araddr = (Aread_count < matrix_width) ? 
             (mat_a_addr_i + {Aread_count, 6'b0}) : 
             (mat_b_addr_i + {(Aread_count - matrix_width), 6'b0});

    if (axi_ar_if.arready) begin
        if (Aread_count != {matrix_width, 1'b0} - 1'd1) 
            Aread_count_n = Aread_count + 3'd1;
        else begin
            ar_state_n = S_IDLE;
            Aread_count_n = 3'd0;
        end
    end
endtask

function automatic [15:0] get_strobe(input [1:0] read_count);
    case(read_count)
        2'b00: get_strobe = 16'h000F;
        2'b01: get_strobe = 16'h00F0;
        2'b10: get_strobe = 16'h0F00;
        2'b11: get_strobe = 16'hF000;
    endcase
endfunction

function automatic [127:0] get_rdata(input [1:0] read_count, input [31:0] axi_rdata);
    case(read_count)
        2'b00: get_rdata = {96'b0, axi_rdata};
        2'b01: get_rdata = {64'b0, axi_rdata, 32'b0};
        2'b10: get_rdata = {32'b0, axi_rdata, 64'b0};
        2'b11: get_rdata = {axi_rdata, 96'b0};
    endcase
endfunction

always_comb begin
    rdata = get_rdata(read_count[1:0], axi_r_if.rdata);
    wdata = accum_i[3 - (write_counter >> 2)][3 - (write_counter & 4'd3)][31:0];
end

assign done_o = !(ar_state || read_state || write_state[1] || write_state[0]);
assign buf_a_wbyteenable_o = get_strobe(read_count[1:0]);
assign buf_b_wbyteenable_o = get_strobe(read_count[1:0]);
assign buf_a_waddr_o = read_count[6:2];
assign buf_b_waddr_o = read_count[6:2] - mat_width_i;
assign buf_a_wdata_o = rdata;
assign buf_b_wdata_o = rdata;
assign axi_ar_if.arvalid = arvalid;
assign axi_ar_if.arsize = 3'b010;
assign axi_ar_if.arburst = 2'b01;
assign axi_ar_if.araddr = araddr;
assign axi_ar_if.arlen = 4'hF;
assign axi_r_if.rready = rready;
assign axi_aw_if.awlen = 4'hF;
assign axi_aw_if.awsize = 3'b010;
assign axi_aw_if.awburst = 2'b01;
assign axi_aw_if.awvalid = awvalid;
assign axi_aw_if.awaddr = mat_c_addr_i;
assign axi_b_if.bready = 1'b1;
assign axi_w_if.wdata = wdata;
assign axi_w_if.wstrb = 4'b1111;
assign axi_w_if.wvalid = wvalid;
assign axi_w_if.wlast = wlast;