Jump to content
  • 0

Pmod DA3 clocking


Ahmed Alfadhel

Question

Hi @jpeyron

Kindly see the attached picture.

I have the following clocking options:

MIG_7series/ui_clk :83 MHz

clk_wiz_0/clk_out_1 : 166 MHz

And I want to feed my Pmod DA3 with the desired clocking rate. But I don't know what to choose from these clocks?

So could you help me in choosing the right clock for the two pin of Pmod DA3 ?

Thanks .

PmodDA3.JPG

Link to comment
Share on other sites

Recommended Posts

It looks to me like DA3_WriteSpi() was adapted from code for a different device and has vestigial and incorrect code.

Reviewing the AD5541A datasheet, several things stand out

  • There is only a single register in the chip so there is no need for the u8 reg parameter.
  • There is no need for a"config byte" to be sent before the data.
  • The transfer is always 16 bits so there is no need to allow for arbitrary length data
  • quoting from the datasheet "Input data is framed by the chip select input, CS. After a high-to-low transition on CS, data is shifted synchronously and latched into the serial input register on the rising edge of the serial clock, SCLK. After 16 data bits have been loaded into the serial input register, a low-to-high transition on CS transfers the contents of the shift register to the DAC register if LDAC is held low". Reviewing the PmodDA3 schematic, the ~LDAC signal is softly pulled to ground with a 10K resistor. So there is no need to explicitly toggle ~LDAC.

What all this means is DA3_WriteSpi could be simplified to something like

void DA3_WriteSpi(PmodDA3 *InstancePtr, u16 wData)
{
    u8 bytearray[2];

    bytearray[0] = ((wData & 0xFF00) >> 8);
    bytearray[1] =  (wData & 0xFF);

    XSpi_Transfer(&InstancePtr->DA3Spi, bytearray, 0, sizeof(bytearray));
}

You would then call it passing in just the instance pointer and the value you want to write to the DAC.

u16 dacValue = 1234;
DA3_WriteSpi(&myDevice, dacValue);

I do not have a PmodDA3 on my bench so I cannot verify the function works, You can give it a try and let us know how it goes.

Link to comment
Share on other sites

Hi @kwilber

I tested your simplified version of DA3_WriteSpi function. But I found part of DIN (Data) signal is under high level of ~CS signal as shown in the second attached picture. Which is meaning part of data signal is unread by the PMOD DA3. 

The first attached picture is showing the measured Analog signal by SMA connector. It is supposed to be 1 kHz sinewave but it is not. Even the shap is still far from regular sinewave. 

Back again to my code, I found the variable Hops_reading is defined as u32. So, I did some changes to my code as follow:

u32 Hops_reading_32;

while(delay_count < 5000000)
  	 		{
  	 			Hops_reading_32 = XIOModule_DiscreteRead(&gpi, 1); // Perform Hop Reading


  	 			

  	 		    u16 Hops_reading_16[2];

  	 		    Hops_reading_16[0] = ((Hops_reading_32 & (0xFFFF0000)) >> 16);
  	 		    Hops_reading_16[1] = (Hops_reading_32 & (0xFFFF));

  	 		    int i;
  	 		    for (i=0;i<=1;i++)
  	 		    {
  	 			 DA3_WriteSpi(&myDevice, Hops_reading_16[i]);
  	 		    }
  	 				
  	 				delay_count++;
  	 		}

After that I re-debugged again my design, but the main problem of "part of DIN (Data) signal is under high level of ~CS signal" is still existed ! as shown in the third attached picture.

The fourth attached picture is showing the analog output from SMA connector. Also, it is supposed to be  1 kHz sinewave signal. But still far away from the regular sinewave !

I am looking forward your help.

Thanks.

 

photo_2019-03-19_21-45-55.jpg

1st

photo_2019-03-19_22-28-53.jpg

photo_2019-03-19_22-31-18.jpg

Link to comment
Share on other sites

Hi @kwilber,

Thank you for your time that you spent to analyze my code and follow up with me my issue.

I thought that the sizeof(Hops_reading) = 32, since it is u32 .

I tried to check that using Print function with Tera Term,

int size_hop;
size_hop = sizeof(Hops_reading);
print(size_hop);

however, I got  'p' on Teram Term  ! 

Why?

Thanks for your support.

Link to comment
Share on other sites

Hi @Ahmed Alfadhel,

I reached out to our content team about the default settings and how to change them for the generic SPI IP Core.

To change the transaction width you will need to edit the DA3 IP in the IP Packager. Once that's open, double clicking on the SPI XCI in the sources pane will open it's customization wizard. The "Transaction Width" drop down can be set to 16 instead of 8. Click OK, merge changes to sources in the IP Packager, then Repackage the IP and close the packager. Update IPs in the host project and carry on as normal with the Pmod IP.

Default settings are in the attached image - They created a default SPI IP using the generator and edited it in IP packager to get this screenshot.

