I have two 64Kx8 bit memory chips which I have connected to an FPGA configured using Qsys as a single 64Kx16 block. I have used a Generic Tri-state controller as interface, with both address width and data width set to 16:

enter image description here

Unfortunately, this doesn't produce the result I want (which is to have a single 128KB block of RAM with 16-bit access). My controller occupies only 64KB of address space. It looks like Qsys treats my SRAM as 32Kx16 block with 16-bit address bus which allows addressing individual bytes.

Is there a way to configure my controller in a way that makes the whole 128KB of memory accessible? Here's a diagram of connections between the chips:


simulate this circuit – Schematic created using CircuitLab

  • 2
    \$\begingroup\$ To be sure - chips are SRAM (24512-15), not DRAM and not SDRAM? Then why not just design very simple memory controller which would set address, wait required number of cycles and get data read (or have data written)? \$\endgroup\$ – Anonymous Apr 9 '17 at 19:09
  • 1
    \$\begingroup\$ @Anonymous, but that's not providing an answer, that's trying to redefine the question :-) \$\endgroup\$ – TonyM Apr 9 '17 at 19:38
  • 1
    \$\begingroup\$ Oh, duh. You should set the address width to 17 bits and not use the LSB. The addresses on the Tri-State controller are always byte address, not word addresses. As long as you are always writing both bytes at the same time, and always write to even addresses, it is safe to drop the LSB. \$\endgroup\$ – Tom Carpenter Apr 9 '17 at 21:34
  • 1
    \$\begingroup\$ @DmitryGrigoryev the way you have connected your RAM, single byte access is not possible (you would have to do manual Read-Modify-Write). The Avalon-MM fabric that is added between the pipeline bridge and the memory will convert the LSB into a byte-enable signal, so if in the future you added byte-enable signals to you memory ICs, you won't need to recompile anything. \$\endgroup\$ – Tom Carpenter Apr 10 '17 at 8:29
  • 1
    \$\begingroup\$ @DmitryGrigoryev Sadly you have to do R-M-W yourself. Qsys systems end up with quite a lot of random IP cores which do pretty much nothing but rearrange signals. It's the price you pay for graphical interfaces. The huge system I've developed over the years has pretty much 1000 IP core instances, of which probably 50-75% are purely custom pass-through cores there solely to get Qsys to connect things up properly. \$\endgroup\$ – Tom Carpenter Apr 10 '17 at 9:32

The issue is one of how Qsys treats addresses. There are two ways in which an Avalon-MM interface can represent its address - as a "symbol address", and as a "word address".

For slaves which are defined with an address unit of SYMBOLS, the LSB represents one symbol (aka the width of one unit in the data bus, e.g. a byte). For an address defined in units of WORDS, the LSB represents one word (aka the width of the data bus). In the case of the Generic Tristate Controller, its Avalon-MM interface is defined in terms of symbols as indicated in the screenshot below:

Address Units

What this means is that the LSB represents a single 8bit symbol. You have 128k symbols of memory which means you need to specify a 17bit address not a 16bit address. The extra bit is due to the fact that you have two symbols per word.

To interface with your memory, you then simply ignore the LSB. The only thing to make sure of when doing this is that you always access the correct address (with LSB tied to zero), and always perform 16bit data accesses by making sure the both byte enable bits are high.

If you want to convert the address units to WORDS, the simplest way is to insert an Avalon-MM Pipeline Bridge. Set the following parameters:

  • Data Width to 16
  • Symbol Width to 8
  • Address Units to WORDS
  • Check the box saying "Use automatically-determined address width"
  • Uncheck both "Pipeline Command Signals" and "Pipeline Response Signals".

You should find that it calculates a word address width of 16 bits. All accesses on the slave of the pipeline bridge will now be in terms of word addresses meaning it will have a 16bit address bus. By unchecking the "Pipeline" boxes, the resulting IP core will have no logic in it at all - it will simply pass through all signals directly.

Qsys will automatically insert Avalon-MM fabric components to map the Word addressed master of the pipeline bridge to the Symbol addressed slave of the Generic Tristate Controller, taking care of translating the 16bit word address to a 17bit symbol address for you.

