Forum: FPGA, VHDL & Co. 64bit Schieberegister


von Marc X. (tuxscreen)


Lesenswert?

Hallo zusammen,

ich bin ein Neuling in Sachen VHDL und habe mir mal ein kleines Projekt 
parat gelegt, welches ich gerne mit einem CPLD durchführen möchte.

Ich möchte ein simples 64bit Schieberegister mit Enable (Latch) bauen.

Den unten angefügten Code habe ich mir aus verschiedenen Beispielen 
zusammengestellt und wollte mir mal Eure Verbesserungsvorschläge 
anhören.

Im Moment suche ich auch noch eine Möglichkeit das zu simulieren, aber 
ich finde nichts - hab ich eventuell etwas vergessen zu installieren?
(WebISE 9.2 von Xilinx)

Sehr unsicher war ich mir bei dem 'process..' im Hauptstrang.
Den hab ich eigentlich nur eingefügt um keine Fehlermeldung mehr wegen 
dem 'if' zu bekommen???
Und irgendwie hab ich das Gefühl das ich hier einiges an Ressourcen 
verschwende, ich bekomme das nur in einem rel. großem CPLD (95144) 
synthetisiert?

Danke und Gruß
Marc
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
use ieee.numeric_std.ALL;
6
7
8
9
entity BIGSHIFTER is 
10
  port(C, SLI : in  std_logic;
11
        Q : out std_logic_vector(63 downto 0));
12
end BIGSHIFTER;
13
14
architecture archi of BIGSHIFTER is
15
  signal tmp: std_logic_vector(63 downto 0);
16
  begin
17
    process (C)
18
      begin 
