Forum: FPGA, VHDL & Co. Synthese eines Address Decoders (VHDL)


von Thomas (Gast)


Lesenswert?

Hallo,

ich versuche gerade nachzuvollziehen was das Synthese-Tool aus meinem 
Code eigentlich macht.

Dazu betrachte ich gerade ein Address Decoder für folgendes Memory 
Layout:

Memory  | Address Offset
-----------------------
Mem 0   | 0x000000
Mem 0-1 | 0x180000
Mem 1   | 0x200000
Mem 1-2 | 0x380000
Mem 2   | 0x400000
Mem 2-3 | 0x580000
Mem 3   | 0x600000
Mem 3-4 | 0x780000
Mem 4   | 0x800000
Mem 4-5 | 0x980000
Mem 5   | 0xA00000
Mem 5-6 | 0xB80000
Mem 6   | 0xC00000
Mem 6-7 | 0xD80000
Mem 7   | 0xE00000
Mem 7-0 | 0xF80000

(Die Namensgebung kommt von den Prozessoren die am Ende darauf zugreifen 
sollen... sollte aber erstmal keine Rolle spielen ;-) )
Das heißt wir haben zwei Arten von Speicher. Zum einen größere 
Hauptspeicher mit 1,5 MB und kleinere Speicher mit 0,5 MB.

Der zugehörige Address Decoder hat folgende Entity:
1
entity addr_dec is
2
3
  generic (
4
    ADDR_WIDTH : natural := 32;
5
    ADDR_OFFSET : std_ulogic_vector(31 downto 0) := (others => '0')
6
  );
7
8
  port (
9
    address : in std_ulogic_vector(ADDR_WIDTH-1 downto 0);
10
    
11
    chipselect : out std_ulogic_vector(SLAVE_QTY-1 downto 0)
12
  );
13
  
14
end addr_dec;

SLAVE_QTY ist dabei eine Konstante die global definiert ist, da sie auch 
in anderen Komponenten genutzt wird. Momentan beträgt sie 16.

Nun habe ich zwei verschiedene Ansätze für die Architektur:

1. Variante bei der ich mir selber rausgesucht habe welche Bits benötigt 
werden und welches Kombinationen zu zum entsprechenden Chipselect führen
1
architecture behavior of addr_dec is
2
3
  signal select_target : std_logic_vector(SLAVE_QTY/2 downto 0);
4
  
5
  signal select_memtype : std_logic;
6
  
7
  signal addr_wo_offset : std_ulogic_vector(ADDR_WIDTH-1 downto 0);
8
9
begin
10
  
11
  addr_wo_offset <= std_ulogic_vector(unsigned(address) - unsigned(ADDR_OFFSET));
12
  
13
  select_memtype <= addr_wo_offset(19) and addr_wo_offset(20);
14
  
15
  set_target : process (addr_wo_offset)
16
    variable one_hot_dec : natural;
17
  begin
18
    one_hot_dec := to_integer(unsigned(addr_wo_offset(23 downto 21)));
19
  
20
    select_target <= (others => '0');
21
    select_target(one_hot_dec) <= '1';
22
  end process;
23
24
  set_output : process (select_target, select_memtype, addr_wo_offset)
25
  begin
26
    