In case you are wondering, I know this works because I came across the same issue with a CFI device on one of the dev kits I am using whereby it was two separate ICs connected together in parallel - though in that case it was two 16bit ICs forming a 32bit bus, and I needed byte level access so the connections got slightly more tricky.

  • \$\begingroup\$ Excellent and definitive answer, upvoted. Why on earth couldn't they use the universally-accepted word 'byte' instead of 'symbol'? \$\endgroup\$ – TonyM Apr 9 '17 at 22:34
  • 1
    \$\begingroup\$ @TonyM because a symbol is not necessarily a byte, it can be any width. A word is the width of the data bus, so it is also possible for word and symbol to both be the same width. \$\endgroup\$ – Tom Carpenter Apr 9 '17 at 22:41
  • \$\begingroup\$ Ah, I got the wrong end of the stick :-) Thanks, Tom. \$\endgroup\$ – TonyM Apr 9 '17 at 22:45
  • \$\begingroup\$ Hi Tom, I got it working by assigning a 17-bit address to the tri-state controller and ignoring the LSb. Interestingly, inserting a bridge between the controller and the CPU to convert words to symbols didn't have any effect: no matter how I configured the Address Units and Address width, I still have to give my controller a 17-bit address for the RAM test to pass. So I ended up removing the bridge altogether. \$\endgroup\$ – Dmitry Grigoryev Apr 11 '17 at 9:47
  • \$\begingroup\$ @DmitryGrigoryev assuming you are using Nios, all addresses are always byte addresses in Nios, regardless of the interface (it does the conversion internally). \$\endgroup\$ – Tom Carpenter Apr 11 '17 at 10:09

I did not use this IP, but what I see from the picture:

  • address width: 16 bits, this means there will be 65536 words of data width;
  • data width: 16 bits, this means 2 bytes;
  • bytes per words: 2, which is 16/2=8 seems to be correct value;
  • byte enable width: 2, meaning 2 wires which disable/enable action on hi-low bytes of the data width of 16 bits (however byte enable is disabled = controller will read/write whole 16-bit data bus, no partial access).

Controller sees 65536 words by 16 bytes, thus 128 kilobytes, and assumes that it can access 16 bits at once not being able to mask respective byte in the word.

How did you connect SRAM chips? Just connected two chips in parallel with address lines and CE/OE?


My controller occupies only 64KB of address space


and unaligned access to this RAM fails

Controller sees 16 bit data, and can read/write only in 16-bit words. To get byte out of it you need to check lowest bit of 17-bit address (with highest 16-bit address being on A0-A15 lines), and activate respective chip (using its CE) for operation, then multiplex data from/to respective data group (A0-A7 or A8-A15). But if you connected CEs together you will not be able to access chips separately.

CEs should act as 17th bit of the address. What I explained above is just one of the options how it can be implemented. You need to revise your circuit, and as I said in the comment to your question, it would be much simpler and effective to design your own controller (and this controller may be more predictable).

Update after circuit diagram addition:

In this configuration whole 128 kilobytes are addressable, but only in 16-bit words. You will not be able to address RAM in individual 8-bit words (bytes).

However what you can do with it: you may consider enabling byte enable, and attaching chip select to byte enable signals. However, anyway, you will have to multiplex data from D7-D0 or D15-D8 into 8-bit register in FPGA.

  • \$\begingroup\$ It's only simpler if the OP has the experience and confidence to define a controller and it's only effective if they have the time and funds to design, develop, testbench, prove and document it. Doing the latter properly is a couple of days work at least, maybe a week. How is that simpler and more effective than pulling up IP they should take an hour? This OP's having trouble but loads of people will have used it that quickly. Can you explain that one to me? :-) \$\endgroup\$ – TonyM Apr 9 '17 at 19:45
  • \$\begingroup\$ @TonyM sure you are right, that's why these building blocks are in there. Connection circuit will define the exact answer. How address is connected, CE, OE? \$\endgroup\$ – Anonymous Apr 9 '17 at 19:47
  • \$\begingroup\$ Correct and the rest of the stuff you're answer covers is good stuff. \$\endgroup\$ – TonyM Apr 9 '17 at 19:49
  • \$\begingroup\$ I could add a 17-th bit of address, but that sound like a dirty workaround since I don't want to access individual bytes (and in my configuration it's impossible anyway) \$\endgroup\$ – Dmitry Grigoryev Apr 9 '17 at 20:27
  • \$\begingroup\$ See update to the answer. Then what you mean when saying in question "unaligned access to this RAM fails"? You want access to be aligned to what? You have 65536 words of 16-bit width. \$\endgroup\$ – Anonymous Apr 9 '17 at 20:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.