FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6355 Discussions

altera_onchip_flash

Altera_Forum
Honored Contributor II
1,070 Views

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) 

// -------------------------------------------------------------------
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
347 Views

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

// 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
0 Kudos
Altera_Forum
Honored Contributor II
347 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
347 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
347 Views

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.
0 Kudos
Reply