FPGA, SoC, And CPLD Boards And Kits
FPGA Evaluation and Development Kits
5892 Discussions

writing/reading sram with cyclone3 in vhdl

Altera_Forum
Honored Contributor II
1,968 Views

Hey, 

i'm trying to write and read to/from the sram with a cyclone3 fpga on a NEEK. I wrote a little code to check if it's working, but it doesn't and i tried very much around but to no avail. The clk input is driven by a pll with 100Mhz (of course i connected the SRAM_clk to it). I changed the configuration scheme to passive serial to use DATA[0] and DATA[1] as regular IO-pins. So here's the code, maybe someone will notice a mistake i haven't come across. 

 

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity videosync is port (clk, nRst: in std_logic; data: inout std_logic_vector(31 downto 0); addr: out std_logic_vector(20 downto 0); nCS, nOE, nWE: out std_logic; nadsc, nbe0, nbe1, nbe2, nbe3: out std_logic; led0, led1, led2, led3: out std_logic; flashnOE, flashnCE: out std_logic); end entity videosync; architecture behave of videosync is -- readram signals type ramState is (write, read); signal ramst : ramState; signal ramcount: integer := 0; signal notWE: std_logic; signal memoryData: std_logic_vector(31 downto 0); begin readram_process: process (clk, nRst) is begin if nRst = '0' then flashnOE <= '1'; flashnCE <= '1'; nadsc <= '1'; nbe0 <= '1'; nbe1 <= '1'; nbe2 <= '1'; nbe3 <= '1'; led0 <= '1'; led1 <= '1'; led2 <= '1'; led3 <= '1'; nCS <= '0'; nOE <= '1'; notWE <= '1'; addr <= (others => '0'); memoryData <= (others => '0'); ramcount <= 0; ramst <= write; elsif rising_edge(clk) then case ramst is when write => if ramcount = 0 then addr <= std_logic_vector(to_unsigned(ramcount, 21)); memoryData <= "11111111000000000000000000000000"; nadsc <= '0'; ramcount <= ramcount + 1; elsif ramcount = 1 then notWE <= '0'; nadsc <= '1'; ramcount <= ramcount + 1; elsif ramcount = 2 then notWE <= '1'; addr <= (others => '0'); ramcount <= ramcount + 1; else ramcount <= 0; ramst <= read; end if; when read => if ramcount = 0 then addr <= std_logic_vector(to_unsigned(0, 21)); nadsc <= '0'; ramcount <= ramcount + 1; elsif ramcount = 1 then nOE <= '0'; nadsc <= '1'; if data = "11111111000000000000000000000000" then led0 <= '0'; else led0 <= '1'; end if; ramcount <= ramcount + 1; elsif ramcount = 2 then if data = "11111111000000000000000000000000" then led1 <= '0'; else led1 <= '1'; end if; ramcount <= ramcount + 1; elsif ramcount = 3 then if data = "11111111000000000000000000000000" then led2 <= '0'; else led2 <= '1'; end if; ramcount <= ramcount + 1; nadsc <= '1'; addr <= (others => '0'); nOE <= '1'; else null; end if; end case; end if; end process readram_process; nWE <= '0' when notWE = '0' else '1'; data <= memoryData when notWE = '0' else (others => 'Z'); end architecture behave; 

 

Thanks for your help, trigit. 

 

P.S. I don't know when exactly the data should arrive on the bus, so i checked some clock cycles for it with the different LEDs. But none of them is flashing :(
0 Kudos
24 Replies
Altera_Forum
Honored Contributor II
722 Views

What is your clock frequency? The SDRAM is quite slow. Check for the datasheet but I think that the read latency is something like 80ns. 

Second, you don't have any connection between your memoryData signal and your data vector. To handle the bidirectionnal bus, you should have something like this outside of the process: 

data <= memoryData;Then to write something on the bus, write it to memoryData, as you did. But to read, first you must set the bus in a tristate mode: 

memoryData <= (others => 'Z'); 

and then read the data from data (not from memoryData!). 

I haven't looked at everything, but it sooks like your notWE signal isn't connected to anything either. You are also directly assigning values to some output ports in the process, and I'm not sure it would work as expected. Are you using VHDL 2008? Because if you don't it should have generated an error. 

Instead of using LEDs, you could use SignalTAP. It would let you see all the signals, and it is easier to check that everything works as expected.
0 Kudos
Altera_Forum
Honored Contributor II
722 Views

Thank you for your reply Daixiwen, but i think you didn't read everything. 

