Forum: FPGA, VHDL & Co. FPGA: Selektive Signalzuweisung mit "with.select"


von Markus W. (markuswe)


Lesenswert?

Hallo,

ich möchte gerne eine selektive Signalzuweisung in einem FPGA umsetzen. 
Hierzu frage ich mich, welche Lösung am geschicktesten ist und hätte 
gerne eure Meinung dazu.

signal addr   : std_logic_vector (11 downto 0);
signal data_x : std_logic_vector (15 downto 0);
signal REG1   : std_logic_vector (15 downto 0);
signal REG2   : std_logic_vector (15 downto 0);
signal REG3   : std_logic_vector (15 downto 0);

1.
with addr select
   data <= data_x when "000000000000" or "000000000001" or 
"000000000010"
           ... "101000100000"
(Syntax so nicht korrekt, nur zur kürzeren Schreibweise hier fürs Forum)
           REG1   when "101000100001",
           REG2   when "101000100010",
           REG3   when "101000100011",
           (others =>'0') when others;

2.
data <= data_x when (ADDR>="000000000000" and ADDR<= "101000100000") 
else
        REG1 when ADDR="101000100001" else
        REG2 when ADDR="101000100010" else
        REG3 when ADDR="101000100011" else
        (others =>'0') when others;

Aus Fall 2 folgt eine priorisierte sequentielle Decodierung welche ich 
so nicht haben möchte. Um jedoch Schreibarbeit zu sparen suche ich nach 
einer ähnlichen Lösung wie in Fall 2 dargestellt. Andernfalls müsse ich 
für jede Adresse die Zuweisung explizit angeben.

Oder gibt es noch weitere elegante Lösungen?

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


Angehängte Dateien:

Lesenswert?

> Aus Fall 2 folgt eine priorisierte sequentielle Decodierung welche ich
> so nicht haben möchte.
Nein.
Weil du ausschliesslich Abhängigkeiten von ADDR drin hast (und zudem 
keinerlei Bereichsüberlappungen) wird das von der Synthese nicht 
priorisiert. Das ist ein ganz einfacher Mux.

Hier einmal ein kleines Beispiel:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Mux is
6
    Port ( out1 : out  STD_LOGIC;
7
           out2 : out  STD_LOGIC;
8
           out3 : out  STD_LOGIC;
9
           in1 : in  STD_LOGIC;
10
           in2 : in  STD_LOGIC;
11
           in3 : in  STD_LOGIC;
12
           sel : in  STD_LOGIC_VECTOR (2 downto 0));
13
end Mux;
14
15
architecture Behavioral of Mux is
16
17
begin
18
   process (in1,in2,in3,sel) begin
19
      case to_integer(unsigned(sel)) is
20
         when 2#000# to 2#011# => out1 <= in1;
21
         when 2#101#           => out1 <= in2;
22
         when 2#110#           => out1 <= in3;
23
         when others           => out1 <= '0';
24
      end case;   
25
   end process;
26
27
   with sel select
28
   out2 <= in1 when "0--",  -- Aufpassen: das funktioniert mit der Synthese,
29
           in2 when "101",  -- gibt aber mit der Simulation Probleme, 
30
           in3 when "110",  -- denn '-' ist ein definierter Wert wie '0' oder '1'
31
           '0' when others;
32
33
   out3 <= in1 when sel>="000" and sel<="011" else
34
           in2 when sel="101" else
35
           in3 when sel="110" else
36
           '0';
37
end Behavioral;
Und das Ergebnis?
Obwohl die Synthese im RTL-Schaltplan noch Unterschiede bringt, wird 
letztlich für alle 3 Ausgänge das selbe erzeugt (siehe Technologie 
Schematic).

von Markus W. (markuswe)


Lesenswert?

Lothar Miller schrieb:
> Und das Ergebnis?
> Obwohl die Synthese im RTL-Schaltplan noch Unterschiede bringt, wird
> letztlich für alle 3 Ausgänge das selbe erzeugt (siehe Technologie
> Schematic).

Vielen Dank für den Hinweis und des guten Beispiels. Sehr Interessant 
auch, dass das Endresultat durch die verschiedenen Schreibweisen nicht 
beeinträchtigt wird. Ich habe mich jetzt zu folgender Schreibweise 
entschieden:
1
with to_integer(unsigned(DSP_ADDR)) select
2
  data  <=  data_x         when  6#000#  to 16#A20#,
3
            REG1           when  16#A21#,
4
            REG2           when  16#A22#,
5
            REG3           when  16#A23#,
6
           (others => '0') when  others;

Mit welchem Programm hast du denn das Schematic erzeugt?

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


Lesenswert?

Mit Xilinx ISE 12 --> Synthesize --> View Technology Schematic

von berndl (Gast)


Lesenswert?

bloede Frage: Was macht das statement mit den 6#ABC# denn?
1
  data  <=  data_x         when  6#000#  to 16#A20#,

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


Lesenswert?

> 6#ABC#
Das wäre ein Fehler, aber es heißt zum Glück 6#000#
Das ist eine 0 zur Basis 6 ;-)

2#1001# = 10#9# = 9
2#1111# = 10#15# = 16#F# = 15

von berndl (Gast)


Lesenswert?

danke, hab's kapiert.

von Markus W. (markuswe)


Lesenswert?

korrekt. Hier hatte sich ein Tippfehler eingeschlichen. Korrekterweise 
sollte es 16#000# anstatt 6#000# heißen. In diesem Fall wäre das 
Ergebnis wie bereits erwähnt das gleiche.

von Harry (Gast)


Lesenswert?

Hallo,
mit Interesse hab ich diesen (doch etwas älteren) Beitrag gelesen, da 
wir im Moment ein ähnliches Problem haben.

