data/full_repos/permissive/484553918/rtl/Memory_Ctrl.sv
1: b'%Error: data/full_repos/permissive/484553918/rtl/Memory_Ctrl.sv:10: Cannot find include file: memory_map.sv\n`include "memory_map.sv" \n         ^~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/484553918/rtl,data/full_repos/permissive/484553918/memory_map.sv\n             data/full_repos/permissive/484553918/rtl,data/full_repos/permissive/484553918/memory_map.sv.v\n             data/full_repos/permissive/484553918/rtl,data/full_repos/permissive/484553918/memory_map.sv.sv\n             memory_map.sv\n             memory_map.sv.v\n             memory_map.sv.sv\n             obj_dir/memory_map.sv\n             obj_dir/memory_map.sv.v\n             obj_dir/memory_map.sv.sv\n%Error: Exiting due to 1 error(s)\n'
module Memory_Ctrl(
  input             clk_i,
  input             rst_i,


  input             cpu_dBus_cmd_valid,
  output reg        cpu_dBus_cmd_ready,
  input             cpu_dBus_cmd_payload_wr,
  input[31:0]       cpu_dBus_cmd_payload_address,
  input[31:0]       cpu_dBus_cmd_payload_data,
  input[3:0]        cpu_dBus_cmd_payload_mask,
  input[2:0]        cpu_dBus_cmd_payload_size,
  output reg        cpu_dBus_rsp_valid,
  output[31:0]      cpu_dBus_rsp_payload_data,

  input             cpu_iBus_cmd_valid,
  output reg        cpu_iBus_cmd_ready,
  input[31:0]       cpu_iBus_cmd_payload_address,
  input[2:0]        cpu_iBus_cmd_payload_size,
  output reg        cpu_iBus_rsp_valid,
  output[31:0]      cpu_iBus_rsp_payload_data,


  output reg        csr_cyc_o,
  output reg        csr_stb_o,
  output reg [5:2]  csr_adr_o,
  output reg        csr_we_o,
  output reg [31:0] csr_dat_o,
  input  wire       csr_ack_i,
  input  wire       csr_stall_i,
  input  wire[31:0] csr_dat_i,


  output reg        sdram_rd,
  output reg        sdram_wr,
  input             sdram_rdy,
  output reg        sdram_ack,
  output reg[23:0]  sdram_addr_x16,
  output reg[15:0]  sdram_wdata,
  input[15:0]       sdram_rdata,
  output reg[1:0]   sdram_wmask,


  output[BOOTROM_ADDR_BITS-1:2] bootrom_addr_o,
  input[31:0]                   bootrom_data_i
);


localparam[2:0] CMD_SIZE_8BIT  = 3'd0;
localparam[2:0] CMD_SIZE_16BIT = 3'd1;
localparam[2:0] CMD_SIZE_32BIT = 3'd2;


enum { STATE_IDLE, STATE_FINISHED, STATE_SDRAM_WAIT, STATE_WAIT_BOOTROM, STATE_BURST_READ_BOOTROM, STATE_SDRAM_ACK, STATE_CSR } mem_state;

wire dBus_is_csr_addr =     addr_is_csr(cpu_dBus_cmd_payload_address[26:0]);
wire dBus_is_sdram_addr =   addr_is_sdram(cpu_dBus_cmd_payload_address[26:0]);
wire iBus_is_sdram_addr =   addr_is_sdram(cpu_iBus_cmd_payload_address[26:0]);

reg[1:0] waitstate_counter;
reg[2:0] words_remaining;


reg[31:0] mem_addr;
reg mem_is_wr;
reg[2:0] mem_size;

reg[31:0] mem_wdata;


enum { PURPOSE_I, PURPOSE_D } mem_purpose;

reg reading_bootrom;

always_comb begin

    cpu_dBus_cmd_ready = (mem_state == STATE_IDLE);
    cpu_iBus_cmd_ready = (mem_state == STATE_IDLE) && !cpu_dBus_cmd_valid;
