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.
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
> 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
entity SPI_top_level is...
architecture Behavioral of SPI_top_level issignal TX_Data : STD_LOGIC_VECTOR (length-1downto0);
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=0Generic ( 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 : inSTD_LOGIC_VECTOR (length-1downto0); -- Send data
RX_Data : outSTD_LOGIC_VECTOR (length-1downto0); -- recieve data
MOSI : outSTD_LOGIC;
MISO : inSTD_LOGIC;
SCLK : outSTD_LOGIC;
SS : outSTD_LOGIC;
TX_Start : inSTD_LOGIC;
TX_Done : outSTD_LOGIC;
clk : inSTD_LOGIC
SPI_Controller : SPI_Master portmap (...);
processbeginwaituntil rising_edge(clk); -- the one and oly clock
case transmitstate iswhen0 => SS <= '0'; -- slave select
transmitstate <= 1;
when1 => TX_Data <= x"D2";
transmitstate <= 2;
when2 => TX_Start<= '0';
TX_Data <= x"00";
transmitstate <= 3;
when8 => TX_Start<= '0';
TX_Data <= readbyte1;
transmitstate <= 9;
when9 => TX_Start<= '0';
TX_Data <= readbyte2;
transmitstate <= 10;
when9 => TX_Start<= '0';
transmitstate <= 10;
when10 => SS <= '1';
transmitstate <= 0;
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
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
IF rising_edge(clk) THEN
flipflops(0) <= tx_done1;
flipflops(1) <= flipflops(0);
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
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;endcase;
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... ;-)
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
Ahh, I see, I could also switch to 16 bit instead of 8 and cut it down
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...endif;
> 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.
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.