They do not know the effects changing C_NUM_TRANSFER_BITS would have on the drivers. If changes to the drivers are necessary, if changes are need to be made they expect that only the XSpi_Config instance in the Pmod's .c driver file would need to be changed.

They believe that the asynchronous clock setting only really needs to be used when ext_spi_clk is not derived from the same clock source as the axi clock. If the Pmod IP guide is followed, the setting might be able to be disabled just fine, since both clocks will come from the same clocking wizard or MIG. Their best guess is that the main use case for the Async clock is for when the AXI Quad SPI is configured as a slave to a SPI master off of the board - all of the Pmod IPs use master mode SPI. 

thank you,

Jon

default-spi.png

Link to comment
Share on other sites

As far as the sizeof()... here is a snip from cppreference.com.

image.png.3556486bd3709299f58e73f650f3a5d5.png

 

As far as your attempt to print the sizeof... if you look at the definition for print(), the argument is a char *, so you would need to pass a string. You passed the value 4 so the print function would interpret that as a string at address 0x00000004 which is going to point to some system dependent binary data.

image.png.7c25e59345dd303fce486d92844f0cf2.png

You can get to the definition by right clicking on "print" in your code and select "Open Declaration". 

image.png.e8ec43db07ac9d772384ee2594a3ba09.png

Link to comment
Share on other sites

Hi @kwilber,

Thank you again for your perfect analyzing of my code.

I made an amendment on the code. I made the the pointer *wData size is u8 again (the original size that I found).

I am now thinking for a substitute  to the parameter sizeof( ) .

Does it possible to pass   1 , since  the pointer *wData is u8 ?

void DA3_WriteSpi(PmodDA3 *InstancePtr, u8 reg, u8 *wData, int nData)
  {
	// As requested by documentation, first byte contains:
	//	bit 7 = 0 because is a write operation
	//	bit 6 = 1 if more than one bytes is written, 0 if a single byte is written
	// 	bits 5-0 - the address
	u8 bytearray[nData+1];
	bytearray[0] = ((nData>1) ? 0x40: 0) | (reg&0x3F);
	memcpy(&bytearray[1],wData, nData);//Copy write commands over to bytearray
	XSpi_Transfer(&InstancePtr->DA3Spi, bytearray, 0, nData+1);

}

Thanks in advance.

Link to comment
Share on other sites

Hi @Ahmed Alfadhel,

"According to the manual, it must only be 0 when ~CS is 1" -- this is incorrect.

As you directly highlighted in the image you attached:

Quote

Alternatively, users hold the LDAC pin at a logic low voltage when bringing the CS pin high to directly transfer the data from the shift register to the DAC register.

The timing diagram instead shows the situation presented in the previous sentence that discusses pulsing the LDAC rather than holding it low.

Thanks,
JColvin

Link to comment
Share on other sites

After going through the code posted in this thread, I want to amend my explanation of the 40 bits from yesterday.

In the testperiph.c file, the DAC is being written at line 104.

DA3_WriteSpi(&myDevice,  0x3A, &Hops_reading, sizeof(Hops_reading));

Hops_reading is a 32 bit value, so sizeof(Hops_reading) = 4.

In PmodDA3.c, in the function DA3_WriteSpi(),  the 4 gets passed as nData. The function prepends a 1 byte control word with address and write information. The function ends up writing all 5 bytes using the Xilinx SPI driver. 5 bytes * 8 bits per byte = 40 bits which is what you observed on the wire.

 

void DA3_WriteSpi(PmodDA3 *InstancePtr, u8 reg, u16 *wData, int nData)
{
    // As requested by documentation, first byte contains:
    //    bit 7 = 0 because is a write operation
    //    bit 6 = 1 if more than one bytes is written, 0 if a single byte is written
    //     bits 5-0 - the address
    u16 bytearray[nData+1];
    bytearray[0] = ((nData>1) ? 0x40: 0) | (reg&0x3F);
    memcpy(&bytearray[1],wData, nData);//Copy write commands over to bytearray
    XSpi_Transfer(&InstancePtr->DA3Spi, &bytearray, 0, nData+1);

}

 

Link to comment
Share on other sites

Hi @kwilber,

Could you visualize in dual mode each of ~CS signal and DIN signal, in order to know if you have the problem I have :

On 3/19/2019 at 10:40 PM, Ahmed Alfadhel said:

part of DIN (Data) signal is under high level of ~CS signal

In fact, I followed your instructions in the PM, but I still with same problem !

Thanks.

Link to comment
Share on other sites

I included visualizations of the ~CS, SCLK and DIN lines in the logic analyzer trace I posted Tuesday at 2:51 AM. In the trace, MOSI is the DIN line, Enable is the ~CS line and Clock is the SCLK line.

Did the Xilinx SDK report any errors while opening the workspace?

