Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Honored Contributor I
810 Views

Reading/Writing from/to 16 Mbit Flash RAM (S29AL016M10TAI020)

Hi, I am trying to interact with a 16 Mbit Flash RAM (S29AL016M10TAI020) in Verilog, but I have some problems. This flash supports byte or word mode, 

 

I have studied the datasheet and I have tried to implement a flash controller in byte mode. 

 

Question: is it necessary to do the Word/Byte Program Command Sequence first (a four cycle operation)? Also, what is the Program Address and the Program Data that I must specify (4th clock cycle of command sequence)? 

 

Also i need some help with the code. I want to read data from the flash so i execute the Word/Byte Program Command Sequence first and then start reading. Am i doing sth wrong? 

 

module flash_controller(clock, reset_n, mem_mode, mem_ce_n, mem_rst_n, mem_oe_n, mem_we_n, address, data, flash_data); // Controller inputs: clock of 10Mhz and negedge reset input clock, reset_n; // Flash Signals output mem_mode, mem_ce_n, mem_rst_n, mem_oe_n, mem_we_n; // in flash they are inputs output address; // in flash it is input inout data; // in flash it is inout // Controller output to check the read data output flash_data; wire nclock; reg cycles; reg write_data; reg read_data; reg mem_rst_n, mem_oe_n, mem_we_n; reg address; assign mem_mode = 1'b0; // to select byte mode assign mem_ce_n = 1'b0; // always at 0 so the chip is enabled // if mem_oe_n == H then write data else Z assign data = (mem_oe_n) ? write_data : 8'bZ; assign flash_data = read_data; // ADDRESSES are latched on the NEGEDGE of mem_we_n // DATA are latched on the POSEDGE of mem_we_n assign nclock = !clock; // clock cycles 1-4: flash programming at byte mode (is it necessary??): // cc1: write AA at AAA // cc2: write 55 at 555 // cc3: write A0 at AAA // cc4: write Program Data at Program Address (whats this?) // clock cycles >= 5: flash reading and showing the data at the output via flash data always @ (posedge clock or posedge nclock or negedge reset_n) begin if (!reset_n) // RESET begin cycles = 3'd0; mem_rst_n = 1'b0; address = 21'd0; end else if (clock) // CLOCK POSEDGE begin if (cycles < 3'd4) // clock cycles 1-4: flash programming begin mem_we_n = 1'b0; // do the negedge of mem_we_n to latch the address mem_oe_n = 1'b1; // output disable mem_rst_n = 1'b1; // no reset case (cycles) 3'd0: begin address = 21'b000000000101010101010; // AAA write_data = 8'b10101010; // AA end 3'd1: begin address = 21'b000000000010101010101; // 555 write_data = 8'b01010101; // 55 end 3'd2: begin address = 21'b000000000101010101010; // AAA write_data = 8'b10100000; // A0 end 3'd3: begin address = 21'd0; // ??? what should I put here, it says the program address write_data = 8'd10; // ??? what should I put here, it says the program data end endcase cycles = cycles + 1; end else // clock cycles >= 5: flash reading begin mem_we_n = 1'b0; // do the negedge of mem_we_n to latch the address mem_oe_n = 1'b0; // output enable address = address + 1; read_data = data; end end else // CLOCK NEGEDGE begin mem_we_n = 1'b1; // do the posedge of mem_we_n to latch the data (write or read) end end endmodule  

 

 

Thanks very much in advance. Any help is appreciated :)
0 Kudos
4 Replies
Highlighted
Honored Contributor I
11 Views

You need to Program code 1st to 4th bus cycle. You can specify data, addr in 4th cycle. 

1st: Addr:AAA, Data:AA 

2nd:Addr:555, Data:55 

3rd:Addr:AAA, Data:A0 

4th: Addr, Data  

For read sequence, just use Addr,Data. I don't think you need to add write command.
0 Kudos
Highlighted
Honored Contributor I
11 Views

