Dynamiczna pamięć RAM

Pozostałe układy mikrokontrolerów, układy peryferyjne i inne, nie mieszczące się w powyższych kategoriach.
Awatar użytkownika
gaweł
Expert
Expert
Posty: 966
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Dynamiczna pamięć RAM

Postautor: gaweł » sobota 20 kwie 2019, 15:45

Dynamiczna pamięć RAM
dram01_i00.jpg


Pamięć operacyjna w systemach mikroprocesorowych oraz z konstrukcjach zawierających mikrokontrolery musi mieć możliwość szybkiego zapisu oraz odczytu danych. Czasy mamy takie, że chciałoby się mieć nieograniczone jej zasoby, gdyż „poważne rzeczy” wymagają „poważnych zasobów”. Zwykle w amatorskich konstrukcjach mikroprocesorowych (ewentualnie bazujących na mikrokontrolerach) stosowane są pamięci statyczne. Pisałem o tym w tym temacie. Tak sobie pomyślałem, że może warto przybliżyć do świadomości konstruktorów trochę informacji na temat pamięci dynamicznych. To już jest rzadkość, by takie dały się zauważyć w różnych konstrukcjach. Właściwie to należałoby stwierdzić, że jest to najpowszechniej używany rodzaj pamięci. Najpowszechniej, bo... w każdym komputerze PC są tego całe „tony”. Znacząco gorzej prezentuje się „asortyment” amatorskich rozwiązań wykorzystujących tego typu pamięci. O ile daje się zauważyć stosowanie pamięci dynamicznych w kooperacji z mikroprocesorem Z80, o tyle w przypadku innych mikroprocesorów czy mikrokontrolerów to już nie koniecznie.

Trochę historii

Pierwszą pamięcią dynamiczną, jaka zdobyła sobie choćby minimalne uznanie konstruktorów była pamięć 4096 * 1 bit. Obecnie pamięci o tej pojemności to można uznać za dobry żart jednak w tych „średniowiecznych” czasach to było coś dużego. Jednak hitem stała się dopiero pamięć 16k * 1 bit (przykładowo o symbolu MK4116). Mając 8 takich kostek można było zbudować pamięć operacyjną o zawrotnej pojemności 16kB. Pomimo pewnej niewygody jej stosowania (wymagała trzech napięć zasilających), to zdobywała coraz większą popularność. Ot choćby popularny mikrokomputer (ZX SPECTRUM) z procesorem Z80 na pokładzie takiej właśnie używał. Kolejnym układem pamięci, który stał się na tyle popularny, że wyrugował z rynku wszystkich swoich poprzedników była pamięć 64k * 1 bit. To już były układy, które przy wymaganiach nawet w dzisiejszych czasach, są nadal atrakcyjne w zastosowaniach. Kolejnym krokiem milowym były pamięci o pojemności 256k * 1 bit. To one stały się standardem w kształtujących się rozwiązaniach komputerów osobistych. W każdym komputerze PC-XT oraz PC-AT można tego znaleźć w dużych ilościach. Pojawienie się komputerów z procesorem Intela 80386 doprowadziło do powszechnego stosowania modułów pamięci, jednak nadal bazujących na wspomnianych układach. Kolejne „zagęszczania struktury” układów spowodowało, że pojawiły się pamięci już nie 1-bitowe lecz 4-bitowe i w późniejszej konsekwencji 8-bitowe. Coraz większe moce obliczeniowe komputerów, a co za tym idzie, szybkość wymiany danych pomiędzy procesorem a pamięcią operacyjną zmusiło do wykombinowania nowego rozwiązania → synchronicznych pamięci dynamicznych. O ile wymieniowe układy pamięci należy uważać za pamięci asynchroniczne (których praca nie jest synchronizowana), to pamięci synchroniczne to jest całkiem inna półka.

Muzealna wystawka

Klasyka pamięci 64k*1 → układ MN4116 MN4164 (*). Produkowany przez wiele znanych firm na całym świecie. Cechą charakterystyczną pamięci o organizacji * 1bit jest rozdzielona szyna danych (o ile można mówić o szynie, gdyż jest jednobitowa), oddzielnie jest wyprowadzenia danych wejściowych (zapisywanych do pamięci) i danych wyjściowych (odczytywanych z pamięci). W typowych rozwiązaniach można je ze sobą łączyć, gdyż linie wyjściowe są trójstanowe i nie będą bruździć w pracy pamięci.
dram01_i01.jpg
dram01_i02.jpg
dram01_i03.jpg
dram01_i04.jpg
dram01_i05.jpg

