data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv
1: b'%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:14: Cannot find include file: prim_assert.sv\n`include "prim_assert.sv" \n         ^~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl,data/full_repos/permissive/509468557/prim_assert.sv\n             data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl,data/full_repos/permissive/509468557/prim_assert.sv.v\n             data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl,data/full_repos/permissive/509468557/prim_assert.sv.sv\n             prim_assert.sv\n             prim_assert.sv.v\n             prim_assert.sv.sv\n             obj_dir/prim_assert.sv\n             obj_dir/prim_assert.sv.v\n             obj_dir/prim_assert.sv.sv\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:15: Cannot find include file: dv_fcov_macros.svh\n`include "dv_fcov_macros.svh" \n         ^~~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:506: Define or directive not defined: \'`DV_FCOV_SIGNAL\'\n  `DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q)\n  ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:506: syntax error, unexpected \'(\'\n  `DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q)\n                  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:507: Define or directive not defined: \'`DV_FCOV_SIGNAL\'\n  `DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q)\n  ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:514: Define or directive not defined: \'`ASSERT\'\n  `ASSERT(IbexDataTypeKnown, (lsu_req_i | busy_o) |-> !$isunknown(lsu_type_i))\n  ^~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:515: Define or directive not defined: \'`ASSERT\'\n  `ASSERT(IbexDataOffsetKnown, (lsu_req_i | busy_o) |-> !$isunknown(data_offset))\n  ^~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:516: Define or directive not defined: \'`ASSERT_KNOWN\'\n  `ASSERT_KNOWN(IbexRDataOffsetQKnown, rdata_offset_q)\n  ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:517: Define or directive not defined: \'`ASSERT_KNOWN\'\n  `ASSERT_KNOWN(IbexDataTypeQKnown, data_type_q)\n  ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:518: Define or directive not defined: \'`ASSERT\'\n  `ASSERT(IbexLsuStateValid, ls_fsm_cs inside {\n  ^~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:523: Define or directive not defined: \'`ASSERT\'\n  `ASSERT(IbexDataAddrUnknown, data_req_o |-> !$isunknown(data_addr_o))\n  ^~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_load_store_unit.sv:526: Define or directive not defined: \'`ASSERT\'\n  `ASSERT(IbexDataAddrUnaligned, data_req_o |-> (data_addr_o[1:0] == 2\'b00))\n  ^~~~~~~\n%Error: Cannot continue\n'
module ibex_load_store_unit
(
    input  logic         clk_i,
    input  logic         rst_ni,


    output logic         data_req_o,
    input  logic         data_gnt_i,
    input  logic         data_rvalid_i,
    input  logic         data_err_i,
    input  logic         data_pmp_err_i,

    output logic [31:0]  data_addr_o,
    output logic         data_we_o,
    output logic [3:0]   data_be_o,
    output logic [31:0]  data_wdata_o,
    input  logic [31:0]  data_rdata_i,


    input  logic         lsu_we_i,
    input  logic [1:0]   lsu_type_i,
    input  logic [31:0]  lsu_wdata_i,
    input  logic         lsu_sign_ext_i,

    output logic [31:0]  lsu_rdata_o,
    output logic         lsu_rdata_valid_o,
    input  logic         lsu_req_i,

    input  logic [31:0]  adder_result_ex_i,

    output logic         addr_incr_req_o,

    output logic [31:0]  addr_last_o,



    output logic         lsu_req_done_o,



    output logic         lsu_resp_valid_o,


    output logic         load_err_o,
    output logic         store_err_o,

    output logic         busy_o,

    output logic         perf_load_o,
    output logic         perf_store_o
);

  logic [31:0]  data_addr;
  logic [31:0]  data_addr_w_aligned;
  logic [31:0]  addr_last_q, addr_last_d;

  logic         addr_update;
  logic         ctrl_update;
  logic         rdata_update;
  logic [31:8]  rdata_q;
  logic [1:0]   rdata_offset_q;
  logic [1:0]   data_type_q;
  logic         data_sign_ext_q;
  logic         data_we_q;

  logic [1:0]   data_offset;

  logic [3:0]   data_be;
  logic [31:0]  data_wdata;

  logic [31:0]  data_rdata_ext;

  logic [31:0]  rdata_w_ext;
  logic [31:0]  rdata_h_ext;
  logic [31:0]  rdata_b_ext;

  logic         split_misaligned_access;
  logic         handle_misaligned_q, handle_misaligned_d;

  logic         pmp_err_q, pmp_err_d;
  logic         lsu_err_q, lsu_err_d;
  logic         data_or_pmp_err;

  typedef enum logic [2:0]  {
    IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT,
    WAIT_RVALID_MIS_GNTS_DONE
  } ls_fsm_e;

  ls_fsm_e ls_fsm_cs, ls_fsm_ns;

  assign data_addr   = adder_result_ex_i;
  assign data_offset = data_addr[1:0];





  always_comb begin
    unique case (lsu_type_i)
      2'b00: begin
        if (!handle_misaligned_q) begin
          unique case (data_offset)
            2'b00:   data_be = 4'b1111;
            2'b01:   data_be = 4'b1110;
            2'b10:   data_be = 4'b1100;
            2'b11:   data_be = 4'b1000;
            default: data_be = 4'b1111;
          endcase
        end else begin
          unique case (data_offset)
            2'b00:   data_be = 4'b0000;
            2'b01:   data_be = 4'b0001;
            2'b10:   data_be = 4'b0011;
            2'b11:   data_be = 4'b0111;
            default: data_be = 4'b1111;
          endcase
        end
      end

      2'b01: begin
        if (!handle_misaligned_q) begin
          unique case (data_offset)
            2'b00:   data_be = 4'b0011;
            2'b01:   data_be = 4'b0110;
            2'b10:   data_be = 4'b1100;
            2'b11:   data_be = 4'b1000;
            default: data_be = 4'b1111;
          endcase
        end else begin
          data_be = 4'b0001;
        end
      end

      2'b10,
      2'b11: begin
        unique case (data_offset)
          2'b00:   data_be = 4'b0001;
          2'b01:   data_be = 4'b0010;
          2'b10:   data_be = 4'b0100;
          2'b11:   data_be = 4'b1000;
          default: data_be = 4'b1111;
        endcase
      end

      default:     data_be = 4'b1111;
    endcase
  end







  always_comb begin
    unique case (data_offset)
      2'b00:   data_wdata =  lsu_wdata_i[31:0];
      2'b01:   data_wdata = {lsu_wdata_i[23:0], lsu_wdata_i[31:24]};
      2'b10:   data_wdata = {lsu_wdata_i[15:0], lsu_wdata_i[31:16]};
      2'b11:   data_wdata = {lsu_wdata_i[ 7:0], lsu_wdata_i[31: 8]};
      default: data_wdata =  lsu_wdata_i[31:0];
    endcase
  end






  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      rdata_q <= '0;
    end else if (rdata_update) begin
      rdata_q <= data_rdata_i[31:8];
    end
  end


  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      rdata_offset_q  <= 2'h0;
      data_type_q     <= 2'h0;
      data_sign_ext_q <= 1'b0;
      data_we_q       <= 1'b0;
    end else if (ctrl_update) begin
      rdata_offset_q  <= data_offset;
      data_type_q     <= lsu_type_i;
      data_sign_ext_q <= lsu_sign_ext_i;
      data_we_q       <= lsu_we_i;
    end
  end





  assign addr_last_d = addr_incr_req_o ? data_addr_w_aligned : data_addr;

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      addr_last_q <= '0;
    end else if (addr_update) begin
      addr_last_q <= addr_last_d;
    end
  end


  always_comb begin
    unique case (rdata_offset_q)
      2'b00:   rdata_w_ext =  data_rdata_i[31:0];
      2'b01:   rdata_w_ext = {data_rdata_i[ 7:0], rdata_q[31:8]};
      2'b10:   rdata_w_ext = {data_rdata_i[15:0], rdata_q[31:16]};
      2'b11:   rdata_w_ext = {data_rdata_i[23:0], rdata_q[31:24]};
      default: rdata_w_ext =  data_rdata_i[31:0];
    endcase
  end






  always_comb begin
    unique case (rdata_offset_q)
      2'b00: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[15:0]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[15]}}, data_rdata_i[15:0]};
        end
      end

      2'b01: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[23:8]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[23]}}, data_rdata_i[23:8]};
        end
      end

      2'b10: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[31:16]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[31]}}, data_rdata_i[31:16]};
        end
      end

      2'b11: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[7:0], rdata_q[31:24]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]};
        end
      end

      default: rdata_h_ext = {16'h0000, data_rdata_i[15:0]};
    endcase
  end


  always_comb begin
    unique case (rdata_offset_q)
      2'b00: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[7:0]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[7]}}, data_rdata_i[7:0]};
        end
      end

      2'b01: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[15:8]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[15]}}, data_rdata_i[15:8]};
        end
      end

      2'b10: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[23:16]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[23]}}, data_rdata_i[23:16]};
        end
      end

      2'b11: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[31:24]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[31]}}, data_rdata_i[31:24]};
        end
      end

      default: rdata_b_ext = {24'h00_0000, data_rdata_i[7:0]};
    endcase
  end


  always_comb begin
    unique case (data_type_q)
      2'b00:       data_rdata_ext = rdata_w_ext;
      2'b01:       data_rdata_ext = rdata_h_ext;
      2'b10,2'b11: data_rdata_ext = rdata_b_ext;
      default:     data_rdata_ext = rdata_w_ext;
    endcase
  end






  assign split_misaligned_access =
      ((lsu_type_i == 2'b00) && (data_offset != 2'b00)) ||
      ((lsu_type_i == 2'b01) && (data_offset == 2'b11));


  always_comb begin
    ls_fsm_ns       = ls_fsm_cs;

    data_req_o          = 1'b0;
    addr_incr_req_o     = 1'b0;
    handle_misaligned_d = handle_misaligned_q;
    pmp_err_d           = pmp_err_q;
    lsu_err_d           = lsu_err_q;

    addr_update         = 1'b0;
    ctrl_update         = 1'b0;
    rdata_update        = 1'b0;

    perf_load_o         = 1'b0;
    perf_store_o        = 1'b0;

    unique case (ls_fsm_cs)

      IDLE: begin
        pmp_err_d = 1'b0;
        if (lsu_req_i) begin
          data_req_o   = 1'b1;
          pmp_err_d    = data_pmp_err_i;
          lsu_err_d    = 1'b0;
          perf_load_o  = ~lsu_we_i;
          perf_store_o = lsu_we_i;

          if (data_gnt_i) begin
            ctrl_update         = 1'b1;
            addr_update         = 1'b1;
            handle_misaligned_d = split_misaligned_access;
            ls_fsm_ns           = split_misaligned_access ? WAIT_RVALID_MIS : IDLE;
          end else begin
            ls_fsm_ns           = split_misaligned_access ? WAIT_GNT_MIS    : WAIT_GNT;
          end
        end
      end

      WAIT_GNT_MIS: begin
        data_req_o = 1'b1;




        if (data_gnt_i || pmp_err_q) begin
          addr_update         = 1'b1;
          ctrl_update         = 1'b1;
          handle_misaligned_d = 1'b1;
          ls_fsm_ns           = WAIT_RVALID_MIS;
        end
      end

      WAIT_RVALID_MIS: begin

        data_req_o = 1'b1;

        addr_incr_req_o = 1'b1;


        if (data_rvalid_i || pmp_err_q) begin

          pmp_err_d = data_pmp_err_i;

          lsu_err_d = data_err_i | pmp_err_q;

          rdata_update = ~data_we_q;

          ls_fsm_ns = data_gnt_i ? IDLE : WAIT_GNT;

          addr_update = data_gnt_i & ~(data_err_i | pmp_err_q);

          handle_misaligned_d = ~data_gnt_i;
        end else begin

          if (data_gnt_i) begin

            ls_fsm_ns = WAIT_RVALID_MIS_GNTS_DONE;
            handle_misaligned_d = 1'b0;
          end
        end
      end

      WAIT_GNT: begin

        addr_incr_req_o = handle_misaligned_q;
        data_req_o      = 1'b1;
        if (data_gnt_i || pmp_err_q) begin
          ctrl_update         = 1'b1;

          addr_update         = ~lsu_err_q;
          ls_fsm_ns           = IDLE;
          handle_misaligned_d = 1'b0;
        end
      end

      WAIT_RVALID_MIS_GNTS_DONE: begin


        addr_incr_req_o = 1'b1;

        if (data_rvalid_i) begin

          pmp_err_d = data_pmp_err_i;

          lsu_err_d = data_err_i;

          addr_update = ~data_err_i;

          rdata_update = ~data_we_q;

          ls_fsm_ns = IDLE;
        end
      end

      default: begin
        ls_fsm_ns = IDLE;
      end
    endcase
  end

  assign lsu_req_done_o = (lsu_req_i | (ls_fsm_cs != IDLE)) & (ls_fsm_ns == IDLE);


  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      ls_fsm_cs           <= IDLE;
      handle_misaligned_q <= '0;
      pmp_err_q           <= '0;
      lsu_err_q           <= '0;
    end else begin
      ls_fsm_cs           <= ls_fsm_ns;
      handle_misaligned_q <= handle_misaligned_d;
      pmp_err_q           <= pmp_err_d;
      lsu_err_q           <= lsu_err_d;
    end
  end





  assign data_or_pmp_err    = lsu_err_q | data_err_i | pmp_err_q;
  assign lsu_resp_valid_o   = (data_rvalid_i | pmp_err_q) & (ls_fsm_cs == IDLE);
  assign lsu_rdata_valid_o  = (ls_fsm_cs == IDLE) & data_rvalid_i & ~data_or_pmp_err & ~data_we_q;


  assign lsu_rdata_o = data_rdata_ext;


  assign data_addr_w_aligned = {data_addr[31:2], 2'b00};


  assign data_addr_o   = data_addr_w_aligned;
  assign data_wdata_o  = data_wdata;
  assign data_we_o     = lsu_we_i;
  assign data_be_o     = data_be;


  assign addr_last_o   = addr_last_q;


  assign load_err_o    = data_or_pmp_err & ~data_we_q & lsu_resp_valid_o;
  assign store_err_o   = data_or_pmp_err &  data_we_q & lsu_resp_valid_o;

  assign busy_o = (ls_fsm_cs != IDLE);





  `DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q)
  `DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q)






  `ASSERT(IbexDataTypeKnown, (lsu_req_i | busy_o) |-> !$isunknown(lsu_type_i))
  `ASSERT(IbexDataOffsetKnown, (lsu_req_i | busy_o) |-> !$isunknown(data_offset))
  `ASSERT_KNOWN(IbexRDataOffsetQKnown, rdata_offset_q)
  `ASSERT_KNOWN(IbexDataTypeQKnown, data_type_q)
  `ASSERT(IbexLsuStateValid, ls_fsm_cs inside {
      IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT,
      WAIT_RVALID_MIS_GNTS_DONE})


  `ASSERT(IbexDataAddrUnknown, data_req_o |-> !$isunknown(data_addr_o))


  `ASSERT(IbexDataAddrUnaligned, data_req_o |-> (data_addr_o[1:0] == 2'b00))

endmodule
module ibex_load_store_unit
(
    input  logic         clk_i,
    input  logic         rst_ni,


    output logic         data_req_o,
    input  logic         data_gnt_i,
    input  logic         data_rvalid_i,
    input  logic         data_err_i,
    input  logic         data_pmp_err_i,

    output logic [31:0]  data_addr_o,
    output logic         data_we_o,
    output logic [3:0]   data_be_o,
    output logic [31:0]  data_wdata_o,
    input  logic [31:0]  data_rdata_i,


    input  logic         lsu_we_i,
    input  logic [1:0]   lsu_type_i,
    input  logic [31:0]  lsu_wdata_i,
    input  logic         lsu_sign_ext_i,

    output logic [31:0]  lsu_rdata_o,
    output logic         lsu_rdata_valid_o,
    input  logic         lsu_req_i,

    input  logic [31:0]  adder_result_ex_i,

    output logic         addr_incr_req_o,

    output logic [31:0]  addr_last_o,



    output logic         lsu_req_done_o,



    output logic         lsu_resp_valid_o,


    output logic         load_err_o,
    output logic         store_err_o,

    output logic         busy_o,

    output logic         perf_load_o,
    output logic         perf_store_o
);


  logic [31:0]  data_addr;
  logic [31:0]  data_addr_w_aligned;
  logic [31:0]  addr_last_q, addr_last_d;

  logic         addr_update;
  logic         ctrl_update;
  logic         rdata_update;
  logic [31:8]  rdata_q;
  logic [1:0]   rdata_offset_q;
  logic [1:0]   data_type_q;
  logic         data_sign_ext_q;
  logic         data_we_q;

  logic [1:0]   data_offset;

  logic [3:0]   data_be;
  logic [31:0]  data_wdata;

  logic [31:0]  data_rdata_ext;

  logic [31:0]  rdata_w_ext;
  logic [31:0]  rdata_h_ext;
  logic [31:0]  rdata_b_ext;

  logic         split_misaligned_access;
  logic         handle_misaligned_q, handle_misaligned_d;

  logic         pmp_err_q, pmp_err_d;
  logic         lsu_err_q, lsu_err_d;
  logic         data_or_pmp_err;

  typedef enum logic [2:0]  {
    IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT,
    WAIT_RVALID_MIS_GNTS_DONE
  } ls_fsm_e;

  ls_fsm_e ls_fsm_cs, ls_fsm_ns;

  assign data_addr   = adder_result_ex_i;
  assign data_offset = data_addr[1:0];





  always_comb begin
    unique case (lsu_type_i)
      2'b00: begin
        if (!handle_misaligned_q) begin
          unique case (data_offset)
            2'b00:   data_be = 4'b1111;
            2'b01:   data_be = 4'b1110;
            2'b10:   data_be = 4'b1100;
            2'b11:   data_be = 4'b1000;
            default: data_be = 4'b1111;
          endcase
        end else begin
          unique case (data_offset)
            2'b00:   data_be = 4'b0000;
            2'b01:   data_be = 4'b0001;
            2'b10:   data_be = 4'b0011;
            2'b11:   data_be = 4'b0111;
            default: data_be = 4'b1111;
          endcase
        end
      end

      2'b01: begin
        if (!handle_misaligned_q) begin
          unique case (data_offset)
            2'b00:   data_be = 4'b0011;
            2'b01:   data_be = 4'b0110;
            2'b10:   data_be = 4'b1100;
            2'b11:   data_be = 4'b1000;
            default: data_be = 4'b1111;
          endcase
        end else begin
          data_be = 4'b0001;
        end
      end

      2'b10,
      2'b11: begin
        unique case (data_offset)
          2'b00:   data_be = 4'b0001;
          2'b01:   data_be = 4'b0010;
          2'b10:   data_be = 4'b0100;
          2'b11:   data_be = 4'b1000;
          default: data_be = 4'b1111;
        endcase
      end

      default:     data_be = 4'b1111;
    endcase
  end







  always_comb begin
    unique case (data_offset)
      2'b00:   data_wdata =  lsu_wdata_i[31:0];
      2'b01:   data_wdata = {lsu_wdata_i[23:0], lsu_wdata_i[31:24]};
      2'b10:   data_wdata = {lsu_wdata_i[15:0], lsu_wdata_i[31:16]};
      2'b11:   data_wdata = {lsu_wdata_i[ 7:0], lsu_wdata_i[31: 8]};
      default: data_wdata =  lsu_wdata_i[31:0];
    endcase
  end






  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      rdata_q <= '0;
    end else if (rdata_update) begin
      rdata_q <= data_rdata_i[31:8];
    end
  end


  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      rdata_offset_q  <= 2'h0;
      data_type_q     <= 2'h0;
      data_sign_ext_q <= 1'b0;
      data_we_q       <= 1'b0;
    end else if (ctrl_update) begin
      rdata_offset_q  <= data_offset;
      data_type_q     <= lsu_type_i;
      data_sign_ext_q <= lsu_sign_ext_i;
      data_we_q       <= lsu_we_i;
    end
  end





  assign addr_last_d = addr_incr_req_o ? data_addr_w_aligned : data_addr;

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      addr_last_q <= '0;
    end else if (addr_update) begin
      addr_last_q <= addr_last_d;
    end
  end


  always_comb begin
    unique case (rdata_offset_q)
      2'b00:   rdata_w_ext =  data_rdata_i[31:0];
      2'b01:   rdata_w_ext = {data_rdata_i[ 7:0], rdata_q[31:8]};
      2'b10:   rdata_w_ext = {data_rdata_i[15:0], rdata_q[31:16]};
      2'b11:   rdata_w_ext = {data_rdata_i[23:0], rdata_q[31:24]};
      default: rdata_w_ext =  data_rdata_i[31:0];
    endcase
  end






  always_comb begin
    unique case (rdata_offset_q)
      2'b00: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[15:0]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[15]}}, data_rdata_i[15:0]};
        end
      end

      2'b01: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[23:8]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[23]}}, data_rdata_i[23:8]};
        end
      end

      2'b10: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[31:16]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[31]}}, data_rdata_i[31:16]};
        end
      end

      2'b11: begin
        if (!data_sign_ext_q) begin
          rdata_h_ext = {16'h0000, data_rdata_i[7:0], rdata_q[31:24]};
        end else begin
          rdata_h_ext = {{16{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]};
        end
      end

      default: rdata_h_ext = {16'h0000, data_rdata_i[15:0]};
    endcase
  end


  always_comb begin
    unique case (rdata_offset_q)
      2'b00: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[7:0]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[7]}}, data_rdata_i[7:0]};
        end
      end

      2'b01: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[15:8]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[15]}}, data_rdata_i[15:8]};
        end
      end

      2'b10: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[23:16]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[23]}}, data_rdata_i[23:16]};
        end
      end

      2'b11: begin
        if (!data_sign_ext_q) begin
          rdata_b_ext = {24'h00_0000, data_rdata_i[31:24]};
        end else begin
          rdata_b_ext = {{24{data_rdata_i[31]}}, data_rdata_i[31:24]};
        end
      end

      default: rdata_b_ext = {24'h00_0000, data_rdata_i[7:0]};
    endcase
  end


  always_comb begin
    unique case (data_type_q)
      2'b00:       data_rdata_ext = rdata_w_ext;
      2'b01:       data_rdata_ext = rdata_h_ext;
      2'b10,2'b11: data_rdata_ext = rdata_b_ext;
      default:     data_rdata_ext = rdata_w_ext;
    endcase
  end






  assign split_misaligned_access =
      ((lsu_type_i == 2'b00) && (data_offset != 2'b00)) ||
      ((lsu_type_i == 2'b01) && (data_offset == 2'b11));


  always_comb begin
    ls_fsm_ns       = ls_fsm_cs;

    data_req_o          = 1'b0;
    addr_incr_req_o     = 1'b0;
    handle_misaligned_d = handle_misaligned_q;
    pmp_err_d           = pmp_err_q;
    lsu_err_d           = lsu_err_q;

    addr_update         = 1'b0;
    ctrl_update         = 1'b0;
    rdata_update        = 1'b0;

    perf_load_o         = 1'b0;
    perf_store_o        = 1'b0;

    unique case (ls_fsm_cs)

      IDLE: begin
        pmp_err_d = 1'b0;
        if (lsu_req_i) begin
          data_req_o   = 1'b1;
          pmp_err_d    = data_pmp_err_i;
          lsu_err_d    = 1'b0;
          perf_load_o  = ~lsu_we_i;
          perf_store_o = lsu_we_i;

          if (data_gnt_i) begin
            ctrl_update         = 1'b1;
            addr_update         = 1'b1;
            handle_misaligned_d = split_misaligned_access;
            ls_fsm_ns           = split_misaligned_access ? WAIT_RVALID_MIS : IDLE;
          end else begin
            ls_fsm_ns           = split_misaligned_access ? WAIT_GNT_MIS    : WAIT_GNT;
          end
        end
      end

      WAIT_GNT_MIS: begin
        data_req_o = 1'b1;




        if (data_gnt_i || pmp_err_q) begin
          addr_update         = 1'b1;
          ctrl_update         = 1'b1;
          handle_misaligned_d = 1'b1;
          ls_fsm_ns           = WAIT_RVALID_MIS;
        end
      end

      WAIT_RVALID_MIS: begin

        data_req_o = 1'b1;

        addr_incr_req_o = 1'b1;


        if (data_rvalid_i || pmp_err_q) begin

          pmp_err_d = data_pmp_err_i;

          lsu_err_d = data_err_i | pmp_err_q;

          rdata_update = ~data_we_q;

          ls_fsm_ns = data_gnt_i ? IDLE : WAIT_GNT;

          addr_update = data_gnt_i & ~(data_err_i | pmp_err_q);

          handle_misaligned_d = ~data_gnt_i;
        end else begin

          if (data_gnt_i) begin

            ls_fsm_ns = WAIT_RVALID_MIS_GNTS_DONE;
            handle_misaligned_d = 1'b0;
          end
        end
      end

      WAIT_GNT: begin

        addr_incr_req_o = handle_misaligned_q;
        data_req_o      = 1'b1;
        if (data_gnt_i || pmp_err_q) begin
          ctrl_update         = 1'b1;

          addr_update         = ~lsu_err_q;
          ls_fsm_ns           = IDLE;
          handle_misaligned_d = 1'b0;
        end
      end

      WAIT_RVALID_MIS_GNTS_DONE: begin


        addr_incr_req_o = 1'b1;

        if (data_rvalid_i) begin

          pmp_err_d = data_pmp_err_i;

          lsu_err_d = data_err_i;

          addr_update = ~data_err_i;

          rdata_update = ~data_we_q;

          ls_fsm_ns = IDLE;
        end
      end

      default: begin
        ls_fsm_ns = IDLE;
      end
    endcase
  end

  assign lsu_req_done_o = (lsu_req_i | (ls_fsm_cs != IDLE)) & (ls_fsm_ns == IDLE);


  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      ls_fsm_cs           <= IDLE;
      handle_misaligned_q <= '0;
      pmp_err_q           <= '0;
      lsu_err_q           <= '0;
    end else begin
      ls_fsm_cs           <= ls_fsm_ns;
      handle_misaligned_q <= handle_misaligned_d;
      pmp_err_q           <= pmp_err_d;
      lsu_err_q           <= lsu_err_d;
    end
  end





  assign data_or_pmp_err    = lsu_err_q | data_err_i | pmp_err_q;
  assign lsu_resp_valid_o   = (data_rvalid_i | pmp_err_q) & (ls_fsm_cs == IDLE);
  assign lsu_rdata_valid_o  = (ls_fsm_cs == IDLE) & data_rvalid_i & ~data_or_pmp_err & ~data_we_q;


  assign lsu_rdata_o = data_rdata_ext;


  assign data_addr_w_aligned = {data_addr[31:2], 2'b00};


  assign data_addr_o   = data_addr_w_aligned;
  assign data_wdata_o  = data_wdata;
  assign data_we_o     = lsu_we_i;
  assign data_be_o     = data_be;


  assign addr_last_o   = addr_last_q;


  assign load_err_o    = data_or_pmp_err & ~data_we_q & lsu_resp_valid_o;
  assign store_err_o   = data_or_pmp_err &  data_we_q & lsu_resp_valid_o;

  assign busy_o = (ls_fsm_cs != IDLE);





  `DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q)
  `DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q)






  `ASSERT(IbexDataTypeKnown, (lsu_req_i | busy_o) |-> !$isunknown(lsu_type_i))
  `ASSERT(IbexDataOffsetKnown, (lsu_req_i | busy_o) |-> !$isunknown(data_offset))
  `ASSERT_KNOWN(IbexRDataOffsetQKnown, rdata_offset_q)
  `ASSERT_KNOWN(IbexDataTypeQKnown, data_type_q)
  `ASSERT(IbexLsuStateValid, ls_fsm_cs inside {
      IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT,
      WAIT_RVALID_MIS_GNTS_DONE})


  `ASSERT(IbexDataAddrUnknown, data_req_o |-> !$isunknown(data_addr_o))


  `ASSERT(IbexDataAddrUnaligned, data_req_o |-> (data_addr_o[1:0] == 2'b00))

endmodule