First of all i'm talking about the SSRAM not the SDRAM, second as i already posted the clock frequency is 100Mhz and third, please have a look at the end of my code: 

nWE <= '0' when notWE = '0' else '1'; data <= memoryData when notWE = '0' else (others => 'Z'); 

 

Quartus II says i'm using VHDL 1993, should i change that? 

What do you mean by i am directly assigning values to some output ports? Are you talking about the control signals? And why shouldn't it work then? 

 

I will look up how to use SignalTAP, but i would be very grateful, if you'll have a look again and then maybe can help me :) 

 

Best regards, trigit
0 Kudos
Altera_Forum
Honored Contributor II
722 Views

Sorry about that, I don't understand how I missed it... Better not to answer anything before my morning coffee ;) 

You are right, you have the correct lines. But I still think you are missing output buffers for the other control signals, including nCS, nOE, nadsc. I thought the synthesizer wouldn't allow you to do that, especially if you are using VHDL 1993 

 

For the SRAM, I thought that this kit used the same one than on the Cyclone III 3C120 development board (that I'm more familiar with, and that uses a 'false' SSRAM). I think you still have a 2 cycles latency to read data. 

 

SignalTap isn't that difficult to learn, and it is a very very useful tool to debug any design. Spend a few hours now to learn to use it now, and you'll spare lots of hours of debugging later ;)
0 Kudos
Altera_Forum
Honored Contributor II
722 Views

I didn't reply to your other question about buffers. 

In VHDL1993 you aren't allowed to read back the value of an 'out' port. This is a problem for registered outputs, because to maintain the value of a register between clock cycles, you need to be able to read it back. That's why I thought that the synthesizer would reject your code. There are two usual ways to fix that:[list][*]declare the port as 'buffer' instead. 'buffer' is like 'out', but allows a read feedback for registers. The problem is that if that signal is connected to another output port on the higher level component, it needs to be declared 'buffer' too instead of 'out'. That's why I call 'buffer' a viral port type, that needs to be propagated along all the hierarchy. I usually advise against it.[*]use a signal as temporary buffer, like you did on the nWE signal. This unnecessarily complicates the code, but lets you keep the 'out' port type[/list] 

This has been considered for a long time as one of the most stupid restrictions of VHDL. There has been a few changes to reduce this problem: in VHDL 2002, you can wire a 'buffer' port from a component to an 'out' port in an entity, removing the 'viral' constrain. In VHDL 2008, you can read back an 'out' port, removing the need for 'buffer' 

Most people stick to VHDL 1993 though, for the sake of compatibility. According to Murphy's law, the day you switch to VHDL 2008, you'll need to use an old tool that only understands VHDL 1993 ;). I also have some customers that require VHDL 1993, so just to be sure I won't have to rewrite everything one day, I still stick to that old standard.
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

Hmm... I figured out how to use SignalTap, but i don't get, why SRAM_clk is always '1'. I connected it to the PLL and its Pin is A2, but it just doesn't change?! 

Any idea what could go wrong? 

I also added the clk from the videosync inst and it doesn't change either. 

The other pins are changing though like expected except for the data pins... 

I am very confused now :|
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

You must remember that SignalTap does a sampling of all your signals with a clock. The signals are only sampled on the rising edge of that clock. If you used your SRAM_clk (or any other pll output at the same frequency) as the SignalTap sampling clock, then you will see SRAM_clk always at the same level. 

Try to keep nOE at 0 for a longer time, it may need an extra cycle. 

 

If you still have problems, try to make a screenshot of the signaltap outputs and post it here.
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

 

--- Quote Start ---  

In VHDL1993 you aren't allowed to read back the value of an 'out' port. 

--- Quote End ---  

- Yeah, i know, but i'm not trying to do it in my code or did i miss something? 

 

 

--- Quote Start ---  

This is a problem for registered outputs, because to maintain the value of a register between clock cycles, you need to be able to read it back. 

--- Quote End ---  

- Why do i want to do that? (except for the nWE signal for which i already did it)
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

You must think of the generated hardware. When you modify a signal in a clocked process, you in fact create a flip-flop that is able to hold a signal between clock edges. A flip flop needs a feedback of its output to function properly, and as a result in VHDL its output needs to be a signal that can be read back. Even if you don't explicitly read back a signal value, the generated hardware requires you to use a buffer. 

As for your other question, I would have normally answered that you would need to do it in order for your code to be accepted by the synthesizer, but obviously in your case it works. I have no explanation for this, in my experience Quartus always rejected my code when I forgot to put a buffer. I wonder if they changed anything in the synthesizer to silently accept that construction (last time I made that kind of mistake was probably with Quartus 7.2).
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