Pamięć 256k*1 bit, z 8 takich układów powstaje pamięć 256kB, pamięć o pojemności znacząco przekraczającej możliwości adresowe 8-bitowców, co wcale nie oznacza, że w 8-bitowcach nie da się takich zastosować.
dram01_i06.jpg
dram01_i07.jpg
dram01_i08.jpg
dram01_i09.jpg
dram01_i10.jpg
dram01_i11.jpg

Kolejne pamięci mają już organizację 4-bitową (a przy okazji linie danych są już dwukierunkowe: te same piny służą do zapisu jak i odczytu danych do/z pamięci). Pamięć 64k*4bity:
dram01_i13.jpg
dram01_i14.jpg
dram01_i15.jpg
dram01_i16.jpg
dram01_i17.jpg

I jako moduły.
dram01_i18.jpg

Pamięci dla systemów 8-bitowych stanowiąca już „kosmos” → pamięć 1MB x 8 bitów.
dram01_i19.jpg


(*) - dzięki Zegar, że uważnie czytasz
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Ostatnio zmieniony niedziela 15 wrz 2019, 22:25 przez gaweł, łącznie zmieniany 4 razy.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse

Awatar użytkownika
gaweł
Expert
Expert
Posty: 966
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: Dynamiczna pamięć RAM

Postautor: gaweł » sobota 20 kwie 2019, 16:43

dram02_i00.jpg

