Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Чт мар 28, 2024 17:41

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Ответить
Имя пользователя:
Заголовок:
Текст сообщения:
Введите текст вашего сообщения. Длина сообщения в символах не более: 60000

Размер шрифта:
Цвет шрифта
Настройки:
BBCode ВКЛЮЧЕН
[img] ВЫКЛЮЧЕН
[flash] ВЫКЛЮЧЕН
[url] ВКЛЮЧЕН
Смайлики ВЫКЛЮЧЕНЫ
Отключить в этом сообщении BBCode
Не преобразовывать адреса URL в ссылки
Вопрос
Теперь гостю придется вводить здесь пароль. Не от своей учетной записи, а ПАРОЛЬ ДЛЯ ГОСТЯ, получить который можно после регистрации на форуме через ЛС.:
Этот вопрос предназначен для выявления и предотвращения автоматических регистраций.
   

Обзор темы - Простой контролер SD-RAM на AHDL
Автор Сообщение
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
2 WingLion
Спасибо. На выходных займусь с MaxPlus - буду разбираться... :)
Сообщение Добавлено: Ср авг 25, 2010 19:26
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
LasyUser писал(а):
CAS before RAS


Вот этот вариант проще всего:

Сначала генерируются периодические CAS и RAS для циклов чтения/записи.
Затем формуруется сигнал WE перед спадом RAS (при записи 0, при чтении 1, для регенерации - тоже 1), и в свободные циклы сигналы CAS и RAS меняются местами.

t.e. на AHDL что-то вроде:

Код:
-- предупреждение: схема накидана за 15 минут без всякой проверки и отладки

SUBDESIGN control(
   CLK : input  --  входная частота (шестикратная частота работы памяти)
                     --  для 60нс DRAM - CLK=50MHz, а рабочая частота памяти - ~8MHz
   WR,RD : input -- сигналы запросов записи и чтения
   RASout,CASout,WEout : output   -- выходные сигналы управления
)
VARIABLE
  CT[2..0]  : DFF;
  RAS,CAS : DFF;
  WE,REFRESH  : DFFE;
BEGIN
CT[2..0].clk = CLK;
CT[] = (CT[] + 1) and (CT[] < 5);
CAS.clk = CLK; RAS.clk = CLK;
CASE CT[] IS
  WHEN 0 => RAS = VCC; CAS = VCC;
  WHEN 1 => RAS = GND; CAS = VCC;
  WHEN 2,3 => RAS = GND; CAS = GND;
  WHEN 4 => RAS = VCC; CAS = GND;
  WHEN others => RAS = VCC; CAS = VCC;
END CASE;

REFRESH.clk = CLK; WE.clk = CLK;
REFRESH.ena = (CT[] == 1); WE.ena = (CT[] == 1);
  CASE (RD,WR) IS
    WHEN B"11" => REFRESH = VCC;  WE = VCC; -- цикл регенерации
    WHEN B"X0" => REFRESH = GND;  WE = GND;-- цикл записи
    WHEN B"01" => REFRESH = GND;  WE = VCC; -- цикл чтения
  END CASE;

  IF !REFRESH  THEN
    RASout = RAS; CASout = CAS; -- циклы чтения/записи
  ELSE
    -- режим "CAS перед RAS"
    RASout = CAS; CASout = RAS; -- цикл регенерации
  END IF;
    WEout = WE;

END;
Сообщение Добавлено: Ср авг 25, 2010 18:49
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
... пардон что ввел в заблуждение "кривым" вопросом :oops:
Посмотрел datasheet http://www.alldatasheet.com/datasheet-pdf/pdf/127338/ETC/NN514256ALJ-60.html- встроенная регенерация в DRAM есть. Хотел прицепить память к Z180 - со "статикой" конечно проще и работать будет пошустрее, но без буфера много не повесишь, поэтому и вспомнил про DRAM (c CPLD и печатная плата должна поменьше быть и разводить попроще ...) - для экспериментов самое то. Режимов регенерации несколько - RAS only, CAS before RAS, hidden refresh ... какой проще с точки зрения реализации ?
... хотел запихнуть логику в EPM7032 - понятно что мультиплексоры адреса можно использовать в виде отдельных корпусов...
Сообщение Добавлено: Ср авг 25, 2010 18:17
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
Я поэтому и пишу, что для таких объемов непонятно, есть там регенерация, или нет. Надо все-таки конкретное наименование смотреть.
Сообщение Добавлено: Вт авг 24, 2010 22:54
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
В РУ5-х режима регенерации по "CAS перед RAS" и не было, для них надо было все столбцы "ручками перебирать" - в смысле отдельным счетчиком.
В Z80 для этого есть регистр R, но он годится только для регенерации микросхем с организацией 16Kx1, потому что перебирает только 128 столбцов.
Сообщение Добавлено: Вт авг 24, 2010 21:36
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
А в РУ5 я этого не помню, в Z80 был специальный выход, чтобы на регенерацию переключаться.
Сообщение Добавлено: Вт авг 24, 2010 21:09
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
Хищник писал(а):
Судя по объему памяти, эти чипы (part number?) вполне могут попадать в оставшиеся 0.01%


