verilog实现任意位二进制转换BCD_第1页
verilog实现任意位二进制转换BCD_第2页
verilog实现任意位二进制转换BCD_第3页
verilog实现任意位二进制转换BCD_第4页
verilog实现任意位二进制转换BCD_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

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

文档简介

1、verilog实现任意位二进制转换BCD作者:kb129   来源:kb129   点击数:1372   更新时间:2014年06月08日   【字体:大 中 小】     一直感觉这是个很简单的问题,直到突然自己连BCD都不太清楚的时候,才发现这没有看起来那么简单,这里介绍里任意位二进制转为BCD的verilog代码,这个转换方法也可以用在C上面,此为原创,转载请注明,谢谢。 基础知识:      BCD:BCD码

2、又称为8421码,      意义:之所以有时候需要将binary转换为BCD,一般是用在本科的实验中,为了将binary显示在数码管中,当然还有很多应用,只是目前我还没有用到。转换算法:左移加3法      移位加3法的具体原理,在网上感觉也没有人能够说的清楚,以后找到书籍再说吧。下面解释下左移加三算法。这里以8bit二进制数FF做例子。该算法的操作为上图。下面对上图的操作进行详细的解释:      由于8bit的二进制最大为FF,转换为十进制

3、为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后,U

4、nits里面为0111,表示为7,此时不能左移,而是对Units加三操作,所以Units的值从0111变为了1010.值得注意的是,只要hundreds,tens和Units中任意一个的值大于或等于5(0101),就要先进行一次自加三的操作,然后才能继续左移,后面的操作同上。注意2:n位的binary就需要进行n次左移注意3:最后一次左移不需要进行add3操作注意4 :  亲自推导16位的,和24位的binary转换,结果正确,所以该算法适用于任意位binaryto  BCD,当然这种论断没有足够的理论依据。verilog代码:说明:对于8bit及以下的binar

5、y,可以使用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, &

6、#160;    binary,      state_en,     BCD);parameter   b_length      = 8;parameter   bcd_len       = 12;parameter   idle       

7、       = 5'b00001;parameter   shift             = 5'b00010;parameter   wait_judge   = 5'b00100;parameter   judge        

8、60;  = 5'b01000;parameter   add_3          = 5'b10000;input       clk;input       rst_n;input    b_length-1:0  binary;input     

9、; state_en;output reg 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;             

10、60;      reg   5:0    c_state, n_state;reg      add3_en;reg      change_done;/this is a three section kind of state code stylealways(posedge clk or negedge rst_n)begin   

11、     if(!rst_n)              c_state <= idle;       else             c_state <= n_state;end/the second sectionalways(po

12、sedge clk or negedge rst_n)begin       if(!rst_n)                  c_state <= idle;       else         

13、0;       case(n_state)                 idle:begin                       

14、60;       if(binary!=0)&&(state_en=1'b1)&&(change_done=0'b0)                                

15、;       n_state <= shift;                              else          

16、60;                           n_state <= idle;                    &

17、#160;     end                 shift: n_state <= wait_judge;       wait_judge: begin             &

18、#160;                 if(change_done=1'b1)                             

19、         n_state <= idle;                               else        

20、;                              n_state <= judge;                 &#

21、160;        end                judge:begin                        

22、0;          if(add3_en)                                       n_s

23、tate <= add_3;                               else                &#

24、160;                      n_state <= shift;                         

25、; end                add_3:begin                               &#

26、160; n_state <= shift;                           end               default: n_state <= idle;&#

27、160;               endcaseend/the third sectionalways(posedge clk or negedge rst_n)begin         if(!rst_n)             

28、     begin                          shift_time  <= 4'b0;              

29、60;           change_done <= 1'b0;                          add3_en  <= 1'b0;    

30、             end         else           case(n_state)           idle:begin    &#

31、160;                     shift_time <= b_length;                         

32、; reg_binary <= binary;                          bcd_h     <= 4'b0;             

33、             bcd_t     <= 4'b0;                          bcd_b     <= 4'

34、;b0;                        end          shift:begin              

35、0;        bcd_h,bcd_t,bcd_b,reg_binary <= bcd_h,bcd_t,bcd_b,reg_binary<<1;                      shift_time <= shift_time-1;    &