Did you program the fpga from the SDK?

 

Link to comment
Share on other sites

Hi @kwilber,

It seems that part of your DIN signal (MOSI) is also under high level of ~CS (Enable)! as shown in the first attached picture. I think that mean part of your data is unread by PMod DA3.

7 hours ago, kwilber said:

Did the Xilinx SDK report any errors while opening the workspace?

Did you program the fpga from the SDK?

I openned your design using Vivado 2018.2 , so just I upgraded the IPs. I didn't use your design or code since it is different from my design, but I took some notes from your design such as you are using different clocks signals for ext_spi_clk and s_axi_aclk . I attached  a snapshot for my design.

Thanks.

 

SPI_signals_Kwibler.JPG

my_design2.JPG

Link to comment
Share on other sites

Inside the AD5541A, the MOSI bits get clocked into a shift register and are held there until the ~CS line goes high. At that time, the bits are transferred from the shift register to the D/A. It does not matter what level is on MOSI at that instant.

In the traces I posted earlier, I included a transition from full scale output to 0. I also show several cycles of writing all possible values in a ramp. The resulting voltage waveform shows the AD5541A is seeing the data correctly. The last four writes to the pmod in the zoomed trace show sending the values 0, 1, 2 and 3 to the D/A. You can observe SCLK's transition in relation to the least significant bits of the data. SCLK is not transitioning when ~CS transitions to high so the data on MOSI is "don't care" at that instant.

I did use different clocks since the microblaze can run at higher clock rates than the AD5541A. Also, when you are troubleshooting, it can sometimes help to slow down the logic.

I see you are using pmod connector JB whereas my project used JA. Just as a test, you might want to try moving your PmodDA3 to JA and use my project as is to replicate my results.

You should be able to launch vivado, open my project then immediately launch the SDK from vivado. You should not have to generate a bitfile. I had included the hardware handoff in the zip file I gave you so you have my exact bitfile. Once the SDK loads, it should automatically load the project and compile it. At that point you can program the fpga from inside the SDK and then run my example app. You should see a sawtooth waveform coming out of the PmodDA3 if all is well.

Link to comment
Share on other sites

Hi @kwilber;

I used the same my design, but I modified my code to generate the sawtooth signal. as you did:

				u16 dacData = 0;

  	 		    while (1)
  	 		    {
  	 		    	  ++dacData;
  	 		          DA3_WriteSpi(&myDevice, dacData);
  	 		    }
              
  	 		   /* int i;
  	 		    for (i=0;i<=1;i++)
  	 		    {
  	 			 DA3_WriteSpi(&myDevice, Hops_reading_16[i]);
  	 		    }*/

And I succeeded to get 266 Hz Sawtooth signal. Are you got the same frequency?

Back to my topic, 

I asked my self why I didn't get the sinwave ? And put the following answers: 

1. Maybe I need to use "AXI GPIO" IP core instead of "IOModule" IP core in my system design.

2. Maybe the sinwave IP core (generated by Matlab System Generator) has improper value of "Explicit Sample Time" or "Simulink System Period". So, I will use Vivado simulator with to view my Sinewave.

Thanks for your Help.  

 

 

photo_2019-03-23_21-57-30.jpg

Link to comment
Share on other sites

My project wrote to the dac about every 4 usec. To write 2 ^ 16 = 65536 values, it took about 262 msec per cycle, which gives a frequency close to 3.81 hz.

I conservatively used ext_spi_clk = 25 Mhz so my sclk rate was 12.5 Mhz. In the zoomed trace, you can see 16 bits took about 1.28 usec  to clock into the pmod. I had ~CS go valid about 1.25 usec before I started writing the bits and kept it valid for about 1.25 usec after the bits were clocked out. The rest of the time was from loop overhead.

You appear to be writing almost 70 times faster. Your waveform is not as smooth as mine, so I would guess you are writing so fast the dac is missing some of your data points. Are you using the version of xspi.c from my example project?

Link to comment
Share on other sites

Hi ,

At first, I want to say thank you guys @kwilber , @jpeyron for feeding me with such  valuable informations . 

In the first attached picture, I am visualizing ~CS (chip select) signal on CH1 and SCLK on CH2. According to Pmod DA3 reference manual (second attached picture) , it must be there 16 pulses only for each active low period of ~CS signal.

Now, I am trying to learn how to set the clock pulses to 16 clock pulses only in this Pmod (DA3) . As you can see in the third attached picture the total count of clock pulses is 39 pulses.

It seems the clock frequency (3.13 MHz) is right according your explanations . 

I think the ~CS signal period need to be fixed, but I don't know how?

Looking forward your ideas. I am grateful for you.

Note : the fouth attached picture is from the data sheet of DAC AD5541A IC

Thanks .

SCLK and CS.jpg

16 pulses.JPG

39 pulses.jpg

Timing diagram.JPG

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...