I'm interfacing an FPGA to a multiplexed SRAM port (ALE, READ, WRITE, DATA/ADDR bus). I want to read from/write to the FPGA internal block RAM (SPARTAN 3E), using burst accesses. This is a write access example. ____ ALE ___/ \__________________________________________________ _______________ __ __ __ ______ WRITE# \______/ \______/ \______/ \______/ ________ ________ ________ ________ ________ DTADD ____/ ADDR \/ DATA0 \/ DATA1 \/ DATA2 \/ DATA3 \______ \________/\________/\________/\________/\________/ For the address load and increment I combined ALE, READ and WRITE signals to generate one clock signal. CLOCK <= WRITE# and READ# and (not ALE); The problem is, to determine if I must load a new address I must know if it is the ALE cycle: if rising_edge (CLOCK) then if (ALE = '1') then -- problem ADDRESS_REG <= DTADD; else ADDRESS_REG <= ADDRESS_REG+1; end if; end if; But the clock is a delayed version ALE, READ# and WRITE#, so the setup/hold times will no be met! What's the best way of doing this? Of course I can use an auxiliar signal: if rising_edge (ALE) then LOAD_ADDR <= '1'; end if; if ((WRITE# = '0') or (READ# = '0')) then -- asyncronous clear LOAD_ADDR <= '0'; end if; And substitute: if (ALE = '1') then for: if (LOAD_ADDR = '1') then But now I have two clock sources/nets (CLOCK and ALE)! Any suggestions? Luiz Carlos
FPGA to SRAM port interface
Started by ●October 9, 2006
Reply by ●October 9, 20062006-10-09
oen_br schrieb:> I'm interfacing an FPGA to a multiplexed SRAM port (ALE, READ, WRITE, > DATA/ADDR bus). > I want to read from/write to the FPGA internal block RAM (SPARTAN 3E), > using burst accesses. > > This is a write access example. > ____ > ALE ___/ \__________________________________________________ > _______________ __ __ __ ______ > WRITE# \______/ \______/ \______/ \______/ > ________ ________ ________ ________ ________ > DTADD ____/ ADDR \/ DATA0 \/ DATA1 \/ DATA2 \/ DATA3 \______ > \________/\________/\________/\________/\________/ > > For the address load and increment I combined ALE, READ and WRITE > signals to generate one clock signal. > CLOCK <= WRITE# and READ# and (not ALE);Clock signal for what? The BRAM inside the FPGA? NO WAY!> The problem is, to determine if I must load a new address I must know > if it is the ALE cycle: > > if rising_edge (CLOCK) then > if (ALE = '1') then -- problem > ADDRESS_REG <= DTADD; > else > ADDRESS_REG <= ADDRESS_REG+1; > end if; > end if; > > But the clock is a delayed version ALE, READ# and WRITE#, so the > setup/hold times will no be met! > > What's the best way of doing this?Use a clean clock (from a XO or so) to clock the FPGA logic. Not clock gating etc.! Build text book style FSMs to contol the BRAM and generate appropiate signals for your external SRAM. Than it will work fine. Hint. Register at least WRITE# to the SRAM, so it will not glitch.> But now I have two clock sources/nets (CLOCK and ALE)!No, you have just one system clock, that generates all other signals. A clean 1 clock design. Just too easy ;-) Regards Falk
Reply by ●October 9, 20062006-10-09
Hi Falk,> Clock signal for what? The BRAM inside the FPGA? NO WAY!Yes, for the BRAM too. Why not? The ALE, READ# and WRITE# signals will never overlap!> Use a clean clock (from a XO or so) to clock the FPGA logic. Not clock > gating etc.! Build text book style FSMs to contol the BRAM and generate > appropiate signals for your external SRAM. Than it will work fine. > > Hint. Register at least WRITE# to the SRAM, so it will not glitch.I don't know what 'XO' means, but I think you mean a crystal (it reminded me Galactica Colonel Tigh :-) ). Anyway the tranfer rate is 60MHz (mega transfers per second), so, to sample ALE, etc, I will need a very high frequency clock signal (200MHz maybe?). Even if it is possible, it will spend a lot of power! Did I misunderstand you? There is no external SRAM, just the internal BRAM used as a mail box! Two processors, each one using one BRAM port. Thank's, Luiz Carlos.
Reply by ●October 9, 20062006-10-09
oen_br wrote:> I'm interfacing an FPGA to a multiplexed SRAM port (ALE, READ, WRITE, > DATA/ADDR bus). > I want to read from/write to the FPGA internal block RAM (SPARTAN 3E), > using burst accesses. > > This is a write access example. > ____ > ALE ___/ \__________________________________________________ > _______________ __ __ __ ______ > WRITE# \______/ \______/ \______/ \______/ > ________ ________ ________ ________ ________ > DTADD ____/ ADDR \/ DATA0 \/ DATA1 \/ DATA2 \/ DATA3 \______ > \________/\________/\________/\________/\________/ > > For the address load and increment I combined ALE, READ and WRITE > signals to generate one clock signal. > CLOCK <= WRITE# and READ# and (not ALE); > > The problem is, to determine if I must load a new address I must know > if it is the ALE cycle: > > if rising_edge (CLOCK) then > if (ALE = '1') then -- problem > ADDRESS_REG <= DTADD; > else > ADDRESS_REG <= ADDRESS_REG+1; > end if; > end if;In order for the CLOCK signal to go high, ALE must be low, in your logic, since (not ALE) is AND'd with WRITE# and READ#. So that implies inside your 'if' the ALE='1' can never be true. Perhaps changing your logic to falling_edge(CLOCK) might fix it within your approach. Or invert the CLOCK signal from what it is now. -Dave -- David Ashley http://www.xdr.com/dash Embedded linux, device drivers, system architecture
Reply by ●October 10, 20062006-10-10
> In order for the CLOCK signal to go high, ALE must > be low, in your logic, since (not ALE) is AND'd with > WRITE# and READ#. So that implies inside your > 'if' the ALE='1' can never be true. > > Perhaps changing your logic to falling_edge(CLOCK) > might fix it within your approach. Or invert the CLOCK > signal from what it is now.Hi David, The clock is right, I need to load the address at the falling edge of ALE. If you consider ALE falling edge generated the rising clock edge, ALE must be low at this point. So, ok, it should be "if (ALE = '0') then". But I'm not sure if the time taken by logic (inverting and anding ALE), and buffering this signal/clock will offer the sufficient setup time for the test. I mean, will it always work? Can I change the speed grade or the family of the FPGA ? Do I need to use some type of time constraint? Luiz Carlos
Reply by ●October 10, 20062006-10-10
oen_br schrieb:>>Clock signal for what? The BRAM inside the FPGA? NO WAY! > > > Yes, for the BRAM too. Why not? > The ALE, READ# and WRITE# signals will never overlap!You better learn about synchronous design. And glitching of clocks.> I don't know what 'XO' means, but I think you mean a crystal (itYes.> reminded me Galactica Colonel Tigh :-) ). > Anyway the tranfer rate is 60MHz (mega transfers per second), so, to > sample ALE, etc, I will need a very high frequency clock signal (200MHz > maybe?). Even if it is possible, it will spend a lot of power! > Did I misunderstand you?> > There is no external SRAM, just the internal BRAM used as a mail box! > Two processors, each one using one BRAM port.Ahhhh, the FPGA is used to connect two processors, right? Hmm, in this xase why do you want to use a FPGA? There are dedicaded dual port memories, ready to use. www.idt.com Regards Falk
Reply by ●October 10, 20062006-10-10
oen_br wrote:>>In order for the CLOCK signal to go high, ALE must >>be low, in your logic, since (not ALE) is AND'd with >>WRITE# and READ#. So that implies inside your >>'if' the ALE='1' can never be true. >> >>Perhaps changing your logic to falling_edge(CLOCK) >>might fix it within your approach. Or invert the CLOCK >>signal from what it is now. > > > Hi David, > > The clock is right, I need to load the address at the falling edge of > ALE. > If you consider ALE falling edge generated the rising clock edge, ALE > must be low at this point. > So, ok, it should be "if (ALE = '0') then". > But I'm not sure if the time taken by logic (inverting and anding ALE), > and buffering this signal/clock will offer the sufficient setup time > for the test. I mean, will it always work? Can I change the speed grade > or the family of the FPGA ? > Do I need to use some type of time constraint? > > Luiz Carlos >The whole point is you want to write the first data at the address specified, the next data at the next address... what if when you load the first address you do a "-1" calculation right then? So when the first data is to get loaded, it does its "+1" and you're at the real address you wanted. So you are loading the address right at the start of each cycle, plenty of setup + hold time in all cases. I just don't like your logic of testing ALE inside the clocked section -- when the clock itself depends on ALE. This is really questionable, get that out of the picture and things will get simpler. -Dave -- David Ashley http://www.xdr.com/dash Embedded linux, device drivers, system architecture
Reply by ●October 10, 20062006-10-10
David Ashley wrote:> oen_br wrote: > >>>In order for the CLOCK signal to go high, ALE must >>>be low, in your logic, since (not ALE) is AND'd with >>>WRITE# and READ#. So that implies inside your >>>'if' the ALE='1' can never be true. >>> >>>Perhaps changing your logic to falling_edge(CLOCK) >>>might fix it within your approach. Or invert the CLOCK >>>signal from what it is now. >> >> >>Hi David, >> >>The clock is right, I need to load the address at the falling edge of >>ALE. >>If you consider ALE falling edge generated the rising clock edge, ALE >>must be low at this point. >>So, ok, it should be "if (ALE = '0') then". >>But I'm not sure if the time taken by logic (inverting and anding ALE), >>and buffering this signal/clock will offer the sufficient setup time >>for the test. I mean, will it always work? Can I change the speed grade >>or the family of the FPGA ? >>Do I need to use some type of time constraint? >> >>Luiz Carlos >> > > > The whole point is you want to write the first data at > the address specified, the next data at the next address... > what if when you load the first address you do a "-1" > calculation right then? So when the first data is to > get loaded, it does its "+1" and you're at the real > address you wanted. So you are loading the address > right at the start of each cycle, plenty of setup + hold > time in all cases. > > I just don't like your logic of testing ALE inside the > clocked section -- when the clock itself depends on > ALE. This is really questionable, get that out of the > picture and things will get simpler. > > -Dave >I've been looking at this more...it seems easy on the face of it but it's somewhat complicated. You want when ALE goes from high to low for the address latch to get the initial address you want to load. And when READ# or WRITE# go from low to high, you want the address latch to get its current value plus one. This implies 2 clocks...which is out of my experience but I suspect isn't synthesizable. Now, if you could have a set-reset latch in the picture that would make everything easy. When ALE is high, the SR goes to 1. When READ# or WRITE# go low, the SR goes to 0. Your original post had the LOAD_ADDR signal getting set when there was a rising_edge of ALE, and an async clear when READ# or WRITE# go low, which is the 2 clock problem in the first place. When would do it is an async set instead of the clocked set. You don't need any clocking on this. I suppose you could describe the logic as 2 nand gates. I looked at xst.pdf and couldn't find a simple set/reset flip flop. Unisim has an entity FDCP which is: D Flip-Flop with Asynchronous Clear and Preset architecture FDCP_V of FDCP is begin VITALBehavior : process(C, CLR, PRE) variable FIRST_TIME : boolean := true ; begin if (FIRST_TIME = true) then Q <= TO_X01(INIT); FIRST_TIME := false; end if; if (CLR = '1') then Q <= '0'; elsif (PRE = '1') then Q <= '1'; elsif (rising_edge(C)) then Q <= D after 100 ps; end if; end process; end FDCP_V; So that would translate to if ALE = '1' then LOAD_ADDR <= '1'; else if READ# = '0' or WRITE# = '0' then LOAD_ADDR <= '0'; end if; However this is an implied latch...which is probably ok in this instance because there is no combinatorial feedback. I'm in over my head. I wish one of the gurus would offer some advice here. :) -Dave -- David Ashley http://www.xdr.com/dash Embedded linux, device drivers, system architecture
Reply by ●October 10, 20062006-10-10
oen_br wrote:> ____ > ALE ___/ \__________________________________________________CLK _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-> _______________ __ __ __ ______ > WRITE# \______/ \______/ \______/ \______/ > ________ ________ ________ ________ ________ > DTADD ____/ ADDR \/ DATA0 \/ DATA1 \/ DATA2 \/ DATA3 \______ > \________/\________/\________/\________/\________/ >> But the clock is a delayed version ALE, READ# and WRITE#, so the > setup/hold times will no be met!No, you want the continuous clock that generated ALE. In a synchronous system, ALE is an input, not a clock. -- Mike Treseler
Reply by ●October 10, 20062006-10-10
> You better learn about synchronous design. And glitching of clocks.Falk, I'm aware of the danger of gererated clocks, but in this case I couldn't see any problem (at least until now). The signals are clean and have some nano-seconds between their activation.> Ahhhh, the FPGA is used to connect two processors, right? > Hmm, in this xase why do you want to use a FPGA? There are dedicaded > dual port memories, ready to use.Not really. The FPGA, besides other functions, connects 4 DSPs, a shared external SRAM and a PCI controller, everybody talking to everybody. I thought this kind of problem was very common (combinatorial clocks using it's source signals as clock enables)! Thanks, Luiz Carlos