end

always @ (posedge clk_i) begin
    sdram_ack <= 0;

    reading_bootrom <= 0;

    cpu_iBus_rsp_valid <= 0;
    cpu_dBus_rsp_valid <= 0;

    if (rst_i) begin
        mem_state <= STATE_IDLE;
        sdram_rd <= 0;
        sdram_wr <= 0;
        waitstate_counter <= 0;
    end else begin
        case (mem_state)
        STATE_IDLE: begin
            waitstate_counter <= 0;

            sdram_wmask <= 2'b11;















            if (cpu_dBus_cmd_valid) begin
              mem_addr <= cpu_dBus_cmd_payload_address;
              mem_is_wr <= cpu_dBus_cmd_payload_wr;
              mem_size <= cpu_dBus_cmd_payload_size;
              mem_wdata <= cpu_dBus_cmd_payload_data;

              if (dBus_is_csr_addr) begin
                mem_state <= STATE_CSR;

`ifdef VERBOSE_MEMCTL
                $display("begin CSR [%08Xh] is_wr=%d msk=%04b sz=%d wdata=%08X", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_wr, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size, cpu_dBus_cmd_payload_data);
`endif

                assert(cpu_dBus_cmd_payload_size == CMD_SIZE_32BIT);
              end else if (dBus_is_sdram_addr && cpu_dBus_cmd_payload_wr && cpu_dBus_cmd_payload_size == CMD_SIZE_32BIT) begin


`ifdef VERBOSE_MEMCTL
                $display("begin 32-bit write [%08Xh] <= %08Xh sz=%d", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_data, cpu_dBus_cmd_payload_size);
`endif

                mem_state <= STATE_SDRAM_WAIT;


                sdram_addr_x16 <= {cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:2], 1'b0};
                sdram_wdata <= cpu_dBus_cmd_payload_data[15:0];
                sdram_wr <= 1;
              end else if (cpu_dBus_cmd_payload_wr && cpu_dBus_cmd_payload_size == CMD_SIZE_8BIT) begin



                assert(cpu_dBus_cmd_payload_data[15:8] == cpu_dBus_cmd_payload_data[7:0]);

`ifdef VERBOSE_MEMCTL
                $display("begin 8-bit write [%08Xh] <= %02Xh msk=%04b", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_data[7:0], cpu_dBus_cmd_payload_mask);
`endif

                mem_state <= STATE_SDRAM_WAIT;

                sdram_addr_x16 <= cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:1];
                sdram_wdata <= cpu_dBus_cmd_payload_data[15:0];
                sdram_wr <= 1;
                sdram_wmask <= cpu_dBus_cmd_payload_mask[1:0] | cpu_dBus_cmd_payload_mask[3:2];
              end else if (cpu_dBus_cmd_payload_wr && cpu_dBus_cmd_payload_size == CMD_SIZE_16BIT) begin


`ifdef VERBOSE_MEMCTL
                $display("begin 16-bit write [%08Xh] <= %04Xh", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_data[15:0]);
`endif

                mem_state <= STATE_SDRAM_WAIT;

                sdram_addr_x16 <= cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:1];
                sdram_wdata <= cpu_dBus_cmd_payload_data[15:0];
                sdram_wr <= 1;
              end else if (!cpu_dBus_cmd_payload_wr) begin

                if (cpu_dBus_cmd_payload_size >= CMD_SIZE_32BIT) begin
                  words_remaining <= (1 << (cpu_dBus_cmd_payload_size - 2)) - 1;
                end else begin
                  words_remaining <= 0;
                end


                if (dBus_is_sdram_addr) begin
`ifdef VERBOSE_MEMCTL
                    $display("begin 32-bit read [%08Xh] msk=%04b sz=%d", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size);
`endif


                    sdram_addr_x16 <= {cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:2], 1'b0};
                    sdram_rd <= 1;

                    mem_state <= STATE_SDRAM_WAIT;
                end else begin