Врядли.
Режим регенерации "CAS перед RAS" работал и в советских 565РУ7 (256Кx1).
Сообщение Добавлено: Вт авг 24, 2010 21:00
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
Судя по объему памяти, эти чипы (part number?) вполне могут попадать в оставшиеся 0.01%
Сообщение Добавлено: Вт авг 24, 2010 19:12
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
LasyUser писал(а):
DRAM типа 256Kx4, 256Kx16 ... контроллер регенерации?


с 99.99% вероятностью эти чипы поддерживают режим автоматической регенерации (со встроенным счётчиком) CAS Before RAS, т.о. остаётся только в свободные от доступа хоста промежутки времени формировать соответствующий цикл, для чего 7032 более чем избыточна ))
Сообщение Добавлено: Вт авг 24, 2010 10:11
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
ATF1502, ATF1504 это Atmel-овские аналоги EPM7032, EPM7064 Alter-ы, только стоят раза в 2 дешевле. После того как что-нибудь "сваяешь" в MaxPlus, остается "скормить" *.pof-файл утилите pof2jed.exe и можно заливать jed-файл в Atmel.
Сообщение Добавлено: Пн авг 23, 2010 20:03
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
LasyUser писал(а):
одскажите хватит ли ресурсов какого-нибудь ATF1502, ATF1504 чтобы слепить на нем контроллер регенерации?


Я с этими ПЛИС не работал, потому не смогу подсказать точно. Хотя, для контроллера регенерации (если не включать в него мультиплексор адресов) должно по идее хватить любой современной ПЛИС.
Сообщение Добавлено: Пн авг 23, 2010 18:53
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
... мои познания в области ПЛИС невелики - немного поделок на WinCupl и MaxPlus. Есть пару десятков корпусов DRAM типа 256Kx4, 256Kx16 - подскажите хватит ли ресурсов какого-нибудь ATF1502, ATF1504 чтобы слепить на нем контроллер регенерации?
Сообщение Добавлено: Пн авг 23, 2010 17:27
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
Вот так примерно должна выглядеть картинка симуляции для контроллера SD-RAM:

Изображение

А это в увеличенном виде - как должно выглядеть соотношение MCLK и MCS:

Изображение

к первой картинке:
Сначала, в районе 820ns идет процедура инициализации после включения питания:
- цикл "предзаряда" (освобождение/сброс банков);
- запись управляющего слова;
- затем несколько циклов регенерации.
после этого SD-RAM готова к работе
здесь эта работа показана в виде цикла чтения пакета (из 64) слов и цикла записи пакета слов.
Для режима чтения/записи по одному слову контроллер надо существенно перекапывать. Но для этого может оказаться проще использовать готовый Альтеровский контроллер SD-RAM, который сейчас раздается просто так вместе с последней версией Quartus-II
Сообщение Добавлено: Чт апр 22, 2010 20:11
  Заголовок сообщения:  Re: Обсуждение переезда на phpbb3  Ответить с цитатой
Последний вариант AHDL кода этого же контроллера.
Главное отличие в том, что сигнал синхронизации для SD-RAM формируется снаружи относительно этой схемы,
и в организации раздельных каналов адреса для записи и для чтения (так было нужно для проекта)


Код:
-----------------------------------
-- Simple SDRAM controller
-- page mode burst read/write
-- latensy = 3, frq = 50..150MHz
-- 2002-2010 (c) Ivan Mak
-- E-mail: ivan_mak@mail.ru aka admin@winglion.ru
-- http://winglion.ru
-----------------------------------

TITLE "SDRAM_controller";

PARAMETERS
   (
   WIDTH   = 16,      -- SDRAM data WIDTH
   OUT_SH   = "YES",      -- "YES" -- 1/2 clk data shift
   PRIORITY = "WRITE"   -- "READ" или "WRITE"
   );

