FPGA移位加三法
介绍
BCD码
BCD码的英文全称是Binary-Coded Decimal,简称BCD,按字面解释是二进制十进制代码,是一种二进制的数字编码形式。
常见的BCD码有8421BCD码,2421BCD码,5421BCD码,余3码以及格雷码等等。
在本文中,我们所采用的BCD码为8421BCD码。
8421码,即从左到右的二进制位权重分别为8、4、2、1。即
| BCD码 | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 |
|---|---|---|---|---|---|---|---|---|---|---|
| 值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
应用场景
数字时钟,需要十进制地显示时分秒;温度显示也需要十进制;次数显示也需要十进制······
错误例子
module func(i_data, o_data)
input wire [7:0] i_data;
output wire [11:0] o_data;
assign o_data[11:8] = i_data / 100;
assign o_data[7:4] = i_data / 10 % 10;
assign o_data[3:0] = i_data % 10;
endmodule
这是我们在做算法题的时候用到的方法,而且Verilog是支持除法和取余运算的,但是这样会耗费太多资源。对于硬件设计来说,我们需要用适合硬件的方法。
8421码与二进制码的关系
对于4位二进制码,是逢16进位。而8421码是逢10进位。
因此,大于9的二进制码,加6就可以得到8421码。
移位加三法
首先给出步骤:(8位二进制数为例)
- BCD码初始化为0。
- 将原二进制码左移一位,左移出的一位添到BCD码的低位上。
- 判断BCD码所对应的个,十,百位是否大于等于5,如果是则该段加3。
- 继续重复以上步骤直到移位8次后停止。
总之,在移位的过程中,如果移位出的数值大于等于5,则将数值加3,再进行移位。对于n位二进制数,就进行n次移位。
例子
以二进制数 0111_1101为例,数值为125。
| 百位 | 十位 | 个位 | 二进制数 | |
|---|---|---|---|---|
| 开始 | 4'b0000 | 4'b0000 | 4'b0000 | 8'b0111_1101 |
| 左移1 | 4'b0000 | 4'b0000 | 4'b0000 | 8'b1111_1010 |
| 左移2 | 4'b0000 | 4'b0000 | 4'b0001 | 8'b1111_0100 |
| 左移3 | 4'b0000 | 4'b0000 | 4'b0011 | 8'b1110_1000 |
| 左移4 | 4'b0000 | 4'b0000 | 4'b0111 | 8'b1101_0000 |
| 加3 | 4'b0000 | 4'b0000 | 4'b1010 | 8'b1101_0000 |
| 左移5 | 4'b0000 | 4'b0001 | 4'b0101 | 8'b1010_0000 |
| 加3 | 4'b0000 | 4'b0001 | 4'b1000 | 8'b1010_0000 |
| 左移6 | 4'b0000 | 4'b0011 | 4'b0001 | 8'b0100_0000 |
| 左移7 | 4'b0000 | 4'b0110 | 4'b0010 | 8'b1000_0000 |
| 加3 | 4'b0000 | 4'b1001 | 4'b0010 | 8'b1000_0000 |
| 左移8 | 4'b0001 | 4'b0010 | 4'b0101 | 8'b0000_0000 |
可以看到,最终结果为 12'b0001_0010_0101。按照8421BCD码解析,即为125。
为什么要大于等于5
之前的联系不是说,大于9嘛?其实这只是一个简单的运算前后顺序关系。
BCD码是4位二进制数表示一个十进制数的1位,如果大于等于5,比如5,4'b0101,下一次移位后变成了4’b1010,而BCD码中是没有4’b1010的,所以要加6,向高位进位。(见联系)
所以移位后加6和移位前加3都是可以的。
具体实现
实现一
RTL结构

- bin[7:0]:二进制数输入
- bcd[11:0]:8421BCD码输出,[11:8] 为百位,[7:4] 为十位,[3:0] 为个位。
- 该模块调用8次移位加3模块,如图:


