Перейти к содержанию
    

Реализация памяти в FLEX10K

Короче мы прикидывали, что отобьем деньги на разработку БМК уже за год, а договор - лет на 5 будет если будет конечно

 

Свежо предание. БМК по несколько тысяч на каждый кристалл (для рентабельности).

До 2022 года успеете реализовать?

Всегда найдется дяденька, которому в 2022 году надо будет 2022 года изготовления.

Впрочем, кусок хлеба на всю жизнь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

нет, теперь он согласен с тем, что память однопортовая. и даже не дает варнингов, но в логе раскопал вот такое инфо:

Info: RAM logic "RAM_bloc:u1|VOB_RAM" is uninferred due to unsupported read-during-write behavior

 

может типа такого?

    process(clk, WE, ADDRESS, DATA)
    begin
    if(rising_edge(clk)) then
        if(we = '1') then
            VOB_RAM(conv_integer(address)) <= data;
                else
                        q <= VOB_RAM(conv_integer(addrress));
        end if;
    
    end if;
    end process;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Свежо предание. БМК по несколько тысяч на каждый кристалл (для рентабельности).

До 2022 года успеете реализовать?

Всегда найдется дяденька, которому в 2022 году надо будет 2022 года изготовления.

Впрочем, кусок хлеба на всю жизнь.

 

На чем основано (личное мнение, аргументы, факты, опыт работы) Ваше высказывание? Производитель БМК дал нам ориентировачную стоимость разработки и изготовления одного кристала (партия от 200 штук). Основываясь на этих данных мы и оценивали рентабельность. Получалось, что стоимость кристала примерно в 2 раза меньше стоимости одной ПЛИС (планировалось одной БМК заменить две ПЛИС). Каюсь, оценивали только текущий вариант с двумя ПЛИС, стоимость варианта с одной большой отечественной ПЛИС - не рассматривали. Если у Вас есть опыт работы с производителями БМК, то прошу поделиться им. Может есть какие-то нюансы, которые мы пока не учитываем.

 

может типа такого?

    process(clk, WE, ADDRESS, DATA)
    begin
    if(rising_edge(clk)) then
        if(we = '1') then
            VOB_RAM(conv_integer(address)) <= data;
                else
                        q <= VOB_RAM(conv_integer(addrress));
        end if;
    
    end if;
    end process;

Так пробовал, и в обе ветки условия по weпробовал добавлять вывод данных (назначение q), и использовать сигнал чтения пробовал, и пробовал разные частоты заводить для чтения и записи, реализовывая их в одном и разных процесах, но никак он меня понять не может - либо двухпортовая память и не поддерживает, либо что-то не то с описанием процесса чтения-во время-записи. :crying:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не сочтите некропостером, но стоит та же задача - разместить память в ячейках памяти не используя альтеровский модуль. Как эта проблема - решилась-то или нет? У меня такие же проблемы как у топикстартера.. Пока единственно до чего дошел это вот такой код

library ieee;
use ieee.std_logic_1164.all;

entity RAM is

    generic 
    (
        DATA_WIDTH : natural := 8;
        ADDR_WIDTH : natural := 6
    );

    port 
    (
        clk        : in std_logic;
        addr    : in natural range 0 to 2**ADDR_WIDTH - 1;
        data    : in std_logic_vector((DATA_WIDTH-1) downto 0);
        we        : in std_logic := '1';
        q        : out std_logic_vector((DATA_WIDTH -1) downto 0)
    );

end entity;

architecture rtl of RAM is

    -- Build a 2-D array type for the RAM
    subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
    type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;

    -- Declare the RAM signal.    
    signal ram : memory_t;

    -- Register to hold the address 
    signal addr_reg : natural range 0 to 2**ADDR_WIDTH-1;

begin

    process(clk)
    begin
    if(rising_edge(clk)) then
            -- Register the address for reading
            addr_reg <= addr;
    end if;
    end process;
    
    B1:block (we = '0') is begin
         q <= guarded ram(addr_reg);
    end block B1;

    B2:block (we = '1') is begin
        ram(addr_reg) <= guarded data;
    end block B2;

end rtl;

 

