Forum: FPGA, VHDL & Co. VHDL,schieberegister probleme


von Mario (Gast)


Lesenswert?

Hallo,

als anfänger versuche ich ein Signal zu verschieben. Dazu habe ich als 
eingagangsclock 27 Mhz, diese habe ich mittels counter dann 
runtergeteilt habe.

Folgender code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity SCHIEBEREGISTER is
    Port (
       EINGANG   : in   std_logic_vector (3 downto 0);
       RESET     : in     std_logic;
       LED      : out   std_logic;
       AUSGANG   : out   std_logic_vector (3 downto 0);
       SAVE0    : buffer std_logic_vector (3 downto 0);
       SAVE1    : buffer std_logic_vector (3 downto 0);
       SAVE2    : buffer std_logic_vector (3 downto 0);
       SAVE3    : buffer std_logic_vector (3 downto 0);
       SAVE4    : buffer std_logic_vector (3 downto 0);
       SAVE5     : buffer std_logic_vector (3 downto 0);
       clk      : in     std_logic);


end SCHIEBEREGISTER;

architecture Behavioral of SCHIEBEREGISTER is
--signal SAVE0,SAVE1,SAVE2,SAVE3,SAVE4 : std_logic_vector (3 downto 0);
signal clk_2 : std_logic;

COMPONENT TAKT
  PORT  ( clk_in : in std_logic;
        reset   : in std_logic;
        clk_out: out std_logic);
end COMPONENT;