代码
移位加3模块
module shift(i_data, o_data);
input wire [19:0] i_data;
output wire [19:0] o_data;
wire [19:0] shift_data;
assign shift_data[19:16] = i_data[19:16] > 4'd4 ? i_data[19:16] + 4'd3 : i_data[19:16];
assign shift_data[15:12] = i_data[15:12] > 4'd4 ? i_data[15:12] + 4'd3 : i_data[15:12];
assign shift_data[11:8] = i_data[11:8] > 4'd4 ? i_data[11:8] + 4'd3 : i_data[11:8];
assign shift_data[7:0] = i_data[7:0];
assign o_data = shift_data << 1'b1;
endmodule
顶层模块
module bin2bcd(bin, bcd);
input wire [7:0] bin;
output wire [11:0] bcd;
wire [19:0] w_0;
wire [19:0] w_1;
wire [19:0] w_2;
wire [19:0] w_3;
wire [19:0] w_4;
wire [19:0] w_5;
wire [19:0] w_6;
wire [19:0] w_7;
shift shift_ins0 (.i_data({12'd0, bin}), .o_data(w_0));
shift shift_ins1 (.i_data(w_0), .o_data(w_1));
shift shift_ins2 (.i_data(w_1), .o_data(w_2));
shift shift_ins3 (.i_data(w_2), .o_data(w_3));
shift shift_ins4 (.i_data(w_3), .o_data(w_4));
shift shift_ins5 (.i_data(w_4), .o_data(w_5));
shift shift_ins6 (.i_data(w_5), .o_data(w_6));
shift shift_ins7 (.i_data(w_6), .o_data(w_7));
assign bcd = w_7[19:8];
endmodule
实现二
- inData[15:0]:二进制数输入
- outData[19:0]:8421BCD码输出,个十百千位同理。
- 本代码通过循环实现。
代码
module BinaryToBCD(
input wire [16-1:0] inData, //二进制输入
output wire [16+3:0] outData //BCD输出
);
parameter bit_binary = 16; //二进制数据位数
reg [bit_binary-1:0] bin;
reg [bit_binary+3:0] ShiftReg;
always@(inData)
begin
bin = inData;
ShiftReg = 'd0;
repeat (bit_binary - 1)
begin
ShiftReg[0] = bin[bit_binary-1];
//adjust by add 3
if(ShiftReg[19:16] > 4)
ShiftReg[19:16] = ShiftReg[19:16] + 2'd3;
else
ShiftReg[19:16] = ShiftReg[19:16];
if(ShiftReg[15:12] > 4)
ShiftReg[15:12] = ShiftReg[15:12] + 2'd3;
else
ShiftReg[15:12] = ShiftReg[15:12];
if(ShiftReg[11:8] > 4)
ShiftReg[11:8] = ShiftReg[11:8] + 2'd3;
else
ShiftReg[11:8] = ShiftReg[11:8];
if(ShiftReg[7:4] > 4)
ShiftReg[7:4] = ShiftReg[7:4] + 2'd3;
else
ShiftReg[7:4] = ShiftReg[7:4];
if(ShiftReg[3:0] > 4)
ShiftReg[3:0] = ShiftReg[3:0] + 2'd3;
else
ShiftReg[3:0] = ShiftReg[3:0];
ShiftReg = ShiftReg << 1;
bin = bin << 1;
end
ShiftReg[0] = bin[bit_binary-1];
end
assign outData = ShiftReg;
endmodule
参考文献
[1] https://blog.51cto.com/u_15076212/3816404 "基于FPGA的二进制转BCD设计与实现(移位加3法)"
[2] https://zhuanlan.zhihu.com/p/209083141 "[走近FPGA]之二进制转BCD码"
FPGA移位加三法的更多相关文章
- 我的 FPGA 学习历程(07)—— BCD 编码:移位加 3 算法
2-10 进制码,也称为 BCD 码,它的编码方式则是通过一个 4 位二进制来表示一个 10 进制数,部分十进制对应的 BCD 码如下 十进制数 | BCD 码 13 --> 0001_0011 ...
- fpga板制作调试过程记录
2010-09-11 22:49:00 昨天淘宝准备买块fpga核心板学习,为了练习焊接,我让老板给我散料及pcb板自己焊接. 一,在物料到之前的准备: 我先设计了一下焊接测试计划 1,检查电路板:特 ...
- 如何对xilinx FPGA进行bit文件加密
记录背景:最近在用Vivado评估国外一个公司所提供的ISE所建的工程时,由于我并没有安装ISE工程,因此将其提供的所有v文件导入到Vivado中,对其进行编译.添加完之后成功建立顶层文件,但奇怪的是 ...
- Altera FPGA 远程升级有关的几个IP的使用
在做在线远程升级的时候,一般需要两步:1.将数据写到外挂的flash中.2重新启动FPGA配置. 不过要做到远程升级,一般需要在原始程序中就考虑到加入远程升级模块,remote updata IP, ...
- FPGA设计中遇到的奇葩问题之“芯片也要看出身”
FPGA设计中遇到的奇葩问题之“芯片也要看出身”(一) 昨夜西风凋碧树.独上高楼,望尽天涯路 2000年的时候,做设计基本都是使用Xilinx公司的Virtex和Virtex-E系列芯片.那时候Alt ...
- 基于Verilog HDL的二进制转BCD码实现
在项目设计中,经常需要显示一些数值,比如温湿度,时间等等.在数字电路中数据都是用二进制的形式存储,要想显示就需要进行转换,对于一个两位的数值,对10取除可以得到其十位的数值,对10取余可以得到个位的数 ...
- GSM BTS Hacking: 利用BladeRF和开源BTS 5搭建基站
引文 如果你已经购买了Nuand(官方)BladeRF x40,那么就可以在上面运行OpenBTS并可以输入一些指令来完成一些任务.一般来说HackRF,是一款覆盖频率最宽的SDR板卡.它几乎所有的信 ...
- 20140704笔试面试总结(java)
1.java数组定义 1.与其他高级语言不同,Java在数组声明时并不为数组分配存储空间,因此,在声明的[]中不能指出数组的长度 2.为数组分配空间的两种方法:数组初始化和使用new运算符 3.未分配 ...
- 列式数据库~clickhouse 底层存储原理
简介:今天介绍列式数据库的一些基本原理 一 数据目录 Data目录 数据存储目录,数据按照part分成多个文件夹,每个文件夹下存储相应数据和对应的元信息文件 Metadata 表定义语句,存储所有表 ...
- A Simple Note on "P4FPGA: A Rapid Prototyping Framework for P4"
论文:P4FPGA: A Rapid Prototyping Framework for P4 Github:https://github.com/p4fpga Reference: Han Wang ...
随机推荐
- 【Lua】VSCode 搭建 Lua 开发环境
前言 最近在找工作,基本所有的岗位都会问到 Lua(甚至拼 UI 的都要求会 Lua),咱能怎么办呢,咱也只能学啊-- 工欲善其事,必先利其器.第一步,先来把环境配置好吧! 当前适用版本: LuaBi ...
- 「Vue系列」之Vue2实现当前组件重新加载
遇到问题的场景:需要把当前组件完全还原成初始化状态,不要页面全部刷新例如:重置按钮,只刷新当前加载组件其他办法:使用vue-router重新定向到当前页面,页面不刷新使用window-reload() ...
- node可以用nvm快速切换版本,golang如何快速切换版本?用gvm就行。
使用 gvm 可以带来以下好处: 快速切换 Golang 版本,方便进行版本测试和开发: 可以在多个项目中同时使用不同版本的 Golang 包和工具,避免冲突: 可以通过 gvm 管理不同版本的 Go ...
- 2023-03-13:给定一个整数数组 A,坡是元组 (i, j),其中 i < j 且 A[i] <= A[j], 这样的坡的宽度为 j - i。 找出 A 中的坡的最大宽度,如果不存在,返回 0
2023-03-13:给定一个整数数组 A,坡是元组 (i, j),其中 i < j 且 A[i] <= A[j], 这样的坡的宽度为 j - i. 找出 A 中的坡的最大宽度,如果不存在 ...
- 2022-08-22:给定一个数组arr,长度为n,最多可以删除一个连续子数组, 求剩下的数组,严格连续递增的子数组最大长度。 n <= 10^6。 来自字节。5.6笔试。
2022-08-22:给定一个数组arr,长度为n,最多可以删除一个连续子数组, 求剩下的数组,严格连续递增的子数组最大长度. n <= 10^6. 来自字节.5.6笔试. 答案2022-08- ...
- 2020-12-13:用最少数量的线程,每个线程执行for的空循环,把cpu打满了。如果在for的空循环里添加打印输出函数,会把cpu打满吗?为什么?
福哥答案2020-12-13:不会.输出会进行io操作,相对于CPU的速度,这是一个非常缓慢的过程,所以CPU会有机会空闲下来.***[评论](https://user.qzone.qq.com/31 ...
- golang基础面试题,不完整
启动流程 Q.go的init函数是什么时候执行的? Q.多个init函数执行顺序能保证吗? Q.go init 的执行顺序,注意是不按导入规则的(这里是编译时按文件名的顺序执行的) Q.init函数能 ...
- 2022-01-10:路径交叉。给你一个整数数组 distance 。 从 X-Y 平面上的点 (0,0) 开始,先向北移动 distance[0] 米,然后向西移动 distance[1] 米,向南
2022-01-10:路径交叉.给你一个整数数组 distance . 从 X-Y 平面上的点 (0,0) 开始,先向北移动 distance[0] 米,然后向西移动 distance[1] 米,向南 ...
- 2021-08-23:超级水王问题。扩展1:摩尔投票。扩展2:给定一个正数K,返回所有出现次数>N/K的数。
2021-08-23:超级水王问题.扩展1:摩尔投票.扩展2:给定一个正数K,返回所有出现次数>N/K的数. 福大大 答案2021-08-23: 扩展1: 1.如果无候选,当前数就是候选,血为1 ...
- CSS3 clip-path:打造独特创意设计效果的秘密武器
大家好,我是程序视点的小二哥. 今天小二哥将给大家分享一篇有前端实验室的文章.一部由CSS技术实现的作品.它将再一次证明CSS的强大力量. 欣赏 这是一部由阿姆斯特丹设计师Bryan James通过3 ...