`ifdef VERBOSE_MEMCTL
                    $display("begin ROM read [%08Xh] msk=%04b sz=%d", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size);
`endif

                    mem_state <= STATE_WAIT_BOOTROM;

                    mem_purpose <= PURPOSE_D;
                end
              end else begin
                $display("begin INVALID OP [%08Xh] is_wr=%d msk=%04b sz=%d", cpu_dBus_cmd_payload_address,
                    cpu_dBus_cmd_payload_wr, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size);
              end

              mem_purpose <= PURPOSE_D;
            end else if (cpu_iBus_cmd_valid) begin



                mem_addr <= cpu_iBus_cmd_payload_address;
                mem_is_wr <= 0;

                if (iBus_is_sdram_addr) begin
`ifdef VERBOSE_MEMCTL
                    $display("begin 32-bit SDRAM read via I-bus [%08Xh] sz=%d", cpu_iBus_cmd_payload_address, cpu_iBus_cmd_payload_size);
`endif


                    sdram_addr_x16 <= {cpu_iBus_cmd_payload_address[$left(sdram_addr_x16) + 1:2], 1'b0};
                    sdram_rd <= 1;

                    mem_state <= STATE_SDRAM_WAIT;
                end else begin
`ifdef VERBOSE_MEMCTL
                    $display("begin 32-bit burst ROM read via I-bus [%08Xh]", cpu_iBus_cmd_payload_address);
`endif

                    mem_addr <= cpu_iBus_cmd_payload_address;
                    mem_state <= STATE_WAIT_BOOTROM;
                end

                mem_purpose <= PURPOSE_I;
                words_remaining <= (1 << (cpu_iBus_cmd_payload_size - 2)) - 1;
            end
        end

        STATE_SDRAM_WAIT: begin


            if (waitstate_counter < 2) begin
                waitstate_counter <= waitstate_counter + 1;
            end else if (sdram_addr_x16[0] == 0 && sdram_ack == 1) begin


                if (mem_is_wr) begin
                    sdram_wr <= 1;
                end else begin
                    sdram_rd <= 1;
                end

                sdram_ack <= 0;


                sdram_addr_x16 <= {mem_addr[$left(sdram_addr_x16) + 1:2], 1'b1};
                sdram_wdata <= mem_wdata[31:16];

                waitstate_counter <= 0;
            end else if (sdram_rdy) begin


                if (mem_is_wr) begin
                  if (mem_size == CMD_SIZE_32BIT) begin


                    if (sdram_addr_x16[0] == 0 && sdram_ack == 0) begin
                        sdram_wr <= 0;
                        sdram_ack <= 1;

                        mem_state <= STATE_SDRAM_WAIT;
                    end else if (sdram_addr_x16[0] == 1) begin

                        sdram_rd <= 0;
                        sdram_wr <= 0;
                        mem_state <= STATE_FINISHED;
                    end
                  end else begin


                    sdram_rd <= 0;
                    sdram_wr <= 0;
                    mem_state <= STATE_FINISHED;

                  end
                end else begin


                    if (sdram_addr_x16[0] == 0 && sdram_ack == 0) begin



                        sdram_rd <= 0;
                        sdram_ack <= 1;

                        mem_state <= STATE_SDRAM_WAIT;
                    end else if (sdram_addr_x16[0] == 1) begin



                        sdram_rd <= 0;
                        sdram_wr <= 0;

                        if (mem_purpose == PURPOSE_I) begin
                            cpu_iBus_rsp_valid <= 1'b1;
                        end else begin
                            cpu_dBus_rsp_valid <= 1;
                        end

                        if (words_remaining == 0) begin
                            mem_state <= STATE_FINISHED;
                        end else begin
                            mem_state <= STATE_SDRAM_ACK;

                            sdram_ack <= 1;
                        end

                        waitstate_counter <= 0;

                        mem_addr <= mem_addr + 4;
                        words_remaining <= words_remaining - 1;
                    end
                end
            end

        end

        STATE_SDRAM_ACK: begin

          sdram_addr_x16 <= {mem_addr[$left(sdram_addr_x16) + 1:2], 1'b0};
          sdram_rd <= 1;
          mem_state <= STATE_SDRAM_WAIT;
          sdram_ack <= 0;
        end

        STATE_FINISHED: begin
            mem_state <= STATE_IDLE;
            sdram_ack <= 1;
        end



        STATE_WAIT_BOOTROM: begin
            mem_addr <= mem_addr + 4;
            mem_state <= STATE_BURST_READ_BOOTROM;
        end

        STATE_BURST_READ_BOOTROM: begin
            if (mem_purpose == PURPOSE_I) begin
                cpu_iBus_rsp_valid <= 1'b1;
            end else begin
                cpu_dBus_rsp_valid <= 1;
            end

            reading_bootrom <= 1;

            if (words_remaining == 0) begin
                mem_state <= STATE_FINISHED;
            end else begin
                mem_state <= STATE_BURST_READ_BOOTROM;
            end

            mem_addr <= mem_addr + 4;
            words_remaining <= words_remaining - 1;
        end

        STATE_CSR: begin
            if (csr_ack_i) begin

                cpu_dBus_rsp_valid <= !csr_we_o;

                mem_state <= STATE_FINISHED;
            end
        end
        endcase
    end

    if (reading_bootrom) begin
`ifdef VERBOSE_MEMCTL
      $display("  ROM read => %08X", bootrom_data_i);
`endif
    end
end


always @ (posedge clk_i, posedge rst_i) begin
    if (rst_i) begin
        csr_cyc_o <= '0;
        csr_stb_o <= '0;
        csr_adr_o <= '0;
        csr_we_o <= '0;
        csr_dat_o <= '0;
    end else begin
        if (mem_state == STATE_IDLE) begin
            if (cpu_dBus_cmd_valid && dBus_is_csr_addr) begin
                csr_cyc_o <= '1;
                csr_stb_o <= '1;
            end


            csr_adr_o[$left(csr_adr_o):2] <= cpu_dBus_cmd_payload_address[$left(csr_adr_o):2];

            csr_we_o <= cpu_dBus_cmd_payload_wr;
            csr_dat_o <= cpu_dBus_cmd_payload_data;
        end else if (mem_state == STATE_CSR) begin
            if (!csr_stall_i) csr_stb_o <= '0;
            if (csr_ack_i) csr_cyc_o <= '0;
        end
    end
end

reg[15:0] sdram_rdata_low;
reg[31:0] cpu_rdata;

always_ff @ (posedge clk_i, posedge rst_i) begin
    if (rst_i) begin
        sdram_rdata_low <= '0;
        cpu_rdata <= '0;
    end else begin


        cpu_rdata <= 'x;

        if (csr_ack_i) begin
            cpu_rdata <= csr_dat_i;
        end

        if (mem_state == STATE_BURST_READ_BOOTROM) begin
            cpu_rdata <= bootrom_data_i;
        end

        if (mem_state == STATE_SDRAM_WAIT) begin

            if (waitstate_counter >= 2 && !(sdram_addr_x16[0] == 0 && sdram_ack == 1) && sdram_rdy && !mem_is_wr) begin
                if (sdram_addr_x16[0] == 0 && sdram_ack == 0) begin
                    sdram_rdata_low <= sdram_rdata;
                end else if (sdram_addr_x16[0] == 1) begin
`ifdef VERBOSE_MEMCTL
                    $display("  finished 32-bit SDRAM read [%08X] => %08X", mem_addr, {sdram_rdata, sdram_rdata_low});
`endif

                    cpu_rdata <= {sdram_rdata, sdram_rdata_low};
                end
            end
        end
    end
end

assign bootrom_addr_o[$left(bootrom_addr_o):2] = mem_addr[$left(bootrom_addr_o):2];

assign cpu_dBus_rsp_payload_data = cpu_rdata;
assign cpu_iBus_rsp_payload_data = cpu_rdata;

endmodule
module Memory_Ctrl(
  input             clk_i,
  input             rst_i,


  input             cpu_dBus_cmd_valid,
  output reg        cpu_dBus_cmd_ready,
  input             cpu_dBus_cmd_payload_wr,
  input[31:0]       cpu_dBus_cmd_payload_address,
  input[31:0]       cpu_dBus_cmd_payload_data,
  input[3:0]        cpu_dBus_cmd_payload_mask,
  input[2:0]        cpu_dBus_cmd_payload_size,
  output reg        cpu_dBus_rsp_valid,
  output[31:0]      cpu_dBus_rsp_payload_data,

  input             cpu_iBus_cmd_valid,
  output reg        cpu_iBus_cmd_ready,
  input[31:0]       cpu_iBus_cmd_payload_address,
  input[2:0]        cpu_iBus_cmd_payload_size,
  output reg        cpu_iBus_rsp_valid,
  output[31:0]      cpu_iBus_rsp_payload_data,


  output reg        csr_cyc_o,
  output reg        csr_stb_o,
  output reg [5:2]  csr_adr_o,
  output reg        csr_we_o,
  output reg [31:0] csr_dat_o,
  input  wire       csr_ack_i,
  input  wire       csr_stall_i,
  input  wire[31:0] csr_dat_i,


  output reg        sdram_rd,
  output reg        sdram_wr,
  input             sdram_rdy,
  output reg        sdram_ack,
  output reg[23:0]  sdram_addr_x16,
  output reg[15:0]  sdram_wdata,
  input[15:0]       sdram_rdata,
  output reg[1:0]   sdram_wmask,


  output[BOOTROM_ADDR_BITS-1:2] bootrom_addr_o,
  input[31:0]                   bootrom_data_i
);



localparam[2:0] CMD_SIZE_8BIT  = 3'd0;
localparam[2:0] CMD_SIZE_16BIT = 3'd1;
localparam[2:0] CMD_SIZE_32BIT = 3'd2;


enum { STATE_IDLE, STATE_FINISHED, STATE_SDRAM_WAIT, STATE_WAIT_BOOTROM, STATE_BURST_READ_BOOTROM, STATE_SDRAM_ACK, STATE_CSR } mem_state;

wire dBus_is_csr_addr =     addr_is_csr(cpu_dBus_cmd_payload_address[26:0]);
wire dBus_is_sdram_addr =   addr_is_sdram(cpu_dBus_cmd_payload_address[26:0]);
wire iBus_is_sdram_addr =   addr_is_sdram(cpu_iBus_cmd_payload_address[26:0]);

reg[1:0] waitstate_counter;
reg[2:0] words_remaining;


reg[31:0] mem_addr;
reg mem_is_wr;
reg[2:0] mem_size;

reg[31:0] mem_wdata;


enum { PURPOSE_I, PURPOSE_D } mem_purpose;

reg reading_bootrom;

always_comb begin

    cpu_dBus_cmd_ready = (mem_state == STATE_IDLE);
    cpu_iBus_cmd_ready = (mem_state == STATE_IDLE) && !cpu_dBus_cmd_valid;
end

always @ (posedge clk_i) begin
    sdram_ack <= 0;

    reading_bootrom <= 0;

    cpu_iBus_rsp_valid <= 0;
    cpu_dBus_rsp_valid <= 0;

    if (rst_i) begin
        mem_state <= STATE_IDLE;
        sdram_rd <= 0;
        sdram_wr <= 0;
        waitstate_counter <= 0;
    end else begin
        case (mem_state)
        STATE_IDLE: begin
            waitstate_counter <= 0;

            sdram_wmask <= 2'b11;















            if (cpu_dBus_cmd_valid) begin
              mem_addr <= cpu_dBus_cmd_payload_address;
              mem_is_wr <= cpu_dBus_cmd_payload_wr;
              mem_size <= cpu_dBus_cmd_payload_size;
              mem_wdata <= cpu_dBus_cmd_payload_data;

              if (dBus_is_csr_addr) begin
                mem_state <= STATE_CSR;

`ifdef VERBOSE_MEMCTL
                $display("begin CSR [%08Xh] is_wr=%d msk=%04b sz=%d wdata=%08X", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_wr, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size, cpu_dBus_cmd_payload_data);
`endif

                assert(cpu_dBus_cmd_payload_size == CMD_SIZE_32BIT);
              end else if (dBus_is_sdram_addr && cpu_dBus_cmd_payload_wr && cpu_dBus_cmd_payload_size == CMD_SIZE_32BIT) begin


`ifdef VERBOSE_MEMCTL
                $display("begin 32-bit write [%08Xh] <= %08Xh sz=%d", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_data, cpu_dBus_cmd_payload_size);
`endif

                mem_state <= STATE_SDRAM_WAIT;


                sdram_addr_x16 <= {cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:2], 1'b0};
                sdram_wdata <= cpu_dBus_cmd_payload_data[15:0];
                sdram_wr <= 1;
              end else if (cpu_dBus_cmd_payload_wr && cpu_dBus_cmd_payload_size == CMD_SIZE_8BIT) begin



                assert(cpu_dBus_cmd_payload_data[15:8] == cpu_dBus_cmd_payload_data[7:0]);

`ifdef VERBOSE_MEMCTL
                $display("begin 8-bit write [%08Xh] <= %02Xh msk=%04b", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_data[7:0], cpu_dBus_cmd_payload_mask);
`endif

                mem_state <= STATE_SDRAM_WAIT;

                sdram_addr_x16 <= cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:1];
                sdram_wdata <= cpu_dBus_cmd_payload_data[15:0];
                sdram_wr <= 1;
                sdram_wmask <= cpu_dBus_cmd_payload_mask[1:0] | cpu_dBus_cmd_payload_mask[3:2];
              end else if (cpu_dBus_cmd_payload_wr && cpu_dBus_cmd_payload_size == CMD_SIZE_16BIT) begin


`ifdef VERBOSE_MEMCTL
                $display("begin 16-bit write [%08Xh] <= %04Xh", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_data[15:0]);
`endif

                mem_state <= STATE_SDRAM_WAIT;

                sdram_addr_x16 <= cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:1];
                sdram_wdata <= cpu_dBus_cmd_payload_data[15:0];
                sdram_wr <= 1;
              end else if (!cpu_dBus_cmd_payload_wr) begin

                if (cpu_dBus_cmd_payload_size >= CMD_SIZE_32BIT) begin
                  words_remaining <= (1 << (cpu_dBus_cmd_payload_size - 2)) - 1;
                end else begin
                  words_remaining <= 0;
                end


                if (dBus_is_sdram_addr) begin
`ifdef VERBOSE_MEMCTL
                    $display("begin 32-bit read [%08Xh] msk=%04b sz=%d", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size);
`endif


                    sdram_addr_x16 <= {cpu_dBus_cmd_payload_address[$left(sdram_addr_x16) + 1:2], 1'b0};
                    sdram_rd <= 1;

                    mem_state <= STATE_SDRAM_WAIT;
                end else begin


`ifdef VERBOSE_MEMCTL
                    $display("begin ROM read [%08Xh] msk=%04b sz=%d", cpu_dBus_cmd_payload_address, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size);
`endif

                    mem_state <= STATE_WAIT_BOOTROM;

                    mem_purpose <= PURPOSE_D;
                end
              end else begin
                $display("begin INVALID OP [%08Xh] is_wr=%d msk=%04b sz=%d", cpu_dBus_cmd_payload_address,
                    cpu_dBus_cmd_payload_wr, cpu_dBus_cmd_payload_mask, cpu_dBus_cmd_payload_size);
              end

              mem_purpose <= PURPOSE_D;
            end else if (cpu_iBus_cmd_valid) begin



                mem_addr <= cpu_iBus_cmd_payload_address;
                mem_is_wr <= 0;

                if (iBus_is_sdram_addr) begin
`ifdef VERBOSE_MEMCTL
                    $display("begin 32-bit SDRAM read via I-bus [%08Xh] sz=%d", cpu_iBus_cmd_payload_address, cpu_iBus_cmd_payload_size);
`endif


                    sdram_addr_x16 <= {cpu_iBus_cmd_payload_address[$left(sdram_addr_x16) + 1:2], 1'b0};
                    sdram_rd <= 1;

                    mem_state <= STATE_SDRAM_WAIT;
                end else begin
`ifdef VERBOSE_MEMCTL
                    $display("begin 32-bit burst ROM read via I-bus [%08Xh]", cpu_iBus_cmd_payload_address);
`endif

                    mem_addr <= cpu_iBus_cmd_payload_address;
                    mem_state <= STATE_WAIT_BOOTROM;
                end

                mem_purpose <= PURPOSE_I;
                words_remaining <= (1 << (cpu_iBus_cmd_payload_size - 2)) - 1;
            end
        end

        STATE_SDRAM_WAIT: begin


            if (waitstate_counter < 2) begin
                waitstate_counter <= waitstate_counter + 1;
            end else if (sdram_addr_x16[0] == 0 && sdram_ack == 1) begin


                if (mem_is_wr) begin
                    sdram_wr <= 1;
                end else begin
                    sdram_rd <= 1;
                end

                sdram_ack <= 0;


                sdram_addr_x16 <= {mem_addr[$left(sdram_addr_x16) + 1:2], 1'b1};
                sdram_wdata <= mem_wdata[31:16];

                waitstate_counter <= 0;
            end else if (sdram_rdy) begin


                if (mem_is_wr) begin
                  if (mem_size == CMD_SIZE_32BIT) begin


                    if (sdram_addr_x16[0] == 0 && sdram_ack == 0) begin
                        sdram_wr <= 0;
                        sdram_ack <= 1;

                        mem_state <= STATE_SDRAM_WAIT;
                    end else if (sdram_addr_x16[0] == 1) begin

                        sdram_rd <= 0;
                        sdram_wr <= 0;
                        mem_state <= STATE_FINISHED;
                    end
                  end else begin


                    sdram_rd <= 0;
                    sdram_wr <= 0;
                    mem_state <= STATE_FINISHED;

                  end
                end else begin


                    if (sdram_addr_x16[0] == 0 && sdram_ack == 0) begin



                        sdram_rd <= 0;
                        sdram_ack <= 1;

                        mem_state <= STATE_SDRAM_WAIT;
                    end else if (sdram_addr_x16[0] == 1) begin



                        sdram_rd <= 0;
                        sdram_wr <= 0;

                        if (mem_purpose == PURPOSE_I) begin
                            cpu_iBus_rsp_valid <= 1'b1;
                        end else begin
                            cpu_dBus_rsp_valid <= 1;
                        end

                        if (words_remaining == 0) begin
                            mem_state <= STATE_FINISHED;
                        end else begin
                            mem_state <= STATE_SDRAM_ACK;

                            sdram_ack <= 1;
                        end

                        waitstate_counter <= 0;

                        mem_addr <= mem_addr + 4;
                        words_remaining <= words_remaining - 1;
                    end
                end
            end

        end

        STATE_SDRAM_ACK: begin

          sdram_addr_x16 <= {mem_addr[$left(sdram_addr_x16) + 1:2], 1'b0};
          sdram_rd <= 1;
          mem_state <= STATE_SDRAM_WAIT;
          sdram_ack <= 0;
        end

        STATE_FINISHED: begin
            mem_state <= STATE_IDLE;
            sdram_ack <= 1;
        end



        STATE_WAIT_BOOTROM: begin
            mem_addr <= mem_addr + 4;
            mem_state <= STATE_BURST_READ_BOOTROM;
        end

        STATE_BURST_READ_BOOTROM: begin
            if (mem_purpose == PURPOSE_I) begin
                cpu_iBus_rsp_valid <= 1'b1;
            end else begin
                cpu_dBus_rsp_valid <= 1;
            end

            reading_bootrom <= 1;

            if (words_remaining == 0) begin
                mem_state <= STATE_FINISHED;
            end else begin
                mem_state <= STATE_BURST_READ_BOOTROM;
            end

            mem_addr <= mem_addr + 4;
            words_remaining <= words_remaining - 1;
        end

        STATE_CSR: begin
            if (csr_ack_i) begin

                cpu_dBus_rsp_valid <= !csr_we_o;

                mem_state <= STATE_FINISHED;
            end
        end
        endcase
    end

    if (reading_bootrom) begin
`ifdef VERBOSE_MEMCTL
      $display("  ROM read => %08X", bootrom_data_i);
`endif
    end
end


always @ (posedge clk_i, posedge rst_i) begin
    if (rst_i) begin
        csr_cyc_o <= '0;
        csr_stb_o <= '0;
        csr_adr_o <= '0;
        csr_we_o <= '0;
        csr_dat_o <= '0;
    end else begin
        if (mem_state == STATE_IDLE) begin
            if (cpu_dBus_cmd_valid && dBus_is_csr_addr) begin
                csr_cyc_o <= '1;
                csr_stb_o <= '1;
            end


            csr_adr_o[$left(csr_adr_o):2] <= cpu_dBus_cmd_payload_address[$left(csr_adr_o):2];

            csr_we_o <= cpu_dBus_cmd_payload_wr;
            csr_dat_o <= cpu_dBus_cmd_payload_data;
        end else if (mem_state == STATE_CSR) begin
            if (!csr_stall_i) csr_stb_o <= '0;
            if (csr_ack_i) csr_cyc_o <= '0;
        end
    end
end

reg[15:0] sdram_rdata_low;
reg[31:0] cpu_rdata;

always_ff @ (posedge clk_i, posedge rst_i) begin
    if (rst_i) begin
        sdram_rdata_low <= '0;
        cpu_rdata <= '0;
    end else begin


        cpu_rdata <= 'x;

        if (csr_ack_i) begin
            cpu_rdata <= csr_dat_i;
        end

        if (mem_state == STATE_BURST_READ_BOOTROM) begin
            cpu_rdata <= bootrom_data_i;
        end

        if (mem_state == STATE_SDRAM_WAIT) begin

            if (waitstate_counter >= 2 && !(sdram_addr_x16[0] == 0 && sdram_ack == 1) && sdram_rdy && !mem_is_wr) begin
                if (sdram_addr_x16[0] == 0 && sdram_ack == 0) begin
                    sdram_rdata_low <= sdram_rdata;
                end else if (sdram_addr_x16[0] == 1) begin
`ifdef VERBOSE_MEMCTL
                    $display("  finished 32-bit SDRAM read [%08X] => %08X", mem_addr, {sdram_rdata, sdram_rdata_low});
`endif

                    cpu_rdata <= {sdram_rdata, sdram_rdata_low};
                end
            end
        end
    end
end

assign bootrom_addr_o[$left(bootrom_addr_o):2] = mem_addr[$left(bootrom_addr_o):2];

assign cpu_dBus_rsp_payload_data = cpu_rdata;
assign cpu_iBus_rsp_payload_data = cpu_rdata;

endmodule