19
        if (C'event and C='1') then 
20
          tmp <= tmp(62 downto 0)& SLI;
21
        end if;
22
    end process;
23
    Q <= tmp;
24
end archi;
25
26
27
library IEEE;
28
use IEEE.STD_LOGIC_1164.ALL;
29
use IEEE.STD_LOGIC_ARITH.ALL;
30
use IEEE.STD_LOGIC_UNSIGNED.ALL;
31
use ieee.numeric_std.ALL;
32
33
entity test1 is
34
   port ( C      : in    std_logic; 
35
          SerialIn    : in    std_logic; 
36
          Enable    : in    std_logic; 
37
          Q : out   std_logic_vector (63 downto 0));
38
end test1;
39
40
architecture BEHAVIORAL of test1 is
41
  signal tmp: std_logic_vector(63 downto 0);
42
   component BIGSHIFTER
43
      port ( C   : in    std_logic;             
44
             SLI : in    std_logic; 
45
             Q   : out   std_logic_vector (63 downto 0));
46
   end component;
47
   
48
begin
49
   my_shift : BIGSHIFTER
50
      port map (C=>C,
51
                SLI=>SerialIn,
52
                Q(63 downto 0)=>tmp(63 downto 0));
53
  process (Enable, tmp)
54
  begin
55
     if (Enable = '1') then
56
        Q <= tmp;
57
     end if;
58
  end process;
59
end BEHAVIORAL;

von Klaus F. (kfalser)


Lesenswert?

Der Code schaut mal gar nicht so schlecht aus, sollte im Prinnzip 
eigentlich funtionieren. Du hast die 2 Funktionen schieben und latchen 
getrennt, das ist OK und verschwendet keine Resource. Man kann das 
sicher auch in einem Prozess zusammenfassen.
Anmerkungen :
- Die libraries STD_LOGIC_ARITH, STD_LOGIC_UNSIGNED und numeric_std 
werden nicht benötigt. Numeric_std und std_logic beißen sich sogar, Du 
solltest nur numeric_std verwenden. Aber in diesem Fall, wie gesagt, 
wird sie überhaupt nicht benötigt, da Du keine einfachen Berechnung 
(z.B. Addition) in diesem Beispiel verwendest.
- Du solltest rising_edge(clock) schreiben, nicht
  clock'event and clock = '1'
- Der Eingang enable ist eigentlich kein enable, jedenfall nicht im 
Sinne dass er das Shiften enabled, sondern wirkt als Übernahme-Latch für 
den Ausgang. Ist das so gewollt?
- Latches sind zwar möglich, aber man sollte sie besser vermeiden 
solange man sie nicht unbedingt benötigt. Besser wäre die Übernahme vom 
Shiftregister an die Ausgänge auch taktsynchron zu machen.
- Zum Simulieren gibt es mehrere Möglichkeiten :
Bei der ISE ist ein Simulator normalerweise dabei, man kann soviel ich 
weiss sogar automatisch eine Testbench erstellen. Beide werden von mir 
nie verwendet.
Besser ist es, Du lädst Dir ModelSim Starter Edition von der Xilinx 
Homepage herunter. Dann schreibst Du Dir eine Testbench, das ist ein 
weiteres VHDL Programm, das deine Schieberregister test1 als Komponente 
aufruft. Diese Testbench hat keine Eingangs- und Ausgangsports mehr, 
sonden alle Signale werden in der Testbench nach deinen Wünschen mittels 
Zuweisungen vom Type a <= '1' after 100 ns; erzeugt.

von Thomas R. (Firma: abaxor engineering) (abaxor)


Lesenswert?

Hallo,

so aufwendig musst du es nicht machen. Im Prinzip musst du nur so etwas 
wie

         sq <= sq (sq'high - 1 downto 0) & SerialIn;

in einen Prozess einbetten.
Denn fogenden Code habe ich nicht getestet.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- wenn schon dann das Package, hier brauchst du es aber auch nicht
use ieee.numeric_std.ALL;
-- die folgenden Packages braucht man nie :-)
--use IEEE.STD_LOGIC_ARITH.ALL;
--use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity test1 is
   port ( C      : in    std_logic;
          SerialIn    : in    std_logic;
          Enable    : in    std_logic;
          Q : out   std_logic_vector (63 downto 0));
end test1;

architecture BEHAVIORAL of test1 is
   signal sq : std_logic_vector (q'range);
begin

q <= sq;

  process (c)
  begin
     if rising_edge(c) then
       if enable = '1' then
         sq <= sq (sq'high - 1 downto 0) & SerialIn;
       end if;
     end if;
  end process;
end BEHAVIORAL;

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


Lesenswert?

> Und irgendwie hab ich das Gefühl das ich hier einiges an Ressourcen
> verschwende, ich bekomme das nur in einem rel. großem CPLD (95144)
> synthetisiert?
Ja, es ist nun mal so, dass du 2 mal 64 Register brauchst:

weil  1) dein Schieberegister
1
        if (C'event and C='1') then 
2
          tmp <= tmp(62 downto 0)& SLI;
3
        end if;
64 Register benötigt (das ist so gewollt)

und  2) dein Ausgangslatch
1
     if (Enable = '1') then
2
        Q <= tmp;
3
     end if;
auch nochmal 64 Register braucht (ist das so gewollt?)

In der Summe 128 Register,
das passt dann in einen 9572 (= 72 FFs) schon nicht mehr rein.

Und wie Thomas schon geschrieben hat, willst du das wahrscheinlich gar 
nicht, was dein Code macht: der shiftet dauernd, und das Ergebnis wird 
am Ausgang sichtbar, solange enable='1' ist.

von Marc X. (tuxscreen)


Lesenswert?

Vielen Dank für Eure ausführlichen Antworten.

Das Ganze ist zur Steuerung einer 8x8 LED-Matrix und da hab ich dann 
endlich mal den Sinn und Zweck eines CPLDs zu nutzen versucht.

Ich möchte in das Schieberegister ein neues Datum reinschieben und 
dieses soll erst zu einem bestimmten Zeitpunkt (am Ende) an die Ausgänge 
übernommen werden, da ich ein zwischenzeitliches Flackern vermeiden 
will.

In dem anderen Fall (enable = '0') will ich noch entscheiden ob die 
Ausgänge high, low oder tristate sind. Wie würde eine solche Zuweisung 
aussehen? Also, wie weise ich dem 64bit Register 64bittig tri-state zu?

Ich möchte noch einen 1bit Ausgang hinzufügen, aus welchem die Bits 
seriell hinausgeschoben werden, sodaß ich mehrere dieser Bausteine 
miteinander verbinden kann. Also quasi das Q'S eines 4094 
Schieberegisters.

Folgender Code soll dies bewerkstelligen (Dank an Thomas):
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use ieee.numeric_std.ALL;
4
5
entity test1 is
6
   port ( C:       in std_logic; -- clock
7
          SerialIn: in std_logic; -- serial input
8
          Enable:   in std_logic; -- latch-enable
9
       Qs: out std_logic;   -- 1bit Ausgang, soll sofort durchgeclocked werden
10
          Q : out std_logic_vector (63 downto 0)); -- latched Ausgang, nur aktiv bei enable='1'
11
end test1;
12
13
architecture BEHAVIORAL of test1 is
14
   signal sq : std_logic_vector (q'range);
15
begin
16
17
  process (c)
18
  begin
19
     if rising_edge(c) then
20
         sq <= sq (sq'high - 1 downto 0) & SerialIn;
21
         Qs <= sq(q'high);
22
       end if;
23
  end process;
24
25
  process (c, enable)
26
  begin
27
    if enable = '1' then -- mit "if rising_edge(c) and enable = '1' then" funktioniert es nicht?
28
      q <= sq;
29
    else
30
       q <= "0000000000000000000000000000000000000000000000000000000000000000"; 
31
      -- geht das auch 'übersichtlicher' ? eventuell auch in Abhängigkeit von range?
32
    end if;
33
  end process;
34
  
35
end BEHAVIORAL;

von Falk B. (falk)


Lesenswert?

@ Marc Wetzel (tuxscreen)

>Ich möchte in das Schieberegister ein neues Datum reinschieben und
>dieses soll erst zu einem bestimmten Zeitpunkt (am Ende) an die Ausgänge

>Ausgänge high, low oder tristate sind. Wie würde eine solche Zuweisung
>aussehen? Also, wie weise ich dem 64bit Register 64bittig tri-state zu?

Also willst du quasi einen 74HC595 als 64 Bit Version nachbauen? Das 
braucht aber 128 FlipFlops.

Einen Vektor komplett auf einen Wert zuzuweisen geht einfach.

1
mein_vektor <= (others=>'Z');

>Ich möchte noch einen 1bit Ausgang hinzufügen, aus welchem die Bits
>seriell hinausgeschoben werden, sodaß ich mehrere dieser Bausteine
>miteinander verbinden kann.

Nichts leichter als das.

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use ieee.numeric_std.ALL;
4
5
entity test1 is
6
   port ( clk       : in std_logic; -- clock
7
          SerialIn  : in std_logic; -- serial input
8
          load      : in std_logic; -- Ausgangsregister laden
9
          Enable    : in std_logic; -- latch-enable
10
          SerialOut : out std_logic; -- Serieller Ausgang, 
11
          Q         : out std_logic_vector (63 downto 0)); -- latched Ausgang, nur aktiv bei enable='1'
12
end test1;
13
14
architecture BEHAVIORAL of test1 is
15
   signal data_shift : std_logic_vector (q'range);
16
   signal data_out   : std_logic_vector (q'range);
17
begin
18
19
-- direkte Zuweisungen
20
21
SerialOut <= data_shift(q'high);
22
23
-- Schieberegister, getaktet
24
25
  process (clk)
26
  begin
27
     if rising_edge(clk) then
28
       if load ='0' then
29
         data_shift <= data_shift (sq'high - 1 downto 0) & SerialIn;         
30
       else
31
         data_out <= data_shift;
32
       end if;
33
     end if;
34
  end process;
35
36
-- Tristate Steuerung, kombinatorisch
37
38
  process (enable, sq)
39
  begin
40
    if enable = '1' then
41
      q <= data_out;
42
    else
43
      q <= (others => 'Z');
44
    end if; 
45
  end process;
46
  
47
end BEHAVIORAL;

MfG
Falk

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.