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


von Carry (Gast)


Angehängte Dateien:

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):
1
signal sum, carry: std_logic_vector (NCELLS downto 0); 
2
[...]
3
  process (CLK)
4
  begin
5
    if (rising_edge(CLK) and ENABLE = '1') then
6
      LINE_OUT <= sum;
7
    end if;
8
  end process;
9
10
  carry(0) <= TRIGGER;
11
  
12
  f: for i in 0 to (NCELLS-1) generate
13
    c: carry_sum port map (sin => '1',
14
                    cin => carry(i),
15
                    sout => sum(i),
16
                    cout => carry(i+1));
17
  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:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
library work;
6
use work.all;
7
8
entity tdc is
9
  generic
10
  (
11
    NCELLS: natural := 10
12
  );
13
  port
14
  (
15
    RESET    : in std_logic;
16
    CLK     : in std_logic;
17
    TRIGGER    : in std_logic;
18
    LINE_OUT : out std_logic_vector((NCELLS-1) downto 0);
19
    ENABLE  : in std_logic
20
  );
21
end tdc;
22
23
architecture carry_chain of tdc is
24
25
component carry_sum
26
    port (
27
        sin : in std_logic;
28
        cin : in std_logic;
29
        sout : out std_logic;
30
        cout : out std_logic );
31
end component;
32
33
signal carry: std_logic_vector (NCELLS downto 0); 
34
signal sum: std_logic_vector (NCELLS downto 0); 
35
attribute keep: boolean;
36
attribute keep of carry: signal is true;
37
attribute keep of sum: signal is true;
38
begin
39
40
  process (RESET, CLK)
41
  begin
42
    if (rising_edge(CLK) and ENABLE = '1') then
43
      LINE_OUT <= sum;
44
    end if;
45
  end process;
46
47
  carry(0) <= TRIGGER;
48
  
49
  f: for i in 0 to (NCELLS-1) generate
50
    c: carry_sum port map (sin => '1',
51
                    cin => carry(i),
52
                    sout => sum(i),
53
                    cout => carry(i+1));
54
  end generate f;
55
56
end;

von Markus F. (mfro)


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)


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:
1
library altera;
2
use altera.altera_primitives_components.carry_sum;

Dann kannst Du die Component weglassen.

von Carry (Gast)


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)


Lesenswert?

1
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
1
LINE_OUT <= (others => '1');

: Bearbeitet durch User
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.