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
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!
EDK Version History
ISE Design Suite 12.3
- http://www.xilinx.com/support/documentation/sw_manuals/xilinx12_4/whatsnew.htm#124
- MicroBlaze Core version 8.00a
- Little Endian (AXI bus) is introduced
- http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_3/irn.pdf
- MicroBlaze version V8.10.a
- The following two new instructions are added:
- Count Leading Zeros (CLZ)
- Memory Barrier (MBAR)
- MicroBlaze version V8.20.a
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!