begin

  taktausgabe: TAKT
  PORT MAP (clk_in=> clk, reset => RESET, clk_out=>clk_2 );

  SCHIEBEREGISTER: process (clk_2,reset)
  begin
    if reset = '1' then
      SAVE0    <="0000";
      SAVE1    <="0000";
      SAVE2    <="0000";
      SAVE3    <="0000";
      SAVE4    <="0000";
      SAVE5    <="0000";

    else
      if (clk_2 = '1' and clk_2'event ) then
        SAVE0<= EINGANG;
        SAVE1<= SAVE0;
        SAVE2<= SAVE1;
        SAVE3<= SAVE2;
        SAVE4<= SAVE3;
        SAVE5<= SAVE4;

  else
        SAVE0  <=SAVE0;
        SAVE1  <=SAVE1;
               SAVE3  <=SAVE3;
               SAVE4  <=SAVE4;
        SAVE5 <=SAVE5;
      end if;
    end if;
  end process SCHIEBEREGISTER;

  AUSGANG<=SAVE5;


Das funktioniert aber so nicht, komisch ist das wenn ich das so 
definiere dann kommt am ausgang nach ca. 2 sek. das signal, tue ich aber 
den SAVE5 weg dann kommt das signal nach 6 sek...


Kann mir jemand helfen? ich wollt nur das signal um 4 takte verzögert 
ausgeben?

Eingang ist hier ein switch
Ausgang sind hier 4 LED
LED ist einfach kontrolle für takt.

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


Lesenswert?

Das sollte wenigstens eine saftige Warnung geben:
1
      if (clk_2 = '1' and clk_2'event ) then
2
        SAVE0<= EINGANG;
3
        SAVE1<= SAVE0;
4
        SAVE2<= SAVE1;
5
        SAVE3<= SAVE2;
6
        SAVE4<= SAVE3;
7
        SAVE5<= SAVE4;
8
     else
9
        SAVE0  <=SAVE0;
10
        SAVE1  <=SAVE1;
11
        SAVE3  <=SAVE3;
12
        SAVE4  <=SAVE4;
13
        SAVE5 <=SAVE5;
14
     end if;
Zudem wird das hier ausreichen und genau das selbe machen:
1
      if (clk_2 = '1' and clk_2'event ) then
2
        SAVE0<= EINGANG;
3
        SAVE1<= SAVE0;
4
        SAVE2<= SAVE1;
5
        SAVE3<= SAVE2;
6
        SAVE4<= SAVE3;
7
        SAVE5<= SAVE4;
8
     end if;

> Dazu habe ich als eingagangsclock 27 Mhz, diese habe ich
> mittels counter dann runtergeteilt habe.
Das ist ein sehr schlechter Designstil.
Ein ideales FPGA-Design hat genau 1 Takt (das gilt besonders für 
Anfänger). Und der Rest wird mit Clock-Enables gemacht.
Siehe Taktung FPGA/CPLD
Was ist dein clk_2? Welche Frequenz hat der?

von Mario (Gast)


Lesenswert?

Mein clk_2 kommt von clk_out welches ich hier definiert habe und dann 
als component definiert habe.

Ja ich bin auch anfänger deswegen meine frage, wie sollte ich es  denn 
machen?

Gruss

Mario




entity TAKT is

   Generic (MAXCOUNT,N :integer:= 53999998); -- EINSTELLBARE VARIABLE 
FÜR ZÄHLER!!
   Port ( clk_in   : in  STD_LOGIC;     -- RICHTIGER CLOCKEINGAGN MIT 27 
MHZ
           reset     : in  STD_LOGIC;     -- RESET UM ZÄHLER AUF NULL ZU 
SETZEN
        clk_out   : out  STD_LOGIC);  -- INTERN VERWENDETER 
RUNTERGEDROSSELTER CLOCK -> HIER 1 HZ
end TAKT;


architecture Behavioral of TAKT is

signal cnt: integer range  0 to N ;

begin


  TAKTGEBER: process (reset,clk_in)
  begin
    if (reset = '1') then
      cnt<=0;
    else
      if (clk_in='1' and clk_in'event) then
        cnt<=cnt+1;
      elsif (cnt = MAXCOUNT) then
        cnt<=0;
      end if;
    end if;
  end process TAKTGEBER;

  TAKTOUT: process (cnt)
  begin
    if ((cnt) < (MAXCOUNT/2)) then
      clk_out<= '0';
    else
      clk_out<= '1';
    end if;
  end process TAKTOUT;


end Behavioral;

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


Lesenswert?

1
      if (clk_in='1' and clk_in'event) then
2
        cnt<=cnt+1;
3
      elsif (cnt = MAXCOUNT) then
4
        cnt<=0;
5
      end if;
Das hast du selber erfunden?
Damit beschreibst du Flipflops (cnt), bei denen der Takteingang Vorrang 
vor dem Reseteingang hat. Sowas kannst du nicht kaufen.

Probiers mal so:
1
entity TAKT is
2
   Generic (MAXCOUNT,N :integer:= 27000000); -- EINSTELLBARE VARIABLE FÜR ZÄHLER!!
3
   Port ( clk_in   : in  STD_LOGIC;     -- RICHTIGER CLOCKEINGAGN MIT 27 MHZ
4
--           reset     : in  STD_LOGIC;     -- RESET nicht nötig.
5
        clk_out   : out  STD_LOGIC);  -- Clock-Enable -> HIER 1 HZ
6
end TAKT;
7
8
architecture Behavioral of TAKT is
9
signal cnt: integer range  0 to N-1 ;
10
begin
11
12
  TAKTGEBER: process (reset,clk_in)
13
  begin
14
      if (clk_in='1' and clk_in'event) then
15
        if (cnt = MAXCOUNT) then
16
           cnt <= 0;
17
           clk_out <= '1'; -- nur 1 Takt aktiv
18
        else
19
           cnt <= cnt+1;
20
           clk_out <= '0';
21
        end if;
22
    end if;
23
  end process TAKTGEBER;
24
25
end Behavioral;

Und dann im Top-Level:
1
  
2
  :
3
  SCHIEBEREGISTER: process (clk,reset)
4
  begin
5
    if reset = '1' then
6
      SAVE0    <="0000";
7
      SAVE1    <="0000";
8
      SAVE2    <="0000";
9
      SAVE3    <="0000";
10
      SAVE4    <="0000";
11
      SAVE5    <="0000";
12
    elsif rising_edge(clk) then
13
      if (clk_2 = '1') then
14
        SAVE0<= EINGANG;
15
        SAVE1<= SAVE0;
16
        SAVE2<= SAVE1;
17
        SAVE3<= SAVE2;
18
        SAVE4<= SAVE3;
19
        SAVE5<= SAVE4;
20
      end if;
21
    end if;
22
  end process;
23
  :

Und sowas ist Käse:
SAVE0    : buffer std_logic_vector...
Gewöhne dir besser an, mit lokalen Signalen zu arbeiten und diese dann 
auf einen OUT Port zuzuweisen.

von Mario (Gast)


Lesenswert?

Hi,

danke für die Antwort!!

fürs verständniss: Was passiert jetzt genau bei der änderung von clk 
='1' and clk'event zu rising_edge(clk) then
                           if (clk_2 = '1') then

>> Und sowas ist Käse:
>> SAVE0    : buffer std_logic_vector...

soll ich dann die zwischenspeicherungen SAVE signale nicht in der entity 
sonern als hilfssignal in der architectur definieren?



Gruss

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


Lesenswert?

> Was passiert jetzt genau bei der änderung von
> clk ='1' and clk'event   zu   rising_edge(clk) then
Nichts, es schreibt sich kürzer.

Der Trick mit dem Clock-Enable liegt darin, dass du vorher clk_2 
verwendet hast:
1
    if (clk_2 = '1' and clk_2'event ) then
2
        SAVE0<= EINGANG;
Und ich verwende clk. Und als Clock-Enable den clk_2, der selber aber 
nur 1 clk-Zyklus lang aktiv ist:
1
    elsif rising_edge(clk) then       -- kompakter
2
    elsif clk ='1' and clk'event then -- alternativ, aber nicht so schön zu lesen
3
        if (clk_2 = '1') then -- ist je Sekunde für 1 clk-Zyklus lang '1'
4
            SAVE0<= EINGANG;


> SAVE signale nicht in der entity
> sonern als hilfssignal in der architectur definieren?
Ja.

von Mario (Gast)


Lesenswert?

Hi, also so funktioniert das auch irgendwie nicht.

Ich verstehe nicht was am Takt falsch sein soll.

ZUM TAKT:

ich habe 27 Mil. takte in einer sekunde. Ich lasse mit steigender Flanke 
den counter hoch zahlen bis 54 Milund sag das mein neues clocksignal dan 
den wert '1' hat wenn der bei kleiner der hälfte der 54Mil. und 0 wenn 
er mehr als der hälfte der 54 Mil. ist. Also habe ich eine sekunde lang 
eine 1 und eine sekunde lang eine 0 am clk_out. ODER TÄUSCHE ICH MICH 
DA?


und dann schiebe ich das signal mit steigneder flanke dieses clk_out 
signals oder nicht?

Ich verzweifele echt langsam am dem zeug...arrrr



Gruss

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


Lesenswert?

> Also habe ich eine sekunde lang eine 1 und eine sekunde lang eine 0 am
> clk_out. ODER TÄUSCHE ICH MICH DA?
Was sagt die Simulation?
Was, du simulierst nicht  :-o

Naja, wie auch immer:
1) Es ist schlecht, einen Takt aus Kombinatorik zu erzeugen.
1
    if ((cnt) < (MAXCOUNT/2)) then
Das Stichwort dazu heißt: Glitches

2) Es ist schlecht, unnötig viele Takte im Design zu haben.
In deinem Design  clk und clk_2
Stichworte hierzu: Taktdomänen und Synchronisation

von Mario (Gast)


Lesenswert?

Ok

aber ich verstehe nicht wie du dann mit deinem code dann auf (eine 
sekunde 1 eine sekunde 0) kommen willst?

Und wie gesagt meine clk_in weiße ich der clk von 27 Mhz zu die auch 
wirklich anliegt zu, und mit clk_out erzeuge ich dann meinen neuen takt 
und dann als componente weisse ich clk_out dem hilfssignal clk_2 zu, 
welches ich dann in der architecture verwende verwende....



Gruss

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


Lesenswert?

> aber ich verstehe nicht wie du dann mit deinem code dann auf (eine
> sekunde 1 eine sekunde 0) kommen willst?
Ich will doch gar keinen Takt mit 1:1 Pulspausenverhältnis.
Ich will jede Sekunde 1 Takt lang ein Enable-Signal.

Ich will jede Sekunde um eins weiterschieben. Wenn das nicht passt, dann 
darfst du auch schreiben:
1
:
2
   Generic (MAXCOUNT :integer:= 2*27000000); -- 2 Sekunden
3
:
4
architecture Behavioral of TAKT is
5
signal cnt: integer range  0 to MAXCOUNT-1 ;
6
begin
7
8
  TAKTGEBER: process (reset,clk_in)
9
  begin
10
      if (clk_in='1' and clk_in'event) then
11
        if (cnt = MAXCOUNT-1) then
12
:

von Mario (Gast)


Lesenswert?

Warum ich frag ist , weil mit meiner Methode auch eine zustätzliche LED 
zum blinken gebracht hab und somit den Takt kontrolliert hab. Nur wenn 
ich das dann so mache:



LEDBLINKEN : process (clk_2) -- KONTROLLE -> TAKTAUSGABE AN LED
  begin
    if rising_edge(clk) then
      if (clk_2='1' ) then
        LED<='1';
      else
        LED<='0';
      end if;
    end if;
  end process LEDBLINKEN;




Gruss und danke noch mal

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


Angehängte Dateien:

Lesenswert?

Ich musste kurz weg, aber hier jetzt eine Waveform der Simulation und 
die dazugehörigen VHDL-Dateien.

EDIT:
1
    if rising_edge(clk) then
2
      if (clk_2='1' ) then
3
        LED<='1';
4
      else
5
        LED<='0';
6
      end if;

Damit leuchtet die LED gerade mal 1/27000000 pro Sekunde.
Das ist kurz....

Probiers mal so:
1
LEDBLINKEN : process (clk_2) -- KONTROLLE -> TAKTAUSGABE AN LED
2
  begin
3
    if rising_edge(clk) then
4
      if (clk_2='1' ) then
5
        LED <= not LED;
6
      end if;
7
    end if;
8
  end process LEDBLINKEN;
Das Signal LED sollte natürlich wieder lokal sein...

von Mario (Gast)


Lesenswert?

Danke ich muss das später mal grüdlich durchgehen und dann meld ich mich 
falls ich darf :)


Gruss und danke nochmal

Mario

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.