MicroBlaze & SRAM

I have an EDK design with a MicroBlaze processor and use the External Memory Controller (EMC) to get access to off-chip SRAM.

I access the SRAM from c using a pointer and have a loop in my program that writes a value and increments the pointer to the next address.

As I am using a pointer to type integer it is increased by 4 locations each time I increment it. The SRAM I am accessing however is 32 bits wide so I am not getting access to the full memory capacity. Is there a setting somewhere for the compiler to tell it to increase by 1 address location or am I using the wrong approach.

I am a beginner with this technology so apologies if this is a dumb question.

>>>

int *sram_addr_data; int i;

sram_addr_data=(int *) XPAR_SRAM0_MEM0_BASEADDR; for(i=0;i>>>

Reply to
Ben G
Loading thread data ...

Ben,

Since you are pointing to a 32-bit value (int), incrementing a pointer to this a value of this type will add the sizeof(int) to the address. Since MicroBlaze addresses are on byte boundaries, the address will be incremented by 4 (32 bits = 4 bytes).

To increase your address by 1 byte, change the type of the variable you are pointing to to a char, which has sizeof(char) = 1 byte.

Matt

Ben G wrote:

Reply to
Matthew Ouellette

You are getting access to full capacity. Addresses are always byte addresses. Integers are 4 bytes wide. When you move from one integer in an array to the next, the address differs by 4.

Cheers, Jon

Reply to
Jon Beniston

Thanks for your help Matt.

I had tried using a char pointer as you suggested but the values I want to write out are 32 bit integers, when I use a char pointer the correct value is not written to SRAM. I have shown a section from the terminal window below that shows this. Have I misinterpreted your suggestion for using a char pointer or can you see a mistake I'm making.

Mem[80F0007E]=126

Mem[80F0007F]=127

*** Error @ Mem[80F00080]=-128 Expected=128***

*** Error @ Mem[80F00081]=-127 Expected=129*** >>

If I use a pointer but set the addresses manually as below it works. I set the value of i to a large integer value and then increment it for each location but set the address directly in the code.

i=268435456; sram_addr_data=(int *) 0x80F00000;

*sram_addr_data = i; i++; sram_addr_data=(int *) 0x80F00001; *sram_addr_data = i; i++; sram_addr_data=(int *) 0x80F00002; *sram_addr_data = i; i++; sram_addr_data=(int *) 0x80F00003; *sram_addr_data = i; i++;

sram_addr_data=(int *) 0x80F00000; mem_fill = *sram_addr_data; xil_printf("\n\rMem[%x]=%d",(int *) sram_addr_data, mem_fill); sram_addr_data=(int *) 0x80F00001; mem_fill = *sram_addr_data; xil_printf("\n\rMem[%x]=%d",(int *) sram_addr_data, mem_fill); sram_addr_data=(int *) 0x80F00002; mem_fill = *sram_addr_data; xil_printf("\n\rMem[%x]=%d",(int *) sram_addr_data, mem_fill); sram_addr_data=(int *) 0x80F00003; mem_fill = *sram_addr_data; xil_printf("\n\rMem[%x]=%d",(int *) sram_addr_data, mem_fill); >>

This code results in the correct display in the terminal window but if I try to put this in a loop to do it automatically how do I get the pointer address to increment the way I need.

The SRAM device I am connecting to has a 19 bit address bus and a 32 bit data bus. Am I right in thinking I should have 2^19 i.e. 524288 addresses each capable of holding 4 bytes therefore 2097152 bytes. This corresponds to the documentation which says the device is 2M. Using the code in my origibal post I am only getting access to a quarter of this.

Again thanks for your assitance, it is much appreciated.

Matthew Ouellette wrote:

Reply to
Ben G

I wonder how you have connected the SRAM to microblaze?

In particular please describe the low order bits of the address bus from the processor, and the low order address bits of the SRAM.

I am guess>I had tried using a char pointer as you suggested but the values I want

If you only do word (4 byte) reads and writes, you probably need something like this:

Address pins CPU SRAM

0 no connection 1 no connection 2 0 3 1 4 2 etc.

If you need byte reads and writes, then your SRAM must support this, and you use the CPU address bits 0 and 1 to select the byte.

Philip

Because the C compiler probably generated a byte write, not a word write

Neither xxxx7E or xxxx7F are word addresses. Word addresses always have the lower 2 bits set to 0, and are not used, as per the description I gave above.

The following code certainly matches my guess that you have not connected the address bus up correctly. That is, you are issuing word writes because you have declared sram_addr_data as an address to an int, yet you are using addresses that are byte addresses (non 0 for two lsbs)

I think the thing you need to grasp is that both byte and word accesses use the same address bits. For words, only every 4th address is valid. i.e. addresses 0, 4, 8, 12, 16, 20, .... This is called aligned access

You can also do byte addressing with these values, and all the ones in between.

Most RISC CPUs run this way. Other CPUs, such as the x86 devices allow un-aligned access, such as a word access from 3, but what actually happens is that the CPU does 2 accesses, to 0 and 4, and then assembles the word from byte 3 in the first word, and bytes 4, 5, and 6 in the second word. Most RISC CPUs dont do this, including microblaze.

If the pointer is an int * then the following

pointer++

will be incremented by 4, which will point to the next word.

If the pointer is an char * then the following

pointer++

will be incremented by 1, which will point to the next byte.

Yes

Because I think you have not connected the address bus up correctly.

Philip

Philip Freidin Fliptronics

Reply to
Philip Freidin

Philip,

many thanks for your help, using your suggestion I am now able to access the full SRAM device. I had connected addr bit 0 to SRAM addr bit 0 not realising this was incorrect, your description was spot on.

Ben.

Reply to
Ben G

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.