Jak działa dynamiczna pamięć RAM
Pamięci dynamiczne znacząco różnią się w budowie i w obsłudze w stosunku do pamięci statycznych. W tych drugich, by zapisać lub odczytać coś, należy wystawić szynę adresową (pełny adres komórki pamięci), szynę danych, sygnał określający czy chodzi o zapis czy o odczyt oraz sygnały wyboru układu (typu chip select). W pamięciach dynamicznych całość działa znacząco inaczej. Pierwszą rzeczą, jaką daje się zauważyć, to jakaś mała liczba linii adresowych (w rzeczywistości jest to połowa szyny adresowej). Drugim elementem jest występowanie nowych sygnałów (/RAS i /CAS). Nie ma sygnału typu chip select.
Również budowa samej komórki jest znacząco odmienna. W pamięciach statycznych jest ona zrealizowana na bazie tranzystorowego przerzutnika bistabilnego. W pamięciach dynamicznych informacja jest przechowywana pod postacią ładunku zgromadzonego w kondensatorze. Tu jak wiadomo, są upływności i inne cholerstwa, które destabilizują układ, czyli pamięć w funkcji czasu traci swoją zawartość. Co jakiś czas musi zostać odświeżona.
dram02_i01.png
Przykładowa pamięć o pojemności 16k*1 bit (o symbolu MK4116, ilustracja powyżej) wymaga następujących napięć zasilających: VBB – -5V, VDD – +12V oraz VCC – +5V. Sygnał DIN jest wejściową szyną danych, DOUT jest wyjściową szyną danych, /W (zanegowane W) określa, czy chodzi o operacją zapisu (= 0) czy odczytu (=1). Ten sygnał ma identyczne znaczenie jak w przypadku pamięci statycznych. \RAS (zanegowany RAS) jest sygnałem strobu części adresu (Row Address Strobe), określa adres (numer) rzędu w pamięci. Podobnie sygnał /CAS (zanegowany CAS) jest sygnałem strobu części adresu (Column Address Strobe), określa adres (numer kolumny). Identycznie jest w przypadku pamięci o większej pojemności (256k * 1 bit, MK41256, ilustracja poniżej).
dram02_i02.png
Zaadresowanie komórki w pamięci (określenie adresu komórki w pamięci) wymaga podania części (połowy) adresu oraz musi wystąpić ujemne zbocze sygnału /RAS (to zbocze zatrzaskuje w pamięci informację o numerze wiersza/rzędu). W dalszej kolejności na istniejących liniach adresowych należy określić adres (numer) kolumny (podać dalszą część adresu) wraz z sygnałem /CAS (istotne jest również ujemne zbocze). Wystąpienie kombinacji <adres>, zbocze sygnału /RAS, <adres>, zbocze sygnału /CAS jest normalnym dostępem do wybranej komórki pamięci. Możliwe jest wystąpienie jedynie części adresu wraz z sygnałem /RAS (bez drugiej połowy adresu w powiązaniu z sygnałem CAS). Taka kombinacja oznacza operację odświeżania danych. Niestety te muszą być odświeżane, gdyż w przeciwnym wypadku nastąpi swoista demencja owej, jak w życiu... W przypadku pamięci o pojemności 16k * 1 bit (pełny adres jest 14-bitowy → połowa adresu jest 7-bitowa → 128 różnych kombinacji adresowych) konieczne jest wykonanie 128 cykli odświeżania w czasie 4ms (typowo).
dram02_i03.png
Identycznie jest w przypadku pamięci o pojemności 64k * 1 bit, z tym, że w tym wariancie konieczne jest wykonanie 256 cykli odświeżania (adres do odświeżania jest 8-bitowy). W przypadku pamięci 256k (gdzie póładres jest 9-bitowy), nadal wymaga się wykonania 256 cykli odświeżania.
dram02_i04.png
Oznacza to, że w ciągu 4ms musi zaistnieć odświeżenia każdego wiersza (wystąpić każda kombinacja linii adresowych wraz ze zboczem sygnału /RAS).
Dlaczego występuje taka dziwna koncepcja rozwiązania dostępu do pamięci? Wyobraźmy sobie matrycę komórek pamięci zorganizowaną jako „kwadratową”, jako ileś wierszy (rzędów), w których w każdym z nich jest taka sama liczba komórek (kolumn). Wystawienie połowy adresu wraz z sygnałem /RAS powoduje „przepisanie” całego rzędu do takiego specjalnego buforka. Jednak owa operacja powoduje, jako akcja wiązana, odświeżenie całego rzędu w kwadratowej matrycy. Jeżeli zostanie podana druga połowa adresu wraz ze zboczem sygnału /CAS do z wspomnianego buforka wybrany bit (jako kolumna) zostanie przekazany do pinów. Wtedy mamy klasyczny dostęp do określonej komórki pamięci. Jeżeli nie wystąpi sygnał /CAS, to mamy jedynie operację odświeżenia pamięci (w rzeczywistości odświeżenia całego rzędu). Jeżeli sprzęt „przeleci” nie rzadziej niż co 4ms każdą kombinację adresową związaną ze strobem /RAS, to zostanie odświeżona cała pamięć (wszystkie komórki). Jest to całkowicie zrozumiałe w przypadku pamięci o pojemności 64k. W pamięciach 256k, pomimo że póładres jest 9-bitowy, nadaj wymagana jest realizacja 256 cykli. Można mniemać, że w tych pamięciach, hardware zawarte w układzie, robi jakieś czarowanie: przykładowo dogenerowuje sobie jeden bit odświeżania albo coś innego (możliwe jest każde rozwiązanie, byle prowadziło do celu). W sumie nie ma to żadnego znaczenia, istotne jest (z punktu widzenia użytkownika) że wymaga to 256 cykli. Tak przez analogię: słowo daję, nie wiem jak działa współczesny telewizor ale wiem jak go się używa i to w sumie jest istotne.
Obsługa pamięci dynamicznej wygląda następująco:
dram02_i05.png
Odpowiednio wcześniej przed wystąpieniem ujemnego zbocza sygnału /RAS na szynę adresową należy podać połowę adresu (w momencie zbocza sygnału adres musi być stabilny). Podobnie, przed ujemnym zboczem sygnału /CAS, na szynie adresowej (tych samych wyprowadzeniach układu pamięci) należy podać drugą połowę adresu (w momencie wystąpienie zbocza wartość adresu ma być stabilna). Taka sekwencja „dwutaktu” oznacza normalny dostęp do określonej komórki pamięci. Rzecz jasna, do kompletu dochodzi sygnał informujący, czy operacja dotyczy zapisu, czy odczytu oraz szyna danych. Ponieważ na szynie adresowej pojawiają się dwa razy różne wartości adresów (jako połówki ogólnie pojętego adresu pamięci), wypływa wniosek, że szyna adresowa jest multipleksowana. Klasyczny wariant obsługi pamięci dynamicznej wygląda następująco:
dram02_i06.png
Samo wachlowanie sygnałami sterującymi to już oddzielna sprawa i w gruncie rzeczy jest trochę zależna od systemu mikroprocesorowego, w którym jest używana dynamiczna pamięć RAM.
Rodzące się tu pytanie, czy obsługa pamięci dynamicznych jest skomplikowana? Jest w dużej mierze kwestią punktu widzenia. Można odpowiedzieć zarówno twierdząco jak i przecząco (i oba warianty będą prawdziwe). Przykładowo w komputerach bazujących na Z80, sam mikroprocesor wspiera operacje odświeżania pamięci. Jednak nie wszystkie procki mają taką funkcjonalność. Tu oczywiście posłużę się przykładem procka stosowanym w komputerach PC-XT. On nie ma sprzętowego wsparcia do odświeżania pamięci (tak jak Z80), jednak pomimo tego jakoś sobie radzi z tym problemem. Rozwiązanie jest w sumie dosyć proste: wykorzystuje się do tego kanał DMA (jako wytransmitowanie zawartości pamięci do „frische luft” czyli nigdzie). Układ DMA co jakiś czas realizuje transmisję danych z pamięci do nikąd. Nawet nie musi dotykać całej pamięci, wystarczy przelecieć połowę szyny adresowej. Podobnie pamięć w kartach graficznych nie jest specjalnie odświeżana, wystarczy, że sam kontroler generując ileś obrazów na sekundę obleci całą potrzebną przestrzeń pamięci. Każdy dostęp do pamięci dynamicznej zawiera „ukrytą” operację odświeżenia.
Można podać kilka innych wariantów przeciwdziałających demencji, co postaram się uczynić w kolejnych odcinkach.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse

Awatar użytkownika
gaweł
Expert
Expert
Posty: 966
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: Dynamiczna pamięć RAM

Postautor: gaweł » sobota 20 kwie 2019, 21:57

dram03_i00.jpg

Pamięć dynamiczna i Z80


Mikroprocesor Z80 wspiera sprzętowo odświeżanie pamięci dynamicznej. Po każdym cyklu pobrania rozkazu do wykonania (cykl M1), realizowana jest operacja odświeżania. Sam procek ma własny licznik, który bierze udział w tej operacji (rejestr R). Rejestr ten pełni rolę rejestru adresowego (właściwie połowy szyny adresowej, gdyż taka jest używana do realizacji operacji odświeżania). Po każdej operacji odświeżania, rejestr ten jest autonomicznie inkrementowany. Pomimo, że sam rejestr jest 8-bitowy, to w operacji odświeżania pamięci bierze udział jedynie 7 bitów. Nie bardzo rozumiem powodów, dla których zostało to w ten sposób zrealizowane. Może ktoś z ZILOG'a zasugerował się, że w systemie z Z80 nie będą używane większe pamięci dynamiczne niż 4k. Cóż, jest jak jest i do tego należy się dostosować. Wiele pamięci dynamicznych wymaga 256 cykli odświeżania i jak to zwykle bywa: na każdą koncepcję można zaproponować antykoncepcję. Skoro sam procek Z80 nie chce wygenerować 8-bitowego adresu do odświeżania, to... dorobimy go sami. To nawet nie jest takie skomplikowane.
Schemat prezentuje poniższy rysunek:
dram03_i01.png

