最近在做一些嵌入式软件相关的工作,经常涉及到对于FPGA寄存器的相关操作。而对于寄存器的操作,软件这边通常是把数据进行组装为一个固定位宽(8bit, 16bit)的数通过localbus总线写到寄存器中。
1. 原码,反码,补码
计算机中的数据都是以二进制的形式进行存储的,确切的说是以二进制补码的形式进行存储的。
正数:对于一个正数来说,其原码,反码,补码均为其自身。
负数:对于一个负数,在C语言里面,char类型占据一个字节,8位,大小是-128~127。反码是符号位保持
不变,其他的变为相反。补码则是在反码的基础上在低位加上1。
注意,-128这一类型的数是没有原码和反码的,只有补码。
补充:+0,-0的原码,反码,补码
+0 00000000 00000000 00000000
-0 10000000 111111111 00000000
2. 位运算的基本运算符
如图所示的是位运算的四个符号。
image.png按位取反:~(10011010) = 01100101
按位与: (10010011)& (00111101) = 00010001
按位或: (10010011) | (00111101) = 10111111
按位异或: (10010011) ^ (00111101) = 10101110
左移:(10001010)<< 2 = 00101000
右移: (10001010) >> 2 = 11100010
不管是有符号书还是无符号数,左移的话,直接丢弃高位,0补最低位。右移的话,符号位会保持不变
对于有符号数,右移之后会在最高位补1。
3. 位运算的常见用法
- 数据拼接
在嵌入式中,数据通常写到8bit或者16bit的寄存器中,因此对于每一bit都要赋予相应的值以供逻辑(FPGA)使用。如一个16bit的寄存器,需要存储的数据是2bit的命令,6bit的地址,8bit的具体数据。而此时给出的命令,地址以及具体数据均为一个unsigned int型(32位,但是有效位分别只有2,6,8)的数据。
unsigned int cmd = 0x1; unsigned int addr = 0x8; unsigned int data = 0xff;
命令,地址,数据在寄存器中以高位到低位的方式进行存储。
那么该16bit寄存器数据可以表示为
unsigned int regData = ((cmd << 14) & 0xffff) + ((addr << 8) & 0xffff) + ((data) & 0xffff);
其实本质就是通过数据的移位将需要到数据bit放到组合后数据相应的位中去即可。
网友评论