EmbDev.net

Forum: FPGA, VHDL & Verilog Spi Flash AT45DB321


Author: Chris Customchris (customchris)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Hi guys, Since UFM in the Machxo2 seems to difficult to setup, I broke 
out the arduino and with a little help figured out how to write 2 bytes 
to memory and read those bytes, i also downloaded Lothar Miller's Spi 
Master and got it talking to an spi encoder by a single 16 bit transfer 
on the Machxo2. Now the hard part, to read my 2 bytes i have to send 
Ox-D2,00,00,00,00,00,00,00,00+ read byte1, 00 + read byte2. To write 
those 2 bytes I have to send 0x82, 00,00,00, my byte, my byte. I know i 
need to build a state machine, i need ChipSelect to stay low durring the 
whole transfer. this one is a little tougher.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
1 useful
not useful
Chris C. wrote:
> I know i need to build a state machine,
Keep things simple and don't worry about big names: each counter is a 
state machine...

> i need ChipSelect to stay low durring the whole transfer.
That easy: you must control SS in your own FSM. Set it low in the first 
state and set it high after the last...

> this one is a little tougher.
It istn't. Its just about learning.
First step is to set up a "top level" module and to use the SPI unit as 
a component inside your top level entity. Then you control that SPI 
module with those three ports you commented out:
   -- TX_Data  : in  STD_LOGIC_VECTOR (length-1 downto 0); -- Send data
   -- TX_Start : in  STD_LOGIC;
   -- TX_Done  : out STD_LOGIC;
In that new top level FSM you simply set up TX_Data and set TX_Start to 
'1'. Then in the next state you set TX_Start to '0' and wait for TX_Done 
to go '1'. If so, you set up TX_Data and set TX_Start to '1' and so 
forth...
entity SPI_top_level is...
:
end SPI_top_level;

architecture Behavioral of SPI_top_level is
  signal TX_Data  :  STD_LOGIC_VECTOR (length-1 downto 0);
  signal TX_Start :  STD_LOGIC;
  signal TX_Done  :  STD_LOGIC;
  signal MOSI ...
  signal MISO ...

  signal transmitstate : integer := 0:

  component SPI_Master is  -- SPI-Modus 0: CPOL=0, CPHA=0
    Generic ( Quartz_Clock : integer   := 50000000;  -- Hertz 
              SPI_Clock_Speed  : integer   :=  2500000;  -- Hertz / calculate reload-value for clock divider
              length         : integer   :=   8        -- Number of bits to be transmited
             ); 
    Port ( TX_Data  : in  STD_LOGIC_VECTOR (length-1 downto 0); -- Send data
           RX_Data  : out STD_LOGIC_VECTOR (length-1 downto 0); -- recieve data
           MOSI     : out STD_LOGIC;                           
           MISO     : in  STD_LOGIC;
           SCLK     : out STD_LOGIC;
           SS       : out STD_LOGIC;
           TX_Start : in  STD_LOGIC;
           TX_Done  : out STD_LOGIC;
           clk      : in  STD_LOGIC
         );
  end component;
   :
   :
   :
begin
   SPI_Controller : SPI_Master port map (...);
   :
   process begin
     wait until rising_edge(clk); -- the one and oly clock
     :
     case transmitstate is
       when 0 => SS <= '0'; -- slave select
                 transmitstate <= 1;
           
       when 1 => TX_Data <= x"D2";
                 TX_Start<= '1';
                 transmitstate <= 2;
                 
       when 2 => TX_Start<= '0';
                 if TX_Done='1' then
                   TX_Data <= x"00";
                   TX_Start<= '1';
                   transmitstate <= 3;
                 end if;
                 
                 
                 :
                 :
                 :
                 

       when 8 => TX_Start<= '0';
                 if TX_Done='1' then
                   TX_Data <= readbyte1;
                   TX_Start<= '1';
                   transmitstate <= 9;
                 end if;
                 
       when 9 => TX_Start<= '0';
                 if TX_Done='1' then
                   TX_Data <= readbyte2;
                   TX_Start<= '1';
                   transmitstate <= 10;
                 end if;

       when 9 => TX_Start<= '0';
                 if TX_Done='1' then
                   transmitstate <= 10;
                 end if;

       when 10 => SS <= '1';
                 transmitstate <= 0;
      :
      :