Działa to w sposób następujący: przerzutnik D (U101A) przechowuje stan linii adresowej A6 w ostatnim cyklu odświeżania (sygnał RFSH ma logikę ujemną → w stanie pasywnym ma wartość 1 i jedynie do zasygnalizowania operacji odświeżania zjeżdża na 0, ponieważ przerzutnik D realizuje wpis na zbocze dodatnie, sygnał zegarowy będący sygnałem RFSH jest zanegowany → wpis do rejestru D następuje przy opadającym zboczu sygnału RFSH). Drugi przerzutnik jest klasyczną dwójką liczącą. Jako sygnał zegarowy wchodzi zanegowany (znowu tu jest istotne zbocze sygnału zegarowego) stan ostatnio używanego adresu A6 w operacji odświeżania. Jeżeli po jakimś czasie A6 wjedzie na górę, to jako sygnał zegarowy dla przerzutnika U101B, zmieni się z jedynki na zero → nic w przerzutniku U101B się nie dzieje. Po kolejnych iluś cyklach odświeżana, oryginalny sygnał A6 zmieni się z jedynki na zero (zanegowany zmieni się z zera na jedynkę → przerzutnik U101B zmieni stan na przeciwny). Reasumując, przerzutnik U101B zmieni stan na przeciwny w sytuacji, gdy linia adresowa A6 w cyklach odświeżania zmieni się z jedynki na zero (tak jakby 7-bitowy licznik się przekręcił). Układ bramkowy U102A … U101D to multiplekser linii adresowej (dla cykli innych niż odświeżanie szyna adresowa będzie dziedziczona od mikroprocesora, dla cykli odświeżania adres do odświeżania będzie dziedziczony od procesora w zakresie młodszych 7 bitów natomiast zostanie dogenerowany ósmy bit).
By to zobrazować na przebiegach zasymulowałem te działania w układach PLD. Komponent dogenerowania ósmego bitu jest następujący:

Kod: Zaznacz cały

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

entity A8gen is port ( Reset   : in std_logic ;
                       AInpBus : in std_logic_vector ( 7 downto 0 ) ;
                       RFSH    : in std_logic ;
                       AOutBus : out std_logic_vector ( 7 downto 0 ) ) ;
end A8gen ;

architecture Behavioral of A8gen is

  signal U101AClk : std_logic ;
  signal U101BClk : std_logic ;
  signal U101A : std_logic ;
  signal U101B : std_logic ;
  signal U102A : std_logic ;
  signal U102B : std_logic ;
  signal U102C : std_logic ;
  signal U102D : std_logic ;

begin
  U101AInstance : process ( Reset , U101AClk )
  begin
    if Reset = '0' then
      U101A <= '0' ;
    else
      if U101AClk'event and U101AClk = '1' then
        U101A <= AInpBus ( 6 ) ;
      end if ;
    end if ;
  end process ;

  U101BInstance : process ( Reset , U101BClk )
  begin
    if Reset = '0' then
      U101B <= '0' ;
    else
      if U101BClk'event and U101BClk = '1' then
        U101B <= not U101B ;
      end if ;
    end if ;
  end process ;

  U101AClk <= not RFSH ;
  U101BClk <= not U101A ;
  U102A <= not RFSH ;
  U102B <= not ( U102A and U101B ) ;
  U102D <= not ( RFSH and AInpBus ( 7 ) ) ;
  U102C <= not ( U102B and U102D ) ;
  AOutBus ( 0 ) <= AInpBus ( 0 ) ;
  AOutBus ( 1 ) <= AInpBus ( 1 ) ;
  AOutBus ( 2 ) <= AInpBus ( 2 ) ;
  AOutBus ( 3 ) <= AInpBus ( 3 ) ;
  AOutBus ( 4 ) <= AInpBus ( 4 ) ;
  AOutBus ( 5 ) <= AInpBus ( 5 ) ;
  AOutBus ( 6 ) <= AInpBus ( 6 ) ;
  AOutBus ( 7 ) <= U102C ;

end Behavioral;
Symulacja działania (napędzana modułem):

Kod: Zaznacz cały

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;

ENTITY a8gen_tb_vhd IS
END a8gen_tb_vhd;

ARCHITECTURE behavior OF a8gen_tb_vhd IS

-- Component Declaration for the Unit Under Test (UUT)
  COMPONENT A8gen PORT( Reset   : in std_logic ;
                        AInpBus : IN std_logic_vector(7 downto 0 ) ;
                        RFSH : IN std_logic;         
                        AOutBus : OUT std_logic_vector(7 downto 0) ) ;
END COMPONENT;

--Inputs
  SIGNAL Reset :  std_logic := '1';
  SIGNAL RFSH :  std_logic := '1';
  SIGNAL AInpBus :  std_logic_vector ( 7 downto 0 ) := (others=>'0' ) ;
  SIGNAL ACnt :  std_logic_vector ( 6 downto 0 ) := (others=>'0' ) ;

  --Outputs
  SIGNAL AOutBus :  std_logic_vector(7 downto 0);

