mikrocontroller.net

Forum: FPGA, VHDL & Co. Generics Probleme


Autor: ope (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich probiere mich gerade an den VHDL generics und Testbenches aus.
Anbei mein sukzessive erweiterter generic counter, für den ich einen
Testbench versuche zu schreiben. Allerdings habe ich Probleme mit der
Instanzierung. Folgendes wird synthetisiert/compiliert:

Counter8 : Counter_G
  generic map(
    BIT_WIDTH   => 8;
    CLOCK_ENABLE  => true;
    DOWN_COUNTER  => false
  );

  port map(
    clk    => clock;
    reset_n    => reset;
    en    => enable;
    count    => count
  );


Bei Testbench aber nicht:

architecture UpCounter of testbench2 is 
  component counter_g
  .....
begin

  -- Instance the counter
  UpCounter: entity work.counter_g
  generic map(
    BIT_WIDTH   => 4,
    CLOCK_ENABLE   => true,
      DOWN_COUNTER  => false,
    LOADABLE  => false
  )
  port map(
    clk    => clock,
    reset_n    => reset,
    en    => en,
    count    => count
  );
  ....


Modelview meckert: Positional associations must be before named
associations. Warum klappt das bei Counter8, aber nicht im TB und warum
ist der Syntax verschieden (konkret vorhandene/fehlende  Semikolon
zwischen generic map und port map)?

Viele Grüße
Olaf

Autor: Sven Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin...

Du hast wiedermal eine Inkonsequenz von VHDL gefunden: genau DA, also
zwischen generic und port-Mapping schreibt die Syntax kein Semikolon
vor.

Wenn das der gleiche Counter_g sein soll, warum hat er unten vier
generichs? Nebenbei sollte oben eigentlich kein <;> stehen...? Kann ich
momentan nicht nachvollziehen, ich setze die Generics immer graphisch,
vielleicht ist das so korrekt.

--
 Sven Johannes

Autor: ope (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn ich es recht verstanden habe, kann ich bei den Generics defaults
angeben, d.h. ich brauche sie nicht bei der Instanzierung mit extra
anzugeben - so geschehen beim synthetisierbaren Counter8 (der sollte
halt nicht loadable sein).

Beim TB wollte ich 4 Versionen testen: Up/Down und Up/Down loadable,
daher habe ich alle 4 Parameter übergeben, also aus Gründen der
Übersicht.

Wie ich gerade gesehen habe, ist meine Counter8 im ISE überhaupt nicht
kompiliert worden - er ist im Module View unter dem Projekt angeordet,
während counter_g und testbench unter dem CPLD sind - so komme ich dann
im ProcessView nicht ran. (Aber ich behaupte mal, er ging schon mal
durch die Synthese - evtl. ohne Semi durch die Probiererei).
Modelsim meckert etwas von:  near "Counter8": expecting: ARCHITECTURE
CONFIGURATION ENTITY LIBRARY PACKAGE USE. Setze ich ein: use entity
work.counter_g(behavioral) davor meint Modelsim:  expecting: STRING
IDENTIFIER.

Irgendwie habe ich offenbar noch immer nicht ganz Prinzip im Detail
begriffen.

Was meinst Du mit generics graphisch machen?

Viele Grüße
Olaf

Autor: ope (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Inzwischen klappt's endlich:

entity counter_g is
  generic (
    BIT_WIDTH:  integer  := 8;  -- design number of taps
    CLOCK_ENABLE:  boolean  := true;-- design
    DOWN_COUNTER:  boolean  := false;-- behavioral down counter
    LOADABLE:  boolean  := false  -- design support preloadable counter
  );
   port (
      clk  : in  std_logic;   -- rising edge trigger count
      reset_n   : in  std_logic;   -- asynchronous reset, low active
      en        : in  std_logic;   -- count enable, high active
      ld  : in  std_logic;   -- data load with clock's rising edge 
      data  : in  std_logic_vector(BIT_WIDTH-1 downto 0);-- preload
data
      count    : out std_logic_vector(BIT_WIDTH-1 downto 0)  -- counter
output
  );
end counter_g;


architecture behavioral of counter_g is

  signal count_s : std_logic_vector(BIT_WIDTH-1 downto 0);

begin
  process(clk, reset_n)
  begin
    if(reset_n = '0') then
      count_s <= (others => '0');
    elsif(rising_edge(clk)) then
      if(LOADABLE) then  -- at synthese configurable
        if(ld = '1') then
          count_s <= data;
        end if;
      end if;
      if(CLOCK_ENABLE) then  -- at synthese configurable
        if(en = '1') then
          if(not DOWN_COUNTER) then
            count_s <= count_s + 1;
          else
            count_s <= count_s - 1;
          end if;
        end if;
      else
        if(not DOWN_COUNTER) then
          count_s <= count_s + 1;
        else
          count_s <= count_s - 1;
        end if;
      end if;
    end if;
  end process;

  count <= count_s;

end behavioral;


und

[vhdl Counter8]

use work.counter_g;

entity Counter8 is
    port(clock    : in std_logic;
      enable   : in std_logic;
         reset    : in std_logic;
  count    : out std_logic_vector(7 downto 0) );
end entity Counter8;


architecture behave of Counter8 is

   component counter_g
     generic(  BIT_WIDTH:  integer;
      CLOCK_ENABLE:  boolean;
      DOWN_COUNTER:  boolean;
      LOADABLE:  boolean);
      port(clk       : in std_logic;
           reset_n: in std_logic;
           en: in std_logic;
           ld: in std_logic;
           data: in std_logic_vector ( BIT_WIDTH - 1 downto 0 );
           count: out std_logic_vector ( BIT_WIDTH - 1 downto 0 ) );
   end component;

  -- Top level signals
  signal ld  : std_logic := '0';   -- unused
  signal data  : std_logic_vector(7 downto 0);    -- unused

begin
   Counter8 : counter_g
     generic map(BIT_WIDTH     => 8)
     port map(  clk    => clock,
             reset_n  => reset,
             en    => enable,
            count    => count,
      ld    => ld,
      data    => data );

end behave;

[/vhdl]

Jetzt die interessanten Fragen.

Warum verhalten sich Xilinx ISE und Modelview syntaktisch verschieden?
Bei Instanzierung kann ich in ISE die generic Parameter wie oben
weglassen, in Modelsim muss ich dieses nochmals angeben - obwohl sie
einen default haben.

Ich möchte für Counter8 keinen Support für loadable haben. Bei der
Synthese wird es korrekter Weise rausgeworfen mit dem Hinweis - nicht
benutzt. Gibt es einen Weg, bei der Instanzierung es gleich weg zu
lassen um so die Warnung erst gar nicht aufkommen zu lassen? d.h. beim
Port map dieses gleich weg zu lassen und die unbenutzten dummy signal
defs auch gleich?, da generic LOADABLE = false ist?

Muss ich jedesmal bei der Instanzierung eines generics die component
Deklartion wie oben ständig mitschleifen? Gibt's eine bessere
Möglichkeit? zB wie das include Konzept von C?

Wie bekommt man das mit den Tabs in ISE und Modelsim hin - irgendwie
verwenden die beide verschiedene, obwohl ich bei Modelsim schon 3 tabs
(wie bei ISE) eingestellt habe.

Viele Grüße
Olaf

Autor: ope (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das ist alles sehr zweifelhaft - da habe ich nun schon das "open"
keyword gefunden - haben will es ISE aber auch nicht:
...
begin
Counter8: counter_g
  generic map(BIT_WIDTH  => 8,
    CLOCK_ENABLE  => true,
    DOWN_COUNTER  => false,
    LOADABLE  => false)
  port map(clk  => clock,
    reset_n  => reset,
    en  => enable,
    count  => count,
    ld  => open,
    data  => open );

end behave;


No default value for unconnected port <ld>.
No default value for unconnected port <data>.

Autor: ope (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
na das war ein Krampf - für alle die es interessiert - hier die Lösung.
Konstruktive Hinweise sind willkommen, TB wave im Anhang (mein erstes
VHDL Progrämmchen :)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;


entity counter_g is
  generic(
    BIT_WIDTH  :  positive  := 8;      -- design number of taps
    CLOCK_ENABLE:  boolean  := true;    -- design
    DOWN_COUNTER:  boolean  := false;  -- behavioral down counter
    LOADABLE    :  boolean  := false    -- design support preloadable counter
  );
  port(
    clk    : in  std_logic;        -- rising edge trigger count
    reset_n  : in  std_logic;        -- asynchronous reset, low active
    en      : in  std_logic := '0';    -- count enable, high active
    ld      : in  std_logic := '0';    -- data load with clock's rising
edge 
    data    : in  std_logic_vector(BIT_WIDTH-1 downto 0) := (others =>
'0');-- preload data
    count    : out std_logic_vector(BIT_WIDTH-1 downto 0)   -- counter
output
  );
end counter_g;


architecture behavioral of counter_g is

  signal count_s : std_logic_vector(BIT_WIDTH-1 downto 0);

begin
  process(clk, reset_n)
  begin
    if(reset_n = '0') then
      count_s <= (others => '0');
    elsif(rising_edge(clk)) then
      if(LOADABLE) then      -- at synthese configurable
        if(ld = '1') then
          count_s <= data;
        end if;
      end if;
      if(CLOCK_ENABLE) then  -- at synthese configurable
        if(en = '1') then
          if(not DOWN_COUNTER) then
            count_s <= count_s + 1;
          else
            count_s <= count_s - 1;
          end if;
        end if;
      else
        if(not DOWN_COUNTER) then
          count_s <= count_s + 1;
        else
          count_s <= count_s - 1;
        end if;
      end if;
    end if;
  end process;

  count <= count_s;

end behavioral;



library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity Counter8 is
  port(
    clock    : in  std_logic;
    enable  : in  std_logic;
    reset    : in  std_logic;
    count    : out std_logic_vector(7 downto 0)
  );
end entity Counter8;


architecture behavioral of Counter8 is

begin
  Counter8: entity work.counter_g
    generic map(
      BIT_WIDTH    => 8,
      CLOCK_ENABLE  =>  true,
      DOWN_COUNTER  =>  false,
      LOADABLE      => false
    )
    port map(
      clk    => clock,
      reset_n  => reset,
      en      => enable,
      count    => count,
      ld      => open,
      data    => open
    );

end behavioral;


Also, mit den Tabs, das ist nicht das wahre ...

Viele Grüße
Olaf

Autor: ope (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nun ist der der Zähler ladbar - allerdings wäre ein Überlauf flag recht
nützlich. Wie macht man es sinnvoller Weise - einfach ein Carry nehmen
für up/down overflow? oder doch zwei getrennte? Und wie implementiert
man es am besten, ohne ein weiteres FF zu verbraten? Eine UND
Verknüpfung (Vergleich) mit count_s =
convert_std_logic(BIT_WIDTH-1,others => '0') bzw. auf 1 (keine Ahnung
auf syntaktische Korrektheit) gibt ja nur einen kurzen Impuls für einen
Takt Zyklus aus, wobei der Reset Fall ausgeschlossen werden muss bei
Vergleich auf 0.

Viele Grüße
Olaf

Autor: ope (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
keine andere Lösung möglich, wirklich nicht???

Viele Grüße
Olaf

Autor: high_speed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Möglichkeit, den Zählerüberlauf zu detektieren wehre die
Erweiterung des Zählers um ein Bit.

signal count_s : std_logic_vector(BIT_WIDTH downto 0);

Wenn dieses Bit high ist wird ein Merker Signal ebenfalls auf high
gesetzt. So kann man feststellen, dass mindestens ein Zählerüberlauf
stattgefunden hat.

Count_OL   : out std_logic;
.....

process(clk, reset_n)
begin
  if(reset_n = '0') then
    Count_OL <= '0';
  elsif(count_s(BIT_WIDTH) = '1') then
    Count_OL <= '1';
  end if;
end process;

Dem Zählerausgang werden aber nur die unteren Bits übergeben.

Count <= count_s (BIT_WIDTH-1 downto 0);

MfG
Holger

Autor: ope (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank; beim ersten Überlauf springt er auf '1', bleibt dort auch
durch das FF, und beim zweiten bleibt er aber auch auf '1', nur ein
reset setzt ihn wieder auf '0', oder sehe ich das falsch? Eine kleine
UND Verknüpfung könnte das Problem lösen (untere 2 bit auf '1' dann
wird Count_OL <= '0'; zB), ist aber problematisch, da generic, d.h.
ich muss ja auch mit einem 2bit Counter rechnen, gff. auch nur mit 1bit
(2:1 Teiler).

Wie löst man in dem Zusammenhang das up/down carry Flag?

Nimmt man besser einen synchronen oder asynchronen reset? Was sind die
Vor/Nachteile?

So'n trivialer Counter und soviele Fragen, kaum zu glauben... ;-)

Viele Grüße
Olaf

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.