Lothar Miller schrieb:
>> Aus Fall 2 folgt eine priorisierte sequentielle Decodierung welche ich
>> so nicht haben möchte.
> Nein.
> Weil du ausschliesslich Abhängigkeiten von ADDR drin hast (und zudem
> keinerlei Bereichsüberlappungen) wird das von der Synthese nicht
> priorisiert. Das ist ein ganz einfacher Mux.

Gilt das auch für (im Rahmen) beliebig viele Eingangskombinationen, oder 
nur für soviele, wie im FPGA halt in eine LUT passen? In deinem Beispiel 
hast du ja nur 4 Kombinationen.
Was passiert, wenn zwar die Abhängigkeit von nur einem Signal bleibt, es 
sehr viele Eingangskombinationen werden, dann müssen im FPGA ja viele 
LUTs hintereinander geschalten werden. Hat dann immer noch jede 
Kombination die gleiche Priorität, unabhängig von der Art der 
Beschreibung?

Ich frage, weil wir im Moment das Problem auf einem Spartan3 haben, dass 
das asynchrone, parallele Interface zu einem Microcontroller plötzlich 
Timing Probleme (teilweise falsche gelesene Werte) verursacht, nachdem 
es zuvor problemlos gelaufen ist.
Wir haben eine Register-Bank im FPGA, die über die Zeit natürlich immer 
wächst, laufend kommen neue Features und Debug-Sachen dazu, die die 
Kombinatorik immer komplexer machen. (Ich erklär es mir so, dass der Mux 
im FPGA mit jedem zusätzlichen Register "tiefer" wird und somit das 
Timing zum Ausgang verschlechtert).

Danke für eure Einschätzung,
lg Harry

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


Lesenswert?

Harry schrieb:
> Was passiert, wenn zwar die Abhängigkeit von nur einem Signal bleibt, es
> sehr viele Eingangskombinationen werden, dann müssen im FPGA ja viele
> LUTs hintereinander geschalten werden. Hat dann immer noch jede
> Kombination die gleiche Priorität, unabhängig von der Art der
> Beschreibung?
Eine LUT ergibt, wenn sie hintereinender geschaltet wird einfach nur 
eine größere LUT.

> (Ich erklär es mir so, dass der Mux im FPGA mit jedem zusätzlichen
> Register "tiefer" wird und somit das Timing zum Ausgang verschlechtert).
Es kommt darauf an, wie stark die Pfade ineinander verschachtelt und 
ausgdekodiert sind.

> Ich frage, weil wir im Moment das Problem auf einem Spartan3 haben, dass
> das asynchrone, parallele Interface zu einem Microcontroller plötzlich
> Timing Probleme (teilweise falsche gelesene Werte) verursacht, nachdem
> es zuvor problemlos gelaufen ist.
Das kannst du doch einfach nachlesen: wenn der uC die Daten liest, 
solange die noch nicht stabil sind, dann musst du Waitstates einfügen 
oder schneller werden.
Aber offenbar hast du diesbezüglich keine Constraints angegeben. Denn 
sonst würde dir die Toolchain schon was sagen, wenns knapp wird...

Die allermeisten Probleme kommen bei asynchronen Zugriffen aus dieser 
Ecke:
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren

von Harry (Gast)


Lesenswert?

Hi Lothar,
vielen Dank für deine rasche Antwort.

Ok, dann ist das mit den mehreren Eingängen also geklärt.

Und, du hast Recht, bei den Timing Constraints haben wir noch 
Nachholbedarf. Wir haben schon welche, aber anscheinend greifen sie 
nicht richtig. Ich muss mir die nochmal genauer anschauen, mich verwirrt 
der UCF Syntax immer wieder aufs Neue... und dem Constraints Editor von 
Xilinx vertrau ich auch nicht so ganz.

Danke auch für den informativen Link, Thema Metastabilität ist immer 
interessant :-) Nur ist es schwierig, bei dem asynchronen EMIF, Sachen 
einzusynchronisieren, denn nach den empfohlenen zwei FF-Stufen ist der 
Microcontroller schon wieder mit anderen Dingen beschäftigt. Aber das 
schau ich mir auch nochmal genauer an.

lg Harry

von Duke Scarring (Gast)


Lesenswert?

Harry schrieb:
> bei dem asynchronen EMIF, Sachen
> einzusynchronisieren
Dort reicht es eigentlich, wenn man /RD und /WR einsychronisiert (siehe 
Link, ab Seite 29). Ggf. muß der Controller wait-states einlegen.

Duke

[1] http://www.pldworld.com/_xilinx/html/training/10_fpga_dsgn_tech.pdf

von berndl (Gast)


Lesenswert?

Du brauchst vor allem die Adresse so frueh wie moeglich. Das musst du am 
Controller halt einstellen. Damit kannst du den 'read' sauschnell 
hinbekommen. Und wie du ja bemerkt hast: Je mehr Register im FPGA, desto 
langsamer wird der 'read'...

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


Lesenswert?

Beim Lesen muss eigentlich gar nichts registriert sein, wenn das Lesen 
nicht Auswirkungen auf das gelesene Register hat (z.B. ein Interruptflag 
löscht). Und beim Schreiben dürfen die Daten ruhig verzögert abgelegt 
werden, sie müssen nur schon dort sein, wenn gleich danach wieder von 
der selben Adresse gelesen wird...

von Harry (Gast)


Lesenswert?

Super, danke für eure Inputs! Werde weitere Tests in der Richtung 
machen.

(Langsam gleitet die Diskussion in offtopic ab, deshalb werde ich 
gegebenenfalls weitere Fragen extra posten!)

Danke an alle, lg

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.