В ячейки-то он размещает, но генерит столько защелок, что просто не влазит в кристал))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задача была "факультативная" ("Попробовать перевести критические куски проекта"). Поэтому была перебита текущей работой и заброшена. Сейчас порылся - у меня вариант с использованием мегафункции. Следовательно вопрос остался открытым. Похоже самый оптимальный вариант это использовать generic по рекомендации TRILLER.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В ячейки-то он размещает, но генерит столько защелок, что просто не влазит в кристал))

 

А других вариантов и нету. Либо блочная память, либо по защелке на бит памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А других вариантов и нету. Либо блочная память, либо по защелке на бит памяти.

 

Наверное я что-то не понимаю или не так выразился. В отчете после синтеза написано, что занято около 1.5К ячеек памяти и использовано ~900 логических ячеек. Тоесть как я понял была сгенерирована какая-то дополнительная логика для работы с памятью.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот кусок из map файла

+----------------------------------------------+
; Analysis & Synthesis Resource Usage Summary ;
+--------------------------------+-------------+
; Resource                      ; Usage      ;
+--------------------------------+-------------+
; Total logic elements          ; 927        ;
; Total combinational functions ; 921        ;
;     -- Total 4-input functions; 401        ;
;     -- Total 3-input functions; 520        ;
;     -- Total 2-input functions; 0          ;
;     -- Total 1-input functions; 0          ;
;     -- Total 0-input functions; 0          ;
; Total registers               ; 6          ;
; I/O pins                      ; 24         ;
; Total memory bits             ; 1536       ;
; Maximum fan-out node          ; addr_reg[1];
; Maximum fan-out               ; 145        ;
; Total fan-out                 ; 3268       ;
; Average fan-out               ; 3.39       ;
+--------------------------------+-------------+

 

и куча подобных сообщений в нем еще:

 

Info (10041): Inferred latch for "ram[0][0]" at RAM.vhd(50)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проблемы такого рода возникают из-за недостаточно ясного описания принципов работы BRAM во всяких даташитах. Дело в том, что чтение в BRAM не является истинно асинхронным. По фронту клока адрес чтения записывается в регистр, а результат чтения через некоторое время, задаваемое одновибратором, запускаемым по фронту клока, защёлкивается во внутренней защёлке, и сохраняется там до завершения следующего такта чтения. Например, если считанная ячейка позднее будет перезаписана в цикле записи, значение в защёлке чтения, немедленно не изменится. В этом отличие блочной памяти от распределённой, которая истинно асинхронная. Таким образом, правильное поведенческое описание псевдоасинхронного чтения делается одной строчкой следующим образом:

always @(posedge clk) if(rd_en) data_ir <= memory(rd_addr);

где регистр data_ir символизирует внутреннюю защёлку. Регистр адреса чтения в явном виде описываться не должен, так как ему всегда соответствует содержимое data_ir.

 

Полный пример описания однопортовой памяти в режиме write through с выходным регистром:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity memory is
port(
	clk:std_logic;
	ce, we:std_logic;
	di:std_logic_vector;
	addr:std_logic_vector; --integer range 0 to depth-1;
	do:out std_logic_vector
);
end entity;
architecture general of memory is
subtype data_t is std_logic_vector(di'length-1 downto 0);
type data_mem_t is array(0 to 2**addr'length-1) of data_t;
signal data_ir:data_t;       --внутренняя защёлка
signal data_mem:data_mem_t;  --вся память
begin
process(clk) is begin
if rising_edge(clk) then
	if ce = '1' then
		do <= data_ir;       --выходной регистр
		if we = '1' then
			data_mem(conv_integer(unsigned(addr))) <= di;
			data_ir <= di;        --writethru
		else
			data_ir <= data_mem(conv_integer(unsigned(addr)));
		end if;
	end if;
end if;
end process;
end architecture;

Примерно в таком виде оно правильно синтезируется для lattice ecp2, в вашем случае режима "write through" может не быть, и потребуется слегка переделать управление data_ir.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Дело в том, что чтение в BRAM не является истинно асинхронным.

А Вы обратили внимание, что ПЛИС - FLEX10K - так тема называется? В ней истинно асинхронная память, как и в последующей за ней ACEX1K, и чтение ее там возможно истинно асинхронным образом, о чем в их даташитах сказано более чем ясно и конкретно. А распределенной памяти в этих семействах не было (и нет) вообще никакой (кроме массива защелок). Так что не вводите людей в заблуждение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...