36、#160;                 if(shift_time=1)     change_done <= 1'b1;                      els

37、e                       change_done <= 1'b0;                     end  wait_jud

38、ge:begin                       if(bcd_h>=4'd5)|(bcd_t>=4'd5)|(bcd_b>=4'd5)                

39、;               add3_en <= 1;                       else          &

40、#160;                    add3_en <= 0;                      if(change_done=1)   BCD <

41、;= bcd_h,bcd_t,bcd_b;                    end        judge:  add3_en <= 0;       add_3: begin      

42、0;                if(bcd_h>=4'd5) bcd_h <= bcd_h + 4'b0011; else bcd_h <= bcd_h;                      &

43、#160;if(bcd_t>=4'd5) bcd_t <= bcd_t + 4'b0011; else bcd_t <= bcd_t;                       if(bcd_b>=4'd5) bcd_b <= bcd_b + 4'b0011; else bcd_b <= bcd_b;

44、0;                  end      default: begin                        

45、60;  change_done <= 1'b0;                           add3_en  <= 1'b0;            

46、      end           endcase        endendmodule代码的仿真:这里对上面的代码进行了仿真,仿真结果显示上面代码可以实现8bitbinary的BCD转换。testbench:module  filter_tb;reg clk;reg rst_n;reg state_en;reg  7:0 binary;wire 11

47、:0 BCD;initial       begin                clk=0;                rst_n=0;      &#

48、160;          state_en = 0;     #100   binary = 8'h3f;     #150   rst_n=1;     #200     state_en =1;endalways  #10  clk=clk;b_to_bcd u_b_to_bcd( .

49、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博客 原文  主题 软件开发           小序 :                先说一个 bear

50、 的亲身体会,bear 在做一些 fpga 小设计时经常会用到数据显示功能,比如数字时钟,数字频率计,温度计,跑表等等,往往我们会选用        led 数码管来做显示,  因为它驱动起来比 lcd 液晶要简单的很多,我们知道 fpga 中寄存器在定义和储存的数据都是采用二进制的格式 ,而 fpga 输出给数码        管做显示的数据必须是十进制的格式 , 之前 bear 经常会选择把一个寄存器的个位和十位分开定义 ,比如在做数字时钟时 ,就会吧 时,分,秒的各位和十位    

51、;    都分别定义成一个变量  ,无疑这种方法会增加代码的复杂度 ,所以考虑需要一个专门把 二进制 的数据转换成 十进制 BCD码的模块 ,在网上有一些, 但是好        像都不太完整 , 所以bear花了一下午写了一个 ,亲测效果不错 ,希望对朋友们有所帮助,下面开始正文。  首先给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例):                1.将二进制码左移一位(或者乘2)  

52、;              2.找到左移后的码所对应的个,十,百位。                3.判断在个位和百位的码是否大于5,如果是则该段码加3。                4.继续重复以上三步直到移位8次后停止。               下面是一个例子 ,将 1111_1111

53、 转换为 BCD码 ,如果8bit数据最终移位得到18bit 数据 ,那么个位,十位,百位分别对应129,1613,1817位。                                        下面给出   CODE:             timescale 1ns / 1ps module bin_dec(c

54、lk,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    

55、17:0shift_reg=18'b000000000000000000; / 计数部分 / 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

56、) 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

57、11:8>=5)         /判断个位是否>5,如果是则+3             begin              if(shift_reg15:12>=5) /判断十位是否>5,如果是则+3                    begin    shift_reg15

58、:12=shift_reg15:12+2'b11;       shift_reg11:8=shift_reg11:8+2'b11; shift_reg=shift_reg<<1;  /对个位和十位操作结束后,整体左移  endelse        begin                    shift_reg15:12=shift_reg15:12; shif

59、t_reg11:8=shift_reg11:8+2'b11; shift_reg=shift_reg<<1;  end           end                       else           begin              if(shift_reg15:

60、12>=5)                  begin    shift_reg15:12=shift_reg15:12+2'b11;    shift_reg11:8=shift_reg11:8;shift_reg=shift_reg<<1;  end              else        begin &