SUBDESIGN sdram
   (
   CLK         : INPUT;
   CLKs      : input;
   RESET      : INPUT;

--   dir signals

   DI[WIDTH-1..0]   : INPUT = GND;   -- input data
   DO[WIDTH-1..0]   : OUTPUT;   -- output data

   RA[23..0]   : INPUT = GND;   -- adress RAM
   WA[23..0]   : INPUT = GND;   -- adress RAM
   CS         : INPUT = GND;   -- select
   WR         : INPUT = VCC;   -- write
   RD         : INPUT = VCC;   -- read

   STOP      : INPUT = VCC;   -- for sinhronize cycle

--   sdram signals

   MD[WIDTH-1..0]   : BIDIR;   -- RAM data bus

   MWE         : OUTPUT;   -- RAM signal WE
   MRAS        : OUTPUT;   -- RAM signal RAS
   MCAS        : OUTPUT;   -- RAM signal CAS

   MCS         : OUTPUT;   -- RAM signal CS
   MBS[1..0]   : OUTPUT;   -- RAM signals BS1,BS0

   MCKE        : OUTPUT;   -- RAM signal CKE
   MCLK        : BIDIR;   -- RAM signal CLK

   MA[11..0]   : OUTPUT;   -- RAM adress bus

   MDQM      : OUTPUT;

--   return signals

   MEM_C      : OUTPUT;   -- memory cycle
   WRITE      : OUTPUT;   -- write data
   READ      : OUTPUT;   -- data read
   VALID      : OUTPUT;

   )
VARIABLE

   ARGX[23..0]   : DFFE;
   ARG[23..0]   : NODE;

   CTT[5..0]   : DFFE;
   TAB[5..0]   : DFF;

   CTT_2      : NODE;
   CTT_3      : NODE;
   CTT_4      : NODE;

   CT[3..0]   : DFFE;   -- counter

   MX[11..0]   : DFF;   -- adress mux

   MY[5..3]   : DFF;   -- dir mux

   MDR[WIDTH-1..0]   : DFF;   -- data reg
   MDRX[WIDTH-1..0]: DFF;   -- data reg
   MDRY[WIDTH-1..0]: DFF;   -- data reg

   PA         : NODE;

   RWC_FIX[2..0]   : DFFE;

   R/W         : NODE;

   WRITE_2      : NODE;

--   MCLKX      : NODE;
--   MCLKY      : NODE;
--   MCLKZ      : NODE;

--   RX_MA[13..0]: DFF;
--   RX_MCKE       : DFF;
--   RX_MBS[1..0]: DFF;
--
--   RX_MCS       : DFF;
--
   RX_MRAS       : DFF;
   RX_MCAS     : DFF;
   RX_MWE      : DFF;



BEGIN

   -- input address register

   ARGX[].clk   = CLK;
--   ARGX[].ena   = VCC; -- fixed adress when bank active
   ARGX[].ena   = MEM_C; -- fixed adress when bank active
   
--   IF (PRIORITY != "READ") and (PRIORITY != "WRITE") THEN
--      ASSERT "PRIORITY parametr muast be READ or WRITE!";
--   END IF;
   
   IF PRIORITY == "WRITE" GENERATE
      CASE (RD,WR) IS
         WHEN 3 => ARGX[] = GND;
         WHEN 1 => ARGX[] = RA[];
         WHEN 2,0 => ARGX[] = WA[];
      END CASE;
      R/W   = DFFE((!(RWC_FIX[] == B"X00") or !(MY[5..3] == B"011")),CLK,,,CTT_2);
   END GENERATE;

   IF PRIORITY == "READ" GENERATE
      CASE (RD,WR) IS
         WHEN 3 => ARGX[] = GND;
         WHEN 1,0 => ARGX[] = RA[];
         WHEN 2 => ARGX[] = WA[];
      END CASE;
      R/W   = DFFE(!(!(RWC_FIX[] == B"0X0") or !(MY[5..3] == B"011")),CLK,,,CTT_2);
   END GENERATE;
   
   ARG[]      = ARGX[];
--   ARGX[].d   = A[];

   RWC_FIX[].clk   = CLK;
   RWC_FIX[].ena   = MEM_C;
   RWC_FIX[]       = (RD,WR,CS);

   -- micro count

   CTT[].clk   = CLK;
   CTT[].clrn   = RESET;
   CTT[].ena   = DFF((!(CT[] == 8) or STOP),CLK,,);

   CTT_2      = DFF(CTT[] == 2,CLK,,);
   CTT_3      = DFF(CTT[] == 3,CLK,,);
   CTT_4      = DFF(CTT[] == 4,CLK,,);

   IF CTT_2 THEN
      CTT[] = TAB[];   -- one command period
   ELSE
      CTT[] = CTT[] - 1;
   END IF;


