mikrocontroller.net

Forum: FPGA, VHDL & Co. Denkfehler bei carry-chains?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Carry (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuche (verzweifelt) eine carry-chain auf einem Intel Max 10 in 
VHDL für einen Time-to-Digital-Converter zu generieren, leider bekomme 
ich es einfach nicht hin. Ich weiß dass man das eigentlich nicht so 
machen sollte, ist eher akademisches Interesse und ein bisschen Übung in 
VHDL. Bisher habe ich folgende Implementierung (Auszug):
signal sum, carry: std_logic_vector (NCELLS downto 0); 
[...]
  process (CLK)
  begin
    if (rising_edge(CLK) and ENABLE = '1') then
      LINE_OUT <= sum;
    end if;
  end process;

  carry(0) <= TRIGGER;
  
  f: for i in 0 to (NCELLS-1) generate
    c: carry_sum port map (sin => '1',
                    cin => carry(i),
                    sout => sum(i),
                    cout => carry(i+1));
  end generate f;


Leider spuckt Quartus beim Post-Mapping nur Flip-Flops mit VCC am 
Eingang aus, wie im Bild zu sehen. Ich hätte erwartet, dass der Ausgang 
LINE_OUT überall '1' ist wenn TRIGGER konstant '0' ist oder umgekehrt, 
also dass der Ausgang in jedem Fall von TRIGGER abhängig ist. Quartus 
sieht das offenbar nicht so, und ich verstehe nicht, was ich falsch 
mache. Kann mir jemand einen Tipp geben?


Hier die komplette Entity:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.all;

entity tdc is
  generic
  (
    NCELLS: natural := 10
  );
  port
  (
    RESET    : in std_logic;
    CLK     : in std_logic;
    TRIGGER    : in std_logic;
    LINE_OUT : out std_logic_vector((NCELLS-1) downto 0);
    ENABLE  : in std_logic
  );
end tdc;

architecture carry_chain of tdc is

component carry_sum
    port (
        sin : in std_logic;
        cin : in std_logic;
        sout : out std_logic;
        cout : out std_logic );
end component;

signal carry: std_logic_vector (NCELLS downto 0); 
signal sum: std_logic_vector (NCELLS downto 0); 
attribute keep: boolean;
attribute keep of carry: signal is true;
attribute keep of sum: signal is true;
begin

  process (RESET, CLK)
  begin
    if (rising_edge(CLK) and ENABLE = '1') then
      LINE_OUT <= sum;
    end if;
  end process;

  carry(0) <= TRIGGER;
  
  f: for i in 0 to (NCELLS-1) generate
    c: carry_sum port map (sin => '1',
                    cin => carry(i),
                    sout => sum(i),
                    cout => carry(i+1));
  end generate f;

end;

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
So, wie Du das gebaut hast, wäre der einzige Ausgang, der sich abhängig 
von den Zuständen der Eingänge ändern würde, das High-Bit der 
Carry-Chain.

Genau das verwirfst Du aber (es steckt in sum nicht drin).

Unabhängig davon kann ich mir nicht recht vorstellen, dass der Code so 
überhaupt durch die Synthese geht (Du belegst LINE_OUT mit sum, die 
Vektoren haben aber unterschiedliche Breite).

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Übrigens: carry_sum ist ja ein Quartus Primitive. Anstatt das über eine 
Component-Deklaration aus dem Nichts "herzuzaubern", wäre wohl so was 
eher angesagt:

library altera;
use altera.altera_primitives_components.carry_sum;


Dann kannst Du die Component weglassen.

von Carry (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Du hast recht, ich habe offenbar die Funktion von carry_sum falsch 
verstanden. Ich hatte erwartet, dass carry_sum ein "sout <= sin xor cin" 
und ein "cout <= sin and cin" macht. Wie soll carry_sum denn eigentlich 
verwendet werden, wenn man beispielsweise einen Counter damit erstellen 
wollen würde?


Markus F. schrieb:
> Übrigens: carry_sum ist ja ein Quartus Primitive. Anstatt das über
> eine
> Component-Deklaration aus dem Nichts "herzuzaubern", wäre wohl so was
> eher angesagt:

Ah, stimmt, das wusste ich nicht.

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
sout <= sin + cin;

cout ist der evt. dabei entstehende Überlauf.

Nachdem sin bei dir fest auf '1' liegt, ist auch sout in der Kette immer 
'1'. TRIGGER bestimmt also lediglich den Wert von carry(NCELLS), das 
verwirfst Du aber. Quartus sieht das und macht entsprechend aus deinem 
Code ein einfaches
LINE_OUT <= (others => '1');

: Bearbeitet durch User

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.

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