data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog/or1k_marocchino_lsu.v
1: b'%Error: data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog/or1k_marocchino_lsu.v:29: Cannot find include file: or1k_defines.v\n`include "or1k_defines.v" \n         ^~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog,data/full_repos/permissive/447681894/or1k_defines.v\n             data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog,data/full_repos/permissive/447681894/or1k_defines.v.v\n             data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog,data/full_repos/permissive/447681894/or1k_defines.v.sv\n             or1k_defines.v\n             or1k_defines.v.v\n             or1k_defines.v.sv\n             obj_dir/or1k_defines.v\n             obj_dir/or1k_defines.v.v\n             obj_dir/or1k_defines.v.sv\n%Error: data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog/or1k_marocchino_lsu.v:70: Define or directive not defined: \'`OR1K_IMM_WIDTH\'\n  input           [`OR1K_IMM_WIDTH-1:0] exec_lsu_imm16_i,  \n                   ^~~~~~~~~~~~~~~\n%Error: Exiting due to 2 error(s)\n'
module or1k_marocchino_lsu
#(
  parameter OPTION_OPERAND_WIDTH        = 32,

  parameter OPTION_DCACHE_BLOCK_WIDTH   = 5,
  parameter OPTION_DCACHE_SET_WIDTH     = 8,
  parameter OPTION_DCACHE_WAYS          = 2,
  parameter OPTION_DCACHE_LIMIT_WIDTH   = 32,
  parameter OPTION_DCACHE_SNOOP         = "NONE",
  parameter OPTION_DCACHE_CLEAR_ON_INIT = 0,

  parameter FEATURE_DMMU_HW_TLB_RELOAD = "NONE",
  parameter OPTION_DMMU_SET_WIDTH      = 6,
  parameter OPTION_DMMU_WAYS           = 1,
  parameter OPTION_DMMU_CLEAR_ON_INIT  = 0,

  parameter OPTION_STORE_BUFFER_DEPTH_WIDTH   = 4,
  parameter OPTION_STORE_BUFFER_CLEAR_ON_INIT = 0
)
(

  input                                 cpu_clk,
  input                                 cpu_rst,

  input                                 pipeline_flush_i,
  input                                 padv_wrbk_i,
  input                                 grant_wrbk_to_lsu_i,

  input                                 dc_enable_i,
  input                                 dmmu_enable_i,
  input                                 supervisor_mode_i,

  input                                 exec_op_lsu_any_i,
  input                                 exec_op_lsu_load_i,
  input                                 exec_op_lsu_store_i,
  input                                 exec_op_msync_i,
  input                                 exec_op_lsu_atomic_i,
  input                           [1:0] exec_lsu_length_i,
  input                                 exec_lsu_zext_i,
  input           [`OR1K_IMM_WIDTH-1:0] exec_lsu_imm16_i,
  input                                 exec_lsu_delay_slot_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_lsu_pc_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_lsu_a1_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_lsu_b1_i,

  input                          [15:0] spr_bus_addr_i,
  input                                 spr_bus_we_i,
  input                                 spr_bus_stb_i,
  input      [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_i,
  output     [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_dc_o,
  output                                spr_bus_ack_dc_o,
  output     [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_dmmu_o,
  output                                spr_bus_ack_dmmu_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] dbus_adr_o,
  output reg                            dbus_req_o,
  output reg [OPTION_OPERAND_WIDTH-1:0] dbus_dat_o,
  output reg                      [3:0] dbus_bsel_o,
  output reg                            dbus_lwa_cmd_o,
  output reg                            dbus_stna_cmd_o,
  output reg                            dbus_swa_cmd_o,
  output reg                            dbus_burst_o,
  input                                 dbus_err_i,
  input                                 dbus_ack_i,
  input      [OPTION_OPERAND_WIDTH-1:0] dbus_dat_i,
  input                                 dbus_burst_last_i,

  input                                 dbus_atomic_flg_i,

  input                          [31:0] snoop_adr_i,
  input                                 snoop_en_i,

  output                                lsu_taking_op_o,
  output                                lsu_valid_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] sbuf_eear_o,
  output reg [OPTION_OPERAND_WIDTH-1:0] sbuf_epcr_o,
  output reg                            sbuf_err_o,

  output                                exec_an_except_lsu_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] wrbk_lsu_result_o,

  output reg                            wrbk_atomic_flag_set_o,
  output reg                            wrbk_atomic_flag_clear_o,

  output reg                            wrbk_except_dbus_err_o,
  output reg                            wrbk_except_dpagefault_o,
  output reg                            wrbk_except_dtlb_miss_o,
  output reg                            wrbk_except_dbus_align_o,
  output reg [OPTION_OPERAND_WIDTH-1:0] wrbk_lsu_except_addr_o
);



  localparam LSUOOW = OPTION_OPERAND_WIDTH;




  reg               s1o_op_lsu_load;
  reg               s1o_op_lsu_store;
  reg               s1o_op_lsu_atomic;
  reg               s1o_op_msync;
  reg               s1o_op_lsu_ls;
  reg  [LSUOOW-1:0] s1o_virt_addr;
  reg  [LSUOOW-1:0] s1o_lsu_b1;
  reg  [LSUOOW-1:0] s1o_sbuf_epcr;
  reg         [1:0] s1o_lsu_length;
  reg               s1o_lsu_zext;

  wire              s1o_dmmu_rdy;
  wire              s1o_dmmu_upd;






  reg               s2o_op_lsu_store;


  reg               s2o_lwa_req;
  reg         [1:0] s2o_length;
  reg               s2o_zext;


  wire              s2t_dc_ack_read;
  reg               s2o_dc_ack_read;
  wire [LSUOOW-1:0] s2t_dc_dat;
  reg  [LSUOOW-1:0] s2o_dc_dat;
  wire              s2t_dc_refill_req;
  reg               s2o_dc_refill_req;
  wire              dc_refill_allowed;
  wire              dc_refill_first;

  wire              s2t_dbus_read_req;
  reg               s2o_dbus_read_req;
  wire              dbus_load_ack;
  wire              dbus_load_err;
  reg  [LSUOOW-1:0] s2o_dbus_dat;


  reg               s2o_stna_req;
  reg               s2o_swa_req;


  reg         [3:0] s2o_bsel;
  reg  [LSUOOW-1:0] s2o_sdat;
  wire              dbus_swa_ack;

  wire              s3t_store_ack;


  wire              dc_snoop2refill;
  wire              dc_snoop2write;


  reg               s3o_ls_ack;


  reg  [LSUOOW-1:0] s2o_epcr;


  reg  [LSUOOW-1:0] s2o_virt_addr;
  reg  [LSUOOW-1:0] s2o_phys_addr;

  wire              lsu_s2_rdy;
  reg               wrbk_lsu_miss_r;




  localparam [6:0] DBUS_IDLE      = 7'b0000001,
                   DMEM_REQ       = 7'b0000010,
                   DBUS_READ      = 7'b0000100,
                   DBUS_TO_REFILL = 7'b0001000,
                   DBUS_DC_REFILL = 7'b0010000,
                   DBUS_SBUF_READ = 7'b0100000,
                   DBUS_WRITE     = 7'b1000000;

  reg        [6:0] dbus_state;

  wire             dbus_idle_state    = dbus_state[0];
  wire             dmem_req_state     = dbus_state[1];
  wire             dbus_read_state    = dbus_state[2];
  assign           dc_refill_allowed  = dbus_state[3];
  wire             dc_refill_state    = dbus_state[4];
  wire             sbuf_read_state    = dbus_state[5];




  wire              sbuf_write;
  wire              sbuf_we;

  wire              sbuf_full;
  wire              sbuf_empty;
  wire [LSUOOW-1:0] sbuf_epcr;
  wire [LSUOOW-1:0] sbuf_virt_addr;
  wire [LSUOOW-1:0] sbuf_phys_addr;
  wire [LSUOOW-1:0] sbuf_dat;
  wire        [3:0] sbuf_bsel;



  wire              s2o_snoop_proc;




  reg               s2o_tlb_miss;
  reg               s2o_pagefault;
  reg               s2o_align;

  wire              s2t_excepts_addr;
  reg               s2o_excepts_addr;

  wire              s3t_dbus_err_nsbuf;
  reg               s2o_dbus_err_nsbuf;

  reg               s2o_excepts_any;



  reg               flush_r;
  wire              flush_by_ctrl;









  wire   lsu_s2_busy = s2o_dc_refill_req | s2o_dbus_read_req |
                       s2o_op_lsu_store                      |
                       (lsu_s2_rdy & wrbk_lsu_miss_r)        |
                       s2o_excepts_any   | s2o_snoop_proc;

  wire   lsu_s1_busy = (s1o_op_lsu_ls & lsu_s2_busy) |
                       s1o_op_msync | s1o_dmmu_upd;

  wire   lsu_s1_adv  = exec_op_lsu_any_i            & (~lsu_s1_busy);
  wire   lsu_s2_adv  = s1o_op_lsu_ls & s1o_dmmu_rdy & (~lsu_s2_busy);
  wire   lsu_s3_adv  = lsu_s2_rdy                   & (~wrbk_lsu_miss_r);

  assign lsu_taking_op_o = lsu_s1_adv;



  assign dbus_load_ack = (dbus_read_state | dc_refill_first) & dbus_ack_i;
  assign dbus_load_err = (dbus_read_state | dc_refill_state) & dbus_err_i;



  assign s3t_store_ack    = sbuf_write |  dbus_swa_ack;

  wire   dc_store_allowed = sbuf_write;






  assign s3t_dbus_err_nsbuf = dbus_load_err | (dbus_swa_cmd_o & dbus_err_i);






  assign flush_by_ctrl = pipeline_flush_i | flush_r;










  wire spr_bus_stb_lsu = spr_bus_stb_i & dbus_idle_state;







  wire [LSUOOW-1:0] s1t_virt_addr = exec_lsu_a1_i + {{(LSUOOW-16){exec_lsu_imm16_i[15]}},exec_lsu_imm16_i};


  wire [LSUOOW-1:0] s1t_sbuf_epcr = exec_lsu_pc_i + {{(LSUOOW-2){exec_lsu_delay_slot_i}},2'b00};



  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      s1o_op_lsu_store  <= 1'b0;
      s1o_op_lsu_load   <= 1'b0;
      s1o_op_lsu_atomic <= 1'b0;
      s1o_op_lsu_ls     <= 1'b0;
    end
    else if (lsu_s1_adv) begin
      s1o_op_lsu_store  <= exec_op_lsu_store_i;
      s1o_op_lsu_load   <= exec_op_lsu_load_i;
      s1o_op_lsu_atomic <= exec_op_lsu_atomic_i;
      s1o_op_lsu_ls     <= (exec_op_lsu_load_i | exec_op_lsu_store_i);
    end
    else if (lsu_s2_adv) begin
      s1o_op_lsu_store  <= 1'b0;
      s1o_op_lsu_load   <= 1'b0;
      s1o_op_lsu_atomic <= 1'b0;
      s1o_op_lsu_ls     <= 1'b0;
    end
  end


  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s1o_op_msync <= 1'b0;
    else if (lsu_s1_adv)
      s1o_op_msync <= exec_op_msync_i;
    else if (dbus_idle_state & sbuf_empty)
      s1o_op_msync <= 1'b0;
  end





  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s1o_virt_addr <= {LSUOOW{1'b0}};
    else if (lsu_s1_adv)
      s1o_virt_addr <= s1t_virt_addr;
  end


  always @(posedge cpu_clk) begin
    if (lsu_s1_adv) begin
      s1o_lsu_b1     <= exec_lsu_b1_i;
      s1o_sbuf_epcr  <= s1t_sbuf_epcr;
      s1o_lsu_length <= exec_lsu_length_i;
      s1o_lsu_zext   <= exec_lsu_zext_i;
    end
  end



  reg [3:0] s2t_bsel;

  always @(s1o_lsu_length or s1o_virt_addr[1:0]) begin
    (* parallel_case *)
    case (s1o_lsu_length)
      2'b00:
      begin
        (* parallel_case *)
        case( s1o_virt_addr[1:0])
          2'b00: s2t_bsel = 4'b1000;
          2'b01: s2t_bsel = 4'b0100;
          2'b10: s2t_bsel = 4'b0010;
          2'b11: s2t_bsel = 4'b0001;
        endcase
      end
      2'b01:
      begin
        (* parallel_case *)
        case(s1o_virt_addr[1])
          1'b0: s2t_bsel = 4'b1100;
          1'b1: s2t_bsel = 4'b0011;
        endcase
      end
      2'b10,
      2'b11: s2t_bsel = 4'b1111;
    endcase
  end


  wire [LSUOOW-1:0] s2t_sdat =
    (s1o_lsu_length == 2'b00) ? {s1o_lsu_b1[7:0],s1o_lsu_b1[7:0],s1o_lsu_b1[7:0],s1o_lsu_b1[7:0]} :
    (s1o_lsu_length == 2'b01) ? {s1o_lsu_b1[15:0],s1o_lsu_b1[15:0]} :
                                s1o_lsu_b1;


  wire s2t_align = s1o_op_lsu_ls &
                   (((s1o_lsu_length == 2'b10) & (|s1o_virt_addr[1:0])) |
                    ((s1o_lsu_length == 2'b01) & s1o_virt_addr[0]));



  wire [LSUOOW-1:0] s2t_phys_addr;
  wire              s2t_cache_inhibit;
  wire              s2t_tlb_miss;
  wire              s2t_pagefault;





  or1k_marocchino_dmmu
  #(
    .FEATURE_DMMU_HW_TLB_RELOAD       (FEATURE_DMMU_HW_TLB_RELOAD),
    .OPTION_OPERAND_WIDTH             (OPTION_OPERAND_WIDTH),
    .OPTION_DMMU_SET_WIDTH            (OPTION_DMMU_SET_WIDTH),
    .OPTION_DMMU_WAYS                 (OPTION_DMMU_WAYS),
    .OPTION_DCACHE_LIMIT_WIDTH        (OPTION_DCACHE_LIMIT_WIDTH),
    .OPTION_DMMU_CLEAR_ON_INIT        (OPTION_DMMU_CLEAR_ON_INIT)
  )
  u_dmmu
  (

    .cpu_clk                          (cpu_clk),
    .cpu_rst                          (cpu_rst),

    .lsu_s1_adv_i                     (lsu_s1_adv),
    .pipeline_flush_i                 (pipeline_flush_i),
    .s1o_dmmu_rdy_o                   (s1o_dmmu_rdy),
    .s1o_dmmu_upd_o                   (s1o_dmmu_upd),

    .dmmu_enable_i                    (dmmu_enable_i),
    .supervisor_mode_i                (supervisor_mode_i),
    .exec_op_lsu_store_i              (exec_op_lsu_store_i),
    .exec_op_lsu_load_i               (exec_op_lsu_load_i),
    .s1o_op_lsu_store_i               (s1o_op_lsu_store),
    .s1o_op_lsu_load_i                (s1o_op_lsu_load),
    .s1o_op_msync_i                   (s1o_op_msync),

    .virt_addr_s1t_i                  (s1t_virt_addr),
    .virt_addr_s1o_i                  (s1o_virt_addr),
    .phys_addr_o                      (s2t_phys_addr),

    .cache_inhibit_o                  (s2t_cache_inhibit),
    .tlb_miss_o                       (s2t_tlb_miss),
    .pagefault_o                      (s2t_pagefault),

    .tlb_reload_ack_i                 (1'b0),
    .tlb_reload_data_i                ({LSUOOW{1'b0}}),
    .tlb_reload_pagefault_clear_i     (1'b0),
    .tlb_reload_req_o                 (),
    .tlb_reload_busy_o                (),
    .tlb_reload_addr_o                (),
    .tlb_reload_pagefault_o           (),

    .spr_bus_addr_i                   (spr_bus_addr_i[15:0]),
    .spr_bus_we_i                     (spr_bus_we_i),
    .spr_bus_stb_i                    (spr_bus_stb_lsu),
    .spr_bus_dat_i                    (spr_bus_dat_i),
    .spr_bus_dat_o                    (spr_bus_dat_dmmu_o),
    .spr_bus_ack_o                    (spr_bus_ack_dmmu_o)
  );


  assign s2t_excepts_addr = s2t_tlb_miss | s2t_pagefault | s2t_align;










  assign dc_snoop2refill = dc_refill_allowed | dc_refill_state;




  assign dc_snoop2write = s2o_stna_req;

  or1k_marocchino_dcache
  #(
    .OPTION_OPERAND_WIDTH         (OPTION_OPERAND_WIDTH),
    .OPTION_DCACHE_BLOCK_WIDTH    (OPTION_DCACHE_BLOCK_WIDTH),
    .OPTION_DCACHE_SET_WIDTH      (OPTION_DCACHE_SET_WIDTH),
    .OPTION_DCACHE_WAYS           (OPTION_DCACHE_WAYS),
    .OPTION_DCACHE_LIMIT_WIDTH    (OPTION_DCACHE_LIMIT_WIDTH),
    .OPTION_DCACHE_SNOOP          (OPTION_DCACHE_SNOOP),
    .OPTION_DCACHE_CLEAR_ON_INIT  (OPTION_DCACHE_CLEAR_ON_INIT)
  )
  u_dcache
  (

    .cpu_clk                    (cpu_clk),
    .cpu_rst                    (cpu_rst),

    .lsu_s1_adv_i               (lsu_s1_adv),
    .lsu_s2_adv_i               (lsu_s2_adv),
    .pipeline_flush_i           (pipeline_flush_i),

    .dc_enable_i                (dc_enable_i),

    .s2o_excepts_addr_i         (s2o_excepts_addr),
    .dbus_err_i                 (dbus_err_i),


    .virt_addr_s1t_i            (s1t_virt_addr),
    .virt_addr_s1o_i            (s1o_virt_addr),
    .virt_addr_s2o_i            (s2o_virt_addr),
    .phys_addr_s2t_i            (s2t_phys_addr),
    .dmmu_cache_inhibit_i       (s2t_cache_inhibit),

    .s1o_op_lsu_load_i          (s1o_op_lsu_load),
    .dc_ack_read_o              (s2t_dc_ack_read),
    .dc_dat_o                   (s2t_dc_dat),

    .s1o_op_lsu_store_i         (s1o_op_lsu_store),
    .dbus_bsel_i                (s2o_bsel),
    .dbus_sdat_i                (s2o_sdat),
    .dc_dat_s2o_i               (s2o_dc_dat),
    .dc_store_allowed_i         (dc_store_allowed),



    .s1o_op_lsu_atomic_i        (s1o_op_lsu_atomic),

    .dc_refill_req_o            (s2t_dc_refill_req),
    .dc_refill_allowed_i        (dc_refill_allowed),
    .refill_first_o             (dc_refill_first),
    .phys_addr_s2o_i            (s2o_phys_addr),
    .dbus_dat_i                 (dbus_dat_i),
    .dbus_ack_i                 (dbus_ack_i),
    .dbus_burst_last_i          (dbus_burst_last_i),

    .dbus_read_req_o            (s2t_dbus_read_req),

    .snoop_adr_i                (snoop_adr_i),
    .snoop_en_i                 (snoop_en_i),
    .s2o_snoop_proc_o           (s2o_snoop_proc),
    .dc_snoop2refill_i          (dc_snoop2refill),
    .dc_snoop2write_i           (dc_snoop2write),

    .spr_bus_addr_i             (spr_bus_addr_i[15:0]),
    .spr_bus_we_i               (spr_bus_we_i),
    .spr_bus_stb_i              (spr_bus_stb_lsu),
    .spr_bus_dat_i              (spr_bus_dat_i),
    .spr_bus_dat_o              (spr_bus_dat_dc_o),
    .spr_bus_ack_o              (spr_bus_ack_dc_o)
  );













  wire sbuf_err = dbus_stna_cmd_o & dbus_err_i;

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      sbuf_err_o <= 1'b0;
    else if (sbuf_err)
      sbuf_err_o <= 1'b1;
  end






  always @(posedge cpu_clk) begin
    if (cpu_rst) begin
      dbus_req_o      <= 1'b0;
      dbus_lwa_cmd_o  <= 1'b0;
      dbus_stna_cmd_o <= 1'b0;
      dbus_swa_cmd_o  <= 1'b0;
      dbus_burst_o    <= 1'b0;
      dbus_state      <= DBUS_IDLE;
    end
    else begin
      (* parallel_case *)
      case (dbus_state)
        DBUS_IDLE: begin
          if (pipeline_flush_i)
            dbus_state <= DBUS_IDLE;
          else if (~sbuf_empty)
            dbus_state <= DBUS_SBUF_READ;
          else if (lsu_s2_adv)
            dbus_state <= DMEM_REQ;
        end

        DMEM_REQ: begin
          if (pipeline_flush_i) begin
            dbus_state <= DBUS_IDLE;
          end
          else if (~sbuf_empty) begin
            dbus_state <= DBUS_SBUF_READ;
          end
          else if (s2o_excepts_addr) begin
            dbus_state <= DBUS_IDLE;
          end
          else if (s2o_swa_req) begin
            dbus_req_o     <= ~dbus_req_o;
            dbus_swa_cmd_o <= 1'b1;
            dbus_state     <= DBUS_WRITE;
          end
          else if (s2o_dc_refill_req) begin
            dbus_req_o   <= ~dbus_req_o;
            dbus_burst_o <= 1'b1;
            dbus_state   <= DBUS_TO_REFILL;
          end
          else if (s2o_dbus_read_req) begin
            dbus_req_o     <= ~dbus_req_o;
            dbus_lwa_cmd_o <= s2o_lwa_req;
            dbus_state     <= DBUS_READ;
          end
          else if (~lsu_s2_adv) begin
            dbus_state <= DBUS_IDLE;
          end
        end

        DBUS_READ: begin
          if (dbus_err_i | dbus_ack_i) begin
            dbus_lwa_cmd_o <= 1'b0;
            dbus_state     <= DBUS_IDLE;
          end
        end

        DBUS_TO_REFILL: begin
          dbus_state <= DBUS_DC_REFILL;
        end

        DBUS_DC_REFILL: begin
          if (dbus_err_i | (dbus_ack_i & dbus_burst_last_i)) begin
            dbus_burst_o <= 1'b0;
            dbus_state   <= DBUS_IDLE;
          end
        end

        DBUS_SBUF_READ: begin
          dbus_req_o      <= ~dbus_req_o;
          dbus_stna_cmd_o <= 1'b1;
          dbus_state      <= DBUS_WRITE;
        end

        DBUS_WRITE: begin

          if (dbus_err_i | dbus_ack_i) begin
            dbus_stna_cmd_o <= 1'b0;
            dbus_swa_cmd_o  <= 1'b0;
          end

          if (dbus_err_i) begin
            dbus_state <= DBUS_IDLE;
          end
          else if (dbus_ack_i) begin
            dbus_state <= sbuf_empty ? DMEM_REQ : DBUS_SBUF_READ;
          end
        end

        default:;
      endcase
    end
  end


  always @(posedge cpu_clk) begin
    (* parallel_case *)
    case (dbus_state)
      DMEM_REQ: begin
        if (pipeline_flush_i | (~sbuf_empty) | s2o_excepts_addr) begin
        end
        else if (s2o_swa_req) begin
          dbus_bsel_o   <= s2o_bsel;
          dbus_adr_o    <= s2o_phys_addr;
          dbus_dat_o    <= s2o_sdat;
        end
        else if (s2o_dc_refill_req) begin
          dbus_bsel_o   <= 4'b1111;
          dbus_adr_o    <= s2o_phys_addr;
        end
        else if (s2o_dbus_read_req) begin
          dbus_bsel_o   <= s2o_bsel;
          dbus_adr_o    <= s2o_phys_addr;
        end
      end

      DBUS_SBUF_READ: begin

        dbus_bsel_o   <= sbuf_bsel;
        dbus_adr_o    <= sbuf_phys_addr;
        dbus_dat_o    <= sbuf_dat;


        sbuf_eear_o   <= sbuf_virt_addr;
        sbuf_epcr_o   <= sbuf_epcr;
      end

      default:;
    endcase
  end




  wire deassert_flush_r =
    dc_refill_allowed ? 1'b0 :
    dc_refill_state   ? (dbus_err_i | (dbus_ack_i & dbus_burst_last_i)) :
    dbus_read_state   ? (dbus_err_i | dbus_ack_i) : 1'b1;

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      flush_r <= 1'b0;
    else if (deassert_flush_r)
      flush_r <= 1'b0;
    else if (pipeline_flush_i)
      flush_r <= 1'b1;
  end







  assign sbuf_write = s2o_stna_req & (~sbuf_full) &
                      (~s2o_snoop_proc) &
                      (~wrbk_lsu_miss_r) & grant_wrbk_to_lsu_i;

  assign sbuf_we    = sbuf_write & (~s2o_excepts_addr) & (~pipeline_flush_i);


  wire   sbuf_ram_empty;
  wire   sbuf_oreg_rdy;
  assign sbuf_empty = sbuf_ram_empty & (~sbuf_oreg_rdy);

  localparam STORE_BUFFER_NUM_TAPS = (1 << OPTION_STORE_BUFFER_DEPTH_WIDTH);


  localparam STORE_BUFFER_DATA_WIDTH = (OPTION_OPERAND_WIDTH * 4) + (OPTION_OPERAND_WIDTH / 8);

  wire [STORE_BUFFER_DATA_WIDTH-1:0] sbuf_in;
  wire [STORE_BUFFER_DATA_WIDTH-1:0] sbuf_out;

  assign sbuf_in = {s2o_bsel, s2o_sdat, s2o_phys_addr, s2o_virt_addr, s2o_epcr};

  assign {sbuf_bsel, sbuf_dat, sbuf_phys_addr, sbuf_virt_addr, sbuf_epcr} = sbuf_out;


  or1k_marocchino_oreg_buff
  #(
    .NUM_TAPS         (STORE_BUFFER_NUM_TAPS),
    .DATA_WIDTH       (STORE_BUFFER_DATA_WIDTH),
    .RAM_EMPTY_FLAG   ("ENABLED"),
    .REG_RDY_FLAG     ("ENABLED")
  )
  u_store_buffer
  (

    .cpu_clk      (cpu_clk),

    .ini_rst      (cpu_rst),
    .ext_rst      (sbuf_err),

    .write_i      (sbuf_we),
    .read_i       (sbuf_read_state),

    .data_i       (sbuf_in),

    .ram_empty_o  (sbuf_ram_empty),

    .ram_full_o   (sbuf_full),

    .rdy_o        (sbuf_oreg_rdy),
    .data_o       (sbuf_out)
  );






  assign dbus_swa_ack = dbus_swa_cmd_o & dbus_ack_i;

  reg s2o_atomic_flag_set;
  reg s2o_atomic_flag_clear;

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl) begin
      s2o_atomic_flag_set   <= 1'b0;
      s2o_atomic_flag_clear <= 1'b0;
    end
    else if (dbus_swa_ack) begin
      s2o_atomic_flag_set   <=   dbus_atomic_flg_i;
      s2o_atomic_flag_clear <= (~dbus_atomic_flg_i);
    end
    else if (lsu_s3_adv) begin
      s2o_atomic_flag_set   <= 1'b0;
      s2o_atomic_flag_clear <= 1'b0;
    end
  end










  always @(posedge cpu_clk) begin
    if (lsu_s2_adv) begin

      s2o_epcr      <= s1o_sbuf_epcr;
      s2o_bsel      <= s2t_bsel;
      s2o_sdat      <= s2t_sdat;

      s2o_length    <= s1o_lsu_length;
      s2o_zext      <= s1o_lsu_zext;

      s2o_virt_addr <= s1o_virt_addr;
      s2o_phys_addr <= s2t_phys_addr;
    end
  end


  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      s2o_op_lsu_store <= 1'b0;
    else if (lsu_s2_adv)
      s2o_op_lsu_store <= s1o_op_lsu_store;
    else if (s3t_store_ack)
      s2o_op_lsu_store <= 1'b0;
  end



  wire deassert_s2o_stna_req = sbuf_write | pipeline_flush_i | s2o_excepts_addr;

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s2o_stna_req <= 1'b0;
    else if (deassert_s2o_stna_req)
      s2o_stna_req <= 1'b0;
    else if (lsu_s2_adv)
      s2o_stna_req <= s1o_op_lsu_store & (~s1o_op_lsu_atomic);
  end


  wire deassert_s2o_swa_req = dbus_swa_cmd_o ? (dbus_err_i | dbus_ack_i) :
                                               (pipeline_flush_i | s2o_excepts_addr);

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s2o_swa_req <= 1'b0;
    else if (deassert_s2o_swa_req)
      s2o_swa_req <= 1'b0;
    else if (lsu_s2_adv)
      s2o_swa_req <= s1o_op_lsu_store & s1o_op_lsu_atomic;
  end



  wire deassert_s2o_dc_refill_req =
    dc_refill_allowed ? 1'b0 :
      (dc_refill_state ? (dbus_err_i | (dbus_ack_i & dbus_burst_last_i)) :
                         (pipeline_flush_i | s2o_excepts_addr));

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s2o_dc_refill_req <= 1'b0;
    else if (deassert_s2o_dc_refill_req)
      s2o_dc_refill_req <= 1'b0;
    else if (lsu_s2_adv)
      s2o_dc_refill_req <= s2t_dc_refill_req;
  end

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      s2o_dc_ack_read <= 1'b0;
    else if (lsu_s2_adv)
      s2o_dc_ack_read <= s2t_dc_ack_read;
    else if (lsu_s3_adv)
      s2o_dc_ack_read <= 1'b0;
  end

  always @(posedge cpu_clk) begin
    if (lsu_s2_adv)
      s2o_dc_dat <= s2t_dc_dat;
  end



  wire deassert_s2o_dbus_read_req =
    dbus_read_state ? (dbus_err_i | dbus_ack_i) :
                      (pipeline_flush_i | s2o_excepts_addr);

  always @(posedge cpu_clk) begin
    if (cpu_rst) begin
      s2o_dbus_read_req <= 1'b0;
      s2o_lwa_req       <= 1'b0;
    end
    else if (deassert_s2o_dbus_read_req) begin
      s2o_dbus_read_req <= 1'b0;
      s2o_lwa_req       <= 1'b0;
    end
    else if (lsu_s2_adv) begin
      s2o_dbus_read_req <= s2t_dbus_read_req;
      s2o_lwa_req       <= s1o_op_lsu_load & s1o_op_lsu_atomic;
    end
  end

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      s3o_ls_ack <= 1'b0;
    else if (dbus_load_ack | s3t_store_ack)
      s3o_ls_ack <= 1'b1;
    else if (lsu_s3_adv)
      s3o_ls_ack <= 1'b0;
  end

  always @(posedge cpu_clk) begin
    if (dbus_load_ack)
      s2o_dbus_dat <= dbus_dat_i;
  end



  always @(posedge cpu_clk) begin
    if (flush_by_ctrl) begin

      s2o_tlb_miss       <= 1'b0;
      s2o_pagefault      <= 1'b0;
      s2o_align          <= 1'b0;

      s2o_dbus_err_nsbuf <= 1'b0;

      s2o_excepts_addr   <= 1'b0;
      s2o_excepts_any    <= 1'b0;
    end
    else if (lsu_s2_adv) begin

      s2o_tlb_miss       <= s2t_tlb_miss;
      s2o_pagefault      <= s2t_pagefault;
      s2o_align          <= s2t_align;

      s2o_excepts_addr   <= s2t_excepts_addr;
      s2o_excepts_any    <= s2t_excepts_addr;
    end
    else if (dbus_err_i) begin
      s2o_dbus_err_nsbuf <= s3t_dbus_err_nsbuf;
      s2o_excepts_any    <= 1'b1;
    end
  end



  assign lsu_s2_rdy  = s2o_dc_ack_read | s3o_ls_ack | s2o_excepts_any;

  assign lsu_valid_o = lsu_s2_rdy | wrbk_lsu_miss_r;

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      wrbk_lsu_miss_r <= 1'b0;
    else if (padv_wrbk_i & grant_wrbk_to_lsu_i)
      wrbk_lsu_miss_r <= 1'b0;
    else if (lsu_s3_adv)
      wrbk_lsu_miss_r <= 1'b1;
  end






  wire [LSUOOW-1:0] s3t_ldat = s2o_dc_ack_read ? s2o_dc_dat : s2o_dbus_dat;


  reg [LSUOOW-1:0] s3t_ldat_aligned;

  always @(s2o_virt_addr[1:0] or s3t_ldat) begin
    (* parallel_case *)
    case(s2o_virt_addr[1:0])
      2'b00: s3t_ldat_aligned = s3t_ldat;
      2'b01: s3t_ldat_aligned = {s3t_ldat[23:0],8'd0};
      2'b10: s3t_ldat_aligned = {s3t_ldat[15:0],16'd0};
      2'b11: s3t_ldat_aligned = {s3t_ldat[7:0],24'd0};
    endcase
  end


  reg [LSUOOW-1:0] s3t_ldat_extended;

  always @(s2o_zext or s2o_length or s3t_ldat_aligned) begin
    (* parallel_case *)
    case({s2o_zext, s2o_length})
      3'b100:  s3t_ldat_extended = {24'd0,s3t_ldat_aligned[31:24]};
      3'b101:  s3t_ldat_extended = {16'd0,s3t_ldat_aligned[31:16]};
      3'b000:  s3t_ldat_extended = {{24{s3t_ldat_aligned[31]}},
                                    s3t_ldat_aligned[31:24]};
      3'b001:  s3t_ldat_extended = {{16{s3t_ldat_aligned[31]}},
                                    s3t_ldat_aligned[31:16]};
      default: s3t_ldat_extended = s3t_ldat_aligned;
    endcase
  end




  reg  [LSUOOW-1:0] s3o_lsu_result;
  reg  [LSUOOW-1:0] s3o_lsu_except_addr;

  reg               s3o_atomic_flag_set;
  reg               s3o_atomic_flag_clear;

  reg               s3o_dbus_err_nsbuf;
  reg               s3o_pagefault;
  reg               s3o_tlb_miss;
  reg               s3o_align;

  reg               s3o_excepts_any;
  

  always @(posedge cpu_clk) begin
    if (lsu_s3_adv) begin

      s3o_lsu_result        <= s3t_ldat_extended;
      s3o_lsu_except_addr   <= s2o_virt_addr;

      s3o_atomic_flag_set   <= s2o_atomic_flag_set;
      s3o_atomic_flag_clear <= s2o_atomic_flag_clear;

      s3o_dbus_err_nsbuf    <= s2o_dbus_err_nsbuf;
      s3o_pagefault         <= s2o_pagefault;
      s3o_tlb_miss          <= s2o_tlb_miss;
      s3o_align             <= s2o_align;

      s3o_excepts_any       <= s2o_excepts_any;
    end
  end


  assign exec_an_except_lsu_o = (wrbk_lsu_miss_r ? s3o_excepts_any : s2o_excepts_any) & grant_wrbk_to_lsu_i;


  always @(posedge cpu_clk) begin
    if (padv_wrbk_i) begin
      if (grant_wrbk_to_lsu_i) begin
        wrbk_lsu_result_o      <= wrbk_lsu_miss_r ? s3o_lsu_result : s3t_ldat_extended;
        wrbk_lsu_except_addr_o <= wrbk_lsu_miss_r ? s3o_lsu_except_addr : s2o_virt_addr;
      end
      else begin
        wrbk_lsu_result_o      <= {LSUOOW{1'b0}};
      end
    end
  end


  always @(posedge cpu_clk) begin
    if (padv_wrbk_i & grant_wrbk_to_lsu_i) begin

      wrbk_atomic_flag_set_o   <= wrbk_lsu_miss_r ? s3o_atomic_flag_set   : s2o_atomic_flag_set;
      wrbk_atomic_flag_clear_o <= wrbk_lsu_miss_r ? s3o_atomic_flag_clear : s2o_atomic_flag_clear;

      wrbk_except_dbus_err_o   <= wrbk_lsu_miss_r ? s3o_dbus_err_nsbuf : s2o_dbus_err_nsbuf;
      wrbk_except_dpagefault_o <= wrbk_lsu_miss_r ? s3o_pagefault      : s2o_pagefault;
      wrbk_except_dtlb_miss_o  <= wrbk_lsu_miss_r ? s3o_tlb_miss       : s2o_tlb_miss;
      wrbk_except_dbus_align_o <= wrbk_lsu_miss_r ? s3o_align          : s2o_align;
    end
    else begin

      wrbk_atomic_flag_set_o   <= 1'b0;
      wrbk_atomic_flag_clear_o <= 1'b0;

      wrbk_except_dbus_err_o   <= 1'b0;
      wrbk_except_dpagefault_o <= 1'b0;
      wrbk_except_dtlb_miss_o  <= 1'b0;
      wrbk_except_dbus_align_o <= 1'b0;
    end
  end
  
endmodule
module or1k_marocchino_lsu
#(
  parameter OPTION_OPERAND_WIDTH        = 32,

  parameter OPTION_DCACHE_BLOCK_WIDTH   = 5,
  parameter OPTION_DCACHE_SET_WIDTH     = 8,
  parameter OPTION_DCACHE_WAYS          = 2,
  parameter OPTION_DCACHE_LIMIT_WIDTH   = 32,
  parameter OPTION_DCACHE_SNOOP         = "NONE",
  parameter OPTION_DCACHE_CLEAR_ON_INIT = 0,

  parameter FEATURE_DMMU_HW_TLB_RELOAD = "NONE",
  parameter OPTION_DMMU_SET_WIDTH      = 6,
  parameter OPTION_DMMU_WAYS           = 1,
  parameter OPTION_DMMU_CLEAR_ON_INIT  = 0,

  parameter OPTION_STORE_BUFFER_DEPTH_WIDTH   = 4,
  parameter OPTION_STORE_BUFFER_CLEAR_ON_INIT = 0
)
(

  input                                 cpu_clk,
  input                                 cpu_rst,

  input                                 pipeline_flush_i,
  input                                 padv_wrbk_i,
  input                                 grant_wrbk_to_lsu_i,

  input                                 dc_enable_i,
  input                                 dmmu_enable_i,
  input                                 supervisor_mode_i,

  input                                 exec_op_lsu_any_i,
  input                                 exec_op_lsu_load_i,
  input                                 exec_op_lsu_store_i,
  input                                 exec_op_msync_i,
  input                                 exec_op_lsu_atomic_i,
  input                           [1:0] exec_lsu_length_i,
  input                                 exec_lsu_zext_i,
  input           [`OR1K_IMM_WIDTH-1:0] exec_lsu_imm16_i,
  input                                 exec_lsu_delay_slot_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_lsu_pc_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_lsu_a1_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_lsu_b1_i,

  input                          [15:0] spr_bus_addr_i,
  input                                 spr_bus_we_i,
  input                                 spr_bus_stb_i,
  input      [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_i,
  output     [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_dc_o,
  output                                spr_bus_ack_dc_o,
  output     [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_dmmu_o,
  output                                spr_bus_ack_dmmu_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] dbus_adr_o,
  output reg                            dbus_req_o,
  output reg [OPTION_OPERAND_WIDTH-1:0] dbus_dat_o,
  output reg                      [3:0] dbus_bsel_o,
  output reg                            dbus_lwa_cmd_o,
  output reg                            dbus_stna_cmd_o,
  output reg                            dbus_swa_cmd_o,
  output reg                            dbus_burst_o,
  input                                 dbus_err_i,
  input                                 dbus_ack_i,
  input      [OPTION_OPERAND_WIDTH-1:0] dbus_dat_i,
  input                                 dbus_burst_last_i,

  input                                 dbus_atomic_flg_i,

  input                          [31:0] snoop_adr_i,
  input                                 snoop_en_i,

  output                                lsu_taking_op_o,
  output                                lsu_valid_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] sbuf_eear_o,
  output reg [OPTION_OPERAND_WIDTH-1:0] sbuf_epcr_o,
  output reg                            sbuf_err_o,

  output                                exec_an_except_lsu_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] wrbk_lsu_result_o,

  output reg                            wrbk_atomic_flag_set_o,
  output reg                            wrbk_atomic_flag_clear_o,

  output reg                            wrbk_except_dbus_err_o,
  output reg                            wrbk_except_dpagefault_o,
  output reg                            wrbk_except_dtlb_miss_o,
  output reg                            wrbk_except_dbus_align_o,
  output reg [OPTION_OPERAND_WIDTH-1:0] wrbk_lsu_except_addr_o
);




  localparam LSUOOW = OPTION_OPERAND_WIDTH;




  reg               s1o_op_lsu_load;
  reg               s1o_op_lsu_store;
  reg               s1o_op_lsu_atomic;
  reg               s1o_op_msync;
  reg               s1o_op_lsu_ls;
  reg  [LSUOOW-1:0] s1o_virt_addr;
  reg  [LSUOOW-1:0] s1o_lsu_b1;
  reg  [LSUOOW-1:0] s1o_sbuf_epcr;
  reg         [1:0] s1o_lsu_length;
  reg               s1o_lsu_zext;

  wire              s1o_dmmu_rdy;
  wire              s1o_dmmu_upd;






  reg               s2o_op_lsu_store;


  reg               s2o_lwa_req;
  reg         [1:0] s2o_length;
  reg               s2o_zext;


  wire              s2t_dc_ack_read;
  reg               s2o_dc_ack_read;
  wire [LSUOOW-1:0] s2t_dc_dat;
  reg  [LSUOOW-1:0] s2o_dc_dat;
  wire              s2t_dc_refill_req;
  reg               s2o_dc_refill_req;
  wire              dc_refill_allowed;
  wire              dc_refill_first;

  wire              s2t_dbus_read_req;
  reg               s2o_dbus_read_req;
  wire              dbus_load_ack;
  wire              dbus_load_err;
  reg  [LSUOOW-1:0] s2o_dbus_dat;


  reg               s2o_stna_req;
  reg               s2o_swa_req;


  reg         [3:0] s2o_bsel;
  reg  [LSUOOW-1:0] s2o_sdat;
  wire              dbus_swa_ack;

  wire              s3t_store_ack;


  wire              dc_snoop2refill;
  wire              dc_snoop2write;


  reg               s3o_ls_ack;


  reg  [LSUOOW-1:0] s2o_epcr;


  reg  [LSUOOW-1:0] s2o_virt_addr;
  reg  [LSUOOW-1:0] s2o_phys_addr;

  wire              lsu_s2_rdy;
  reg               wrbk_lsu_miss_r;




  localparam [6:0] DBUS_IDLE      = 7'b0000001,
                   DMEM_REQ       = 7'b0000010,
                   DBUS_READ      = 7'b0000100,
                   DBUS_TO_REFILL = 7'b0001000,
                   DBUS_DC_REFILL = 7'b0010000,
                   DBUS_SBUF_READ = 7'b0100000,
                   DBUS_WRITE     = 7'b1000000;

  reg        [6:0] dbus_state;

  wire             dbus_idle_state    = dbus_state[0];
  wire             dmem_req_state     = dbus_state[1];
  wire             dbus_read_state    = dbus_state[2];
  assign           dc_refill_allowed  = dbus_state[3];
  wire             dc_refill_state    = dbus_state[4];
  wire             sbuf_read_state    = dbus_state[5];




  wire              sbuf_write;
  wire              sbuf_we;

  wire              sbuf_full;
  wire              sbuf_empty;
  wire [LSUOOW-1:0] sbuf_epcr;
  wire [LSUOOW-1:0] sbuf_virt_addr;
  wire [LSUOOW-1:0] sbuf_phys_addr;
  wire [LSUOOW-1:0] sbuf_dat;
  wire        [3:0] sbuf_bsel;



  wire              s2o_snoop_proc;




  reg               s2o_tlb_miss;
  reg               s2o_pagefault;
  reg               s2o_align;

  wire              s2t_excepts_addr;
  reg               s2o_excepts_addr;

  wire              s3t_dbus_err_nsbuf;
  reg               s2o_dbus_err_nsbuf;

  reg               s2o_excepts_any;



  reg               flush_r;
  wire              flush_by_ctrl;









  wire   lsu_s2_busy = s2o_dc_refill_req | s2o_dbus_read_req |
                       s2o_op_lsu_store                      |
                       (lsu_s2_rdy & wrbk_lsu_miss_r)        |
                       s2o_excepts_any   | s2o_snoop_proc;

  wire   lsu_s1_busy = (s1o_op_lsu_ls & lsu_s2_busy) |
                       s1o_op_msync | s1o_dmmu_upd;

  wire   lsu_s1_adv  = exec_op_lsu_any_i            & (~lsu_s1_busy);
  wire   lsu_s2_adv  = s1o_op_lsu_ls & s1o_dmmu_rdy & (~lsu_s2_busy);
  wire   lsu_s3_adv  = lsu_s2_rdy                   & (~wrbk_lsu_miss_r);

  assign lsu_taking_op_o = lsu_s1_adv;



  assign dbus_load_ack = (dbus_read_state | dc_refill_first) & dbus_ack_i;
  assign dbus_load_err = (dbus_read_state | dc_refill_state) & dbus_err_i;



  assign s3t_store_ack    = sbuf_write |  dbus_swa_ack;

  wire   dc_store_allowed = sbuf_write;






  assign s3t_dbus_err_nsbuf = dbus_load_err | (dbus_swa_cmd_o & dbus_err_i);






  assign flush_by_ctrl = pipeline_flush_i | flush_r;










  wire spr_bus_stb_lsu = spr_bus_stb_i & dbus_idle_state;







  wire [LSUOOW-1:0] s1t_virt_addr = exec_lsu_a1_i + {{(LSUOOW-16){exec_lsu_imm16_i[15]}},exec_lsu_imm16_i};


  wire [LSUOOW-1:0] s1t_sbuf_epcr = exec_lsu_pc_i + {{(LSUOOW-2){exec_lsu_delay_slot_i}},2'b00};



  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      s1o_op_lsu_store  <= 1'b0;
      s1o_op_lsu_load   <= 1'b0;
      s1o_op_lsu_atomic <= 1'b0;
      s1o_op_lsu_ls     <= 1'b0;
    end
    else if (lsu_s1_adv) begin
      s1o_op_lsu_store  <= exec_op_lsu_store_i;
      s1o_op_lsu_load   <= exec_op_lsu_load_i;
      s1o_op_lsu_atomic <= exec_op_lsu_atomic_i;
      s1o_op_lsu_ls     <= (exec_op_lsu_load_i | exec_op_lsu_store_i);
    end
    else if (lsu_s2_adv) begin
      s1o_op_lsu_store  <= 1'b0;
      s1o_op_lsu_load   <= 1'b0;
      s1o_op_lsu_atomic <= 1'b0;
      s1o_op_lsu_ls     <= 1'b0;
    end
  end


  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s1o_op_msync <= 1'b0;
    else if (lsu_s1_adv)
      s1o_op_msync <= exec_op_msync_i;
    else if (dbus_idle_state & sbuf_empty)
      s1o_op_msync <= 1'b0;
  end





  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s1o_virt_addr <= {LSUOOW{1'b0}};
    else if (lsu_s1_adv)
      s1o_virt_addr <= s1t_virt_addr;
  end


  always @(posedge cpu_clk) begin
    if (lsu_s1_adv) begin
      s1o_lsu_b1     <= exec_lsu_b1_i;
      s1o_sbuf_epcr  <= s1t_sbuf_epcr;
      s1o_lsu_length <= exec_lsu_length_i;
      s1o_lsu_zext   <= exec_lsu_zext_i;
    end
  end



  reg [3:0] s2t_bsel;

  always @(s1o_lsu_length or s1o_virt_addr[1:0]) begin
    (* parallel_case *)
    case (s1o_lsu_length)
      2'b00:
      begin
        (* parallel_case *)
        case( s1o_virt_addr[1:0])
          2'b00: s2t_bsel = 4'b1000;
          2'b01: s2t_bsel = 4'b0100;
          2'b10: s2t_bsel = 4'b0010;
          2'b11: s2t_bsel = 4'b0001;
        endcase
      end
      2'b01:
      begin
        (* parallel_case *)
        case(s1o_virt_addr[1])
          1'b0: s2t_bsel = 4'b1100;
          1'b1: s2t_bsel = 4'b0011;
        endcase
      end
      2'b10,
      2'b11: s2t_bsel = 4'b1111;
    endcase
  end


  wire [LSUOOW-1:0] s2t_sdat =
    (s1o_lsu_length == 2'b00) ? {s1o_lsu_b1[7:0],s1o_lsu_b1[7:0],s1o_lsu_b1[7:0],s1o_lsu_b1[7:0]} :
    (s1o_lsu_length == 2'b01) ? {s1o_lsu_b1[15:0],s1o_lsu_b1[15:0]} :
                                s1o_lsu_b1;


  wire s2t_align = s1o_op_lsu_ls &
                   (((s1o_lsu_length == 2'b10) & (|s1o_virt_addr[1:0])) |
                    ((s1o_lsu_length == 2'b01) & s1o_virt_addr[0]));



  wire [LSUOOW-1:0] s2t_phys_addr;
  wire              s2t_cache_inhibit;
  wire              s2t_tlb_miss;
  wire              s2t_pagefault;





  or1k_marocchino_dmmu
  #(
    .FEATURE_DMMU_HW_TLB_RELOAD       (FEATURE_DMMU_HW_TLB_RELOAD),
    .OPTION_OPERAND_WIDTH             (OPTION_OPERAND_WIDTH),
    .OPTION_DMMU_SET_WIDTH            (OPTION_DMMU_SET_WIDTH),
    .OPTION_DMMU_WAYS                 (OPTION_DMMU_WAYS),
    .OPTION_DCACHE_LIMIT_WIDTH        (OPTION_DCACHE_LIMIT_WIDTH),
    .OPTION_DMMU_CLEAR_ON_INIT        (OPTION_DMMU_CLEAR_ON_INIT)
  )
  u_dmmu
  (

    .cpu_clk                          (cpu_clk),
    .cpu_rst                          (cpu_rst),

    .lsu_s1_adv_i                     (lsu_s1_adv),
    .pipeline_flush_i                 (pipeline_flush_i),
    .s1o_dmmu_rdy_o                   (s1o_dmmu_rdy),
    .s1o_dmmu_upd_o                   (s1o_dmmu_upd),

    .dmmu_enable_i                    (dmmu_enable_i),
    .supervisor_mode_i                (supervisor_mode_i),
    .exec_op_lsu_store_i              (exec_op_lsu_store_i),
    .exec_op_lsu_load_i               (exec_op_lsu_load_i),
    .s1o_op_lsu_store_i               (s1o_op_lsu_store),
    .s1o_op_lsu_load_i                (s1o_op_lsu_load),
    .s1o_op_msync_i                   (s1o_op_msync),

    .virt_addr_s1t_i                  (s1t_virt_addr),
    .virt_addr_s1o_i                  (s1o_virt_addr),
    .phys_addr_o                      (s2t_phys_addr),

    .cache_inhibit_o                  (s2t_cache_inhibit),
    .tlb_miss_o                       (s2t_tlb_miss),
    .pagefault_o                      (s2t_pagefault),

    .tlb_reload_ack_i                 (1'b0),
    .tlb_reload_data_i                ({LSUOOW{1'b0}}),
    .tlb_reload_pagefault_clear_i     (1'b0),
    .tlb_reload_req_o                 (),
    .tlb_reload_busy_o                (),
    .tlb_reload_addr_o                (),
    .tlb_reload_pagefault_o           (),

    .spr_bus_addr_i                   (spr_bus_addr_i[15:0]),
    .spr_bus_we_i                     (spr_bus_we_i),
    .spr_bus_stb_i                    (spr_bus_stb_lsu),
    .spr_bus_dat_i                    (spr_bus_dat_i),
    .spr_bus_dat_o                    (spr_bus_dat_dmmu_o),
    .spr_bus_ack_o                    (spr_bus_ack_dmmu_o)
  );


  assign s2t_excepts_addr = s2t_tlb_miss | s2t_pagefault | s2t_align;










  assign dc_snoop2refill = dc_refill_allowed | dc_refill_state;




  assign dc_snoop2write = s2o_stna_req;

  or1k_marocchino_dcache
  #(
    .OPTION_OPERAND_WIDTH         (OPTION_OPERAND_WIDTH),
    .OPTION_DCACHE_BLOCK_WIDTH    (OPTION_DCACHE_BLOCK_WIDTH),
    .OPTION_DCACHE_SET_WIDTH      (OPTION_DCACHE_SET_WIDTH),
    .OPTION_DCACHE_WAYS           (OPTION_DCACHE_WAYS),
    .OPTION_DCACHE_LIMIT_WIDTH    (OPTION_DCACHE_LIMIT_WIDTH),
    .OPTION_DCACHE_SNOOP          (OPTION_DCACHE_SNOOP),
    .OPTION_DCACHE_CLEAR_ON_INIT  (OPTION_DCACHE_CLEAR_ON_INIT)
  )
  u_dcache
  (

    .cpu_clk                    (cpu_clk),
    .cpu_rst                    (cpu_rst),

    .lsu_s1_adv_i               (lsu_s1_adv),
    .lsu_s2_adv_i               (lsu_s2_adv),
    .pipeline_flush_i           (pipeline_flush_i),

    .dc_enable_i                (dc_enable_i),

    .s2o_excepts_addr_i         (s2o_excepts_addr),
    .dbus_err_i                 (dbus_err_i),


    .virt_addr_s1t_i            (s1t_virt_addr),
    .virt_addr_s1o_i            (s1o_virt_addr),
    .virt_addr_s2o_i            (s2o_virt_addr),
    .phys_addr_s2t_i            (s2t_phys_addr),
    .dmmu_cache_inhibit_i       (s2t_cache_inhibit),

    .s1o_op_lsu_load_i          (s1o_op_lsu_load),
    .dc_ack_read_o              (s2t_dc_ack_read),
    .dc_dat_o                   (s2t_dc_dat),

    .s1o_op_lsu_store_i         (s1o_op_lsu_store),
    .dbus_bsel_i                (s2o_bsel),
    .dbus_sdat_i                (s2o_sdat),
    .dc_dat_s2o_i               (s2o_dc_dat),
    .dc_store_allowed_i         (dc_store_allowed),



    .s1o_op_lsu_atomic_i        (s1o_op_lsu_atomic),

    .dc_refill_req_o            (s2t_dc_refill_req),
    .dc_refill_allowed_i        (dc_refill_allowed),
    .refill_first_o             (dc_refill_first),
    .phys_addr_s2o_i            (s2o_phys_addr),
    .dbus_dat_i                 (dbus_dat_i),
    .dbus_ack_i                 (dbus_ack_i),
    .dbus_burst_last_i          (dbus_burst_last_i),

    .dbus_read_req_o            (s2t_dbus_read_req),

    .snoop_adr_i                (snoop_adr_i),
    .snoop_en_i                 (snoop_en_i),
    .s2o_snoop_proc_o           (s2o_snoop_proc),
    .dc_snoop2refill_i          (dc_snoop2refill),
    .dc_snoop2write_i           (dc_snoop2write),

    .spr_bus_addr_i             (spr_bus_addr_i[15:0]),
    .spr_bus_we_i               (spr_bus_we_i),
    .spr_bus_stb_i              (spr_bus_stb_lsu),
    .spr_bus_dat_i              (spr_bus_dat_i),
    .spr_bus_dat_o              (spr_bus_dat_dc_o),
    .spr_bus_ack_o              (spr_bus_ack_dc_o)
  );













  wire sbuf_err = dbus_stna_cmd_o & dbus_err_i;

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      sbuf_err_o <= 1'b0;
    else if (sbuf_err)
      sbuf_err_o <= 1'b1;
  end






  always @(posedge cpu_clk) begin
    if (cpu_rst) begin
      dbus_req_o      <= 1'b0;
      dbus_lwa_cmd_o  <= 1'b0;
      dbus_stna_cmd_o <= 1'b0;
      dbus_swa_cmd_o  <= 1'b0;
      dbus_burst_o    <= 1'b0;
      dbus_state      <= DBUS_IDLE;
    end
    else begin
      (* parallel_case *)
      case (dbus_state)
        DBUS_IDLE: begin
          if (pipeline_flush_i)
            dbus_state <= DBUS_IDLE;
          else if (~sbuf_empty)
            dbus_state <= DBUS_SBUF_READ;
          else if (lsu_s2_adv)
            dbus_state <= DMEM_REQ;
        end

        DMEM_REQ: begin
          if (pipeline_flush_i) begin
            dbus_state <= DBUS_IDLE;
          end
          else if (~sbuf_empty) begin
            dbus_state <= DBUS_SBUF_READ;
          end
          else if (s2o_excepts_addr) begin
            dbus_state <= DBUS_IDLE;
          end
          else if (s2o_swa_req) begin
            dbus_req_o     <= ~dbus_req_o;
            dbus_swa_cmd_o <= 1'b1;
            dbus_state     <= DBUS_WRITE;
          end
          else if (s2o_dc_refill_req) begin
            dbus_req_o   <= ~dbus_req_o;
            dbus_burst_o <= 1'b1;
            dbus_state   <= DBUS_TO_REFILL;
          end
          else if (s2o_dbus_read_req) begin
            dbus_req_o     <= ~dbus_req_o;
            dbus_lwa_cmd_o <= s2o_lwa_req;
            dbus_state     <= DBUS_READ;
          end
          else if (~lsu_s2_adv) begin
            dbus_state <= DBUS_IDLE;
          end
        end

        DBUS_READ: begin
          if (dbus_err_i | dbus_ack_i) begin
            dbus_lwa_cmd_o <= 1'b0;
            dbus_state     <= DBUS_IDLE;
          end
        end

        DBUS_TO_REFILL: begin
          dbus_state <= DBUS_DC_REFILL;
        end

        DBUS_DC_REFILL: begin
          if (dbus_err_i | (dbus_ack_i & dbus_burst_last_i)) begin
            dbus_burst_o <= 1'b0;
            dbus_state   <= DBUS_IDLE;
          end
        end

        DBUS_SBUF_READ: begin
          dbus_req_o      <= ~dbus_req_o;
          dbus_stna_cmd_o <= 1'b1;
          dbus_state      <= DBUS_WRITE;
        end

        DBUS_WRITE: begin

          if (dbus_err_i | dbus_ack_i) begin
            dbus_stna_cmd_o <= 1'b0;
            dbus_swa_cmd_o  <= 1'b0;
          end

          if (dbus_err_i) begin
            dbus_state <= DBUS_IDLE;
          end
          else if (dbus_ack_i) begin
            dbus_state <= sbuf_empty ? DMEM_REQ : DBUS_SBUF_READ;
          end
        end

        default:;
      endcase
    end
  end


  always @(posedge cpu_clk) begin
    (* parallel_case *)
    case (dbus_state)
      DMEM_REQ: begin
        if (pipeline_flush_i | (~sbuf_empty) | s2o_excepts_addr) begin
        end
        else if (s2o_swa_req) begin
          dbus_bsel_o   <= s2o_bsel;
          dbus_adr_o    <= s2o_phys_addr;
          dbus_dat_o    <= s2o_sdat;
        end
        else if (s2o_dc_refill_req) begin
          dbus_bsel_o   <= 4'b1111;
          dbus_adr_o    <= s2o_phys_addr;
        end
        else if (s2o_dbus_read_req) begin
          dbus_bsel_o   <= s2o_bsel;
          dbus_adr_o    <= s2o_phys_addr;
        end
      end

      DBUS_SBUF_READ: begin

        dbus_bsel_o   <= sbuf_bsel;
        dbus_adr_o    <= sbuf_phys_addr;
        dbus_dat_o    <= sbuf_dat;


        sbuf_eear_o   <= sbuf_virt_addr;
        sbuf_epcr_o   <= sbuf_epcr;
      end

      default:;
    endcase
  end




  wire deassert_flush_r =
    dc_refill_allowed ? 1'b0 :
    dc_refill_state   ? (dbus_err_i | (dbus_ack_i & dbus_burst_last_i)) :
    dbus_read_state   ? (dbus_err_i | dbus_ack_i) : 1'b1;

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      flush_r <= 1'b0;
    else if (deassert_flush_r)
      flush_r <= 1'b0;
    else if (pipeline_flush_i)
      flush_r <= 1'b1;
  end







  assign sbuf_write = s2o_stna_req & (~sbuf_full) &
                      (~s2o_snoop_proc) &
                      (~wrbk_lsu_miss_r) & grant_wrbk_to_lsu_i;

  assign sbuf_we    = sbuf_write & (~s2o_excepts_addr) & (~pipeline_flush_i);


  wire   sbuf_ram_empty;
  wire   sbuf_oreg_rdy;
  assign sbuf_empty = sbuf_ram_empty & (~sbuf_oreg_rdy);

  localparam STORE_BUFFER_NUM_TAPS = (1 << OPTION_STORE_BUFFER_DEPTH_WIDTH);


  localparam STORE_BUFFER_DATA_WIDTH = (OPTION_OPERAND_WIDTH * 4) + (OPTION_OPERAND_WIDTH / 8);

  wire [STORE_BUFFER_DATA_WIDTH-1:0] sbuf_in;
  wire [STORE_BUFFER_DATA_WIDTH-1:0] sbuf_out;

  assign sbuf_in = {s2o_bsel, s2o_sdat, s2o_phys_addr, s2o_virt_addr, s2o_epcr};

  assign {sbuf_bsel, sbuf_dat, sbuf_phys_addr, sbuf_virt_addr, sbuf_epcr} = sbuf_out;


  or1k_marocchino_oreg_buff
  #(
    .NUM_TAPS         (STORE_BUFFER_NUM_TAPS),
    .DATA_WIDTH       (STORE_BUFFER_DATA_WIDTH),
    .RAM_EMPTY_FLAG   ("ENABLED"),
    .REG_RDY_FLAG     ("ENABLED")
  )
  u_store_buffer
  (

    .cpu_clk      (cpu_clk),

    .ini_rst      (cpu_rst),
    .ext_rst      (sbuf_err),

    .write_i      (sbuf_we),
    .read_i       (sbuf_read_state),

    .data_i       (sbuf_in),

    .ram_empty_o  (sbuf_ram_empty),

    .ram_full_o   (sbuf_full),

    .rdy_o        (sbuf_oreg_rdy),
    .data_o       (sbuf_out)
  );






  assign dbus_swa_ack = dbus_swa_cmd_o & dbus_ack_i;

  reg s2o_atomic_flag_set;
  reg s2o_atomic_flag_clear;

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl) begin
      s2o_atomic_flag_set   <= 1'b0;
      s2o_atomic_flag_clear <= 1'b0;
    end
    else if (dbus_swa_ack) begin
      s2o_atomic_flag_set   <=   dbus_atomic_flg_i;
      s2o_atomic_flag_clear <= (~dbus_atomic_flg_i);
    end
    else if (lsu_s3_adv) begin
      s2o_atomic_flag_set   <= 1'b0;
      s2o_atomic_flag_clear <= 1'b0;
    end
  end










  always @(posedge cpu_clk) begin
    if (lsu_s2_adv) begin

      s2o_epcr      <= s1o_sbuf_epcr;
      s2o_bsel      <= s2t_bsel;
      s2o_sdat      <= s2t_sdat;

      s2o_length    <= s1o_lsu_length;
      s2o_zext      <= s1o_lsu_zext;

      s2o_virt_addr <= s1o_virt_addr;
      s2o_phys_addr <= s2t_phys_addr;
    end
  end


  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      s2o_op_lsu_store <= 1'b0;
    else if (lsu_s2_adv)
      s2o_op_lsu_store <= s1o_op_lsu_store;
    else if (s3t_store_ack)
      s2o_op_lsu_store <= 1'b0;
  end



  wire deassert_s2o_stna_req = sbuf_write | pipeline_flush_i | s2o_excepts_addr;

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s2o_stna_req <= 1'b0;
    else if (deassert_s2o_stna_req)
      s2o_stna_req <= 1'b0;
    else if (lsu_s2_adv)
      s2o_stna_req <= s1o_op_lsu_store & (~s1o_op_lsu_atomic);
  end


  wire deassert_s2o_swa_req = dbus_swa_cmd_o ? (dbus_err_i | dbus_ack_i) :
                                               (pipeline_flush_i | s2o_excepts_addr);

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s2o_swa_req <= 1'b0;
    else if (deassert_s2o_swa_req)
      s2o_swa_req <= 1'b0;
    else if (lsu_s2_adv)
      s2o_swa_req <= s1o_op_lsu_store & s1o_op_lsu_atomic;
  end



  wire deassert_s2o_dc_refill_req =
    dc_refill_allowed ? 1'b0 :
      (dc_refill_state ? (dbus_err_i | (dbus_ack_i & dbus_burst_last_i)) :
                         (pipeline_flush_i | s2o_excepts_addr));

  always @(posedge cpu_clk) begin
    if (cpu_rst)
      s2o_dc_refill_req <= 1'b0;
    else if (deassert_s2o_dc_refill_req)
      s2o_dc_refill_req <= 1'b0;
    else if (lsu_s2_adv)
      s2o_dc_refill_req <= s2t_dc_refill_req;
  end

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      s2o_dc_ack_read <= 1'b0;
    else if (lsu_s2_adv)
      s2o_dc_ack_read <= s2t_dc_ack_read;
    else if (lsu_s3_adv)
      s2o_dc_ack_read <= 1'b0;
  end

  always @(posedge cpu_clk) begin
    if (lsu_s2_adv)
      s2o_dc_dat <= s2t_dc_dat;
  end



  wire deassert_s2o_dbus_read_req =
    dbus_read_state ? (dbus_err_i | dbus_ack_i) :
                      (pipeline_flush_i | s2o_excepts_addr);

  always @(posedge cpu_clk) begin
    if (cpu_rst) begin
      s2o_dbus_read_req <= 1'b0;
      s2o_lwa_req       <= 1'b0;
    end
    else if (deassert_s2o_dbus_read_req) begin
      s2o_dbus_read_req <= 1'b0;
      s2o_lwa_req       <= 1'b0;
    end
    else if (lsu_s2_adv) begin
      s2o_dbus_read_req <= s2t_dbus_read_req;
      s2o_lwa_req       <= s1o_op_lsu_load & s1o_op_lsu_atomic;
    end
  end

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      s3o_ls_ack <= 1'b0;
    else if (dbus_load_ack | s3t_store_ack)
      s3o_ls_ack <= 1'b1;
    else if (lsu_s3_adv)
      s3o_ls_ack <= 1'b0;
  end

  always @(posedge cpu_clk) begin
    if (dbus_load_ack)
      s2o_dbus_dat <= dbus_dat_i;
  end



  always @(posedge cpu_clk) begin
    if (flush_by_ctrl) begin

      s2o_tlb_miss       <= 1'b0;
      s2o_pagefault      <= 1'b0;
      s2o_align          <= 1'b0;

      s2o_dbus_err_nsbuf <= 1'b0;

      s2o_excepts_addr   <= 1'b0;
      s2o_excepts_any    <= 1'b0;
    end
    else if (lsu_s2_adv) begin

      s2o_tlb_miss       <= s2t_tlb_miss;
      s2o_pagefault      <= s2t_pagefault;
      s2o_align          <= s2t_align;

      s2o_excepts_addr   <= s2t_excepts_addr;
      s2o_excepts_any    <= s2t_excepts_addr;
    end
    else if (dbus_err_i) begin
      s2o_dbus_err_nsbuf <= s3t_dbus_err_nsbuf;
      s2o_excepts_any    <= 1'b1;
    end
  end



  assign lsu_s2_rdy  = s2o_dc_ack_read | s3o_ls_ack | s2o_excepts_any;

  assign lsu_valid_o = lsu_s2_rdy | wrbk_lsu_miss_r;

  always @(posedge cpu_clk) begin
    if (flush_by_ctrl)
      wrbk_lsu_miss_r <= 1'b0;
    else if (padv_wrbk_i & grant_wrbk_to_lsu_i)
      wrbk_lsu_miss_r <= 1'b0;
    else if (lsu_s3_adv)
      wrbk_lsu_miss_r <= 1'b1;
  end






  wire [LSUOOW-1:0] s3t_ldat = s2o_dc_ack_read ? s2o_dc_dat : s2o_dbus_dat;


  reg [LSUOOW-1:0] s3t_ldat_aligned;

  always @(s2o_virt_addr[1:0] or s3t_ldat) begin
    (* parallel_case *)
    case(s2o_virt_addr[1:0])
      2'b00: s3t_ldat_aligned = s3t_ldat;
      2'b01: s3t_ldat_aligned = {s3t_ldat[23:0],8'd0};
      2'b10: s3t_ldat_aligned = {s3t_ldat[15:0],16'd0};
      2'b11: s3t_ldat_aligned = {s3t_ldat[7:0],24'd0};
    endcase
  end


  reg [LSUOOW-1:0] s3t_ldat_extended;

  always @(s2o_zext or s2o_length or s3t_ldat_aligned) begin
    (* parallel_case *)
    case({s2o_zext, s2o_length})
      3'b100:  s3t_ldat_extended = {24'd0,s3t_ldat_aligned[31:24]};
      3'b101:  s3t_ldat_extended = {16'd0,s3t_ldat_aligned[31:16]};
      3'b000:  s3t_ldat_extended = {{24{s3t_ldat_aligned[31]}},
                                    s3t_ldat_aligned[31:24]};
      3'b001:  s3t_ldat_extended = {{16{s3t_ldat_aligned[31]}},
                                    s3t_ldat_aligned[31:16]};
      default: s3t_ldat_extended = s3t_ldat_aligned;
    endcase
  end




  reg  [LSUOOW-1:0] s3o_lsu_result;
  reg  [LSUOOW-1:0] s3o_lsu_except_addr;

  reg               s3o_atomic_flag_set;
  reg               s3o_atomic_flag_clear;

  reg               s3o_dbus_err_nsbuf;
  reg               s3o_pagefault;
  reg               s3o_tlb_miss;
  reg               s3o_align;

  reg               s3o_excepts_any;
  

  always @(posedge cpu_clk) begin
    if (lsu_s3_adv) begin

      s3o_lsu_result        <= s3t_ldat_extended;
      s3o_lsu_except_addr   <= s2o_virt_addr;

      s3o_atomic_flag_set   <= s2o_atomic_flag_set;
      s3o_atomic_flag_clear <= s2o_atomic_flag_clear;

      s3o_dbus_err_nsbuf    <= s2o_dbus_err_nsbuf;
      s3o_pagefault         <= s2o_pagefault;
      s3o_tlb_miss          <= s2o_tlb_miss;
      s3o_align             <= s2o_align;

      s3o_excepts_any       <= s2o_excepts_any;
    end
  end


  assign exec_an_except_lsu_o = (wrbk_lsu_miss_r ? s3o_excepts_any : s2o_excepts_any) & grant_wrbk_to_lsu_i;


  always @(posedge cpu_clk) begin
    if (padv_wrbk_i) begin
      if (grant_wrbk_to_lsu_i) begin
        wrbk_lsu_result_o      <= wrbk_lsu_miss_r ? s3o_lsu_result : s3t_ldat_extended;
        wrbk_lsu_except_addr_o <= wrbk_lsu_miss_r ? s3o_lsu_except_addr : s2o_virt_addr;
      end
      else begin
        wrbk_lsu_result_o      <= {LSUOOW{1'b0}};
      end
    end
  end


  always @(posedge cpu_clk) begin
    if (padv_wrbk_i & grant_wrbk_to_lsu_i) begin

      wrbk_atomic_flag_set_o   <= wrbk_lsu_miss_r ? s3o_atomic_flag_set   : s2o_atomic_flag_set;
      wrbk_atomic_flag_clear_o <= wrbk_lsu_miss_r ? s3o_atomic_flag_clear : s2o_atomic_flag_clear;

      wrbk_except_dbus_err_o   <= wrbk_lsu_miss_r ? s3o_dbus_err_nsbuf : s2o_dbus_err_nsbuf;
      wrbk_except_dpagefault_o <= wrbk_lsu_miss_r ? s3o_pagefault      : s2o_pagefault;
      wrbk_except_dtlb_miss_o  <= wrbk_lsu_miss_r ? s3o_tlb_miss       : s2o_tlb_miss;
      wrbk_except_dbus_align_o <= wrbk_lsu_miss_r ? s3o_align          : s2o_align;
    end
    else begin

      wrbk_atomic_flag_set_o   <= 1'b0;
      wrbk_atomic_flag_clear_o <= 1'b0;

      wrbk_except_dbus_err_o   <= 1'b0;
      wrbk_except_dpagefault_o <= 1'b0;
      wrbk_except_dtlb_miss_o  <= 1'b0;
      wrbk_except_dbus_align_o <= 1'b0;
    end
  end
  
endmodule