SPI; simulating an input (rx)

  • Thread starter Brandon Spiteri
  • Start date
B

Brandon Spiteri

Hi,
I have managed to transmit some character (one after the other) using this code from;

http://eewiki.net/pages/viewpage.action?pageId=4096096

I used continuous mode and I got the right characters on MOSI, one after the other, the only thing is that there are 4 clock cycles of high impedance between each 8-bit char. Is this oki?

I am planning to interface with MAX1416 ADC.


Also, I need to simulate an SPI input coming from the ADC. What is the best way to do it?

Shall I use the same method I used for transmitting but this time in the test bench?

I am using quartus and ModelSim.

thanks
 
G

GaborSzakacs

Brandon said:
Hi,
I have managed to transmit some character (one after the other) using this code from;

http://eewiki.net/pages/viewpage.action?pageId=4096096

I used continuous mode and I got the right characters on MOSI, one after the other, the only thing is that there are 4 clock cycles of high impedance between each 8-bit char. Is this oki?

I am planning to interface with MAX1416 ADC.


Also, I need to simulate an SPI input coming from the ADC. What is the best way to do it?

Shall I use the same method I used for transmitting but this time in the test bench?

I am using quartus and ModelSim.

thanks

From your screen-shot, it looks like the high-Z occurs when the receiver
is not looking at the data, so it should be OK. On the other hand it
might be a good idea to go through your code to see why that's
happening.

As for simulating data in the opposite direction, there's no reason you
can't instantiate a synthesizable module from the testbench to provide
stimulus. That assumes of course that the module behaves the way you
expect the ADC to behave. Have checked whether Maxim (or whoever makes
the ADC) has a simulation model?
 
B

Brandon Spiteri

From your screen-shot, it looks like the high-Z occurs when the receiver

is not looking at the data, so it should be OK. On the other hand it

might be a good idea to go through your code to see why that's

happening.



As for simulating data in the opposite direction, there's no reason you

can't instantiate a synthesizable module from the testbench to provide

stimulus. That assumes of course that the module behaves the way you

expect the ADC to behave. Have checked whether Maxim (or whoever makes

the ADC) has a simulation model?

Thanks for your reply Gabor, I looked in the datasheet of the ADC but there wasn't much SPI waveforms to check with. Do you have any idea where can I look for a valid waveform example for MAX1416 please?
 
K

KJ

Thanks for your reply Gabor, I looked in the datasheet of the ADC but there
wasn't much SPI waveforms to check with. Do you have any idea where can I look
for a valid waveform example for MAX1416 please?

Datasheet, page 23

KJ
 
B

Brandon Spiteri

Hi,
thanks a lot for the help, I managed to understand a lot and perform some simulations with success.
I followed the flow chart and got the correct sequences on the logic analyser for the transmission (MOSI)

Now I have this dilemma on how to amalgamate the DRDY pin of the ADC mentioned:

http://datasheets.maximintegrated.com/en/ds/MAX1415-MAX1416.pdf
page. 29 is the flow chart

with the SPI code found here:

https://www.eewiki.net/display/LOGIC/Serial+Peripheral+Interface+(SPI)+Master+(VHDL)

If I understand correctly, this is used mainly when reading from MISO. Is it a good idea to
use DRDY as an enable for SCLK in order to wait for the data to be ready? Or is there a better way?

thanks
 
K

KJ

I would suggest that you use DRDY as an input to the 'user logic' that drives the SPI controller. It should not be used to directly modify SCLK, that defeats the purpose of re-using an existing design.

Kevin Jennings
 
B

Brandon Spiteri

thanks for the fast reply. What do you think of this modification of spi.vhdl with DRDY ?

WHEN execute =>

busy <= '1'; --set busy signal
ss_n(slave) <= '0'; --set proper slave select output

--system clock to sclk ratio is met
IF(count = clk_ratio) THEN

count <= 1; --reset system-to-spi clock counter
assert_data <= NOT assert_data; --switch transmit/receive indicator

IF(clk_toggles = d_width*2 + 1) THEN -- (==17)
clk_toggles <= 0; --reset spi clock toggles counter
ELSE
clk_toggles <= clk_toggles + 1; --increment spi clock toggles counter
END IF;
--spi clock toggle needed
IF(clk_toggles <= d_width*2 AND ss_n(slave) = '0') THEN
sclk <= NOT sclk; --toggle spi clock
END IF;
--receive spi clock toggle
IF(assert_data = '0' AND clk_toggles < last_bit_rx + 1 AND ss_n(slave) = '0' AND DRDY = '0') THEN
rx_buffer <= rx_buffer(d_width-2 DOWNTO 0) & miso; --shift in received bit
END IF;
--transmit spi clock toggle
IF(assert_data = '1' AND clk_toggles < last_bit_rx) THEN
mosi <= tx_buffer(d_width-1); --clock out data bit
tx_buffer <= tx_buffer(d_width-2 DOWNTO 0) & '0'; --shift data transmit buffer
END IF;
--last data receive, but continue
IF(clk_toggles = last_bit_rx AND cont = '1' AND DRDY = '0') THEN
tx_buffer <= tx_data; --reload transmit buffer
clk_toggles <= last_bit_rx - d_width*2 + 1; --reset spi clock toggle counter
continue <= '1'; --set continue flag
END IF;
--normal end of transaction, but continue
IF(continue = '1') THEN

continue <= '0'; --clear continue flag
busy <= '0'; --clock out signal that first receive data is ready
rx_data <= rx_buffer; --clock out received data to output port
END IF;

--end of transaction
IF((clk_toggles = d_width*2 + 1) AND cont = '0') THEN

busy <= '0'; --clock out not busy signal
ss_n <= (OTHERS => '1'); --set all slave selects high
mosi <= 'Z'; --set mosi output high impedance
rx_data <= rx_buffer; --clock out received data to output port
state <= ready; --return to ready state
ELSE --not end of transaction
state <= execute; --remain in execute state
END IF;

ELSE --system clock to sclk ratio not met
count <= count + 1; --increment counter
state <= execute; --remain in execute state
END IF;
 
K

KJ

thanks for the fast reply. What do you think of this modification of spi.vhdl
with DRDY ?

I think
- You completely ignored my suggestion to use DRDY as an input to the 'userlogic' that drives the SPI controller.
- Assuming you started from known working SPI controller code, you've hobbled it at best to make it into something that will only work under very special circumstances.

Had you followed my suggestion, your new code would be generating the following outputs from a 'User_Logic' entity:

- Enable, Addr and Tx_Data. How these are generated could be made to be a function of Drdy.
- You would likely have to only define constants for the following outputs:cpol, cpha, cont and clk_div.

The 'User_Logic' entity would then be connected to the 'Spi_Master' entity.Then as you think of other requirements you would modify 'User_Logic' some more until everything is working properly. Some modifications like:

- What should you do if DRDY never comes back? You have no timeout, probably a hard reset is the only escape
- Do you really want every SPI operation to depend on DRDY?

The basic idea is that if you have some known working code for some widget,and you modify it, you're more likely to break it then to improve it if you didn't write it yourself in the first place. Instead, you should presentan interface to the widget (i.e. the entity) that encourages one to use the widget, not modify the widget. The SPI_Master interface looks like it presented a simple address/data interface with handshaking that would be fairly easy to understand then simply use.

Kevin Jennings
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top