BEGIN

-- Instantiate the Unit Under Test (UUT)
  uut: A8gen PORT MAP ( Reset => Reset ,
                        AInpBus => AInpBus ,
                        RFSH => RFSH ,
                        AOutBus => AOutBus ) ;
  AInpBus ( 0 ) <= ACnt ( 0 ) ;
  AInpBus ( 1 ) <= ACnt ( 1 ) ;
  AInpBus ( 2 ) <= ACnt ( 2 ) ;
  AInpBus ( 3 ) <= ACnt ( 3 ) ;
  AInpBus ( 4 ) <= ACnt ( 4 ) ;
  AInpBus ( 5 ) <= ACnt ( 5 ) ;
  AInpBus ( 6 ) <= ACnt ( 6 ) ;
  AInpBus ( 7 ) <= '0' ;
  tb : PROCESS
  BEGIN
    RFSH <= '1' ;
    Reset <= '0' ;
    wait for 100 ns ;
    Reset <= '1' ;
    wait for 100 ns ;
    for Inx in 0 to 1023 loop
      RFSH <= '0' ;
      wait for 100 ns ;
      RFSH <= '1' ;
      wait for 200 ns ;
      ACnt <= ACnt + 1 ;
      wait for 100 ns ;
    end loop ;
  wait; -- will wait forever
  END PROCESS;

END;

generuje następujące przebiegi:
dram03_i02.png

W cyklach odświeżania występuje powielenie adresu generowanego przez procesor aż do momentu, gdzie A6 zmienia się z jedynki na zero. Potem układ robi to co należy ignorując „sugestie” procesora.
dram03_i03.png
Czyli jak się trochę postarać, to można mieć to co się chce pomimo że środowisko tego nie daje.
Doskonale to działa, nie wykazuje żadnych wyścigów lub niestabilności. Posiłkując się oryginalną dokumentacją ZILOG'a mamy:
dram03_i05.png
Dodając do tego przebiegi sygnałów przy normalnym zapisie i odczycie pamięci RAM:
dram03_i06.png
to łatwo jest zauważyć, że jakakolwiek obsługa pamięci jest „odpalana” sygnałem /MREQ. Występuje on zarówno w cyklu M1, jak i w cyklu odświeżania. Identycznie jest przy zapisie i odczycie danych do/z pamięci. Co najważniejsze, przy każdym normalnym dostępie do pamięci generowany jest dodatkowo sygnał /RD lub /WR, natomiast nie występują one w cyklu odświeżania. To pozwala na proste skonstruowanie obsługi pamięci dynamicznej w świecie Z80. Może to być następujące (te dwie kostki DRAM wypełniają całą przestrzeń adresową dla Z80):
dram03_i07.png
Istotnych jest tu kilka szczegółów. Jeżeli mamy zespół MPX (zbudowany na bazie 74HCT157), sterowany (w sensie selekcji wejścia) sygnałem /MREQ (niezanegowanym), to na wejścia A (A0, A1, A2 …) należy podać starszą połowę adresu, na wejścia B (B0, B1, B2 …) należy podać młodszą połowę adresu. Pamiętając, że w stanie pasywnym sygnał /MREQ jest jedynką, to MPX 74HCT157 na wejściu selekcji również ma jedynkę → łączy wyjścia z wejściami B. Zbocze opadające /MREQ staje się sygnałem /RAS dla pamięci dynamicznych (zatrzaskuje w pamięciach adres rzędu). Po kilkunastu nanosekundach (opóźnienie wniesione przez propagację jednej bramki między /MREQ a wejściami selekcji w 74HCT157) zostaje przełączony adres dla pamięci dynamicznych (zespół 74HCT157 wystawi starszą połowę adresu). Jeżeli będzie to cykl odświeżania (nie wystąpi stan aktywny na linii /RD ani na linii /WR), to nie wygeneruje się sygnał /CAS (jako wyjścia bramki AND z ewentualnym opóźnieniem na propagacji sygnału przez kolejne bramki w torze). Będzie to klasyczny cykl odświeżenia pamięci. W przypadku, gdy wystąpi /RD albo /WR, to wygeneruje się sygnał /CAS (zespół 74HCT157 już przygotował drugą połowę adresu na szynie adresowej do pamięci). Sygnał /CAS spowoduje realizację standardowego dostępu do pamięci. Biorąc pod uwagę, że jest dogenerowany ósmy bit do odświeżania pamięci dynamicznej, to właściwie nie ma znaczenia przemieszanie linii adresowych na szynie adresowej do pamięci. Ważne jest jedynie, by młodsza część adresu (gdyż ona niesie w sobie adres do odświeżania) wystąpiła na wejściach B (chyba, że zostanie wniesiona negacja w torze selekcji i wtedy wejścia A i B w układzie 74HCT157 zamieniają się miejscami). W przypadku, gdyby w systemie Z80 była stosowana pamięć 4116 (16k * 1 bit), to należy pamiętać, że ona ma 7-bitowy adres do odświeżania (oraz multipleksowane są 14 bitów na 7 bitów), to przy zboczu /RAS muszą wystąpić linie adresowe A0 .. A6 z procesora (inaczej nie odświeży się cała pamięć) i jest zbędny układ do dogenerowania A7 do celów odświeżania.
Oczywiście były to tylko wstępne rozważania, gdyż realne rozwiązania muszą ujmować dodatkowo układy pamięci typu EPROM, które współdzielą przestrzeń z pamięciami dynamicznymi, toteż konieczne staje się dodanie trochę logiki kombinacyjnej do selekcji określonych układów pamięci.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse

Awatar użytkownika
gaweł
Expert
Expert
Posty: 966
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: Dynamiczna pamięć RAM

Postautor: gaweł » niedziela 08 wrz 2019, 22:44

Pamięci dynamiczne w systemie C51

dram05_i00.jpg


Ze względu na pewną specyfikę związaną z budową i działaniem pamięci dynamicznych, wymagają one specyficznego podejścia do ich obsługi. Największym problemem dotykającym te pamięci jest swoista demencja. Coś co zostało zapisane w pamięci dynamicznej, pozostawione samo sobie, powoli jest tracone. Informacje, które kiedyś znajdowały się w pamięci ulegają zatarciu. Można oczywiście przeciwdziałać temu zjawisku i co jakiś czas ją odświeżać, wtedy pamięć wraca, nie odchodzi w niebyt. Wymaga to specjalnego podejścia do problemu. Jest kilka sposobów na rozwiązanie problemu, poniżej jest przedstawione jedno z możliwych podejść do rozwiązania. Jak mówi stare inżynierskie porzekadło „rozwiązań jest tyle inu jest inżynierów”. Bazując na własnych ostatnich przemyśleniach tą złotą myśl można rozwinąć do „problem nie leży w problemie a w podejściu do problemu”. Dlaczego tak wielu znakomitych twórców nie chce angażować się w tematykę, nie podejmuje próby zmierzenia się z dość ciekawym tematem?
Problem można rozwiązać na kilka sposobów. Pierwsze pamięci nie pozwalały na zbyt wiele, dysponowały standardowym trybem pracy (zwykły dostęp do pamięci: znaczenie ma sygnał RAS i CAS) oraz trybem odświeżania (z istotnym tylko RAS). W niektórych systemach tematykę można zcedować na kogoś innego, czego przykładem może być system Z80, który „coś załatwia za nas”. Ten procek, co nie jest tajemnicą, sam dba o rozwiązywanie problemu przeciwdziałania demencji. Robi to... jak robi. Można mieć kilka uwag do filozofii, od choćby problematyka siedmiu bitów. Ten procek jest jaki jest i należy do niego się dostosować, no cóż tolerancja jest ważna.
Jednak wracając do głównego nurtu... Odświeżanie w każdym wariancie asynchronicznych pamięci dynamicznym można zrealizować na dwa sposoby: dając specjalizowany cykl odświeżania (jak w Z80: tylko RAS) lub zrobić z jakimś określonym interwałem czasowym odczyt całej pamięci (RAS w parze z CAS, ach te pary). W istocie, to nie ma potrzeby gmerać w całej pamięci, wystarczy w istotnym jej fragmencie.
Rozpatrzmy taki przykład (oczywiście schemat w istotnym do ilustracji fragmencie). Jest jakiś maleńki (w skali kosmosu) systemik:
dram05_i01.png
gdzie CPU to:
dram05_i02.png
Jednostka centralna zawiera procek z rodziny C51, do którego jest przyłączona zewnętrzna pamięć RAM. Powszechnie wiadomo jak to się robi: potrzebny jest zatrzask 8-bitowy z wpisem sygnałem ALE. Daje to nam szynę danych, szynę adresową i dwa sygnały sterujące: strob zapisu oraz strob odczytu.
Te wszystkie element trafiają do czegoś takiego:
dram05_i03.png
Mamy multipleksowaną szynę adresową i logikę bramkową, która wytwarza sygnały RAS i CAS. W gruncie rzeczy niezbędna jest jedna bramka, reszta może być negatorami, gdyż są to jedynie elementy, które wnoszą opóźnienie sygnałów wynikające z czasu propagacji. W przypadku użycia negatorów warto zwrócić uwagę na potencjalnie występujące zjawisko związane z odwróceniem logiki sygnałów (pamięci potrzebują logicznego zera w stanie aktywnym). Dla multipleksu ma to już mniejsze znaczenie, gdyż zawsze pozostaje manewr zamiany wejść A i B.
Do dawania znaków życia, stosowany jest transfer szeregowy na jakikolwiek emulator terminala (zawsze daje to jakąś możliwość porozumienia), czyli interface jest następujące:
dram05_i04.png
Podaję trochę szczegółów, bo jak wiadomo, szczegóły są ważne. Idea rozwiązania jest następująca (obsługa programowa):
  • licznik T0 pracujący w trybie 16-bitowym generuje przerwania,
  • każde przerwania wygarnia z pamięci (tak sobie a muzom) pierwsze 256 bajtów pamięci.
