AFON // радиотехник affonya@mail.ru
← Проекты на VHDL

Проект 42. Двоично-десятичный преобразователь

Восьмиразрядное число превращается в три десятичные цифры без единой операции деления — алгоритмом double dabble, основанным на сдвигах и коррекции по три.

Задача

Перевести двоичное число в три десятичных разряда без деления.

Тип схемы: Конечный автомат с составным сдвиговым регистром.
Модуль: bin2bcd. Среда: Quartus, Vivado, ISE или свободный GHDL для моделирования. Теорию по языку смотрите в статье VHDL — язык описания аппаратуры, по самим микросхемам — на странице ПЛИС.

Алгоритм

  1. Поместить входное число в младшую часть общего сдвигового регистра.
  2. Проверить каждый BCD-разряд: если он больше четырёх, прибавить тройку.
  3. Сдвинуть весь регистр целиком на один разряд влево.
  4. Повторить коррекцию и сдвиг по числу входных бит и забрать старшую часть как результат.

Код на VHDL

Код проверен компилятором GHDL: проходит анализ и элаборацию без ошибок и предупреждений. Скачать: v42.vhd

--=====================================================
-- Проект 42. Двоично-десятичный преобразователь (double dabble)
-- Восьмиразрядное двоичное число превращается
-- в три десятичных разряда без операции деления.
--=====================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity bin2bcd is
    port (
        clk     : in  std_logic;
        rst     : in  std_logic;
        start   : in  std_logic;
        bin_in  : in  std_logic_vector(7 downto 0);
        bcd_out : out std_logic_vector(11 downto 0);     -- сотни-десятки-единицы
        done    : out std_logic
    );
end entity bin2bcd;

architecture rtl of bin2bcd is
    type state_t is (IDLE, SHIFT, ADJUST, FINISH);
    signal state : state_t := IDLE;
    signal shreg : std_logic_vector(19 downto 0);        -- 12 бит BCD + 8 бит числа
    signal cnt   : integer range 0 to 7 := 0;
begin
    process (clk, rst)
        variable d : std_logic_vector(19 downto 0);
    begin
        if rst = '1' then
            state <= IDLE;
            done  <= '0';
        elsif rising_edge(clk) then
            done <= '0';
            case state is
                when IDLE =>
                    if start = '1' then
                        shreg <= (11 downto 0 => '0') & bin_in;
                        cnt   <= 0;
                        state <= ADJUST;
                    end if;

                when ADJUST =>                            -- коррекция разрядов BCD по 3
                    d := shreg;
                    if unsigned(d(11 downto 8)) > 4 then
                        d(11 downto 8) := std_logic_vector(unsigned(d(11 downto 8)) + 3);
                    end if;
                    if unsigned(d(15 downto 12)) > 4 then
                        d(15 downto 12) := std_logic_vector(unsigned(d(15 downto 12)) + 3);
                    end if;
                    if unsigned(d(19 downto 16)) > 4 then
                        d(19 downto 16) := std_logic_vector(unsigned(d(19 downto 16)) + 3);
                    end if;
                    shreg <= d;
                    state <= SHIFT;

                when SHIFT =>
                    shreg <= shreg(18 downto 0) & '0';    -- сдвиг всего слова влево
                    if cnt = 7 then
                        state <= FINISH;
                    else
                        cnt   <= cnt + 1;
                        state <= ADJUST;
                    end if;

                when FINISH =>
                    done  <= '1';
                    state <= IDLE;
            end case;
        end if;
    end process;

    bcd_out <= shreg(19 downto 8);
end architecture rtl;

Пояснения

  • Коррекция «если больше четырёх — прибавить три» компенсирует то, что при сдвиге BCD-разряд способен перейти за границу 9 без переноса в следующий десятичный разряд.
  • Тот же результат получается циклом вычитания степеней десяти, но double dabble работает за фиксированное число тактов независимо от значения числа.
  • Алгоритм легко расширяется на большую разрядность — добавляется лишь ширина сдвигового регистра и число BCD-разрядов для коррекции.

Что дальше

Следующие проекты — в разделе проекты на VHDL. Сравнить подход с языком Verilog можно в статье Verilog, а разобраться в устройстве самих кристаллов — в статье ПЛИС: FPGA и CPLD.