You only need to issue the 3 (or more) cycle 'unlock' sequence when you're writing/erasing a FLASH device but not when you're reading from it. Any operation that changes the contents must be preceded by the unlock sequence (unless you've already activated the unlock bypass - I suggest you get something working before experimenting with that). There are some other special commands that require unlock codes. However, you don't need to unlock the device to read from it, just present the address and assert CE# & OE# (WE# de-asserted). 

 

If you haven't already, I suggest you start by looking to implement a command like 'Manufacturer ID' to prove your basic code sequence. This should return you a known, fixed value which, I hope, should help consolidate the basic timings your code generates. 

 

Cheers, 

Alex
0 Kudos
Highlighted
Honored Contributor I
11 Views

Thank you very much for your response. I have tried to implement a smal FSM to do the reading operation. Actually, in my system I only need to read from the flash and not to write. 

 

I have attached the code in the next reply.
0 Kudos
Highlighted
Honored Contributor I
11 Views

Am I doing something wrong? Thnx again :) 

 

module Flash_Ctrl(clock, reset_n, read, data_out, BYTEn, RESETn, CEn, WEn, OEn, A, D); // System Signals input clock; // posedge clock: 100 MHz input reset_n; // negative reset input read; // read flag: 1 -> read, 0 -> idle output data_out; // data read from Flash /* Flash Memory Operations ---------------------------------------------------------------------------- |Operation | BYTEn | RESETn | CEn | WEn | OEn | A | D | ---------------------------------------------------------------------------- | Read | 0 | 1 | 0 | 1 | 0 | <address> | <mem> | | Inactive | 0 | 1 | 0 | 1 | 1 | XX...X | ZZ...Z | | Reset | 0 | 0 | X | X | X | XX...X | ZZ...Z | ---------------------------------------------------------------------------- */ // Flash Signals output BYTEn, RESETn, CEn, WEn, OEn; output A; input D; // Registers reg CEn, OEn; reg A; reg data_out; // ================================================================ // ----------------------- Flash Controller ----------------------- // ================================================================ // Flash States reg flash_state; parameter IDLE = 0, READ_START = 1, READ_1 = 2, READ_2 = 3, READ_3 = 4, READ_END = 5; // Wire Flash Signals assign RESETn = reset_n; // reset according to system reset assign BYTEn = 1'b0; // byte mode assign WEn = 1'b1; // always read mode // Address Access Time wire tAA; // Address to read from reg address; // Flash State Machine always @(posedge clock or negedge reset_n) begin if (!reset_n) // Reset begin CEn <= 1'b1; OEn <= 1'b1; A <= 21'b0; flash_state <= IDLE; data_out <= 8'bF0; address <= 21'b0; end else // Clock begin CEn <= 1'b1; OEn <= 1'b1; A <= A; address <= address; // Examining flash states case (flash_state) // Flash = IDLE IDLE: begin if (read) // read operation should start flash_state <= READ_START; else flash_state <= IDLE; end // Flash = READ_START READ_START: begin CEn <= 1'b0; A <= address; flash_state <= READ_1; // tAS = 0 ns end // Flash = READ_1 READ_1: begin CEn <= 1'b0; OEn <= 1'b0; A <= inner_A; if (tAA) // tAA = 100 ns flash_state <= READ_2; else flash_state <= READ_1; end // Flash = READ_2 READ_2: begin data_out <= D; // read the data flash_state <= READ_3; end // Flash = READ_3 READ_3: begin flash_state <= READ_END; address <= address + 1; // next address to read from end // Flash = READ_END READ_END: begin flash_state <= IDLE; end // Flash = DEFAULT default: begin flash_state <= IDLE; end endcase end // tAA = 100 ns time generation reg tAA_cnt; assign tAA = (tAA_cnt == 10); always @(posedge clock or negedge reset_n) begin if (!reset_n) tAA_cnt <= 0; else begin if (time_is_tAA) tAA_cnt <= 0; else if (flash_state == READ_START_1) tAA_cnt <= tAA_cnt + 1; end end endmodule
0 Kudos