I tyle wystarczy.

Wygarnięcie 256 bajtów daje każdą kombinację w zakresie młodszej części adresowej, która poprzez MPX wchodzi do pamięci wraz z sygnałem RAS, czyli niesie w sobie adres do odświeżenia. Każdy strob rzędu odświeża cały rząd w DRAM, czyli odczyt pierwszych 256 bajtów realizuje odświeżenie całej pamięci DRAM.
Królik doświadczalny, środowisko bytowe do ćwiczenia różnych wariantów programowego odświeżania.
dram05_i05.jpg
dram05_i06.jpg
dram05_i07.jpg
dram05_i08.jpg
Kawałek softu, cała tajemnica związana z odświeżaniem pamięci:

Kod: Zaznacz cały

Timer0InterruptService:         ;
;****************
      PUSH   PSW         ;
      PUSH   REG1         ;
      PUSH   ACC         ;
      MOV   R1 , #255      ;
Tim0IrqS_1:               ;
      MOVX   A , @R1      ;
      DJNZ   R1 , Tim0IrqS_1   ;
      MOVX   A , @ R1      ;
      MOV   TH0 , # 0F0H   ;
      POP   ACC         ;
      POP   REG1         ;
      POP   PSW         ;
      RETI            ;


Cały soft:
dram.zip
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse

Awatar użytkownika
gaweł
Expert
Expert
Posty: 966
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: Dynamiczna pamięć RAM

Postautor: gaweł » środa 18 wrz 2019, 21:59

Badania

Dysponując jeszcze zestawem badawczym, bo uchowała mi się przez kilka dni "lotnicza" (lotnicza, bo wszystko lata :D ) konstrukcja, to zrobiłem "badania naukowe". Otóż, dokonałem pewnej optymalizacji układu do postaci:
dram06_i01.png
Dałem sygnał wysterowania MPX "wcześniej" w czasie, czyli za pierwszą bramką razem z sygnałem RAS oraz sygnał CAS również przyśpieszyłem w czasie (jest po 4 bramkach). Działa:
dram06_i02.png

Metodą silnie eksperymentalną (metoda prób i błędów) ustaliłem, że minimalna liczba bramek 08 odsuwających sygnał CAS wynosi 4 bramki. Jeżeli jest mniej, działa chimerycznie:
dram06_i03.png
Może być użytych więcej bramek niż 4 → działa dobrze. Może warto pokusić się o dodatkowe badania i sprawdzić zachowanie się dla układów w technologii HC (HCT). W układzie zastosowane były układy 74LS08 i 74157, bo takie miałem pod ręką.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse


Wróć do „Inne mikroklocki, również peryferyjne”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości