实验十 二进制转BCD码

一、实验设计目标

本文实现一个二进制转十进制的电路,8位拨码开关(SW7-SW0)作为一组8位二进制输入信号,程序将8位二进制输入转为3位十进制表示,经由数码管显示输出。

二、实验设计思路

在数字逻辑设计课程中,我们已经学过了BCD码的相关知识,它用4位二进制数来表示1位十进制数中的09,是二进制编码的十进制代码,常见的BCD码有8421BCD码,2421BCD码,5421BCD码,余3码以及格雷码等等。在这篇文章中,我们所采用的BCD码为8421BCD码,8421BCD码各位的权值为8、4、2、1,用00001001表示十进制数,其它几种BCD码编码方式在这里不过多赘述。

实现这样的一个效果,可以先大致的将电路分为二进制转化和数码管显示两个部分,框架如图10.1所示,本实验主要讲述二进制转化部分。

img

图10.1 二进制转BCD码动态显示框架

二进制转BCD码看起来最简单的方法是用除法运算来获得百位、十位、个位上的值,但实际上这种方式取模会占用过多资源,底层电路设计十分复杂,这告知我们选择合适的算法对于系统是有很大帮助的,因此通常使用加3移位法实现二进制转BCD码。

在这里简单介绍一下加3移位法的原理。我们知道,四位二进制大于15才进位,而8421BCD码是大于9就进位,若四位二进制大于9时进位,这样得到的就是15的BCD码,因此将大于9的四位二进制数加6就能得到其BCD码。对于大于四位的二进制数,通过左移,逢9加6进位,即可转换任意位的二进制数,比如说,对于5位二进制数,由高4位二进制数左移一位得到,那么将前4位得到的BCD码也左移一位,并重新判断低四位是否大于9,若大于9,则加6进位,即可得到5位二进制数对应的BCD码。

加3移位法相比与加6移位法在算法上的结果是等效的,但占用的资源更小,相比于加6移位法先移位,再判断低4位是否大于9,加3移位法是先判断低四位是否大于4,再进行移位。值得一提的是,加3移位法对于最后的低4位而言无需判断低4位是否大于4,因为已经没有移位操作了。

参考网上的一个将八位二进制数255,将其转为8421BCD码的例子给大家加以说明。

0 1111 1111; //原数

1 0000 0001; //左移一次

2 0000 0011; //左移二次

3 0000 0111; //左移三次,检查低四位>4?

3.1. 0000 1010; //大于4,加3进行调整

4 0001 0101; //左移四次,检查低四位>4?

4.1. 0001 1000; //大于4,加3进行调整

5 0011 0001; //左移五次

6 0110 0011; //左移六次,检查高四位>4?

6.1. 1001 0011; //大于4,加3进行调整

7 1 0010 0111; //左移七次,检查低四位>4?

7.1. 1 0010 1010; //大于4,加3进行调整

8 10 0101 0101; //左移八次(得到BCD码255)

理解了算法,接下来就是如何实现算法。实现同样功能有不同的算法,同样的,实现算法也有各式各样的电路。如何让实现的电路简单有效,就是FPGA工程师的价值所在。直白的看来,实现加3移位法,需要通过寄存器进行若干次的移位,并判断检查是否需要进位,这样“简单粗暴”实现的电路,完成一组数据的转化需要经过多个时钟周期,电路实际上也较为复杂。在这里,针对8位二进制数,我们实现的加3移位法电路结构如图10.2所示。

img

图10.2 加3移位法电路

在这个电路中,Adder模块实现输入大于4就加3进位的功能,再通过人为的“移位”操作,就实现了加3移位法。具体实现过程可以理解为,首先,0和高三位(a7、a6、a5)的数据构成左移三次后的低四位二进制数据,经过Adder1模块后,得到调整后的数据;调整后数据的低三位和a4构成左移四次后的低四位数据,这四位数据作为Adder2模块的输入,就实现了“移位”,再通过Adder2进行调整数据即可;Adder3部分与Adder2部分一致,实现了左移五次的数据修正;这时,经过Adder1、Adder2和Adder3处理后的数据与a2构成了左移六次的数据,这七位有效数据的高三位可能会大于4,因而高四位和低四位都需要进行数据的调整,也就是分别通过Adder4和Adder5来修正;Adder6和Adder7与Adder4和Adder5一致,实现左移七位后的数据调整;最后,在高位填0并与最低位的a0构成最终左移八次的十二位数据。

Adder模块的功能为当输入大于4时,加3调整,当输入小于等于4时,保持原值,其电路结构如下,通过比较器,多路选择器和加法器实现功能。图10.3是Adder模块的功能框图。

img

图10.3 Adder模块功能图

数码管动态显示模块和开关的使用方法可以参考之前的实验。数码管动态显示框图如图10.4所示。

img

图10.4 数码管动态显示框图

三、功能模块图与输入输出引脚说明

该工程包含顶层模块binary2bcdlight与底层模块binary2bcd、adder3、和Digitron_NumDisplay_module。整个工程的模块功能图参考图10.4即可。下面介绍一下顶层模块各主要引脚的功能:

(1)clk:50MHz的基准时钟信号输入。

(2)SW:开关输入,8个数码管的状态值最终显示在数码管上。

(3)Digitron_Out:七段数码管的显示输出,共有八位总线。

(4)DigitronCS_Out:数码管的片选信号,共有四位总线。

四、程序设计

下面给出了二进制转BCD码模块的参考代码。通过七个adder3模块以及人为的移位实现转换。

img

10.5 二进制转BCD码模块

下面是adder3模块的代码,通过case语句实现功能。

img

10.6 加三方法模块

接下来是动态显示的各部分代码,与之前实验相同不赘述。

五、FPGA管脚配置

下面是Anlogic FPGA的IO Constraint图,CLK时钟输入信号、数码管片选信号DigitronCS_Out和数码管输出显示信号Digitron_Out的配置方式与之前相同, SW0-SW7控制数码管显示的数据。相应引脚连接信息已经在第一篇的1.3节中做过详细介绍,这里就不再赘述。

set_pin_assignment { DigitronCS_Out[0] } { LOCATION = C9; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DigitronCS_Out[1] } { LOCATION = B6; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DigitronCS_Out[2] } { LOCATION = A5; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DigitronCS_Out[3] } { LOCATION = A3; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[0] } { LOCATION = A4; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[1] } { LOCATION = A6; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[2] } { LOCATION = B8; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[3] } { LOCATION = E8; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[4] } { LOCATION = A7; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[5] } { LOCATION = B5; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[6] } { LOCATION = A8; IOSTANDARD = LVCMOS33; }

set_pin_assignment { Digitron_Out[7] } { LOCATION = C8; IOSTANDARD = LVCMOS33; }

set_pin_assignment { clk } { LOCATION = R7; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[0] } { LOCATION = A9; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[1] } { LOCATION = A10; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[2] } { LOCATION = B10; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[3] } { LOCATION = A11; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[4] } { LOCATION = A12; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[5] } { LOCATION = B12; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[6] } { LOCATION = A13; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW[7] } { LOCATION = A14; IOSTANDARD = LVCMOS33; }

六、实验结果

当把开关拨到不同的状态,数码管会显示不同的二进制转成的数据。