I added an extra cycle with nOE = 0 but nothing changed. I attached 2 screenshots of SignalTap, maybe you'll find something :) 

I don't get why the data signals behave like that, because i obviously put "11111111000000000000000000000000" in memoryData. :confused: 

 

Does the numbers in the timeline represent the clock cycles or what do they stand for?
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

ah... i just made a mistake here with SignalTap. I used the 50Mhz Input as the clock for SignalTap. Now it looks better, but it doesn't change anything at all for the data pins and the result :( 

If you have any code which will write and then read data from the SSRAM, i would be very thankful, if you would provide it to me. I looked in the internet for everything related to this and i found some sram controller but nothing ever worked. I didn't think it would be that hard to get the SSRAM to run, especially i looked through the data sheet and everything but to no avail. 

Thank you for your effort and if you have any idea, please let me know
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

 

--- Quote Start ---  

i don't get, why SRAM_clk is always '1' 

--- Quote End ---  

 

You're acquiring a 100 MHz clk with a 100 MHz sampling clock, what do you expect... 

 

You didn't mention the involved chip type, but the RAM signals don't look like correct SSRAM control.
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

 

--- Quote Start ---  

You didn't mention the involved chip type, but the RAM signals don't look like correct SSRAM control. 

--- Quote End ---  

What do you mean by that? I used all signals i found for the SSRAM in the cycloneIII reference manual or do you mean the timing and values of the signals? If so, would you mind correcting them? 

 

At the time when i took the screenshots (and wondered why SRAM_clk is always '1') my sampling clock was running at 50Mhz by accidence, as i stated in my last post. 

EDIT: oh wait, then of course it can't be otherwise too, because it's even slower... sorry, my bad :rolleyes: 

 

I also forgot the chip type, it's the ISSI IS61LPS25636A-200TQLI on the NEEK.
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

Because you don't show all SSRAM controls signals, I can't say, if there are more errors. But nCS and nWE respectively nOE have to be activated simultaneously, but you do sequentially. 

 

P.S.: Sorry, I see that the control signal is nADV, which has to be activated in front of read and write. Can youe tell about the state of the other control signals?
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

Ah, now i know what you mean. 

The other control signals are not accessible with the cycloneIII. 

nADV, nADSP, CE2, ZZ and MODE are hardwired i guess (at least it looks like that in the cycloneIII schematic). In the cycloneIII reference manual there are only the signals i used, so i think it's possible to use the SSRAM only with them 

 

P.S: i also tried activating nCS and nWE/nOE simultaneously, but i got the same result. do i need the signals nADV, nADSP or nADSC to perform a single write/read? i thought they are used to perform burst operations
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

Yes the numbers are clock cycles. If you can, try to regroup the address signals together. Then you'll get a single line with the address in hexadecimal form. You can do the same thing with the data. 

 

I think that you need to hold oen low for several cycles. The be_n* signals should also be low when you write. They are used to select which bytes to write in the 32-bit word.
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

 

--- Quote Start ---  

The be_n* signals should also be low when you write. 

--- Quote End ---  

 

Very true. It's a sufficient reason to make the test fail. If it still doesn't work, can you show a Signaltap recording with better time resolution? It's possible to generate a higher frequency sampling clock (e.g. 200 MHz) to see the bus signal timing.
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

Here you are. Hopefully you will find something, because i just don't get it why it shouldn't work :|

0 Kudos
Altera_Forum
Honored Contributor II
723 Views

I wonder, if SRAM_DATA (I guess, the top entity port) is correctly wired to memory_data? 

 

To check the RAM operation, a sequence like below should be performed: 

write data xx to address 1 

write data yy to address 2 

read from address 1 

read from address 2
0 Kudos
Altera_Forum
Honored Contributor II
723 Views

That was a pretty good idea, i think. As you can see, the data bus just changes the first 16 bits and the output enable doesn't even work at all (the sram doesn't put anything on the bus). I don't know why this happens though, maybe you got an idea? I tried the sequence two times with nADSC enabled before read/write operations and without it and it doesn't change anything.

0 Kudos
Altera_Forum
Honored Contributor II
603 Views

Did you change your code a lot since the first post? because both "data" and "memorydata" (from the first code) should be exactly the same when we_n is '0' (with at most one sample clock delay) but it doesn't seem to be the case. Are you sure you are looking at the right data signals?

0 Kudos
Reply