先说一个 bear 的亲身体会,bear 在做一些 fpga 小设计时经常会用到数据显示功能,比如数字时钟,数字频率计,温度计,跑表等等,往往我们会选用
led 数码管来做显示, 因为它驱动起来比 lcd 液晶要简单的很多,我们知道 fpga 中寄存器在定义和储存的数据都是采用二进制的格式 ,而 fpga 输出给数码
管做显示的数据必须是十进制的格式 , 之前 bear 经常会选择把一个寄存器的个位和十位分开定义 ,比如在做数字时钟时 ,就会吧 时,分,秒的各位和十位
都分别定义成一个变量 ,无疑这种方法会增加代码的复杂度 ,所以考虑需要一个专门把 二进制 的数据转换成 十进制 BCD码的模块 ,在网上有一些,但是好
像都不太完整 , 所以bear花了一下午写了一个 ,亲测效果不错 ,希望对朋友们有所帮助,下面开始正文。
首先给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例):
1.将二进制码左移一位(或者乘2)
2.找到左移后的码所对应的个,十,百位。
3.判断在个位和百位的码是否大于5,如果是则该段码加3。
4.继续重复以上三步直到移位8次后停止。
下面是一个例子 ,将 1111_1111 转换为 BCD码 ,如果8bit数据最终移位得到18bit 数据 ,那么个位,十位,百位分别对应12~9,16~13,18~17位。
之前写的代码在转换完之后没有对count清零,所以在仿真时候需要用rst_n清零,感谢博友onlytime417的提示,经过修改之后可以对不同的输入值连续转换,而不需要rst_n的复位,下面是修改后的代码以及仿真结果,(该转换模块已经在实际项目中应用)。
CODE:
`timescale 1ns / 1ps
module bin_dec(clk,bin,rst_n,one,ten,hun,count,shift_reg
);
input [7:0] bin;
input clk,rst_n;
output [3:0] one,ten;
output [3:0] count;
output [1:0] hun;
output [17:0]shift_reg;
reg [3:0] one,ten;
reg [1:0] hun;
reg [3:0] count;
reg [17:0]shift_reg=18'b000000000000000000;
// 计数部分
always @ ( posedge clk or negedge rst_n )
begin
if( !rst_n )
count<=0;
else if (count==9)
count<=0;
else
count<=count+1;
end
// 二进制转换为十进制 /
always @ (posedge clk or negedge rst_n )
begin
if (!rst_n)
shift_reg=0;
else if (count==0)
shift_reg={10'b0000000000,bin};
else if ( count<=8) //实现8次移位操作
begin
if(shift_reg[11:8]>=5) //判断个位是否>5,如果是则+3
begin
if(shift_reg[15:12]>=5) //判断十位是否>5,如果是则+3
begin
shift_reg[15:12]=shift_reg[15:12]+2'b11;
shift_reg[11:8]=shift_reg[11:8]+2'b11;
shift_reg=shift_reg<<1; //对个位和十位操作结束后,整体左移
end
else
begin
shift_reg[15:12]=shift_reg[15:12];
shift_reg[11:8]=shift_reg[11:8]+2'b11;
shift_reg=shift_reg<<1;
end
end
else
begin
if(shift_reg[15:12]>=5)
begin
shift_reg[15:12]=shift_reg[15:12]+2'b11;
shift_reg[11:8]=shift_reg[11:8];
shift_reg=shift_reg<<1;
end
else
begin
shift_reg[15:12]=shift_reg[15:12];
shift_reg[11:8]=shift_reg[11:8];
shift_reg=shift_reg<<1;
end
end
end
end
/输出赋值//
always @ ( posedge clk or negedge rst_n )
begin
if ( !rst_n )
begin
one<=0;
ten<=0;
hun<=0;
end
else if (count==9) //此时8次移位全部完成,将对应的值分别赋给个,十,百位
begin
one<=shift_reg[11:8];
ten<=shift_reg[15:12];
hun<=shift_reg[17:16];
end
end
endmodule
以下是仿真结果,bin为输入的二进制码,为了便于对比,仿真时也化成十进制显示了,one,ten,hun分别对应BCD码的个,十,百位。
修改前的仿真结果:
修改后的仿真结果:
小序:先说一个 bear 的亲身体会,bear 在做一些 fpga 小设计时经常会用到数据显示功能,比如数字时钟,数字频率计,温度计,跑表等等,往往我们会选用led 数码管来做显示,因为它驱动起来比 lcd 液晶要简单的很多,我们知道 fpga 中寄存器在定义和储存的数据都是采用二进制的格式 ,而 fpga 输出给数码管做显示...
本文主要对有符号数的
十进制
与二进制表示以及一些数值变换进行简单的总结。定义一个宽度为 DW 的二进制补码格式的数据 dbin ,其表示的有符号
十进制
数字为 ddec 。
reg [DW-1:0] dbin ;
1.
十进制
有符号数转二进制补码
正数的补码为原码。假如
十进制
数 ddec 为负数,则计算其对应的二进制补码的方法主要有 2 种:
①将ddec 最高位符号位改写为 1,剩余数值部分取反加一。例如,4bit 数字 -6 的数值部分为 4’b0110,取反加一后为 4’b0010,高位改写后为
Verilog
基础知识数字进制格式标识符数据类型寄存器类型线网类型参数类型
数字进制格式
Verilog
数字进制格式包括二进制,八进制,
十进制
,十六进制。常用为二进制,
十进制
,十六进制
二进制表示为: 4’b101 代表4位二进制数1010
十进制
表示为:4’d10 代表4位
十进制
数10(二进制数1010)
十六进制表示为4’ha 代表4位十六进制数a(二进制数1010)
4代表位宽, b o d h分别代表2、8、10、16进制(位宽默认为32)
同时可用_增加程序可读性,如16’b1010
verilog
快速将二进制转成
BCD码
FPGA的到的数值最后在数码管、LED、LCD显示,最直接的方式是
利用
求商/求余,但是这种方式非常占用内部资源的,这时候很多时候都会采用将二进制数
转换
成
BCD码
,最后再显示。
转换
成
BCD码
的方式有很多,这个就要根据自己的需要做出选择。我想介绍的是一种高速
转换
的方式:
利用
简单的状态机和一个自定义的
函数
来实现这个功能。
函数
介绍:
BCD码
就是
利用
四个二进制位表示...
大概
转换
的思路就是
二进制码
的最高位与格雷码最高位保持一致,其余通过自生移位与异或得到,如b[2]为格雷码逻辑右移两位(逻辑右移,最高位补0)再自身四位异或,0与任何数异或均为其本身。
^(gray>>i)表示先逻辑右移i位,再自身四位异或。
二、
二进制码
到格雷码
转换
。
转换
原理
转换
思路大概就是格雷码最高位与
二进制码
一致,其余各位为
二进制码
对应位与其相邻的高位异或,如格雷码的第二位为二进制的第二位与
二进制码
的第三位异或。因此实现代码则为二进
在涉及到ASCII等编码的时候,往往需要使用
十进制
计数器来进行测试,下面分享一种简单的测试用的10进制计数器程序:
reg[3:0] dec_cnt[3:0];
//10进制加法器
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
dec_cnt[0] <= 4'b0;
dec_cnt[1] <= 4'b0;
dec_cnt[2] <= 4'b0;
先来举个例子吧!!!
我们都知道一个数字用2进制的方式来表达是用0或1来表示的,其中0表示整除没有余数,如若有余数则用1表示。
其实呢,转二进制是非常简单的,每一个数字都是有权重位的
随机一串二进制的数字:1 0 0 1 1
每个数字表达的意思为:124
这个二进制的数字为:16+8+4+2+1=21
每一个二进制的数字都是这样累计出来的,你学会了吗,是不是很简单!!!
Verilog
是一种硬件描述语言,可以用于设计和描述数字逻辑电路。
利用
Verilog
将
二进制码
转换
为
十进制
BCD码
可以通过使用计算模块和状态机来实现。
首先我们需要一个计算模块,该模块能够将
二进制码
转换
为
十进制
数。该模块可以采用乘法操作符和加法操作符来实现。以4位
二进制码
为例,我们可以将每一位的权重分别为8、4、2、1,然后将各位的乘积相加,即可得到对应的
十进制
数。
然后我们需要一个状态机来控制
二进制码
的
转换
。状态机可以根据输入的
二进制码
和当前的状态来判断
转换
的过程。状态机需要有一个初始状态和一个结束状态,当输入的
二进制码
全部
转换
完毕后,状态机将从
转换
状态切换到结束状态。
在状态机的
转换
过程中,我们需要使用一个计数器来记录当前
转换
的位数,以便在每一位完成
转换
后自动切换到下一位的
转换
。计数器的大小应与输入的
二进制码
的位数一致。
最后,我们需要一个输出模块来将
转换
后的
十进制
BCD码
输出。输出模块需要在状态机
转换
完成后将结果输出,并且需要确保输出的
BCD码
的位数正确。
综上所述,
利用
Verilog
将
二进制码
转换
为
十进制
BCD码
可以通过计算模块、状态机和输出模块的组合实现。这样可以将输入的
二进制码
逐位
转换
为
十进制
数,最终得到对应的
BCD码
输出。