第二章:数制与编码——二进制、八进制、十六进制及其转换,原码、反码、补码,格雷码与BCD码

各位同学,欢迎来到第二章。这一章的内容,说白了就是数字电路的“语言基础”。你想想看,我们平时用的十进制,在FPGA的世界里根本行不通。FPGA只认0和1,也就是二进制。所以,搞懂数制转换和编码,是咱们入行的第一道门槛。

我个人习惯,在开始讲新项目前,一定会先确认数据格式。是二进制?还是BCD码?搞错了,整个逻辑都得重来。今天我们就把这些基础打牢。

2.1 二进制、八进制、十六进制

先说说为什么要有这么多进制。二进制是机器语言,但写起来太长了。比如一个8位二进制数“10110010”,你看着不晕吗?所以工程师们发明了八进制和十六进制,作为二进制的“缩写”。

二进制:基数为2,只有0和1。逢二进一。

八进制:基数为8,数字0~7。逢八进一。一个八进制位正好对应3个二进制位。

十六进制:基数为16,数字0~9和A~F(A=10, B=11, C=12, D=13, E=14, F=15)。逢十六进一。一个十六进制位对应4个二进制位。

我在项目中遇到过,用十六进制写寄存器地址,比二进制方便太多了。比如地址0x3F,一看就知道是二进制的0011 1111,省事。

2.2 进制转换方法

转换其实不难,记住两个方向:

  • 其他进制转十进制:按权展开相加。比如二进制1011 = 1×2³ + 0×2² + 1×2¹ + 1×2⁰ = 8+0+2+1=11。
  • 十进制转其他进制:除基取余法。比如十进制13转二进制:13÷2=6余1,6÷2=3余0,3÷2=1余1,1÷2=0余1,从下往上读余数:1101。

嗯,这里要注意:二进制转八进制,从右向左每3位一组,不够补0。二进制转十六进制,每4位一组。反过来也一样。

快速记忆口诀

二进制转八进制,三位一组要记牢;

二进制转十六进制,四位一组别混淆;

十进制转二进制,除二取余倒着读。

2.3 原码、反码、补码

这部分是很多初学者的噩梦。但说白了,就是计算机怎么表示正数和负数的问题。

原码:最高位是符号位(0正1负),其余位是数值的绝对值。比如+3的原码是0011,-3的原码是1011。

反码:正数的反码等于原码;负数的反码是符号位不变,数值位按位取反。比如-3的反码是1100。

补码:正数的补码等于原码;负数的补码是反码加1。比如-3的补码是1101。

为什么要有补码?因为CPU做减法太麻烦,用补码可以把减法变成加法。比如3 + (-3) = 0,用补码算:0011 + 1101 = 10000,丢掉最高位的进位,就是0000,完美。

避坑指南:我曾经在写一个状态机时,把负数直接当原码用了,结果比较器死活不对。后来发现,FPGA里的有符号数默认是补码形式。所以,写代码时一定要搞清楚数据是有符号还是无符号。

2.4 格雷码

格雷码是一种循环二进制码,特点是相邻两个数之间只有一位不同。这个特性在异步时钟域传输中特别有用。

比如二进制:000→001→010→011,从001到010变了两位。而格雷码:000→001→011→010,每次只变一位。

我在项目中用过格雷码做FIFO的读写指针同步,避免了多比特信号跨时钟域时的亚稳态问题。嗯,这个后面讲跨时钟域时会细说。

二进制转格雷码:最高位不变,其余位是当前位与上一位的异或。比如二进制1011,格雷码就是1110。

格雷码转二进制:最高位不变,其余位是当前格雷码位与上一位二进制位的异或。

2.5 BCD码

BCD码(Binary-Coded Decimal)是用4位二进制数表示1位十进制数。比如十进制25,BCD码就是0010 0101。

BCD码的好处是方便人机交互,比如数码管显示、按键输入。但缺点是浪费比特位,因为4位二进制本来可以表示0~15,但BCD只用到0~9。

个人经验:我建议在做数字时钟或计数器时,优先用BCD码。因为显示的时候不需要再做二进制到十进制的转换,省一个译码模块。但如果是做大量运算,比如滤波算法,还是用纯二进制更高效。

2.6 知识体系结构图

下面这张图,是我自己总结的数制与编码的知识脉络。你把它记在脑子里,后面学什么都不会乱。

数制与编码 数制基础 二进制 八进制 十六进制 十进制 机器数编码 原码 反码 补码 应用编码 格雷码 BCD码 图:数制与编码知识体系结构

2.7 实战小练习

光说不练假把式。给你留几个小题目,自己动手算一算:

  1. 将十进制数 47 转换为二进制、八进制、十六进制。
  2. 写出 -15 的8位原码、反码、补码。
  3. 将二进制 11010110 转换为格雷码。
  4. 将十进制数 89 用BCD码表示。

答案我就不写了,你自己算完对照一下。嗯,这里提醒一句:补码的符号位扩展要小心,8位补码扩展到16位,高位全部补符号位,不是补0。

好了,这一章就到这里。数制与编码是数字电路的基石,你把它吃透了,后面学组合逻辑、时序逻辑都会轻松很多。


公众号:蓝海资料掘金营,微信deep3321