verilog实现任意位二进制转换BCD.docx
- 文档编号:27753384
- 上传时间:2023-07-04
- 格式:DOCX
- 页数:22
- 大小:275.32KB
verilog实现任意位二进制转换BCD.docx
《verilog实现任意位二进制转换BCD.docx》由会员分享,可在线阅读,更多相关《verilog实现任意位二进制转换BCD.docx(22页珍藏版)》请在冰豆网上搜索。
verilog实现任意位二进制转换BCD
verilog实现任意位二进制转换BCD
kb129 来源:
kb129 点击数:
1372 更新时间:
2014年06月08日 【字体:
大中小】
一直感觉这是个很简单的问题,直到突然自己连BCD都不太清楚的时候,才发现这没有看起来那么简单,这里介绍里任意位二进制转为BCD的verilog代码,这个转换方法也可以用在C上面,此为原创,请注明,谢谢。
根底知识:
BCD:
BCD码又称为8421码,
意义:
之所以有时候需要将binary转换为BCD,一般是用在本科的实验中,为了将binary显示在数码管中,当然还有很多应用,只是目前我还没有用到。
转换算法:
左移加3法
移位加3法的具体原理,在网上感觉也没有人能够说的清楚,以后找到书籍再说吧。
下面解释下左移加三算法。
这里以8bit二进制数FF做例子。
该算法的操作为上图。
下面对上图的操作进展详细的解释:
由于8bit的二进制最大为FF,转换为十进制为255。
所以需要使用三个BCD码来表示所有的8bit二进制数。
上图的hundreds表示百位的BCD,tens表示十位的BCD,Units表示个位的BCD。
算法的操作为一直将binary数据左移,移出的数据按顺序存在hundreds,tens,Units。
例如上面的shift1,shift2,shift3操作后,Units变为了0111,至于为何在shift3后进展add3操作,是因为在算法中每一次左移,都要对hundreds,tens和Units进展判断,如果hundreds,tens和Units里面的值大于或等于5,就将hundreds,tens和Units自加3.所以shift3后,Units里面为0111,表示为7,此时不能左移,而是对Units加三操作,所以Units的值从0111变为了1010.值得注意的是,只要hundreds,tens和Units中任意一个的值大于或等于5〔0101〕,就要先进展一次自加三的操作,然后才能继续左移,后面的操作同上。
注意2:
n位的binary就需要进展n次左移
注意3:
最后一次左移不需要进展add3操作
注意4:
亲自推导16位的,和24位的binary转换,结果正确,所以该算法适用于任意位binary
to BCD,当然这种论断没有足够的理论依据。
verilog代码:
说明:
对于8bit与以下的binary,可以使用case语句实现移位加三算法。
由于这里说明的是任意位的二进制数,转为BCD,所以我的代码中设计了一个状态机,来控制移位,加三和完毕操作。
由于代码编写时间仓促,其中或许有些bug。
//name:
二进制转BCD
//data:
2014-04-17atkb129
//info:
as2**8=255 changetoBCDthenthisneed3timesof“8421〞
moduleb_to_bcd(
clk,
rst_n,
binary,
state_en,
BCD
);
parameter b_length =8;
parameter bcd_len =12;
parameter idle =5'b00001;
parameter shift =5'b00010;
parameter wait_judge =5'b00100;
parameter judge =5'b01000;
parameter add_3 =5'b10000;
input clk;
input rst_n;
input [b_length-1:
0] binary;
input state_en;
outputreg [bcd_len-1:
0] BCD;
reg [b_length-1:
0] reg_binary;
reg [3:
0] bcd_b,bcd_t,bcd_h;
reg [3:
0] shift_time;
reg [5:
0] c_state,n_state;
reg add3_en;
reg change_done;
//thisisathreesectionkindofstatecodestyle
always(posedgeclkornegedgerst_n)
begin
if(!
rst_n)
c_state<=idle;
else
c_state<=n_state;
end
//thesecondsection
always(posedgeclkornegedgerst_n)
begin
if(!
rst_n)
c_state<=idle;
else
case(n_state)
idle:
begin
if((binary!
=0)&&(state_en==1'b1)&&(change_done==0'b0))
n_state<=shift;
else
n_state<=idle;
end
shift:
n_state<=wait_judge;
wait_judge:
begin
if(change_done==1'b1)
n_state<=idle;
else
n_state<=judge;
end
judge:
begin
if(add3_en)
n_state<=add_3;
else
n_state<=shift;
end
add_3:
begin
n_state<=shift;
end
default:
n_state<=idle;
endcase
end
//thethirdsection
always(posedgeclkornegedgerst_n)
begin
if(!
rst_n)
begin
shift_time <=4'b0;
change_done<=1'b0;
add3_en <=1'b0;
end
else
case(n_state)
idle:
begin
shift_time<=b_length;
reg_binary<=binary;
bcd_h <=4'b0;
bcd_t <=4'b0;
bcd_b <=4'b0;
end
shift:
begin
{bcd_h,bcd_t,bcd_b,reg_binary}<={bcd_h,bcd_t,bcd_b,reg_binary}<<1;
shift_time<=shift_time-1;
if(shift_time==1) change_done<=1'b1;
else change_done<=1'b0;
end
wait_judge:
begin
if((bcd_h>=4'd5)||(bcd_t>=4'd5)||(bcd_b>=4'd5))
add3_en<=1;
else
add3_en<=0;
if(change_done==1) BCD<={bcd_h,bcd_t,bcd_b};
end
judge:
add3_en<=0;
add_3:
begin
if(bcd_h>=4'd5)bcd_h<=bcd_h+4'b0011;elsebcd_h<=bcd_h;
if(bcd_t>=4'd5)bcd_t<=bcd_t+4'b0011;elsebcd_t<=bcd_t;
if(bcd_b>=4'd5)bcd_b<=bcd_b+4'b0011;elsebcd_b<=bcd_b;
end
default:
begin
change_done<=1'b0;
add3_en <=1'b0;
end
endcase
end
endmodule
代码的仿真:
这里对上面的代码进展了仿真,仿真结果显示上面代码可以实现8bitbinary的BCD转换。
testbench:
module filter_tb;
regclk;
regrst_n;
regstate_en;
reg [7:
0]binary;
wire[11:
0] BCD;
initial
begin
clk=0;
rst_n=0;
state_en=0;
#100 binary=8'h3f;
#150 rst_n=1;
#200 state_en=1;
end
always #10 clk=~clk;
b_to_bcdu_b_to_bcd
(
.clk(clk),
.rst_n(rst_n),
.binary(binary),
.state_en(state_en),
.BCD(BCD)
);
endmodule
仿真结果:
二进制的3f=十进制的63
利用verilog将二进制码转换为十进制BCD码
时间 2014-02-2010:
54:
17CSDN博客
原文 c:
\iknow\docshare\data\cur_work\\li200503028\article\details\19507061?
utm_source=tuicool
主题软件开发
小序:
先说一个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位。
下面给出 CODE:
`timescale1ns/1ps
modulebin_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(posedgeclkornegedgerst_n)
begin
if(!
rst_n)
count<=0;
elseif(count<=8)
count<=count+1;
else
count<=9;
end
//////////////////////二进制转换为十进制/////////////////
always(posedgeclkornegedgerst_n)
begin
if(!
rst_n)
shift_reg=0;
elseif(count==0)
shift_reg={10'b0000000000,bin};
elseif(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(posedgeclkornegedgerst_n)
begin
if(!
rst_n)
begin
one<=0;
ten<=0;
hun<=0;
end
elseif(count==9) //此时8次移位全部完成,将对应的值分别赋给个,十,百位
begin
one<=shift_reg[11:
8];
ten<=shift_reg[15:
12];
hun<=shift_reg[17:
16];
end
end
以下是仿真结果,bin为输入的二进制码,为了便于比照,仿真时也化成十进制显示了,one,ten,hun分别对应BCD码的个,十,百位。
根本思路是把二进制按4位一组分开,把每一组对应的二进制数转换成bcd码表,最后把所有位进展bcd码相加,第一个4位的码表也可以省略,第二个4位对于关系是
4'h0:
10'h000;
4'h1:
10'h016;
4'h2:
10'h032;
4'h3:
10'h048;
4'h4:
10'h064;
4'h5:
10'h080;
4'h6:
10'h096;
4'h7:
10'h112;
4'h8:
10'h128;
4'h9:
10'h144;
4'ha:
10'h160;
4'hb:
10'h176;
4'hc:
10'h192;
4'hd:
10'h208;
4'he:
10'h224;
4'hf:
10'h240;
第3组对于你来说只有3位
4'h0:
14'h0000;
4'h1:
14'h0256;
4'h2:
14'h0512;
4'h3:
14'h0768;
4'h4:
14'h1024;
4'h5:
14'h1280;
4'h6:
14'h1536;
4'h7:
14'h1792;
把11位二进制查表得出的3个数进展bcd码相加
这里把每个结果按同级单个bcd码相加,也就是>9对结果加6,>19对结果加12,>29对结果加18类推,当然高一级的bcd码要加上低一级的进位,也就是高出4位的局部,最后把结果拼接
给你一个16位有符号的例子
modulebcd(clk,
hex,
dec);
inputclk;
input[16:
0]hex;
output[19:
0]dec;
wire[15:
0]rrhex;
reg[3:
0]rhex[3:
0];
reg[17:
0]rhexd;
reg[13:
0]rhexc;
reg[9:
0]rhexb;
reg[3:
0]rhexa;
reg[5:
0]resa,resb,resc,resd;
reg[3:
0]rese;
assignrrhex=hex[16]?
~hex[15:
0]+1'b1:
hex[15:
0];//去符号
assigndec={rese,resd[3:
0],resc[3:
0],resb[3:
0],resa[3:
0]};
always(posedgeclk)//第一级存放器
begin
rhex[3]<=rrhex[15:
12];
rhex[2]<=rrhex[11:
8];
rhex[1]<=rrhex[7:
4];
rhex[0]<=rrhex[3:
0];
end
always(posedgeclk)//第二级存放器,千
begin
case(rh
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- verilog 实现 任意 二进制 转换 BCD