--   SDRAM data

   -- mode sdram      bit2..0 - 000 - 1byte
   --                       001 - 2byte
   --                       010 - 4byte
   --                       011 - 8byte
   --                       111 - page
   --                       other - reserved
   --               bit3   - 0 - seqential
   --                        1 - interleave
   --               bit6..4 - 010 - cas latency = 2
   --                       011 - cas latency = 3
   --                       other - reserved
   --               bit7   - 0 (?test?)
   --               bit8   - 0 reserved
   --               bit9   - 0 burst read & burst write
   --                         1 burst read & single write
   --             bit11..10  - 00 reserved
   --              BS[1..0]  - 00 reserved

   -- sdram commands   RAS,CAS,WE
   --                  000   - mode register write
   --                  001 - auto refresh      -- cken=0 -> self refresh
   --                                    -- CS=H -> SR exit
   --                                    RCW=110  -> SR exit
   --                  010 - bank precharge -- A10=0 precharge bank
   --                                  -- A10=1 precharge all
   --                  011 - bank active
   --                  100 - write          -- A10=1 - auto precharge
   --                  101 - read          -- A10=1 - auto precharge
   --                  110 - burst stop
   --                  111 - no operation


--   R/W   = DFFE((!(RWC_FIX[] == B"X00") or !(MY[5..3] == B"011")),CLK,,,CTT_2);

   -- comand counter

   CT[].clk   = CLK;
   CT[].clrn   = RESET;
   CT[].ena   = CTT_2;

   IF DFF((CT[3..0] == 12),CLK,,) THEN
      CT[] = 8;
   ELSE
      CT[] = CT[]+1;
   END IF;

   -- SDRAM command & times table

   TAB[].clk   = CLK;
   MY[].clk   = CLK;

   CASE CT[3..0] IS      -- MY[] -- RAS,CAS,WE

      -- init commands
      WHEN 0 =>  TAB[] = 4; MY[] =  B"010";   -- precharge ALL
      WHEN 1 =>  TAB[] = 4; MY[] =  B"000";   -- set mode register
      WHEN 2 =>  TAB[] = 8; MY[] =  B"001";   -- autorefresh
      WHEN 3 =>  TAB[] = 8; MY[] =  B"001";   -- autorefresh
      WHEN 4 =>  TAB[] = 8; MY[] =  B"001";   -- autorefresh
      WHEN 5 =>  TAB[] = 8; MY[] =  B"001";   -- autorefresh
      WHEN 6 =>  TAB[] = 8; MY[] =  B"001";   -- autorefresh
      WHEN 7 =>  TAB[] = 8; MY[] =  B"001";   -- autorefresh

      -- cycle commands (realy 5 items)
      WHEN 8 =>  TAB[] = 4; MY[] =  B"011";  -- bank active
                  -- ! words count (0->64)
      WHEN 9 =>  TAB[] = 0; MY[] = (B"10",R/W);  -- bank read/write
      WHEN 10 => TAB[] = 4; MY[] =  B"110";  -- burst stop!
      WHEN 11 => TAB[] = 4; MY[] =  B"010";  -- bank precharge
      WHEN 12 => TAB[] = 8; MY[] =  B"001";  -- autorefresh
      WHEN 13 => TAB[] = 4; MY[] =  B"111";  -- NOP no executed
      WHEN 14 => TAB[] = 4; MY[] =  B"111";  -- NOP no executed
      WHEN 15 => TAB[] = 4; MY[] =  B"111";  -- NOP no executed
   END CASE;

   MCLK   = TRI(LCELL(!CLKs),VCC);

   -- address MUX

   PA      = DFF(!(CT[2..0] == 0),CLK,,);

   MX[].clk   = CLK;
   CASE (CT3,PA) IS
      WHEN 0 => MX[] = (B"010000000000"); -- precharge all
      WHEN 1 => MX[] = (B"000000110111"); -- SDRAM mode
      WHEN 2 => MX[] = (ARG[21..10]); -- adress RAS  -- 4k
      WHEN 3 => MX[] = (B"00",ARG[9..0]); -- adress CAS  -- 1k
   END CASE;


   -- input register

   MDR[].clk   = CLK;
   MDR[].d      = DI[];

--   WRITE_2    = (DFF(DFF(DFF(WRITE,CLK,,),CLK,,),CLK,,));
   WRITE_2    = DFF(DFF(WRITE or DFF(WRITE,CLK,,),CLK,,),CLK,,);
--   WRITE_2    = DFF(WRITE,CLK,,);

   FOR i IN 0 TO WIDTH-1 GENERATE
      MD[i] = TRI(MDR[i],WRITE_2);
   END GENERATE;

   -- output register' -- for 1/2 shift

