FPGARelated.com
Forums

MicroBlaze & SRAM

Started by Ben G September 27, 2004
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<NUM_LOOP;i++)
{      	
	*sram_addr_data = i;
	sram_addr_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:
> 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<NUM_LOOP;i++) > { > *sram_addr_data = i; > sram_addr_data++; > } > > >>>>
Ben G <nospam@nospam.nospam> wrote in message news:<2rqnfnF1d29pnU1@uni-berlin.de>...
> 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.
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
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:
> 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 >
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 guessing you have CPU addr bit 0 to SRAM addr bit 0.
This is not correct.

On Tue, 28 Sep 2004 11:02:30 +0100, Ben G <nospam@nospam.nospam> wrote:
>I had tried using a char pointer as you suggested but the values I want >to write out are 32 bit integers
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
>when I use a char pointer the correct value is not written to SRAM.
Because the C compiler probably generated a byte write, not a word write
>Mem[80F0007E]=126 > >Mem[80F0007F]=127
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.
>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.
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=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++;
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.
>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.
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.
>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.
Yes
>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.
Because I think you have not connected the address bus up correctly. Philip Philip Freidin Fliptronics
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.