OhmSweetOhm

Diffrence between writing to the FPGA and writing to the FLASH

Recommended Posts

Hello

 

I have a Problem i have a DAC that is controlled by the Papilio one 250k. I have a 512 byte array with a sine wave stored in it and I read the array to a IO port.

 

Now the problem:

It works most of the time if I programm it only to the FPGA. By working I mean that i can see a beautiful sine wave at the oszi. If I programm it several times it works not always, but the programming of the FPGA is so quick I can try until it works.

If it doesn't work the wave form is periodic, not a sine tough. But this tells me that the read of the array works but not the write.

 

If I programm the SPI flash it doesn't work and I get a wave form but it isn't a sine at all.

 

I initalize the array a such:

type memory_t is array(0 to 511) of std_logic_vector(7 downto 0);-- Declare the RAMsignal ram_bank : memory_t;

and i access it as so:

-------------------------------------------------------------------------- write Portprocess(clk_200)begin	if(falling_edge(clk_200)) then 		if(w_en = '1') then			ram_bank(to_integer(unsigned(add_w))) <= ram_in;		end if;	end if;end process;	-------------------------------------------------------------------------- read Portprocess(clk_200)begin	if(rising_edge(clk_200)) then		if(r_en = '1') then			ram_out <= ram_bank(to_integer(unsigned(add_r)));		end if;	end if;end process;

I tried to run both processes at the rising edge but this doesn't work at all.

The read and write is controlled by a FSM, there is never a read and write at the same time.

As you can see I use the ram at 200MHz, is this to fast?

I use a microblaze MCS to controll the hole thing, so the MCS has the array static in it and writes it to the dac controller fsm, it stores it in the array and after that it is read periodical.

 

If anyone has a clue.

 

Ohm

 

dac_man.vhd

Share this post


Link to post
Share on other sites

Hello Ohm,

 

Nothing comes to mind as to what is going wrong, we would probably need to see the whole project. Not sure how soon I would be able to take a good look though since I'm super busy trying to get the Papilio DUO delivered.

 

If you download the latest version of DesignLab there is a ZPUino project that already does this same thing. Take a look at the Benchy Waveform Generator project, maybe it will help...

 

Jack.

Share this post


Link to post
Share on other sites

Hello Jack,

 

I had a look at the example as you said, in the example the function gen is realized through a LUT and only can produce sin, cos and square.

I wanted to make an arbitary waveforme gen. I made a quick project with an array with static values and i read them out, the same as in my other project, simply with a FSM.

It worked realy good but only the static values.

 

I had a look at the technology schematic, there is clearly a dual port bram, which seems correctly wired.

I also tried a few different procces properties and design strategies but everything exept the default values made it worse.

I also buffered all the inputs for the bram with a register stage.

 

If you want to have a look:

https://www.dropbox.com/s/grpoczc0q0dk7l6/m_blaze_test.zip?dl=0

 

Thanks for your help.

 

Happy new year!

 

Ohm

 

 

Share this post


Link to post
Share on other sites

Some things occur to me.  These are oriented toward the Spartan 6 but I'd expect them to be similar on the Spartan 3E.  Oh and I'm kind of a newbie so these are just ideas.

 

1. You really shouldn't need to be using the separate rising / falling clock edges like you're doing.  The block RAM is dual ported; you can have one port doing write while another is doing read.  But there are some limitations.  Quoting from a book on the subject,  "The inference rules and limitations are specific to a synthesis tool. For example, XST cannot infer dual-ported BRAMs with different port widths, read and write capability on both ports, or different clocks on each port."  [stavinov, Evgeni (2011-05-18). 100 Power Tips for FPGA Designers (p. 165). OutputLogic.com. Kindle Edition.]  And "different clocks on each port" might include using different edges of the same clock.

 

2. It seems best to use the same clock edge for everything.  Speaking of which, in the ZIP file you attached, the code is different from your initial post; it uses falling_edge() for both ports of ram_bank, and one other place, but rising_edge() in other places.

 

3. Admittedly, that doesn't explain why it didn't work when you used the same clock edge on both ports, but that could just be some unrelated problem.

 

4. You ask if 200MHz is too fast.  As I look at "main.twr" (file you included in your ZIP) I see at the bottom, "Maximum frequency: 23.753MHz".  Now, that's relative to the 32MHz system clock and not the 200MHz derived clock, but still, it's not meeting it.  That file also lists a few of the worst-performing logic paths.  One of them is allowed only 1.250 ns, trying to squeeze some event between a tick of the 32MHz clock and a tick of the 200MHz clock.  Since this is going to an I/O port it probably shouldn't be a big issue.  But maybe by adding an entry to the UCF file, telling ISE to relax about the timing of this one particular path, you could see if there are timing failures in your actual logic.

 

5. I see some timing information in "main.syr" too.

Share this post


Link to post
Share on other sites

Hello

 

I managed to solve the problem. Now I have an working arbitary wave gen with 100MS using this board: http://www.wayengineer.com/blackgold-high-speed-adda-module-for-fpga-development-board-p-2753.html#.VKVu_HubjDE

and a papilio.

 

The actual fix was quite simple, as there are two different clock domains in the system, 32MHz and 200MHz I guessed that the problem must be somewhere in the interface between the two clock domains.

 

In my first post i used different clk edges on the bram but I made a mistake there because the r_en signal is only for one cycle high. So from rising edge to rising edge but the data is only stored in the ram at the rising edge so it didn't work.

 

Now I use both ports at the falling edge, which I changed between posts.

 

I also added a register stage for all the interface signals between the microblaze and my module. Now it works.

 

Ohm

 

dac_man.vhd

Share this post


Link to post
Share on other sites

Hello Jack,

 

I'm using a Microblaze with a simple interface (parallel 8 bit data and 4 controll lines) to send the data to the dac_man module.

This could be improved using a simple SPI interface.

 

In the Microblaze I have a static array with 256 values for the waveform. With a simple for loop I clock the data into the bram, using an auto increment and an adress reset. (I reset the address and then clock the data in)

 

I have the 512 byte bram divided into two parts of 256 byte, so I can read from one block and write into the other, when all the data is written I can switch the blocks with a signal line.

 

The waveform is static though but you could let the microblaze calculate it, or use the build in serial interface to recieve data from the pc.

 

The microblaze project is in the zip file in the workspace/SoftProc_App. I simply followed this tutorial to get the microblaze running: http://jimselectronicsblog.blogspot.co.at/2014/03/implementing-microblaze-mcs-on-papilio.html, which you posted allready on the learning page. http://www.gadgetfactory.net/2014/03/microblaze-mcs-step-by-step-tutorial-for-the-papilio/

 

Thanks for the always quick response and the work you put into this.

 

Ohm

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now