61、#160;                  shift_reg15:12=shift_reg15:12; shift_reg11:8=shift_reg11:8; shift_reg=shift_reg<<1;  end           end            end   end /输出赋值/ always ( posedge clk or negedg

62、e 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; hun<=shift_reg17:16;

63、0;   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:

64、 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: 1

65、4'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位的部分,最后把结果拼接 给你一个

66、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+1'b1 : hex15:0; /去符号assign dec = rese,resd3:0,resc3:0,resb

67、3: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) 4'h0: rhexd <= 18'h00000; 4'h1: rhexd <= 18'h04096; 4'h2: rhexd <= 18'h08192; 4

68、9;h3: rhexd <= 18'h12288; 4'h4: rhexd <= 18'h16384; 4'h5: rhexd <= 18'h20480; 4'h6: rhexd <= 18'h24576; 4'h7: rhexd <= 18'h28672; default: rhexd <= 10'h00000; endcaseendalways(posedge clk)begin case(rhex2) 4'h0: rhexc <= 14'h0000;

69、4'h1: rhexc <= 14'h0256; 4'h2: rhexc <= 14'h0512; 4'h3: rhexc <= 14'h0768; 4'h4: rhexc <= 14'h1024; 4'h5: rhexc <= 14'h1280; 4'h6: rhexc <= 14'h1536; 4'h7: rhexc <= 14'h1792; 4'h8: rhexc <= 14'h2048; 4'h9: rh

70、exc <= 14'h2304; 4'ha: rhexc <= 14'h2560; 4'hb: rhexc <= 14'h2816; 4'hc: rhexc <= 14'h3072; 4'hd: rhexc <= 14'h3328; 4'he: rhexc <= 14'h3584; 4'hf: rhexc <= 14'h3840; default: rhexc <= 14'h0000; endcaseend always(posedge

71、 clk)begin case(rhex1) 4'h0: rhexb <= 10'h000; 4'h1: rhexb <= 10'h016; 4'h2: rhexb <= 10'h032; 4'h3: rhexb <= 10'h048; 4'h4: rhexb <= 10'h064; 4'h5: rhexb <= 10'h080; 4'h6: rhexb <= 10'h096; 4'h7: rhexb <= 10'h11

72、2; 4'h8: rhexb <= 10'h128; 4'h9: rhexb <= 10'h144; 4'ha: rhexb <= 10'h160; 4'hb: rhexb <= 10'h176; 4'hc: rhexb <= 10'h192; 4'hd: rhexb <= 10'h208; 4'he: rhexb <= 10'h224; 4'hf: rhexb <= 10'h240; default: rhexb &l

73、t;= 10'h000; endcaseend always(posedge clk)begin rhexa <= rhex0;endalways(posedge clk)begin resa = addbcd4(rhexa3:0,rhexb3:0,rhexc3:0, rhexd3:0); resb = addbcd4(resa5:4, rhexb7:4,rhexc7:4, rhexd7:4); resc = addbcd4(resb5:4, rhexb9:8,rhexc11:8, rhexd11:8); resd = addbcd4(resc5:4, 4'h0, rhe

74、xc13:12,rhexd15:12); rese = resd5:4 + rhexd17:16;endfunction 5:0 addbcd4; input 3:0 add1,add2,add3,add4;begin addbcd4 = add1 + add2 + add3 + add4; if(addbcd4 > 6'h1d) />29 最低有一个可能出现0xf,但由二进制转换而来的数在这里不会出现大于40的情况 addbcd4 = addbcd4 + 5'h12; else if(addbcd4 > 5'h13) />19 addbcd4

75、= addbcd4 + 4'hc; else if(addbcd4 > 4'h9) />9 addbcd4 = addbcd4 + 4'h6;endendfunctionendmodule利用verilog将二进制码转换为十进制BCD码 分类: FPGA verilog 2014-02-20 10:54 2359人阅读 评论(7) 收藏 举报 二进制十进制BCDverilog          小序:               

76、先说一个 bear 的亲身体会,bear 在做一些 fpga 小设计时经常会用到数据显示功能,比如数字时钟,数字频率计,温度计,跑表等等,往往我们会选用       led 数码管来做显示, 因为它驱动起来比 lcd 液晶要简单的很多,我们知道 fpga 中寄存器在定义和储存的数据都是采用二进制的格式 ,而 fpga 输出给数码       管做显示的数据必须是十进制的格式 , 之前 bear 经常会选择把一个寄存器的个位和十位分开定义 ,比如在做数字时钟时 ,就会吧 时,分,秒的各位和十位 

77、     都分别定义成一个变量  ,无疑这种方法会增加代码的复杂度 ,所以考虑需要一个专门把 二进制 的数据转换成 十进制 BCD码的模块 ,在网上有一些,但是好       像都不太完整 , 所以bear花了一下午写了一个 ,亲测效果不错 ,希望对朋友们有所帮助,下面开始正文。                               首先给出

78、二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例):               1.将二进制码左移一位(或者乘2)               2.找到左移后的码所对应的个,十,百位。               3.判断在个位和百位的码是否大于5,如果是则该段码加3。          &#

79、160;    4.继续重复以上三步直到移位8次后停止。               下面是一个例子 ,将 1111_1111 转换为 BCD码 ,如果8bit数据最终移位得到18bit 数据 ,那么个位,十位,百位分别对应129,1613,1817位。                                  

80、0;            之前写的代码在转换完之后没有对count清零,所以在仿真时候需要用rst_n清零,感谢博友onlytime417的提示,经过修改之后可以对不同的输入值连续转换,而不需要rst_n的复位,下面是修改后的代码以及仿真结果,(该转换模块已经在实际项目中应用)。               CODE:       &#

81、160;  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

82、   3:0 count;reg    17:0shift_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 cl

83、k 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      i

84、f(shift_reg11:8>=5)         /判断个位是否>5,如果是则+3            begin             if(shift_reg15:12>=5) /判断十位是否>5,如果是则+3                   begin   shif

85、t_reg15:12=shift_reg15:12+2'b11;      shift_reg11:8=shift_reg11:8+2'b11;shift_reg=shift_reg<<1;  /对个位和十位操作结束后,整体左移 end             else       begin               

86、;    shift_reg15:12=shift_reg15:12;shift_reg11:8=shift_reg11:8+2'b11;shift_reg=shift_reg<<1; end          end                    else      &

87、#160;   begin             if(shift_reg15:12>=5)                 begin   shift_reg15:12=shift_reg15:12+2'b11;   shift_reg11:8=shift_reg11:8;shift_reg=shift_reg<<1; end  

88、0;          else       begin                   shift_reg15:12=shift_reg15:12;shift_reg11:8=shift_reg11:8;shift_reg=shift_reg<<1; end          end    

89、      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&

90、lt;=shift_reg11:8;ten<=shift_reg15:12;hun<=shift_reg17:16;   endendendmodule   以下是仿真结果,bin为输入的二进制码,为了便于对比,仿真时也化成十进制显示了,one,ten,hun分别对应BCD码的个,十,百位。修改前的仿真结果:                          

91、60; 修改后的仿真结果:二进制 转换成十进制 BCD码(加3移位法) 2010-07-05 15:53:35 分类:   "二进制数调整BCD码的方法是将二进制码左移8次,每次移位后都检查低四位LSD+3是否大于7,如是则加3,否则不加,高4位MSD作同样处理"一、为什么左移8次原寄存器是存二进制数的,新寄存器是存十进制数的,当然要左移8次,把数据全部移进去。但这里要注意两件事,第一,如果只安排一个字节作十进制寄存器,原数据要小于 64H(即100)。第二,由于新寄存器是十进制的,要随时调整。二、检查 半字节+3 是否大于 7,是,则 +3在

92、 51 系列里有十进制调节指令(半字节大于 9,则加 6,应该不难理解),PIC 里没有,只好采取变通的方法。检查 半字节+3 是否大于 7,也就是检查半字节是否大于 4。因为,如果大于 4(比如 5、6),下一步左移就要溢出了,所以加 3,等于左移后的加 6,起到十进制调节的作用。那为什么要绕个圈子去检测 半字节+3 是否大于 7 呢?这样程序编起来会简练一些。一个例子假如有一个八位二进制数255,我把他转255的十进制数0        1111 1111    原数1        0000 0001    ;左移一次2        0000 0011   ; 左移二次3     

温馨提示

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

评论

0/150

提交评论