CPLD Seriell zu Parallel

Gast #252818
Lesenswert?
• ▲
▼
an sich ein simples Schieberegister, seriell rein, die einzelnen Taps
geben am Ende des Einschiebens (zB nach 8 Takten) die Daten parallel
wieder. Bsp. gibt's zu Hauf beim googeln; ich mogel mich aber selber
an einer Musterimpl. hier vorbei ;-)

BTW, der "concat" Operator ist in VHDL das "&". Wenn Du soetwas
findest, bist Du bereits recht nahe 'dran.

Viele Grüße
Olaf
Gast #252820
Lesenswert?
• ▲
▼
Hier ist was aus einem alten Design: 16Bit zu parallel mit Latch.

-- VHDL Entity adc_aquisor_lib.serial2parallel.symbol
--
-- Created: by - jschuhm.ti.com (ASICundFPGA-Rechner4)
--          at - 14:25:58 28.11.2004
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY serial2parallel IS
   PORT(
      clk_en      : IN     std_logic;
      clock       : IN     std_logic;
      inputserial : IN     std_logic;
      readenable  : IN     std_logic;
      reset       : IN     std_logic;
      output      : OUT    std_logic_vector (15 DOWNTO 0)
   );

END serial2parallel ;

-- VHDL Architecture adc_aquisor_lib.serial2parallel.symbol
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;


ARCHITECTURE struct OF serial2parallel IS

   -- Internal signal declarations
   SIGNAL parallel : std_logic_vector(15 DOWNTO 0);
   SIGNAL updown   : std_logic;

   -- signal declarations for instance 'localshifter' of 'shiftsp'
   SIGNAL mw_localshifterreg_cval : std_logic_vector(15 DOWNTO 0);
   SIGNAL mw_localshifterreg_nval : std_logic_vector(15 DOWNTO 0);

BEGIN

   updown <= '1';    <- vorwaerts zaehlen

   -- instance 'locallatch'
   locallatchcombo_proc: PROCESS (readenable, reset, parallel)
   BEGIN
      IF (reset = '1' OR reset = 'H') THEN
         output <= "0000000000000000";
      ELSIF (reset = '0' OR reset = 'L') THEN
         IF (readenable = '1' OR readenable = 'H') THEN
            output <= parallel;
         END IF;
      END IF;
   END PROCESS locallatchcombo_proc;

   -- 'localshifter'
   parallel <= mw_localshifterreg_cval;
   localshifterseq_proc: PROCESS (clock, reset)
   BEGIN
      IF (reset = '1' OR reset = 'H') THEN
         mw_localshifterreg_cval <= "0000000000000000";
      ELSIF (clock'EVENT AND clock='1') THEN
         IF (clk_en = '1' OR clk_en = 'H') THEN
            mw_localshifterreg_cval <= mw_localshifterreg_nval;
         END IF;
      END IF;
   END PROCESS localshifterseq_proc;
   localshiftercombo_proc: PROCESS (updown, inputserial,
mw_localshifterreg_cval)
   VARIABLE temp_dout : std_logic_vector(17 DOWNTO 0);
   BEGIN
      IF (updown = '1' OR updown = 'H') THEN
         temp_dout := inputserial & inputserial &
mw_localshifterreg_cval;
      ELSIF (updown = '0' OR updown = 'L') THEN
         temp_dout := mw_localshifterreg_cval & inputserial &
inputserial;
      ELSE
         temp_dout := (OTHERS => 'X');
      END IF;
   mw_localshifterreg_nval <= temp_dout(16 DOWNTO 1);
   END PROCESS localshiftercombo_proc;

   -- Instance port mappings.

END struct;
Angehängte Dateien:
Gast #252821
Lesenswert?
• ▲
▼
Bonjour,

danke Jürgen für den ausführlichen Quelltext. Hatte es mit Olafs
Variante mal probiert. Sieht jetzt so aus als würde es funzen. Kann die
Daten aber nochnicht verifizieren. Ist das denn richtig, das der &
Operator gleichzeitig das neue Bit von rechts reinschiebt und somit
eine Shiftfunktion erübrigt?

also würde '10' & '1' zu '101' ?
jetzt mal abgesehen davon, ob ich die syntac richtig habe.
also meine Version:

  sipo:process
  variable reg : std_logic_vector(BITS-1 downto 0);
  variable n : natural;
  begin
    wait until rising_edge(ADU_SCLK);
    if ADU_DRDY = '0' then
      n := 15;
    end if;
    if n > 0 then
      reg := reg(BITS-2 downto 0) & ADU_DOUT; --
      n := n-1;
    else n := n;
    end if;
    if n = 0 then
      FD <= reg;
    end if;
  end process sipo;

Er setzt hier einen 16Bit seriellen Wert um und weisst ihnam Ende FD
zu. ADU_DOUT liefert immer ein Bit.
Richtig so oder irgendwelche Ergänzungen?

Danke Björn
Gast #252822
Lesenswert?
• ▲
▼
>Ist das denn richtig, das der & Operator gleichzeitig das neue Bit von
>rechts reinschiebt und somit eine Shiftfunktion erübrigt?

nein, der & Op "klebt" im Grunde nur zusammen. In der Zeile siehst Du
auch, dass das linke Arg von & um 1 verkürzt wurde. Anonsten gäb's
Mecker vom compiler.
1
reg := reg(BITS-2 downto 0) & ADU_DOUT;

Viele Grüße
Olaf
Gast #252823
Lesenswert?
• ▲
▼
Hi Olaf,

danke für die Antwort. Dabei klebt der & Operator ein Bit (ADU_DOUT)
von rechts dran. Das linke Argument wird um eins verkürzt, aber wo?
wird dies links oder rechts abgeschnitten? Für meine Anwendung muss es
links rausfallen und ich hänge rechts das neue Bit dran. Ich hoffe das
klappt so... :-)

Was meinst Du ?

Danke Björn
Gast #252825
Lesenswert?
• ▲
▼
jo, links. Man muss dabei beachten, dass es zwei Zählweisen gibt:
1
std_logic_vector(7 downto 0)
und
1
std_logic_vector(0 to 7)
Beide sind 8 bit lang, aber das Indexierungsergebnis ist jeweils ein
Anderes (das gleiche gilt, wenn Du mal irgendwann die attribute
einsetzt). Generell ist es klug, nur eine zu verwenden.

Meist gibts Du zB. die BIT_WIDTH mit 8 an, d.h. bei der Deklaration
schreibst Du dann:
1
std_logic_vector(BIT_WIDTH-1 downto 0)
um zur obigen Dekl. zu kommen. Konsequenter Weise musst Du dann
1
std_logic_vector(BIT_WIDTH-2 downto 0)
bzw. bei Dir
1
reg(BITS-2 downto 0) & ADU_DOUT;
schreiben, um das obere Bit "rauszuschubsen" und das untere
"anzuheften".

Viele Grüße
Olaf
Gast #252826
Lesenswert?
• ▲
▼
Hallo Leute,

vielen Dank für Eure Antworten! Das hat mir sehr geholfen. Somit weiss
ich das der Teil funktionieren müsste. Leider ist an meiner Schaltung
noch irgendwas im Argen. Werde mich mal wider melden, wenn ich das
geregelt habe!

Ciao Björn

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren