Thursday, December 22, 2011

Little Endian support in MicroBlaze: Application Notes

Little Endian support is added to MicroBlaze in EDK 12.3 by adding AXI bus support. This notes focuses on the differences in MicroBlaze core and features added by each EDK version, and software changes needed for Little Endian support.

EDK Version History

ISE Design Suite 12.3
ISE Design Suite 13.1
ISE Design Suite 13.2 & 13.3
  • MicroBlaze version V8.20.a
Software Changes
 Since the MicroBlaze CPU as well as the AXI bus both supports Little Endian, there is no specific changes required except for the following conditions:

1) Reading or writing data using different type of pointers
 

For example, reading an half-word using word pointer. Writing a byte to a word pointer. For example, in AXI UART 16550 driver,  for Big endian, the data byte has to be read or written in address (C_BASEADDR + 0x1000 + 3). For Little Endian, (C_BASEADDR + 0x1000) address has to be read/write.

2) Byte array is merged into half-word or word

For example, in AXI Ethernet Lite driver, when writing MAC address to transmit dual port memory, for Big Endian, it has to be written as follows:

Word 0 = (MAC[0] << 24) | (MAC[1] << 16) | (MAC[2] << 8) | MAC[3];
Word 1 = (MAC[4] << 24) | (MAC[5] << 16)

For Little Endian, it has to be written as follows:

Word 0 = (MAC[3] << 24) | (MAC[2] << 16) | (MAC[1] << 8) | MAC[0];
Word 1 = (MAC[5] << 8) | MAC[4]

In similar way, when reading Ethernet packet type and packet length from AXI Ethernet Lite receive dual port memory, the code should be as follows:

unsigned char *dpm_buf;

Ethernet packet type = (dpm_buf[12] << 8) | dpm_buf[13]
Packet data length = (dpm_buf[16] << 8) | dpm_buf[17]

Otherwise, if you read these fields as word or halfword, you need to convert them explicitly by ntohl/ntohs functions or lwr/lhur instructions.

3) Half-word or word is converted into byte array


4) Self-modifying code
 

If you use self-modifying code, please update it as specified in "Self-modifying Code" section of MicroBlaze Processor Reference Guide for EDK 13.3.
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_3/mb_ref_guide.pdf

5) Memory Barrier Instruction
In places where memory synchronization is required, use the (mbar) memory barrier instruction.

Condtional Assembly in GCC
 

Sometimes you may need to conditionally assemble your assembly source using the predefined compiler macros in GCC. However, the compiler predefined macros are not accessible in GCC assembler. You may need to change the file extension of your assembly source into capital S, ".S" (not small '.s') and use C style #ifdef..#else..#endif. For example, to conditionally assemble your assembly source according to endian, use the constructs as follows:

#ifdef __LITTLE_ENDIAN__
#else
#endif

or

#ifdef __BIG_ENDIAN__
#else
#endif


But, the compiler flag is -mlittle-endian for little endian and -mbig-endian for big endian.

Enjoy the FPGA!

No comments: