Follow up of 2a: EEPROM State Machine and Initialise. In this post, I read a value from an address in the EEPROM. The slide switches on the Arty define what address to read. The state machine from the previous post already reserved a state for this activity. I just have to implement it.
SPI READ conversation
The sentence takes 32 clock ticks:
- CS low
- send 8 bits read instruction 0000 0011
- send 16 bits address
- read the 8 bits that appear on SO
- CS high
image source: 25LC256 datasheet
Implement read state in my eeprom state machine
This isn't very different from the init_noprot state in the previous post. Just 4 bytes instead of 2. The 16 bits address is all '0', except the 4 least significant bits. Those are the values set by the slide switches (see step 3 to 8 in the code).
when read => -- read command 8 bits if (step = 0) then -- write read command (0b00000011) bitbang_cs_n <= '0'; step <= 1; -- next step data_out <= "00000011"; -- read command start <= '1'; elsif (step = 1) then -- wait for ack from spi if (busy = '1') then -- wait for spi buzy step <= 2; end if; elsif (step = 2) then -- finalise read command if not (busy = '1') then -- wait until spi no longer buzy -- finished start <= '0'; step <= 3; end if; -- address 16 bits elsif (step = 3) then -- MSBs step <= 4; -- next step data_out <= "00000000"; -- address MSB start <= '1'; elsif (step = 4) then -- wait for ack from spi if (busy = '1') then -- wait for spi buzy step <= 5; end if; elsif (step = 5) then -- finalise address MSB if not (busy = '1') then -- wait until spi no longer buzy -- finished start <= '0'; step <= 6; end if; elsif (step = 6) then -- LSBs step <= 7; -- next step data_out (3 downto 0) <= addr(3 downto 0); -- address LB start <= '1'; elsif (step = 7) then -- wait for ack from spi if (busy = '1') then -- wait for spi buzy step <= 8; end if; elsif (step = 8) then -- finalise address LSB if not (busy = '1') then -- wait until spi no longer buzy -- finished start <= '0'; step <= 9; end if; -- read data elsif (step = 9) then -- read from address step <= 10; -- next step data_out <= "00000000"; -- address MSB start <= '1'; elsif (step = 10) then -- wait for ack from spi if (busy = '1') then -- wait for spi buzy step <= 11; end if; elsif (step = 11) then -- finalise read from address if not (busy = '1') then -- wait until spi no longer buzy -- finished start <= '0'; state <= accept; step <= 0; bitbang_cs_n <= '1'; end if; end if;
Test
It works. The protocol analyser shows the init sequence from the previous post, then from row 10 on, the read sequence. The returned data is 0x00. The 16 bits address value is 0x0007. That's because I had set the slide switches to off -on-on-on. Confirmation that that part works too.
The EEPROM I use has never been written too (wait for the next post). I don't know if a new EEPROM has all values set to 0 fresh-from-factory, or if my design isn't correct yet. The next blog, where I'll write to the EEPROM, will learn ...
Side note: this project will not be easy on the eeprom. It has a limited number of write cycles per address, and I'm not going to implement a strategy to deal with that. The exercise is to see if I can get a non-trivial SPI conversation going.
Top Comments