二进制转为BCD码 左移加三法

快速认识

二进制数转换为BCD码的加3移位法原理_FPGA基础知识极简教程(10)二进制到BCD转换算法…

为了快速了解这个算法,我觉得先看一个小例子比较合适: 我们假设的二进制数为8位(11110011),如何将其转换为BCD码呢? 8位2进制数最大能表示的数字为255,用BCD码表示,需要12位来表示。上面的二进制数是1111_0011,对应的十进制为243,我们知道,它的BCD码形式为:0010_0100_0011。 有了这些先验知识,我们来看看如何转换的!

首先,先将BCD码计数器清零,之后将二进制数和BCD码计数器统统左移,二进制数移出来的最高位放到BCD码计数器的最低位,如下表所示!
在这里插入图片描述
每一次移位之后都判断下,BCD码计数器的十、分以及个位是否大于4,如果任何一位(4bit)大于4,则对其加3,之后继续移位,如此下去,直到移位次数为二进制数的位数之后,停止移位,此时得到的BCD码计数值便是转换后的值。

//伪代码
for(移位次数小于16次(binary的位数))
   各位置的BCD和binary都左移1if(有BCD>4) then 各位置的BCD+3
   else 回到第一步继续左移

用VHDL写一个有限状态机来解决吧~

在这里插入图片描述
上图方框中为n_state的值。

LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;
--二进制转BCD码
ENTITY b_to_bcd IS
   PORT (
      
      clk       : IN STD_LOGIC;
      rst_n     : IN STD_LOGIC;
      binary    : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
      state_en  : IN STD_LOGIC;
      BCD       : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
   );
END b_to_bcd;

ARCHITECTURE trans OF b_to_bcd IS
   SIGNAL reg_binary  : STD_LOGIC_VECTOR(15 DOWNTO 0):="0000000000000000"; 
   SIGNAL bcd_b       : STD_LOGIC_VECTOR(3 DOWNTO 0):="0000";
   SIGNAL bcd_t       : STD_LOGIC_VECTOR(3 DOWNTO 0):="0000";
   SIGNAL bcd_h       : STD_LOGIC_VECTOR(3 DOWNTO 0):="0000";
   SIGNAL bcd_s       : STD_LOGIC_VECTOR(3 DOWNTO 0):="0000";
   --以从10000不断-1直到00001的方式记录左移次数
   SIGNAL push_count  : STD_LOGIC_VECTOR(4 DOWNTO 0):="00000";
   SIGNAL c_state     : STD_LOGIC_VECTOR(5 DOWNTO 0):="000000";
   SIGNAL n_state     : STD_LOGIC_VECTOR(5 DOWNTO 0):="000000";
   --当有BCD位>4的时候,add3_en=1表示接下来要+3了
   SIGNAL add3_en     : STD_LOGIC:='0';
   --当左移次数达到2^len(reg_binary)时,change_done
   SIGNAL change_done : STD_LOGIC:='0';
BEGIN
--这一个process在系统启动初始化
   PROCESS (clk, rst_n)
   BEGIN
      IF ((NOT(rst_n)) = '1') THEN
         c_state <= "000001";
      ELSIF (clk'EVENT AND clk = '1') THEN
         c_state <= n_state;
      END IF;
   END PROCESS;
   
--这一个process是n_state的有限状态机的状态转换
   PROCESS (clk, rst_n)
   BEGIN
      IF ((NOT(rst_n)) = '1') THEN
         n_state <= "000001";
      ELSIF (clk'EVENT AND clk = '1') THEN
         CASE n_state IS
            WHEN "000001" =>
               IF (state_en = '1') THEN--state_en是直接连在1上的,所以只要n_state=000001,就会立刻变为000010
                  n_state <= "000010";
               ELSE
                  n_state <= "000001";
               END IF;
            WHEN "000010" => 
               n_state <= "000100";
            WHEN "000100" =>
               IF (change_done = '1') THEN--判断是否转换完成
                  n_state <= "000001";
               ELSE
                  n_state <= "001000";
               END IF;
            WHEN "001000" =>
               IF (add3_en = '1') THEN
                  n_state <= "010000";
               ELSE
                  n_state <= "000010";--继续转换
               END IF;
            WHEN "010000" =>
               n_state <= "000010";
            WHEN OTHERS =>
               n_state <= "000001";
         END CASE;
      END IF;
   END PROCESS;
   --这一部分是根据n_state有限状态机的状态进行操作,
   --不断地左移,判断各个BCD位(4bit一个BCD位)>4+=3continue左移
   PROCESS (clk, rst_n)
   BEGIN
      IF ((NOT(rst_n)) = '1') THEN
         push_count <= "00000";
         change_done <= '0';
         add3_en <= '0';
      ELSIF (clk'EVENT AND clk = '1') THEN
         CASE n_state IS
            WHEN "000001" =>
               push_count <= "10000";
               reg_binary <= binary;
               bcd_s <= "0000";
               bcd_h <= "0000";
               bcd_t <= "0000";
               bcd_b <= "0000";
            WHEN "000010" =>
               bcd_s <= (bcd_s(2 DOWNTO 0) & bcd_h(3));--左移
               bcd_h <= (bcd_h(2 DOWNTO 0) & bcd_t(3));--左移
               bcd_t <= (bcd_t(2 DOWNTO 0) & bcd_b(3));--左移
               bcd_b <= (bcd_b(2 DOWNTO 0) & reg_binary(15));--左移
               reg_binary <= (reg_binary(14 DOWNTO 0) & '0');--左移
               
               push_count <= push_count - "00001";--移动计数
               IF (push_count = "00001") THEN--减到1表示完成移动16bit(从push_count的初始值10000减一减到00001)
                  change_done <= '1';
               ELSE
                  change_done <= '0';
               END IF;
            WHEN "000100" =>
               IF ((bcd_s >= "0101") OR (bcd_h >= "0101") OR (bcd_t >= "0101") OR (bcd_b >= "0101")) THEN--判断是否大于5
                  add3_en <= '1';
               ELSE
                  add3_en <= '0';
               END IF;
               IF (change_done = '1') THEN
                  BCD <= (bcd_s & bcd_h & bcd_t & bcd_b);--输出BCD码
               END IF;
            WHEN "001000" =>
               add3_en <= '0';
            WHEN "010000" =>
               IF (bcd_s >= "0101") THEN
                  bcd_s <= bcd_s + "0011";--3
               ELSE
                  bcd_s <= bcd_s;
               END IF;
               IF (bcd_h >= "0101") THEN
                  bcd_h <= bcd_h + "0011";--3
               ELSE
                  bcd_h <= bcd_h;
               END IF;
               IF (bcd_t >= "0101") THEN
                  bcd_t <= bcd_t + "0011";--3
               ELSE
                  bcd_t <= bcd_t;
               END IF;
               IF (bcd_b >= "0101") THEN
                  bcd_b <= bcd_b + "0011";--3
               ELSE
                  bcd_b <= bcd_b;
               END IF;
            WHEN OTHERS =>
               change_done <= '0';
               add3_en <= '0';
         END CASE;
      END IF;
   END PROCESS;
   
   
END trans;





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值