27
    if (addr_wo_offset(31 downto 24) /= (addr_wo_offset(31 downto 24)'range => '0')) then
28
      chipselect <= (others => '0');
29
    else
30
      for i in chipselect'range loop
31
        
32
        if (i mod 2 = 0) then
33
          -- even
34
          chipselect(i)  <= select_target(i/2) and not(select_memtype);
35
        else
36
          -- odd
37
          chipselect(i) <= select_target((i-1)/2) and (select_memtype);
38
        end if;
39
        
40
      end loop;
41
    end if;
42
    
43
  end process;
44
45
end behavior;

und die 2. Variante bei der ich einfache die Start- und Endadressen 
definiere und gucke ob die Adresse in diesem bereich liegt.
1
architecture behavior of addr_dec is
2
3
  type t_segment is record
4
    start_addr : std_ulogic_vector(ADDR_WIDTH-1 downto 0);
5
    end_addr : std_ulogic_vector(ADDR_WIDTH-1 downto 0);
6
  end record;
7
  type t_segment_array is array (natural range <>) of t_segment;
8
  constant SEGMENTS : t_segment_array(0 to 15) := (
9
    (X"00000000", X"00180000"), (X"00180000", X"00200000"), (X"00200000", X"00380000"),
10
    (X"00380000", X"00400000"), (X"00400000", X"00580000"), (X"00580000", X"00600000"),
11
    (X"00600000", X"00780000"), (X"00780000", X"00800000"), (X"00800000", X"00980000"),
12
    (X"00980000", X"00A00000"), (X"00A00000", X"00B80000"), (X"00B80000", X"00C00000"),
13
    (X"00C00000", X"00D80000"), (X"00D80000", X"00E00000"), (X"00E00000", X"00F80000"),
14
    (X"00F80000", X"01000000") );
15
  
16
  signal addr_wo_offset : std_ulogic_vector(ADDR_WIDTH-1 downto 0);
17
18
begin
19
  
20
  addr_wo_offset <= std_ulogic_vector(unsigned(address) - unsigned(ADDR_OFFSET));
21
  
22
  set_chipselect: process (addr_wo_offset)
23
  begin
24
    for i in 0 to 15 loop
25
      if ((unsigned(addr_wo_offset) >= unsigned(SEGMENTS(i).start_addr))
26
            and (unsigned(addr_wo_offset) < unsigned(SEGMENTS(i).end_addr))) then
27
        chipselect(i) <= '1';
28
      else
29
        chipselect(i) <= '0';
30
      end if;
31
    end loop;
32
  end process;
33
34
end behavior;

So, nun is klar das er in der RTL mir bei der ersten Variante Logik aus 
dem One-Hot-Decoder und den Und Gattern baut, so wie ich das ja 
beschrieben habe und bei der 2. Variante nen haufen vergleicher. Wenn er 
das jetz aber auf die LUTs abbildet, sollte doch bei gleichem Verhalten 
auch das gleiche rauskommen oder?
Das Synthese-Tool von Altera macht aus der 1. Variante Logik mit 21 LUTs 
und aus der 2. Logik mit 24 LUTs. Das ist das was ich nicht ganz 
verstehe, ich dachte das Synthese-Tool geht alle eingangsmöglichkeiten 
durch und schaut was an den ausgängen danach anliegt und erstellt anhand 
dieser Informationen entsprechend die LUTs. Nun sollten aber beide 
Beschreibungen funktionell das gleiche machen, oder? (oder liegt as an 
irgendwelchen 'X' und 'U' zuständen?). Habt ihr vlt noch ne Idee woher 
der Unterschied kommt.

Na ja, da die zweite Variante besser anpassbar bei Veränderungen des 
Memory Layouts ist und 3 LUTs auch fast nichts sind werde ich wohl eher 
diese Variante bevorzugen.

Vielen Dank schon mal für eure Antworten und Grüße
Thomas

von Michel (Gast)


Lesenswert?

Vielleicht formulierst Du Deine Frage nochmal präziser?

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


Lesenswert?

Naja...
Gleich ist nicht Gleich. Schon der kleinste Unterschied  bringt da oft 
eigenartige Ergebnisse: 
http://www.lothar-miller.de/s9y/archives/52-Kompakte-Flankenerkennung.html

von Thomas (Gast)


Lesenswert?

Na hauptsächlich wollte ich wissen, wie die 3 LUTs unterschied zustande 
kommen. Wenn mir vlt noch jemand sagen kann ob meine Ansatz überhaupt 
richtig ist, dass bei der Synthese einfach alle Eingangsmöglichkeiten 
versucht werden, dabei geschaut wird was am Ausgang passiert und anhand 
dessen dann die die LUTs erstellt werden.

Grüße
Thomas

von bko (Gast)


Lesenswert?

Ein kleinwenig Erklärung dazu findet sich hier
http://de.wikipedia.org/wiki/Logiksynthese
und hier:
http://de.wikipedia.org/wiki/Verfahren_nach_Quine_und_McCluskey
Zitat:
>Das Verfahren nach Quine und McCluskey (QMCV, nach Willard Van Orman
>Quine und Edward J. McCluskey) ist eine Methode, um Boolesche Funktionen
>zu minimieren (...) Das Verfahren benötigt im schlechtesten Fall
>exponentielle Laufzeit, um eine minimale Lösung zu finden. Das Verfahren
>findet immer eine minimale Lösung, es ist jedoch möglich, dass es noch
>andere (gleichwertige) Lösungen gibt, die nicht gefunden werden. Da das
>zugrunde liegende Problem NP-vollständig ist, und unter der Annahme,
>dass P ≠ NP gilt, gibt es kein in diesem Sinne effizientes Verfahren.

von Fritz J. (fritzjaeger)


Lesenswert?

Hallo Thomas

folgende verbreiteten Irrtümern sitzt du auf:

-die FPGA-tools wissen was für Dich otpimal ist und nehmen dir die 
Entscheidung über für Dich richtige Implementierung ab
-LUT ist alles
-VHDL ist eine Hochsprache zur Beschreibung von Funktionen in Hardware
-die kombinatorische Funktion ist alles was eine digitale Schaltung 
bestimmt


Synthesetools setzen zuerst um was du beschrieben hast, Signal um 
Signal,Block um Block.
Erst dann folgen verschiedene Optimierungsroutinen, die einzeln 
aktiviert sein müssen.

Hast Du einen Komperator beschrieben, setzen
die Tools einen Komperator an. Der kann aus LUTS aufgebaut sein, kann 
aber auch (bspw bei größer|kleiner Vergleichern)
 als "Arithmetik" Subtrahierer aufgebaut sein.
 FPGA haben Strukturen die sich für klein granulare logische 
Verknüpfungen anbieten,
 (LUT's), Strukturen die Optimal für breite/Schnelle Addierer sind 
(Carry-Chain) und Blöcke für breite, konzentrierte Logik
 (BlockRAMS genutz als ROM-LUT). Wobei optimal heißen kann:
 -wenig Ressourcen genutzt
 -wenig LUT's genutzt
 -schnell
 -leicht routbar
 -leicht testbar

 Eine Optimal kleine Schaltung kann schlecht routbar sein. Bspw. kann 
bei einem kleinem zentraler Adressdecoder es schwierig sein
 die ChipSelect Leitungen an die im FPGA vestreut liegenden Datenbus 
Eingangs-FF der einzelnen Module zu verdrahten. Besser waren da
 dezentrale Adressdecoder in der Nähe des Moduls. Das ist wie beim 
Entflechten eines PCB's, schnell hat man sich durch falsche Platzierung
 eines kleinen Blocks die optimale Gesamtlösung für das Gesamt-PCB 
verbaut.

 Einige wenige Logik-Optimierungen können die Tools, aber immer unter 
der Verbidungen das diese Optimierung aktiviert ist und an der 
Beschreibung
 funktionall nicht verändert wird. Beispielsweise bleiben Signale die 
einer "Zwischenvariable" entsprechen erhalten, auch wenn sie in einer 
LUT verschwinden könnten.
 Könnte ja sein das der Anwender nach diesem Signal in der Netzliste 
sucht un es an einen Hardware-debugger wie Chipscope anzuschliessen.

-Für deine Schaltung empfehle ich dir den Synthesereport durchzulesen. 
Dort steht welche Hardwareblöcke in der Beschreibung erkannt worden und 
was daraus gebaut wurde,
Bei Xilinx sieht das so aus:
 Related source file is 
"C:/Users/KommPute/FPGA/Misc/FloatCounter/FloatPointCount/flcnt.vhd".
    Found 12-bit register for signal <count_q>.
    Found 12-bit adder for signal <count_q$add0000> created at line 145.
    Found 17-bit comparator equal for signal <do_tick_0$cmp_eq0000> 
created at line 120.
    Found 4-bit up counter for signal <expo_q>.
    Found 17-bit register for signal <prescale_limit_q>.
    Found 17-bit comparator not equal for signal 
<prescale_limit_q$cmp_ne0000> created at line 109.
    Found 17-bit up counter for signal <prescale_q>.
    Summary:
  inferred   2 Counter(s).
  inferred  29 D-type flip-flop(s).
  inferred   1 Adder/Subtractor(s).
  inferred   2 Comparator(s).

-Eine Blick in den RTL-View hilft auch meist weiter.
-Wieviel Resourcen ein Komperator verbraucht sollte im Library Guide 
stehen.
-Bei den Optimierungen sollte "Flatten Netlist" aktiviert sein oder 
sowas wie Optimierungen über Hierarchiegrenzen.
-Eine Idee wie stark sich die VHDL-Beschreibung auf die Implemtierung 
auswirkt vermittelt das WP 274 von Xilinx. In dem Forums-thread: 
Beitrag "Sinn von "MULT_AND""
wird andiskutiert, was es noch so neben den LUT's gibt.
-Und nicht vergessen:
Die tools setzen das um was du beschrieben hast und nehmen dir keine 
Designentscheidungen ab.

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


Lesenswert?

Thomas schrieb:
> Das heißt wir haben zwei Arten von Speicher. Zum einen größere
> Hauptspeicher mit 1,5 MB und kleinere Speicher mit 0,5 MB.
Ich würde das anhand der signifikanten Bits ausklamüsern:

Erst mal die unnötigen Nullen weg:
Memory  |
-----------------------

Mem 0   | 0x000000  --> 000 0 0
Mem 0-1 | 0x180000  --> 000 1 1
Mem 1   | 0x200000  --> 001 0 0
Mem 1-2 | 0x380000  --> 001 1 1
Mem 2   | 0x400000  --> 010 0 0
Mem 2-3 | 0x580000  --> 010 1 1
Mem 3   | 0x600000  --> 011 0 0
Mem 3-4 | 0x780000  --> 011 1 1
Mem 4   | 0x800000  --> 100 0 0
Mem 4-5 | 0x980000  --> 100 1 1
Mem 5   | 0xA00000  --> 101 0 0
Mem 5-6 | 0xB80000  --> :
Mem 6   | 0xC00000  -->
Mem 6-7 | 0xD80000  -->
Mem 7   | 0xE00000  -->
Mem 7-0 | 0xF80000  --> 111 1 1

Und dann sieht man sofort: das oberste Nibble geht schon sehr stark in 
Richtung "der Chipselect"...

Jetzt nur noch das obere Bit vom Nibble davor mit reingepackt:
1
process (addr) 
2
variable i : integer :=0;
3
begin
4
  cs <= x"0000";                                    -- erst mal kein CS aktiv
5
  i := to_integer(unsigned(addr(23 downto 21)) * 2; -- grob auswählen
6
  if (addr(20 downto 19) = "11" then                -- Feinbestimmung
7
     i := i+1;                                      -- "ungerader" Chipselect
8
  end if;
9
  cs(i) <= '1';                                     -- i enthält den aktiven CS
10
end process;

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.