Forum: FPGA, VHDL & Co. Generics Probleme


von ope (Gast)


Angehängte Dateien:

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:
1
Counter8 : Counter_G
2
  generic map(
3
    BIT_WIDTH   => 8;
4
    CLOCK_ENABLE  => true;
5
    DOWN_COUNTER  => false
6
  );
7
8
  port map(
9
    clk    => clock;
10
    reset_n    => reset;
11
    en    => enable;
12
    count    => count
13
  );

Bei Testbench aber nicht:
1
architecture UpCounter of testbench2 is 
2
  component counter_g
3
  .....
4
begin
5
6
  -- Instance the counter
7
  UpCounter: entity work.counter_g
8
  generic map(
9
    BIT_WIDTH   => 4,
10
    CLOCK_ENABLE   => true,
11
      DOWN_COUNTER  => false,
12
    LOADABLE  => false
13
  )
14
  port map(
15
    clk    => clock,
16
    reset_n    => reset,
17
    en    => en,
18
    count    => count
19
  );
20
  ....

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

von Sven Johannes (Gast)


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

von ope (Gast)


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

von ope (Gast)


Lesenswert?

Inzwischen klappt's endlich:
1
entity counter_g is
2
  generic (
3
    BIT_WIDTH:  integer  := 8;  -- design number of taps
4
    CLOCK_ENABLE:  boolean  := true;-- design
5
    DOWN_COUNTER:  boolean  := false;-- behavioral down counter
6
    LOADABLE:  boolean  := false  -- design support preloadable counter
7
  );
8
   port (
9
      clk  : in  std_logic;   -- rising edge trigger count
10
      reset_n   : in  std_logic;   -- asynchronous reset, low active
11
      en        : in  std_logic;   -- count enable, high active
12
      ld  : in  std_logic;   -- data load with clock's rising edge 
13
      data  : in  std_logic_vector(BIT_WIDTH-1 downto 0);-- preload
14
data
15
      count    : out std_logic_vector(BIT_WIDTH-1 downto 0)  -- counter
16
output
17
  );
18
end counter_g;
19
20
21
architecture behavioral of counter_g is
22
23
  signal count_s : std_logic_vector(BIT_WIDTH-1 downto 0);
24
25
begin
26
  process(clk, reset_n)
27
  begin
28
    if(reset_n = '0') then
29
      count_s <= (others => '0');
30
    elsif(rising_edge(clk)) then
31
      if(LOADABLE) then  -- at synthese configurable
32
        if(ld = '1') then
33
          count_s <= data;
34
        end if;
35
      end if;
36
      if(CLOCK_ENABLE) then  -- at synthese configurable
37
        if(en = '1') then
38
          if(not DOWN_COUNTER) then
39
            count_s <= count_s + 1;
40
          else
41
            count_s <= count_s - 1;
42
          end if;
43
        end if;
44
      else
45
        if(not DOWN_COUNTER) then
46
          count_s <= count_s + 1;
47
        else
48
          count_s <= count_s - 1;
49
        end if;
50
      end if;
51
    end if;
52
  end process;
53
54
  count <= count_s;
55
56
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

von ope (Gast)


Lesenswert?

das ist alles sehr zweifelhaft - da habe ich nun schon das "open"
keyword gefunden - haben will es ISE aber auch nicht:
1
...
2
begin
3
Counter8: counter_g
4
  generic map(BIT_WIDTH  => 8,
5
    CLOCK_ENABLE  => true,
6
    DOWN_COUNTER  => false,
7
    LOADABLE  => false)
8
  port map(clk  => clock,
9
    reset_n  => reset,
10
    en  => enable,
11
    count  => count,
12
    ld  => open,
13
    data  => open );
14
15
end behave;

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

von ope (Gast)


Angehängte Dateien:

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 :)
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_arith.all;
4
use ieee.std_logic_unsigned.all;
5
6
7
entity counter_g is
8
  generic(
9
    BIT_WIDTH  :  positive  := 8;      -- design number of taps
10
    CLOCK_ENABLE:  boolean  := true;    -- design
11
    DOWN_COUNTER:  boolean  := false;  -- behavioral down counter
12
    LOADABLE    :  boolean  := false    -- design support preloadable counter
13
  );
14
  port(
15
    clk    : in  std_logic;        -- rising edge trigger count
16
    reset_n  : in  std_logic;        -- asynchronous reset, low active
17
    en      : in  std_logic := '0';    -- count enable, high active
18
    ld      : in  std_logic := '0';    -- data load with clock's rising
19
edge 
20
    data    : in  std_logic_vector(BIT_WIDTH-1 downto 0) := (others =>
21
'0');-- preload data
22
    count    : out std_logic_vector(BIT_WIDTH-1 downto 0)   -- counter
23
output
24
  );
25
end counter_g;
26
27
28
architecture behavioral of counter_g is
29
30
  signal count_s : std_logic_vector(BIT_WIDTH-1 downto 0);
31
32
begin
33
  process(clk, reset_n)
34
  begin
35
    if(reset_n = '0') then
36
      count_s <= (others => '0');
37
    elsif(rising_edge(clk)) then
38
      if(LOADABLE) then      -- at synthese configurable
39
        if(ld = '1') then
40
          count_s <= data;
41
        end if;
42
      end if;
43
      if(CLOCK_ENABLE) then  -- at synthese configurable
44
        if(en = '1') then
45
          if(not DOWN_COUNTER) then
46
            count_s <= count_s + 1;
47
          else
48
            count_s <= count_s - 1;
49
          end if;
50
        end if;
51
      else
52
        if(not DOWN_COUNTER) then
53
          count_s <= count_s + 1;
54
        else
55
          count_s <= count_s - 1;
56
        end if;
57
      end if;
58
    end if;
59
  end process;
60
61
  count <= count_s;
62
63
end behavioral;

1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_arith.all;
4
use ieee.std_logic_unsigned.all;
5
6
entity Counter8 is
7
  port(
8
    clock    : in  std_logic;
9
    enable  : in  std_logic;
10
    reset    : in  std_logic;
11
    count    : out std_logic_vector(7 downto 0)
12
  );
13
end entity Counter8;
14
15
16
architecture behavioral of Counter8 is
17
18
begin
19
  Counter8: entity work.counter_g
20
    generic map(
21
      BIT_WIDTH    => 8,
22
      CLOCK_ENABLE  =>  true,
23
      DOWN_COUNTER  =>  false,
24
      LOADABLE      => false
25
    )
26
    port map(
27
      clk    => clock,
28
      reset_n  => reset,
29
      en      => enable,
30
      count    => count,
31
      ld      => open,
32
      data    => open
33
    );
34
35
end behavioral;

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

Viele Grüße
Olaf

von ope (Gast)


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

von ope (Gast)


Lesenswert?

keine andere Lösung möglich, wirklich nicht???

Viele Grüße
Olaf

von high_speed (Gast)


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

von ope (Gast)


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

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.