Перейти к содержанию
    

Дробное двоичное в BCD

Всем привет!

Есть 9 бит дробной части двоичного числа

Нужно получить 3 десятичных знака для последующего вывода на 7 сегментный индикатор

 

Подскажите, может есть какой то хитрый приём как это реализовать?

Для целой части понравился вариант как на картинке, а для дробной что-то не нашёл

bcd04.png

 

Verilog HDL, Altera MAX II EPM240

 

Спасибо за ответы по существу

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всем привет!

Есть 9 бит дробной части двоичного числа

Нужно получить 3 десятичных знака для последующего вывода на 7 сегментный индикатор

 

Подскажите, может есть какой то хитрый приём как это реализовать?

Для целой части понравился вариант как на картинке, а для дробной что-то не нашёл

bcd04.png

 

Verilog HDL, Altera MAX II EPM240

 

Спасибо за ответы по существу

 

BCD все равно что преобразовывать, поставьте какой-то конвертор перед подачей данных на BCD для дробной части для коректного преобразования

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

// [b]Binary to BCD converter - Shift and Add-3 Algorithm[/b]

always_comb begin
    
     thousands = 0;
     hundreds = 0;
     tens = 0;
     ones = 0;
     empty = 0;
     
    for(j=15;j>=0;j--)begin
        if(thousands >=5)
            thousands = thousands + 3;
        if(hundreds >=5)
            hundreds = hundreds + 3;
        if(tens >=5)
            tens = tens + 3;
        if(ones >=5)
            ones = ones + 3;
        if(empty >=5)
            empty = empty + 3;
        
        thousands = thousands << 1;
        thousands[0] = hundreds[3];
        
        hundreds = hundreds << 1;
        hundreds[0] = tens[3];
        
        tens = tens << 1;
        tens[0] = ones[3];
        
        ones = ones << 1;
        ones[0] = empty[3];
        
        empty = empty << 1;
        empty[0] = data_in[j];
    end
    
    data[0] = thousands;
    data[1] = hundreds;
    data[2] = tens;
    data[3] = ones;
    
end

 

Опробовал лично - все работает

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет

Проверьте для двоичного числа 0.101000000 (0,625 десятичное) например. Что на выходе?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подскажите, может есть какой то хитрый приём как это реализовать?

Для целой части понравился вариант как на картинке, а для дробной что-то не нашёл

Если целую часть Вы знаете как перевести, то для дроби можно поступить следующим образом..

Дробь умножить на десятичную 100 (сотню), а в двоичной коде эта сотня будет 1100100. Так как умножителя на этой ПЛИС нет, но надо выполнить три суммирования с соответствующими сдвигами (т.к. есть три единицы в двоичном представлении сотни). Полученное число будет уже целое, и его уже легче преобразовать в BCD.

Если сотни будет мало, то возьмите тысячу. Только там есть пять единиц подряд 1111101000, Тогда вместо 5-и идущих подряд сложений выполнить одно сложение и одно вычитание, т.к. 1111101000 = (10000001000 - 0000100000)....

Уточняю, для трех слагаемых два сумматора, т.е. на один меньше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я как то делал компонент перевода дробной части в BCD.

Кажется алгоритм основан на Shift and Add 3. Сейчас уже не помню.

Вот код

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.Math_real.ALL;

ENTITY tr3_bin2bcd_frac IS
   GENERIC( 
      InputWidth   : integer := 16;
      OutputDigits : integer := 16
   );
   PORT( 
      clk        : IN     STD_LOGIC;
      d          : IN     std_logic_vector (InputWidth-1 DOWNTO 0);
      q          : OUT    std_logic_vector (4*OutputDigits-1 DOWNTO 0);
      q_we       : OUT    STD_LOGIC;
      nrst       : IN     std_logic;
      int_ready  : IN     std_logic  := '1';
      frac_ready : BUFFER std_logic
   );

-- Declarations

END tr3_bin2bcd_frac;

architecture Behavioral of tr3_bin2bcd_frac is

constant NumberOfDigits: integer := OutputDigits;
--constant NumberOfDigits: integer := integer(Ceil(real(InputWidth) * 0.30103));
--constant NeededOutputWidth: integer := NumberOfDigits * 4;

type TCorrectTable is array(0 to 15) of std_logic_vector(3 downto 0);
constant Correct8_sub3: TCorrectTable :=
    (x"0", x"1", x"2", x"3",
    x"4", x"5", x"6", x"7",
    x"5", x"6", x"7", x"8",
    x"9", x"A", "----", "----"    -- max input = 13(dec)
    );

signal dBuf: std_logic_vector(InputWidth-1 downto 0);        -- буфер аргумента
signal qBuf: std_logic_vector(4*OutputDigits-1 downto 0);    -- буфер результата

type TState is (Buffering, Shifting);
signal State, LastState: TState;
signal ShiftCounter: integer range 0 to InputWidth-1;
signal first_flag : boolean := true;

begin

process(clk, nrst)
    variable tmpBuf_v : std_logic_vector(qBuf'left downto 0);
begin
    if nrst = '0' then
        dBuf <= (others => '0');
        qBuf <= (others => '0');
        ShiftCounter <= 0;
        State <= Buffering;
        q <= (others => '0');
        q_we <= '0';
        first_flag <= true;
        frac_ready <= '0';
    elsif rising_edge(clk) then
        
        -- default value
        q_we <= '0';
        LastState <= State;
        
        -- fsm
        case State is
            when Buffering =>
                if LastState /= Buffering then
                    q <= qBuf;
                    q_we <= '1' and int_ready;
            end if;
                frac_ready <= '1';
                dBuf <= d;
                qBuf <= (others => '0');
                ShiftCounter <= InputWidth-1;
                if (dBuf /= d or first_flag) and (int_ready = '1' and frac_ready = '1') then
                    first_flag <= false;
                    State <= Shifting;
                    frac_ready <= '0';
                end if;
                
            when Shifting =>
                tmpBuf_v := dBuf(0) & qBuf(qBuf'left downto 1);
                for i in  NumberOfDigits downto 1 loop
                    qBuf(i*4-1 downto i*4-4) <= Correct8_sub3(CONV_INTEGER(unsigned(tmpBuf_v(i*4-1 downto i*4-4))));
                end loop;                
                dBuf <= dBuf(0) & dBuf(InputWidth-1 downto 1);                
                if ShiftCounter = 0 then
                    State <= Buffering;
                    frac_ready <= '1';
                else
                    ShiftCounter <= ShiftCounter - 1;
                end if;
                
            when others => 
                State <= Buffering;
        end case;
        
    end if;
end process;

end Behavioral;

Все должно работать.

Вход int_ready можно не использовать и подать на него 1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Check this out! :laughing:

module bin2bcd(/*AUTOARG*/
   // Outputs
   S, 
   // Inputs
   A
   );
   input [3:0] A;
   output [3:0] S;
   reg [3:0] S;
   always @(A)
     case(A)//synopsys parallel_case
       0 : S=0;
       1 : S=1;
       2 : S=2;
       3 : S=3;
       4 : S=4;
       5 : S=8;
       6 : S=9;
       7 : S=10;
       8 : S=11;
       9 : S=12;
      default : S=4'bxxxx;
     endcase
endmodule // bin2bcd

module Binary_to_BCD_8(P,B);
   output [9:0] P; //BCD form of B
   input [7:0] B;
   wire [3:0]  co1, co2, co3, co4;
   wire [2:0]  co6;
   
   assign      P[0]= B[0];
   
   bin2bcd C1(.A({1'b0,B[7:5]}),
              .S(co1));
   bin2bcd C2(.A({co1[2:0],B[4]}),
              .S(co2));
   bin2bcd C3(.A({co2[2:0],B[3]}),
              .S(co3));
   bin2bcd C4(.A({co3[2:0],B[2]}),
              .S(co4));
   bin2bcd C5(.A({co4[2:0],B[1]}),
              .S(P[4:1]));
   bin2bcd C6(.A({1'b0,co1[3],co2[3],co3[3]}),
              .S({P[9],co6}));
   bin2bcd C7(.A({co6,co4[3]}),
              .S(P[8:5]));
   
endmodule // Binary_to_BCD_8

module test();
   reg [7:0] B;
   wire [9:0] P;
   // End of automatics
   Binary_to_BCD_8 Binary_to_BCD_8(/*AUTOINST*/
                                   // Outputs
                                   .P   (P[9:0]),
                                   // Inputs
                                   .B   (B[7:0]));
   initial begin
      $monitor($time,,"Bin=%0x BCD = %0x",B,P);
      B=0;
      repeat(256) #10 
      B=B+1;
      $finish;
   end
endmodule // test

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...