Got the idea?

Author: Chris Customchris (customchris)
Posted on:

Rate this post
0 useful
not useful
ive been trying similar code, with mine i was only getting d2 and 2x00 
bytes out then it would reset,not sure why. With the the one you just 
posted, im getting all of the clocks and cs is working, but no d2 on 
mosi.

Author: Chris Customchris (customchris)
Posted on:
Attached files:

Rate this post
0 useful
not useful
This time I switched a few things around and got it to throw out My xd2, 
but only 3 bytes follow till it resets back to xd2?

Author: Chris Customchris (customchris)
Posted on:

Rate this post
0 useful
not useful
I Figured it out! TX_DONE was 3 clock pulses wide, so i sent it through 
a single edge detector and voila, everything is showing perfectly out to 
the logic analyzer!

tx_done <= flipflops(0) and not flipflops(1);
  ------ Administration --------
   PROCESS(clk)  --  single edge based interupt
   BEGIN
    IF rising_edge(clk) THEN
      flipflops(0) <= tx_done1;
      flipflops(1) <= flipflops(0);
    END IF;
  END PROCESS;

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Chris C. wrote:
> This time I switched a few things around and got it to throw out My xd2,
> but only 3 bytes follow till it resets back to xd2?
You are right. Run a simulation on it. Then you will see the problem 
easily...

It is a problem in handshaking. After a minor chage it looks ok (see 
Waveform from simulation):
       :
       :
       when spi_etx =>
             SS      <= '1'; -- disable Slave Select 
             TX_Done <= '1';
--             if(TX_Start = '0') then 
               spitxstate <= spi_stx;
--             end if;
     end case;
       :
       :

Chris C. wrote:
> I Figured it out! TX_DONE was 3 clock pulses wide, so i sent it through
> a single edge detector
You are right: a workaround can also fit things together... ;-)

: Edited by Moderator
Author: Chris Customchris (customchris)
Posted on:
Attached files:

Rate this post
0 useful
not useful
I had also tried that thinking it would help, but in silicon it was a 
looped Cs and nothing else. Here she is.

Author: Chris Customchris (customchris)
Posted on:

Rate this post
0 useful
not useful
Thank YOU Lothar, one last thing, how can i reduce the delay between 
bytes? right now from CS to CS is 4.42uS, i can shave off nearly 1uS by 
removing some delay between bytes, Im limited to the 50mhz clk due to 
all of my other process's in this project are timed with 50mhz, Far 
toooo much to go back and recode. I have the Spi Clock at 25mhz, maxed 
out.

Ahh, I see, I could also switch to 16 bit instead of 8 and cut it down 
by 400ns.

: Edited by User
Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Chris C. wrote:
> how can i reduce the delay between bytes?
At the moment these is one "SCLK idle cycle" hidden in the spitxstate 
FSM. MAybe you get rid of that by setting the delay in spi_stx to 0:
             if(TX_Start = '1') then 
                spitxstate <= spi_txactive; 
                SS         <= '0';
                delay      <= 0; -- clock_delay; -- clock_delay adds a SCLK idle cycle here...
             end if;     

> I have the Spi Clock at 25mhz, maxed out.
Up to now you use 2.5MHz...

For a 25MHz SPI clock you will need no prescaler at all, because with 
every 50MHz clock the SPI clock must be toggled. You will have to look 
close at the bit timing at this edge of speed.

Author: Chris Customchris (customchris)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Will try more after work today, I gotta get a few hours of sleep lol

THis seems to be 25mhz 25ns high, 15ns low.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Chris C. wrote:
> THis seems to be 25mhz 25ns high, 15ns low.
You should have a look at the signal with an analog scope...

Author: Chris Customchris (customchris)
Posted on:

Rate this post
0 useful
not useful
So sending and recieving is working, as long as im not trying to put 
rx_reg into a "byte", strangely if i add "adjuster0 <= rx_reg;" right 
after If tx_done = '1' then, suddenly i dont even get a response from 
the flash, as seen on the logic analyzer.

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.