verilog实现任意位二进制转换BCD.doc_第1页
verilog实现任意位二进制转换BCD.doc_第2页
verilog实现任意位二进制转换BCD.doc_第3页
verilog实现任意位二进制转换BCD.doc_第4页
verilog实现任意位二进制转换BCD.doc_第5页
免费预览已结束,剩余13页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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转换,结果正确,所以该算法适用于任意位binarytoBCD,当然这种论断没有足够的理论依据。verilog代码:说明:对于8bit及以下的binary,可以使用case语句实现移位加三算法。由于这里说明的是任意位的二进制数,转为BCD,所以我的代码中设计了一个状态机,来控制移位,加三和结束操作。由于代码编写时间仓促,其中或许有些bug。/name: 二进制转BCD/data: 2014-04-17 at kb129/info: as 2*8=255 change to BCD then this need 3 times of “8421”module b_to_bcd( clk, rst_n, binary, state_en, BCD);parameter b_length = 8;parameter bcd_len = 12;parameter idle = 5b00001;parameter shift = 5b00010;parameter wait_judge = 5b00100;parameter judge = 5b01000;parameter add_3 = 5b10000;input clk;input rst_n;input b_length-1:0 binary;inputstate_en;output regbcd_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;regadd3_en;regchange_done;/this is a three section kind of state code stylealways(posedge clk or negedge rst_n)begin if(!rst_n) c_state = idle; else c_state = n_state;end/the second sectionalways(posedge clk or negedge rst_n)begin if(!rst_n) c_state = idle; else case(n_state) idle:begin if(binary!=0)&(state_en=1b1)&(change_done=0b0) n_state = shift; else n_state = idle; end shift: n_state = wait_judge;wait_judge: begin if(change_done=1b1) 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;endcaseend/the third sectionalways(posedge clk or negedge rst_n)begin if(!rst_n) begin shift_time = 4b0; change_done = 1b0; add3_en= 1b0; end else case(n_state) idle:begin shift_time = b_length; reg_binary = binary;bcd_h = 4b0; bcd_t = 4b0; bcd_b = 4b0; end shift:begin bcd_h,bcd_t,bcd_b,reg_binary = bcd_h,bcd_t,bcd_b,reg_binary1; shift_time = shift_time-1; if(shift_time=1) change_done = 1b1;else change_done =4d5)|(bcd_t=4d5)|(bcd_b=4d5) add3_en = 1; else add3_en = 0; if(change_done=1) BCD = bcd_h,bcd_t,bcd_b; end judge: add3_en =4d5) bcd_h = bcd_h + 4b0011; else bcd_h =4d5) bcd_t = bcd_t + 4b0011; else bcd_t =4d5) bcd_b = bcd_b + 4b0011; else bcd_b = bcd_b; end default: begin change_done = 1b0; add3_en= 1b0; end endcase endendmodule代码的仿真:这里对上面的代码进行了仿真,仿真结果显示上面代码可以实现8bitbinary的BCD转换。testbench:module filter_tb;reg clk;reg rst_n;reg state_en;reg 7:0 binary;wire 11:0BCD;initial begin clk=0;rst_n=0; state_en = 0; #100 binary = 8h3f; #150 rst_n=1; #200 state_en =1;endalways #10 clk=clk;b_to_bcd u_b_to_bcd(.clk(clk),.rst_n(rst_n),.binary(binary),.state_en(state_en),.BCD(BCD);endmodule仿真结果:二进制的3f=十进制的63利用verilog将二进制码转换为十进制BCD码时间2014-02-20 10:54:17 CSDN博客 原文 /li200503028/article/details/19507061 主题 软件开发 小序 : 先说一个 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 数据 ,那么个位,十位,百位分别对应129,1613,1817位。 下面给出 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:0shift_reg; reg 3:0 one,ten; reg 1:0 hun; reg 3:0 count; reg 17:0shift_reg=18b000000000000000000; / 计数部分 / always ( posedge clk or negedge rst_n ) begin if( !rst_n ) count=0; else if (count=8) count=count+1; else count=9; end / 二进制转换为十进制 / always (posedge clk or negedge rst_n ) begin if (!rst_n) shift_reg=0; else if (count=0) shift_reg=10b0000000000,bin; else if ( count=5) /判断个位是否5,如果是则+3 begin if(shift_reg15:12=5) /判断十位是否5,如果是则+3 begin shift_reg15:12=shift_reg15:12+2b11; shift_reg11:8=shift_reg11:8+2b11; shift_reg=shift_reg1; /对个位和十位操作结束后,整体左移 endelse begin shift_reg15:12=shift_reg15:12; shift_reg11:8=shift_reg11:8+2b11; shift_reg=shift_reg=5) begin shift_reg15:12=shift_reg15:12+2b11; shift_reg11:8=shift_reg11:8;shift_reg=shift_reg1; end else begin shift_reg15:12=shift_reg15:12; shift_reg11:8=shift_reg11:8; shift_reg=shift_reg1; 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_reg11:8; ten=shift_reg15:12; hun9对结果加6,19对结果加12,29对结果加18类推,当然高一级的bcd码要加上低一级的进位,也就是高出4位的部分,最后把结果拼接 给你一个16位有符号的例子module bcd(clk, hex, dec);input clk;input 16:0 hex;output 19:0 dec;wire 15:0 rrhex;reg 3:0 rhex3: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;assign rrhex = hex16 ? hex15:0+1b1 : hex15:0; /去符号assign dec = rese,resd3:0,resc3:0,resb3:0,resa3:0;always(posedge clk) /第一级寄存器begin rhex3 = rrhex15:12; rhex2 = rrhex11:8; rhex1 = rrhex7:4; rhex0 = rrhex3:0;endalways(posedge clk) /第二级寄存器,千begin case(rhex3) 4h0: rhexd = 18h00000; 4h1: rhexd = 18h04096; 4h2: rhexd = 18h08192; 4h3: rhexd = 18h12288; 4h4: rhexd = 18h16384; 4h5: rhexd = 18h20480; 4h6: rhexd = 18h24576; 4h7: rhexd = 18h28672; default: rhexd = 10h00000; endcaseendalways(posedge clk)begin case(rhex2) 4h0: rhexc = 14h0000; 4h1: rhexc = 14h0256; 4h2: rhexc = 14h0512; 4h3: rhexc = 14h0768; 4h4: rhexc = 14h1024; 4h5: rhexc = 14h1280; 4h6: rhexc = 14h1536; 4h7: rhexc = 14h1792; 4h8: rhexc = 14h2048; 4h9: rhexc = 14h2304; 4ha: rhexc = 14h2560; 4hb: rhexc = 14h2816; 4hc: rhexc = 14h3072; 4hd: rhexc = 14h3328; 4he: rhexc = 14h3584; 4hf: rhexc = 14h3840; default: rhexc = 14h0000; endcaseend always(posedge clk)begin case(rhex1) 4h0: rhexb = 10h000; 4h1: rhexb = 10h016; 4h2: rhexb = 10h032; 4h3: rhexb = 10h048; 4h4: rhexb = 10h064; 4h5: rhexb = 10h080; 4h6: rhexb = 10h096; 4h7: rhexb = 10h112; 4h8: rhexb = 10h128; 4h9: rhexb = 10h144; 4ha: rhexb = 10h160; 4hb: rhexb = 10h176; 4hc: rhexb = 10h192; 4hd: rhexb = 10h208; 4he: rhexb = 10h224; 4hf: rhexb = 10h240; default: rhexb = 10h000; endcaseend always(posedge clk)begin rhexa 6h1d) /29 最低有一个可能出现0xf,但由二进制转换而来的数在这里不会出现大于40的情况 addbcd4 = addbcd4 + 5h12; else if(addbcd4 5h13) /19 addbcd4 = addbcd4 + 4hc; else if(addbcd4 4h9) /9 addbcd4 = addbcd4 + 4h6;endendfunctionendmodule利用verilog将二进制码转换为十进制BCD码 分类: FPGA verilog 2014-02-20 10:54 2359人阅读 评论(7) 收藏 举报 二进制十进制BCDverilog 小序: 先说一个 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 数据 ,那么个位,十位,百位分别对应129,1613,1817位。 之前写的代码在转换完之后没有对count清零,所以在仿真时候需要用rst_n清零,感谢博友onlytime417的提示,经过修改之后可以对不同的输入值连续转换,而不需要rst_n的复位,下面是修改后的代码以及仿真结果,(该转换模块已经在实际项目中应用)。 CODE:timescale 1ns / 1psmodule 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:0shift_reg;reg 3:0 one,ten;reg 1:0 hun;reg 3:0 count;reg 17:0shift_reg=18b000000000000000000;/ 计数部分 /always ( posedge clk or negedge rst_n )beginif( !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=10b0000000000,bin; else if ( count=5) /判断个位是否5,如果是则+3 begin if(shift_reg15:12=5) /判断十位是否5,如果是则+3 begin shift_reg15:12=shift_reg15:12+2b11; shift_reg11:8=shift_reg11:8+2b11;shift_reg=shift_reg1; /对个位和十位操作结束后,整体左移end else begin shift_reg15:12=shift_reg15:12;shift_reg11:8=shift_reg11:8+2b11;shift_reg=shift_reg=5) begin shift_reg15:12=shift_reg15:12+2b11; shift_reg11:8=shift_reg11:8;shift_reg=shift_reg1;end else begin shift_reg15:12=shift_reg15:12;shift_reg11:8=shift_reg11:8;shift_reg=shift_reg1;end end end end/输出赋

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论