Sorry, you need to enable JavaScript to visit this website.

SPI pin mapping when use PMOD

Unsolved
4 posts / 0 new
niky0913's picture
niky0913
Junior(0)
SPI pin mapping when use PMOD

Hello guys~
I designed a SPI design and connected to PL(EMIO).
Because I am using zedboard and PMOD module from Maxim.(SPI module)
But my design doesn't work, so I am checking what I have done.
I found 6pins of SPI pin declaration, but I am not sure I did make a good connection to physical pin.

1. Could you let me know which pin should be connected with SS, MOSI, MISO, SCK?
(*)I am using only 1 SPI as a master mode.

spi_0_io0_io : inout STD_LOGIC;
spi_0_io1_io : inout STD_LOGIC;
spi_0_sck_io : inout STD_LOGIC;
spi_0_ss1_o : out STD_LOGIC;
spi_0_ss2_o : out STD_LOGIC;
spi_0_ss_io : inout STD_LOGIC

2. Should I have to set and enable every pin using "set direction and discrete write" funtion?

3. In the middle of debugging, I found my process is pending, actually wait for transaction permanetly..
Could it be a result of wrong pin connection?

*part of code
-----------------------------------------------------
//Wait for transaction to complete. Check to see if Tx_Empty flag is set before proceeding.
while( !(XSpiPs_ReadReg( unPeripheralAddressSPI, 0x64 ) & 0x00000004));
------------------------------------------------------

*whole code

int SpiRW( u32 unPeripheralAddressSPI, unsigned int unCPHA, unsigned int unCPOL, u8* auchWriteBuf, u8* auchReadBuf, int unNumBytes, u8 uchCsActiveHigh )
/**
* \brief Perform a SPI read or write.
* \par Details
* This function provides a combination SPI Read and Write to the chosen SPI port in the design
* CPHA and CPOL can be set to 0 or 1
* Pointers are provided to u8 buffers containing the data to be written and received
* Data in the auchWriteBuf will be clocked out (MSB first) onto the MOSI pin
* Data from the MISO pin will be placed into the auchReadBuf
* uchCsActiveHigh==TRUE allows SS configurations to be used
* uchCsActiveHigh==FALSE allows SS# configurations to be used
*
* \param[in] unPeripheralAddressSPI - @help
* \param[in] unCPHA - phase of SCK (edge to trigger on). 0=Leading edge, 1=Trailing edge
* \param[in] unCPOL - polarity of SCK. 0=Active high, 1=Active low
* \param[in] auchWriteBuf - pointer to write data buffer
* \param[in] auchReadBuf - pointer to read data buffer
* \param[in] unNumBytes - number of bytes to transfer
* \param[in] uchCsActiveHigh - polarity of slave select 0=active low, 1=active high
*
* \retval Always returns 0
*/
{
int i;
unsigned int unControlData = 0x00000186;

//If CPHA or CPOL = 1, we need to set the corresponding bits in the control register
unControlData = unControlData | (unCPHA << 4);
unControlData = unControlData | (unCPOL << 3);

//Write config data to SPICR. We need the inhibit bit=1.
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x60, unControlData);

//Deassert CS to 1 to ensure SPI slave is inactive
if( uchCsActiveHigh )
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFE);
else
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFF);

for( i = 0; i < unNumBytes; i++)
{
if( auchWriteBuf != 0 )
{
//Write data to SPIDTR. This is the data that will be transferred to the SPI slave.
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x68, auchWriteBuf[ i ]);
//Debug//printf( "Write %02x; ", auchWriteBuf[i]);
}
else
{
//Write data to SPIDTR. This is the data that will be transferred to the SPI slave.
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x68, 0x00);
}

//Write config data to SPICR. We need the inhibit bit=1.
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x60, unControlData);

//Assert CS for our PMOD part
if( uchCsActiveHigh )
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFF);
else
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFE);

//Un-inhibit our SPI master to transfer the data
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x60, unControlData & 0xFFFFFEFF);

printf( "Read %02x\r\n", XSpiPs_ReadReg( unPeripheralAddressSPI, 0x64 ));
//Wait for transaction to complete. Check to see if Tx_Empty flag is set before proceeding.
while( !(XSpiPs_ReadReg( unPeripheralAddressSPI, 0x64 ) & 0x00000004));

//Inhibit SPI master to prevent further action
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x60, unControlData);

//Read received data
if( (auchReadBuf != 0) )
{
auchReadBuf[ i ] = XSpiPs_ReadReg(unPeripheralAddressSPI, 0x6C);
//Debug//printf( "Read %02x\r\n", auchReadBuf[i]);
}
}
if( uchCsActiveHigh )
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFE);
else
XSpiPs_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFF);
return 0;
}

TroutChaser's picture
TroutChaser
Moderator(18)
Which Maxim PMOD are you using?

Once you have made the SPI interface on the Zynq Processing system 'External' and let Vivado 'Create HDL Wrapper' the tools should have instantiated IO buffers for you in the HDL wrapper. Now you will want to connect the 'io' signals required to the correct pins, with the correct  IO standard (LVCMOS33 in this case) by creating a constraints file either directly or using the IO Planning view after synthesis.
 
Depending on the SPI PMOD you are using you will want to connect to spi_0_sck_io , spi_0_io0_io, probably spi_0_ss_io , and possibily spi_0_io1_io (if you are reading back from the SPI PMOD). If your PMOD uses more than one chip select you will need to connect that as well. The pin assignments depend on the pin out of your PMOD.
 
Maxim has example code for most of their PMODs in the zedboard community projects area although most of them are written to use the axi_spi cores rather than the ps_spi, so you may need to make some modifications.
 
Which Maxim PMOD are you using?
 
-Gary

niky0913's picture
niky0913
Junior(0)
Gary, Thanks for you fast

Gary, Thanks for you fast reply.
I am using MAX31723 and other PMOD modules based on SPI.
What is the difference btw axi_spi and ps_spi?
Base on my understanding axi_spi is implemented on PL side and ps_spi is PS side...
Am I right?

studogger's picture
studogger
Junior(0)
MAX31723 project

Hi,

Did you find a good tutorial/example for the MAX31723 (for the Zedboard, but I'll take anything in Vivado 2014.x)? If so, I am interested in seeing it. I have tried to follow "Zynq Workshop for Beginners" by Rich Griffin but can't get it to work. I can generate a bitstream and launch the application in SDK, but the program hangs when I am running it on the FPGA.

As far as my debugging has gone, it looks like the program hangs sometime after the first or second peripheral initialization command. I have tried going back and verifying the constraints, but the workshop centered around a one-shot run for completion and I am uncertain if I have the correct design when starting that step. This makes debugging all that more miserable, and maybe impossible.

Again, any tutorial centering on talking to a PMOD (preferably using SPI on the PL side) would be much appreciated.

Thanks!