Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

altera_onchip_flash

The submodule "altera_onchip_flash_avmm_data_controller" in this IP has some problem.

WRITE_STATE, this FSM will unexpectedly been hold when I continues write data to flash.

It will cause status stock in write busy. csr_readdata[1:0] will equal to 2'b10 which means BUSY_WRITE for a long time.

It might be something wrong with its' state machine.

I guess the register "write_count " is overflow, so I replace "write_count != 0" to "write_count > 0" .

Finally, it work out.

// -------------------------------------------------------------------

// Avalon_MM data interface fsm - communicate between Avalon_MM and Flash IP (Write Operation)

// -------------------------------------------------------------------

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    // -------------------------------------------------------------------

    // Avalon_MM data interface fsm - communicate between Avalon_MM and Flash IP (Write Operation)

    // -------------------------------------------------------------------

    always @ (posedge clock) begin

    if (~reset_n_w) begin

    write_state <= WRITE_STATE_IDLE;

    write_wait <= 0;

    end

    else begin

    case (write_state)

    WRITE_STATE_IDLE: begin

    // reset all register

    write_count <= 0;

    write_timeout <= 1'b0;

    enable_drclk_neg_pos_write_reg <= 0;

    // check command

    if (avmm_write) begin

    if (~valid_csr_erase && ~is_erase_busy && ~is_read_busy) begin

    write_wait <= 1;

    // address legality check

    if (is_addr_writable && is_valid_write_burst_count) begin

    write_state <= WRITE_STATE_WRITE;

    write_count <= DATA_WIDTH[5:0];

    end

    else begin

    write_state <= WRITE_STATE_ERROR;

    write_wait <= 0;

    write_count <= 2;

    end

    end

    end

    end

    WRITE_STATE_WRITE: begin

    if (write_count > 0) begin//(write_count != 0) begin

    write_drclk_en <= 1;

    write_count <= write_count - 16'd1;

    end

    else begin

    enable_drclk_neg_pos_write_reg <= 1;

    write_drclk_en <= 0;

    write_count <= FLASH_BUSY_TIMEOUT_CYCLE_MAX_INDEX[15:0];

    write_state <= WRITE_STATE_WAIT_BUSY;

    end

    end

    WRITE_STATE_WAIT_BUSY: begin

    if (flash_busy_reg) begin

    write_count <= FLASH_WRITE_TIMEOUT_CYCLE_MAX_INDEX[15:0];

    write_state <= WRITE_STATE_WAIT_DONE;

    end

    else begin

    if (write_count > 0) //(write_count != 0)

    write_count <= write_count - 16'd1;

    else begin

    write_timeout <= 1'b1;

    write_count <= FLASH_RESET_CYCLE_MAX_INDEX[15:0];

    write_state <= WRITE_STATE_RESET;

    end

    end

    end

    WRITE_STATE_WAIT_DONE: begin

    if (~flash_busy) begin

    write_count <= FLASH_RESET_CYCLE_MAX_INDEX[5:0];

    write_state <= WRITE_STATE_RESET;

    end

    else begin

    if (write_count > 0) begin//(write_count != 0) begin

    write_count <= write_count - 16'd1;

    end

    else begin

    write_timeout <= 1'b1;

    write_count <= FLASH_RESET_CYCLE_MAX_INDEX[15:0];

    write_state <= WRITE_STATE_RESET;

    end

    end

    end

    WRITE_STATE_RESET: begin

    if (write_timeout) begin

    csr_status_w_pass <= 1'b0;

    end

    else begin

    csr_status_w_pass <= flash_sp_pass_reg;

    end

    if (write_count == 1) begin

    write_wait <= 0;

    end

    if (write_count > 0) begin//(write_count != 0) begin

    write_count <= write_count - 16'd1;

    end

    else begin

    write_state <= WRITE_STATE_IDLE;

    end

    end

    WRITE_STATE_ERROR: begin

    csr_status_w_pass <= 0;

    if (write_count == 1) begin

    write_wait <= 0;

    end

    if (write_count > 0) begin//(write_count != 0) begin

    write_count <= write_count - 16'd1;

    end

    else begin

    write_state <= WRITE_STATE_IDLE;

    end

    end

    default: begin

    write_state <= WRITE_STATE_IDLE;

    end

    endcase

    end

    end
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    i replace all (write_count != 0) to (write_count > 0) in the WRITE_STATE FSM

    WRITE_STATE_WRITE: begin

    if (write_count > 0) begin//(write_count != 0) begin

    write_drclk_en <= 1;

    write_count <= write_count - 16'd1;

    end

    else begin

    enable_drclk_neg_pos_write_reg <= 1;

    write_drclk_en <= 0;

    write_count <= FLASH_BUSY_TIMEOUT_CYCLE_MAX_INDEX[15:0];

    write_state <= WRITE_STATE_WAIT_BUSY;

    end

    end
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I do some simulation. Two type coding looks totally different on technology map.

    A type coding : "write_count != 0"

    The FSM will fail if there is a glitch on clock.

    B type coding : "write_count > 0"

    The FSM will be fine if there is a glitch on clock.

    By the way, my device is MAX10. I think MAX10's clock may have some problem.

    Where can i share these simulation file?

    Can anyone teach me why these two type coding make so much different on the end?

    Thanks a lot.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think you saw success with the modification you made because the actual problem is a timing error. You must have gotten lucky on the new compile to have it not lock up the internal logic. The real issue is a timing bug with the busy signal. The fix I put in place for the 14.1 standard release code was to change line 446 from:

    always @ (negedge reset_n or negedge is_busy or posedge flash_osc) begin

    to

    always @ (negedge reset_n or negedge is_busy or posedge clock) begin

    The problem was that the flash_busy_reg signal needed to get latched in the clock domain, not the flash_osc domain. When I made this change it resolved all the timing errors and also worked flawlessly. After I reported this to Altera they informed me that there is a patch to install on 14.1 that also fixes this.