快速认识
二进制数转换为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都左移1位
if(有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?+=3:continue左移
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;