--   MDRX[].clk  = !CLK;
--   MDRX[].clk  = !LCELL(CLK);
   MDRX[].clk  = MCLK;
   MDRX[].d   = MD[];

   -- output register

   MDRY[].clk  = CLK;

   IF (OUT_SH == "YES") GENERATE
      MDRY[].d   = MDRX[];   --    1/2 clk data shift
   ELSE GENERATE
      MDRY[].d   = MD[];      -- no 1/2 clk data shift
   END GENERATE;

   DO[]      = MDRY[];

--   IF (M_REG == "YES") GENERATE
--      MA[]      = RX_MA[13..0];
----      MCKE      = RX_MCKE;
--      MCKE      = VCC;
--      MBS[1..0]   = RX_MBS[1..0];
--      MCS         = RX_MCS;
--
----      MRAS      = RX_MRAS;
----      MCAS        = RX_MCAS;
----      MWE         = RX_MWE;
--
--      MRAS      = DFF(DFF(RX_MRAS,CLK,,),CLK,,);
--      MCAS        = DFF(DFF(RX_MCAS,CLK,,),CLK,,);
--      MWE         = DFF(DFF(RX_MWE,CLK,,),CLK,,);
--
--      MDQM      = GND;
--   ELSE GENERATE

      MA[] = MX[];

--      (MDQM,MCKE,MRAS,MCAS,MWE,MBS1,MBS0) = (GND,VCC,MY[5..3],ARG[23..22]);

      (MDQM,MCKE,MRAS,MCAS,MWE,MBS1,MBS0) = (GND,VCC,RX_MRAS,RX_MCAS,RX_MWE,ARG[23..22]);

      -- RX_MRAS,RX_MCAS,RX_MWE

      MCS      = DFF((!(CTT[] == 1)),CLK,,);

--   END GENERATE;
--   (MDQM,MCKE,MRAS,MCAS,MWE,MBS1,MBS0) = (GND,VCC,MY[5..3],ARG[23..22]);

--   RX_MA[13..0]= MX[];
--   RX_MCKE       = VCC;
--   RX_MBS[1..0]= ARG[23..22];
--
--   RX_MA[13..0].clk   = CLK;
--   RX_MCKE.clk       = CLK;
--   RX_MBS[1..0].clk    = CLK;
--
--   RX_MCS       = DFF((!(CTT[] == 1)),CLK,,); RX_MCS.clk = CLK;
--
   RX_MRAS       = MY5;  RX_MRAS.clk = CLK;
   RX_MCAS     = MY4;  RX_MCAS.clk = CLK;
   RX_MWE      = MY3;   RX_MWE.clk  = CLK;

   -- return signals

   -- write cycle
--   WRITE = DFFE((MY[5..3] == B"100"),CLK,,,CTT_3);
   WRITE = DFFE((MY[5..3] == B"100"),CLK,,,CTT_4);
   -- mem cycle
   MEM_C = DFFE((MY[5..3] == B"001"),CLK,,,VCC);
--   MEM_C = PA;
   -- read sysle
   READ  = DFFE(((RWC_FIX[] == B"010") & (MY[5..3] == B"101")),CLK,,,CTT_3);
   -- data valid
   VALID   = DFF(DFF(DFF(DFF(DFF(READ,CLK,,),CLK,,),CLK,,),CLK,,),CLK,,);


END;




Проверялся в работе на реальном проекте на Cyclone-II с рабочей частотой до 150MHz
Сообщение Добавлено: Чт апр 22, 2010 19:40
  Заголовок сообщения:  Re: Простой контролер SD-RAM на AHDL  Ответить с цитатой
Цитата:
Что нужно переделать в Вашем контроллере SDRAM (viewtopic.php?f=11&t=341) для
работы с чипом от Микрона,типа MT48LC4M32B2 (http://download.micron.com/pdf/datashee ... RAMx32.pdf)?


1. В первую очередь выставить параметр WIDTH =32.
2. Прогнать схему в симуляторе, в конкретном месте (с назначениями пинов), с конкретной ПЛИС, там где предполагается ее использовать.
3. "Поиграться" с установкой дополнительных задержек (на логических ячейках) для сигнала MCLK - синхронизации, подаваемой на SD-RAM с целью получения попадания фронта сигнала синхронизации в серединку импульса сигнала MCS.
В идеальном варианте, если используемая ПЛИС имеет PLL, сделать на нем сигналы синхронизации CLK и MCLK со смещением по фазе относительно друг друга.
Сообщение Добавлено: Чт апр 22, 2010 18:58

Часовой пояс: UTC + 3 часа [ Летнее время ]


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB