Forum: FPGA, VHDL & Co. unsigned => hex


von Gast (Gast)


Lesenswert?

Hallo an Alle,

hätte da ein Problem bei der Umrechnung einer Zahl im unsigned(7 downto 
0) Format in hex (3 downto 0)

Die Zahl in unsigned ist z.b.: 11111111 -> 255
Diese soll in drei hex zahlen der Form 3 downto 0 gebracht werden
also hex1 = 0x02
hex2 = 0x05
hex3 = 0x05

wie kann das am effektivsten gelöst werden da meine Umrechnung zu 
langsam scheint für die Hardwarebeschreibung nach der Synthese um genau 
10 MHz zu wenig.

thx

von spartanne (Gast)


Lesenswert?

Eine Möglichkeit wäre es (falls verfügbar) ein BlockRAM als Decoder-ROM 
zu nutzen. Die Adresse ist dein Eingangsdatum, am Datenausgang erhälst 
du deine neu formatierten Daten.
Dann noch den Datenausgang auf die 3 Signale mappen:
hex1 <= data_out(12 downto 8);
hex2 <= data_out(7 downto 4);
hex3 <= data_out(3 downto 0);
Also ein BlockRAM organisiert als 256x12. Musst du dann nur noch 
initialisieren und fertig. Schnell, verbraucht keine Logikresourcen, 
Ergebnis nach einem Takt.

von Gast (Gast)


Lesenswert?

des ganze soll aber in "Software" gelöst werden also sprich eine eigne 
function

hab mal sowas uneffektives geschrieben aber dass ist anscheinend nicht 
die beste Lösung:

 type afield is array(3 downto 0) of std_ulogic_vector(3 downto 0);

 function unstohex(cValue : unsigned(cCounterWidth-1 downto 0)) return 
afield is
    variable hund : unsigned(cCounterWidth-1 downto 0);
    variable space : afield;
    variable zehn : unsigned(cCounterWidth-1 downto 0);
    variable ein : unsigned(cCounterWidth-1 downto 0);


    begin
      hund := (cValue/100);
      zehn := (cValue-cValue/100)/10;
      ein := cValue-(cValue/100+((cValue-cValue/100)/10));

      space(3) := dectohex(to_unsigned(0,cCounterWidth));
      space(2) := dectohex(hund);
      space(1) := dectohex(zehn);
      space(0) := dectohex(ein);

      return space;
   end function;

   function dectohex(cin : unsigned(cCounterWidth-1 downto 0)) return 
std_ulogic_vector is
   begin
       case cin is
        when "00000000" => return "0000";
        when "00000001" => return "0001";
        when "00000010" => return "0010";
        when "00000011" => return "0011";
        when "00000100" => return "0100";
        when "00000101" => return "0101";
        when "00000110" => return "0110";
        when "00000111" => return "0111";
        when "00001000" => return "1000";
        when "00001001" => return "1001";
        when others => return "XXXX";
      end case;
   end function;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> des ganze soll aber in "Software" gelöst werden
Ein FPGA ist keine Software.
1
      hund := (cValue/100);
2
      zehn := (cValue-cValue/100)/10;
3
      ein := cValue-(cValue/100+((cValue-cValue/100)/10));
Aha, ein C Programmierer am FPGA.
Du hast auf den mir bekannten FPGAs keine kombinatorische Divison. 
Deshalb kannst du so etwas zwar beschreiben und simulieren, aber niemals 
in reale Hardware abbilden.
Auf welcher FPGA Plattform arbeitest du?

Wenn du neu auf dem Gebiet der Hardwarebeschreibung bist, dann vergiss 
mal zwischendurch (so etwa bis Anfang 2010) die Keywords function und 
procedure. Das sind in der /Beschreibungssprache VHDL/ ganz andere 
Syntaxelemente als in der Programmiersprache C. Und die machen daher 
auch ganz was anderes.
Du sollest dich eher mal damit befassen, was Komponenten und Instanzen 
sind.

EDIT:
1
      :
2
      space(1) := dectohex(zehn);
3
        :
4
        :
5
        when "00001000" => return "1000";
6
        when "00001001" => return "1001";
7
        when others => return "XXXX";
8
      :
warum schreibst du nicht einfach "nur":
1
      space(1) <= zehn(3 downto 0);
Das ist eine Zuweisung der unteren 4 Bits.
Wobei ich den Sinngehalt des davor geschriebenen bereits kommentiert 
habe.


BTW:
Am besten vergisst du auch gleich mal das Keyword variable und 
verwendest (vorerst) nur Signale. Das ist ein ernstgemeinter Tipp, kein 
Witz.
Du stehst noch wesentlich weiter vorne am Anfang, als du selber meinst 
;-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Diese soll in drei hex zahlen der Form 3 downto 0 gebracht werden
Was du also willst, sind BCD-Zahlen (Binär Codierte Dezimalzahlen)
Ich habe mir zu dem Thema hier mal was festgehalten:
http://www.lothar-miller.de/s9y/categories/28-Vektor-nach-BCD

von Gast111 (Gast)


Lesenswert?

Dieses Problem hatte ich letztens auch. Hier meine Lösung. Sie ist nicht 
generisch und braucht 4 Takte pro Dezimalstelle. Dafür ist sie sehr 
klein synthetisierbar (4 Slices). Für mehrstellige Dezimalzahlen muss 
man mehrere dieser Blöcke kaskadieren.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_unsigned.all;
4
use ieee.numeric_std.all;
5
6
-- -------------------------------------------------------------------------
7
-- Funktionsweise: Siehe Xilinx Application Note XAPP029
8
-- http://www.xilinx.com/support/documentation/application_notes/xapp029.pdf
9
-- -------------------------------------------------------------------------
10
11
entity bin2bcd is port (  clk        : in  std_logic;
12
                  init        : in  std_logic;
13
                  bin_in      : in  std_logic;
14
                  bcd_out      : out  std_logic_vector(3 downto 0);
15
                  bcd_carry_out  : out  std_logic);
16
end bin2bcd;
17
18
19
architecture behavior of bin2bcd is
20
21
  signal shiftreg    : std_logic_vector(3 downto 0)  := "0000";
22
23
begin
24
25
  process(clk) is
26
  begin
27
    if rising_edge(clk) then
28
29
      if init = '1' then
30
        shiftreg  <= "0000";
31
      else
32
        case shiftreg(3 downto 0) is
33
          when "0101"    => shiftreg <= "000" & bin_in;
34
          when "0110"    => shiftreg <= "001" & bin_in;
35
          when "0111"   => shiftreg <= "010" & bin_in;
36
          when "1000"   => shiftreg <= "011" & bin_in;
37
          when "1001"   => shiftreg <= "100" & bin_in;
38
          when others   => shiftreg <= shiftreg(2 downto 0) & bin_in;
39
        end case;
40
      end if;
41
42
    end if;
43
  end process;
44
45
  bcd_out      <= shiftreg(3 downto 0);
46
  bcd_carry_out  <=  '1'  when conv_integer(shiftreg(3 downto 0)) >= 5 and init = '0'  else
47
              '0';
48
49
end behavior;

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.