Verilog系列:大小端
在计算机系统设计的过程中,经常会遇到数据存放的大小端(Endian)问题,也即数据在存储器中的存放顺序问题.如果没有对数据在存储器中存放的大小端没有正确的理解,那么极有可能导致想要的结果与期望不一样.为了加深对于大小端的理解,我们可以通过一个小故事来了解大小端的来历. “endian”一词来源于十八世纪爱尔兰作家乔纳森·斯威夫特(Jonathan Swift)的小说《格列佛游记》(Gulliver's Travels)。小说中,小人国为水煮蛋该从大的一端(Big-End)剥开还是小的一端(Little-End)剥开而争论,区别在于一派要求从鸡蛋的大头把鸡蛋打破,另一派要求从鸡蛋的小头把鸡蛋打破,争论的双方分别被称为“大端派”和“小端派”。作者借由该小说讽刺英国的政党之争。就像大小国而在实际的应用过程中,人们对于使用哪种字节的排序还是存在着各种分歧.在1980年,丹尼·科恩(Danny Cohen),一位网络协议的早期开发者,在其著名的论文"OnHoly Wars and a Plea for Peace"中,为平息一场关于字节该以什么样的顺序传送的争论,而第一次引用了该词。
在哪种字节顺序更合适的问题上,人们表现得非常情绪化,实际上,就像鸡蛋的问题一样,没有技术上的原因来选择字节顺序规则,因此,争论沦为关于社会政治问题的争论,只要选择了一种规则并且始终如一地坚持,其实对于哪种字节排序的选择是任意的。
在计算机系统中,每个地址单元对应着一个字节,一般情况下一个字节为8位,但是在C语言中除了8位的char之外,还有16位的short型\32位的long型(不同编译器可能不同),对于数据存储位数大于8位的处理器(16位或者32位等)来说,那么必然存在如何将多个字节的数据进行顺序存储.在具体应用过程中出现了大小端的数据存储方式.例如, X86架构的处理器采用的的是小端模式(目前Intel X86是唯一坚持使用小端模式的架构),C51采用的是大端模式,大部分ARM和DSP均采用小端模式,有些ARM处理器可以随时在程序中对大小端模式进行切换,MIPS等要么全部采用大端方式要么提供选项支持大端模式,即大小端可切换.另外,在C语言中,默认采用的是小端模式,JAVA采用的是大端模式.
【示例】
、下面将上述数据按照大小端方式分别进行存储。
【Big-Endian】:低地址存放数据高位
高位地址 | addr[3] | data[7:0] | 'h78 |
| addr[2] | data[15:8] | 'h56 |
addr[1] | data[23:16] | 'h34 | |
低位地址 | addr[0] | data[31:24] | 'h12 |
如果按照不同的数据传输类型,那么每次传输的数据格式如下:
传输类型 | 偏移地址 | 'h12 | 'h34 | 'h56 | 'h78 |
data[31:24] | data[23:16] | data[15:8] | data[7:0] | ||
字 | 0 | √ | √ | √ | √ |
半字 | 0 | √ | √ | - | - |
半字 | 2 | - | - | √ | √ |
字节 | 0 | √ | - | - | - |
字节 | 1 | - | √ | - | - |
字节 | 2 | - | - | √ | - |
字节 | 3 | - | - | - | √ |
【Little-Endian】:低地址存放数据低位
高位地址 | addr[3] | data[31:24] | 'h12 |
| addr[2] | data[23:16] | 'h34 |
addr[1] | data[15:8] | 'h56 | |
低位地址 | addr[0] | data[7:0] | 'h78 |
如果按照不同的数据传输类型,那么每次传输的数据格式如下:
传输类型 | 偏移地址 | 'h12 | 'h34 | 'h56 | 'h78 |
data[31:24] | data[23:16] | data[15:8] | data[7:0] | ||
字 | 0 | √ | √ | √ | √ |
半字 | 0 | | | √ | √ |
半字 | 2 | √ | √ | | |
字节 | 0 | - | - | - | √ |
字节 | 1 | - | - | √ | - |
字节 | 2 | - | √ | - | - |
字节 | 3 | √ | - | - | - |