專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

verilog實(shí)現(xiàn)任意位二進(jìn)制轉(zhuǎn)換BCD

作者:kb129   來(lái)源:kb129   點(diǎn)擊數(shù):  更新時(shí)間:2014年06月08日   【字體:
    一直感覺這是個(gè)很簡(jiǎn)單的問(wèn)題,直到突然自己連BCD都不太清楚的時(shí)候,才發(fā)現(xiàn)這沒有看起來(lái)那么簡(jiǎn)單,這里介紹里任意位二進(jìn)制轉(zhuǎn)為BCD的verilog代碼,這個(gè)轉(zhuǎn)換方法也可以用在C上面,此為原創(chuàng),轉(zhuǎn)載請(qǐng)注明,謝謝。

基礎(chǔ)知識(shí):

      BCD:BCD碼又稱為8421碼,

      意義:之所以有時(shí)候需要將binary轉(zhuǎn)換為BCD,一般是用在本科的實(shí)驗(yàn)中,為了將binary顯示在數(shù)碼管中,當(dāng)然還有很多應(yīng)用,只是目前我還沒有用到。

轉(zhuǎn)換算法:左移加3法

      移位加3法的具體原理,在網(wǎng)上感覺也沒有人能夠說(shuō)的清楚,以后找到書籍再說(shuō)吧。下面解釋下左移加三算法。這里以8bit二進(jìn)制數(shù)FF做例子。

該算法的操作為上圖。下面對(duì)上圖的操作進(jìn)行詳細(xì)的解釋:

      由于8bit的二進(jìn)制最大為FF,轉(zhuǎn)換為十進(jìn)制為255。所以需要使用三個(gè)BCD碼來(lái)表示所有的8bit二進(jìn)制數(shù)。上圖的hundreds表示百位的BCD,tens表示十位的BCD,Units表示個(gè)位的BCD。算法的操作為一直將binary數(shù)據(jù)左移,移出的數(shù)據(jù)按順序存在hundreds,tens,Units。例如上面的shift1,shift2,shift3操作后,Units變?yōu)榱?111,至于為何在shift3后進(jìn)行add3操作,是因?yàn)樵谒惴ㄖ忻恳淮巫笠,都要?duì)hundreds,tens和Units進(jìn)行判斷,如果hundreds,tens和Units里面的值大于或等于5,就將hundreds,tens和Units自加3.所以shift3后,Units里面為0111,表示為7,此時(shí)不能左移,而是對(duì)Units加三操作,所以Units的值從0111變?yōu)榱?010.值得注意的是,只要hundreds,tens和Units中任意一個(gè)的值大于或等于5(0101),就要先進(jìn)行一次自加三的操作,然后才能繼續(xù)左移,后面的操作同上。

注意2:n位的binary就需要進(jìn)行n次左移

注意3:最后一次左移不需要進(jìn)行add3操作

注意4 :  親自推導(dǎo)16位的,和24位的binary轉(zhuǎn)換,結(jié)果正確,所以該算法適用于任意位binary

to  BCD,當(dāng)然這種論斷沒有足夠的理論依據(jù)。

verilog代碼:

說(shuō)明:對(duì)于8bit及以下的binary,可以使用case語(yǔ)句實(shí)現(xiàn)移位加三算法。由于這里說(shuō)明的是任意位的二進(jìn)制數(shù),轉(zhuǎn)為BCD,所以我的代碼中設(shè)計(jì)了一個(gè)狀態(tài)機(jī),來(lái)控制移位,加三和結(jié)束操作。由于代碼編寫時(shí)間倉(cāng)促,其中或許有些bug。

//name: 二進(jìn)制轉(zhuǎn)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              = 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;
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;                    
reg   [5:0]    c_state, n_state;
reg      add3_en;
reg      change_done;
//this is a three section kind of state code style
always@(posedge clk or negedge rst_n)

begin
        if(!rst_n)
              c_state <= idle;
       else
             c_state <= n_state;
end
//the second section
always@(posedge clk or negedge rst_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
//the third section
always@(posedge clk or negedge rst_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; else bcd_h <= bcd_h;
                       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;
                   end
      default: begin
                           change_done <= 1'b0;
                           add3_en  <= 1'b0;
                  end
           endcase
        end
endmodule

代碼的仿真:這里對(duì)上面的代碼進(jìn)行了仿真,仿真結(jié)果顯示上面代碼可以實(shí)現(xiàn)8bitbinary的BCD轉(zhuǎn)換。

testbench:

module  filter_tb;
reg clk;
reg rst_n;
reg state_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_bcd u_b_to_bcd
(
 .clk(clk),
 .rst_n(rst_n),
 .binary(binary),
 .state_en(state_en),
 .BCD(BCD)
);
endmodule

仿真結(jié)果:二進(jìn)制的3f=十進(jìn)制的63



關(guān)閉窗口

相關(guān)文章