реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Block RAM на VHDL в Spartan3, Could not implement Block RAM. Is the read address registered using th
Vadim_nsk
сообщение Jun 28 2006, 09:38
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 7-09-05
Из: г. Новосибирск
Пользователь №: 8 335



При описании памяти как массива производится чтение и запись по разным адресам, при этом чтение производится ассинхронно, а запись синхронно.
При объявлении массива указываю атрибут:
attribute syn_ramstyle : string;
attribute syn_ramstyle of data_array_1 : signal is "block_ram";--"no_rw_check";

При этом Synplify Pro 8.4 в отчете выдает следующее сообщение:
Could not implement Block RAM. Is the read address registered using the same clock as the RAM?

Код примерно следующий:

entity name is
clock : in std_logic;
din : in signed( 15 downto 0 );
write : in std_logic;
dout : out signed( 15 downto 0 );
...
end name;

architecture name_body of name is

subtype data_type is signed( 15 downto 0 );
type data_array_type is array( 0 to 7 ) of data_type;
signal data_array_1 : data_array_type := ( others => to_signed( 0, data_type'length ) );
signal data_array_2 : data_array_type := ...;
attribute syn_ramstyle : string;
attribute syn_ramstyle of data_array_1 : signal is "block_ram";--"no_rw_check";
attribute syn_ramstyle of data_array_2 : signal is "block_ram";--"no_rw_check";

signal rd1_addr, wr1_addr : unsigned( 2 downto 0 ) := to_unsigned( 0, 4 );
signal rd2_addr, wr2_addr : unsigned( 2 downto 0 ) := to_unsigned( 0, 4 );
signal A, C : data_type := to_signed( 0, data_type'length );

body

A <= data_array_1( to_integer( rd1_addr ) );
C <= data_array_2( to_integer( rd2_addr ) );

process( reset, clock )
begin
if reset = '1' then
A <= to_signed( 0, data_type'length );
C <= to_signed( 0, data_type'length );
rd1_addr <= ...;
wr1_addr <= ...;
rd2_addr <= ...;
wr2_addr <= ...;
...
elsif rising_edge( clock ) then
dout <= A * C;
if write = '1' then
data_array_1( to_integer( wr1_addr ) ) <= din;
end if;
rd1_addr <= rd1_addr + 1;
wr1_addr <= wr1_addr + 1;
rd2_addr <= rd2_addr + 1;
end if;
end process;

end name_body;

Как нужно описывать RAM в виде массива, чтобы Synplify сделал из него BlockRAM?
Go to the top of the page
 
+Quote Post
oval
сообщение Jun 28 2006, 09:43
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 265
Регистрация: 15-03-05
Из: Москва
Пользователь №: 3 367



Цитата(Vadim_nsk @ Jun 28 2006, 13:38) *
При описании памяти как массива производится чтение и запись по разным адресам, при этом чтение производится ассинхронно, а запись синхронно.
При объявлении массива указываю атрибут:
attribute syn_ramstyle : string;
attribute syn_ramstyle of data_array_1 : signal is "block_ram";--"no_rw_check";

При этом Synplify Pro 8.4 в отчете выдает следующее сообщение:
Could not implement Block RAM. Is the read address registered using the same clock as the RAM?

Код примерно следующий:

entity name is
clock : in std_logic;
din : in signed( 15 downto 0 );
write : in std_logic;
dout : out signed( 15 downto 0 );
...
end name;

architecture name_body of name is

subtype data_type is signed( 15 downto 0 );
type data_array_type is array( 0 to 7 ) of data_type;
signal data_array_1 : data_array_type := ( others => to_signed( 0, data_type'length ) );
signal data_array_2 : data_array_type := ...;
attribute syn_ramstyle : string;
attribute syn_ramstyle of data_array_1 : signal is "block_ram";--"no_rw_check";
attribute syn_ramstyle of data_array_2 : signal is "block_ram";--"no_rw_check";

signal rd1_addr, wr1_addr : unsigned( 2 downto 0 ) := to_unsigned( 0, 4 );
signal rd2_addr, wr2_addr : unsigned( 2 downto 0 ) := to_unsigned( 0, 4 );
signal A, C : data_type := to_signed( 0, data_type'length );

body

A <= data_array_1( to_integer( rd1_addr ) );
C <= data_array_2( to_integer( rd2_addr ) );

process( reset, clock )
begin
if reset = '1' then
A <= to_signed( 0, data_type'length );
C <= to_signed( 0, data_type'length );
rd1_addr <= ...;
wr1_addr <= ...;
rd2_addr <= ...;
wr2_addr <= ...;
...
elsif rising_edge( clock ) then
dout <= A * C;
if write = '1' then
data_array_1( to_integer( wr1_addr ) ) <= din;
end if;
rd1_addr <= rd1_addr + 1;
wr1_addr <= wr1_addr + 1;
rd2_addr <= rd2_addr + 1;
end if;
end process;

end name_body;

Как нужно описывать RAM в виде массива, чтобы Synplify сделал из него BlockRAM?


Канал чтения должен быть также синхронным. Не поленитесь, посмотрите в документацию на Synplify, там все достаточно подробно расписано smile.gif
Go to the top of the page
 
+Quote Post
avesat
сообщение Jun 28 2006, 10:03
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 14-08-05
Из: Украина
Пользователь №: 7 621



Проще использовать готовые RAM блоки, рекомендованые под архитектуру спартана. И они сразу будут размещаться в BlockRAM.


--------------------
"Мы будем играть, пока не треснут наши гитары, и все те, кто любит рок - я отдаю вам честь!" AC/DC
Go to the top of the page
 
+Quote Post
des00
сообщение Jun 28 2006, 10:44
Сообщение #4


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



откуда у блочной памяти асинхронные сбросы ?
читаем lib.pdf от хилых про BRAM изучаем


--------------------
Go to the top of the page
 
+Quote Post
Vadim_nsk
сообщение Jun 28 2006, 11:47
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 7-09-05
Из: г. Новосибирск
Пользователь №: 8 335



Цитата(oval @ Jun 28 2006, 16:43) *
Канал чтения должен быть также синхронным. Не поленитесь, посмотрите в документацию на Synplify, там все достаточно подробно расписано smile.gif

Да в том то и дело, что не поленился... Может я конечно чего-то недопонимаю...
Пример из файла reference.pdf, стр. 10-84 (документация Synplify):
"Two-write Port RAM Example"

WRITE_RAM : process (clk)
begin
if rising_edge(clk) then
if (wren_a = '1') then
mem(to_integer(unsigned(addr_a))) <= data_a;
end if;
if (wren_b='1') then
mem(to_integer(unsigned(addr_b))) <= data_b;
end if;
addr_a_reg <= addr_a;
addr_b_reg <= addr_b;
end if;
end process WRITE_RAM;
q_a <= mem(to_integer(unsigned(addr_a_reg)));
q_b <= mem(to_integer(unsigned(addr_b_reg)));

Как видно, чтение ассинхронное.

Чтение внутрь процесса вносил (под клок), результат тот же...

Что же касается сброса, то он относится не к памяти, а к всему вычислительному блоку (надо же мне както инициализировать сигналы).

Готовые RAM блоки, рекомендованые под архитектуру спартана использовать можно, но их тяжеловато подстраивать под конкретный размер массива данных. Я пытался сделать компонент в общем виде под задаваемую разрядность и объем данных.
Go to the top of the page
 
+Quote Post
des00
сообщение Jun 28 2006, 12:07
Сообщение #6


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



какая разница ? вы позволили синтезатору доопределить поведение памяти при сигналах сброса, т.к. память описана в таком процессе. Вот он и доопределил.
Опишите память в отдельных процессах. и будет вам благо. Ест-но латентность памяти на доступ нужно учесть ручками.


--------------------
Go to the top of the page
 
+Quote Post
vetal
сообщение Jun 28 2006, 12:09
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



Возможно, что дело еще в:
Код
rd1_addr <= rd1_addr + 1;
wr1_addr <= wr1_addr + 1;
rd2_addr <= rd2_addr + 1;



Добавьте дополнительные регистры в код :rd1_addr_br,wr1_addr_br,rd2_addr_br и делайте примерно так:
Код
...
--synthesis translate_off
rd1_addr <= ...;
wr1_addr <= ...;
rd2_addr <= ...;
wr2_addr <= ...;
--synthesis translate_on
...
data_array_1( to_integer( wr1_addr_br ) ) <= din;
...
wr1_addr_br<=wr1_addr+1;
wr1_addr<=wr1_addr+1;
...
Go to the top of the page
 
+Quote Post
oval
сообщение Jun 28 2006, 12:16
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 265
Регистрация: 15-03-05
Из: Москва
Пользователь №: 3 367



Цитата(Vadim_nsk @ Jun 28 2006, 15:47) *
Цитата(oval @ Jun 28 2006, 16:43) *
Канал чтения должен быть также синхронным. Не поленитесь, посмотрите в документацию на Synplify, там все достаточно подробно расписано smile.gif

Да в том то и дело, что не поленился... Может я конечно чего-то недопонимаю...
Пример из файла reference.pdf, стр. 10-84 (документация Synplify):
"Two-write Port RAM Example"

WRITE_RAM : process (clk)
begin
if rising_edge(clk) then
if (wren_a = '1') then
mem(to_integer(unsigned(addr_a))) <= data_a;
end if;
if (wren_b='1') then
mem(to_integer(unsigned(addr_b))) <= data_b;
end if;
addr_a_reg <= addr_a;
addr_b_reg <= addr_b;
end if;
end process WRITE_RAM;
q_a <= mem(to_integer(unsigned(addr_a_reg)));
q_b <= mem(to_integer(unsigned(addr_b_reg)));

Как видно, чтение ассинхронное.

Чтение внутрь процесса вносил (под клок), результат тот же...


Обратите внимание, что адрес чтения защелкивается. Посмотрите в документе Synplicity FPGA Synthesis раздел Design Optimization -> Inferring RAMs.

Цитата
Что же касается сброса, то он относится не к памяти, а к всему вычислительному блоку (надо же мне както инициализировать сигналы).


Разнесите по разным процессам память и остальную логику.
Go to the top of the page
 
+Quote Post
Gorby
сообщение Jun 28 2006, 12:16
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 449
Регистрация: 28-10-04
Из: Украина
Пользователь №: 1 002



Извините, что врываюсь...

Почему-то никто ни слова не произнес про COREGEN. Это ж самый верный способ получить требуемую память. Прекрасно конфигурируется и заведомо работает. А в Симплифае вставляется как блэк-бокс. Правда, непереносимо. Так и BRAM сама по себе непереносима.


--------------------
Умею молчать на 37 языках...
Go to the top of the page
 
+Quote Post
Mad Makc
сообщение Jun 28 2006, 13:11
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 244
Регистрация: 2-10-04
Из: Мухосранска
Пользователь №: 763



Цитата
Почему-то никто ни слова не произнес про COREGEN.

Потому что не удобно.Сегодня я хочу память в 2К слов.Завтра дадут ценное указание и память станет 4К слов.А послезавтра разрядность увеличить придётся.
По мне править код намного проще и удобней, чем занового генерить ядра.
Go to the top of the page
 
+Quote Post
Wild
сообщение Jun 29 2006, 11:54
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 216
Регистрация: 26-05-06
Из: Коломна
Пользователь №: 17 479



Если адрес чтения успевает устанавливаться к серидине такта, а данные на выходе обязательно надо получить к началу следующего такта, можно писать по фронту, а читать по спаду.

Сообщение отредактировал Wild - Jun 29 2006, 11:55
Go to the top of the page
 
+Quote Post
maior
сообщение Jun 29 2006, 14:26
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 177
Регистрация: 21-10-04
Пользователь №: 948



Hо ведь есть еще стандартные примитивы памяти (блочной и распределенной),
на базе которых можно сделать универсальные параметризиремые (через generic)
бибиотечные элементы. Я так и делал для виртексов 2 и 4 (один элемент годился для обоих
и позволял строить память почти любой конфигурации!).
Для спартанов - тоже не должно быть проблем.
И не заморачивался ни с coregen, ни с behaviorial, которое по-разному и неустойчиво
интерпретируется разными синтезаторами в разных условиях и для
разных (даже слегка разных!) чипов.
Go to the top of the page
 
+Quote Post
Gorby
сообщение Jun 30 2006, 09:32
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 449
Регистрация: 28-10-04
Из: Украина
Пользователь №: 1 002



Цитата(maior @ Jun 29 2006, 18:26) *
Hо ведь есть еще стандартные примитивы памяти (блочной и распределенной),
на базе которых можно сделать универсальные параметризиремые (через generic)
бибиотечные элементы. Я так и делал для виртексов 2 и 4 (один элемент годился для обоих
и позволял строить память почти любой конфигурации!).
Для спартанов - тоже не должно быть проблем.
И не заморачивался ни с coregen, ни с behaviorial, которое по-разному и неустойчиво
интерпретируется разными синтезаторами в разных условиях и для
разных (даже слегка разных!) чипов.


Фактически, вы руками доделали некоторую часть работы. Которую запросто мог за вас сделать Кореген. Более того, вам пришлось разбираться с тонкостями использования тех примитивов - причем обременительными тонкостями, типа зануления старших адресов если используется не вся память и построение дешифраторов, если требуется бОльшая. И зачем?! Когда есть кореген, одним движением пальца делающий все это.

Насчет переносимости, разных синтезаторов и проч. Сдается мне, что проблему сильно преувеличивают.

Не знаю, кто как, но я только один раз кардинально менял окружение. С Леонардо Спектрум для Atmel FPSLIC прыгнул на Spartan2 и XST (ISE). Разумеется, блоки памяти потребовали кардинальной переделки. Которая заключалась всего лишь в генерации оных в Корегене.
Затем перешел на Спартан 3, так ничего и не поменялось. Сгенерировал то же самое в Корегене.

А теперь пожалуйста ответьте, как часто вам, уважаемые коллеги, пришлось переходить (в ходе разработки ОДНОГО изделия) на кардинально другие FPGA и кардинально другие синтезаторы?

Ото ж... А на рихтовку своих исходников с целью сделать их универсальными вы потратите очень много времени с непредсказуемым результатом. (речь идет об аппаратно-специфических вещах, память, DDR регистры и проч.).

Моя идеология проста: делаем на plain VHDL все, что можно. По возможности без атрибутов и прочих бубенцов. Все специфическое включаем в блэк-боксы, их генерируем в целевой среде. Констрейны и прочие весьма зависимые прибамбасы (распиновка, типы выводов и тд) делаем исключительно в целевой среде. И не паримся. При переходе на что-то другое у нас остается везде компилируемый чистый VHDL, блэк-боксы создаем по-новой - тут уж никуда не деться. А констрейны, пинауты и иже с ними в новой среде все равно придется вбивать по-новой. Каламбурчик.


--------------------
Умею молчать на 37 языках...
Go to the top of the page
 
+Quote Post
maior
сообщение Jun 30 2006, 12:58
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 177
Регистрация: 21-10-04
Пользователь №: 948



Цитата(Gorby @ Jun 30 2006, 13:32) *
... Фактически, вы руками доделали некоторую часть работы. Которую запросто мог за вас сделать Кореген....

... Более того, вам пришлось разбираться с тонкостями использования тех примитивов - причем обременительными тонкостями,....

.. А на рихтовку своих исходников с целью сделать их универсальными вы потратите очень много времени с непредсказуемым результатом. (речь идет об аппаратно-специфических вещах, память, DDR регистры и проч.)...


ОДИН раз сделал - и больше уже не пришлось делать что-то еще.. Вот уже пару лет как
пользую свою библиотеку памяти для разных проектов. Идея была
создать для зайлинкса такой же набор LPM памяти какая есть у
альтеры. У меня они даже совместимы по entity и generic, так-что можно
прыгать с зайлинкса на альтеру без труда. Посмотрел бы я на вас с
вашим corgen в такой ситуации.
Coregen (для памяти) - в отстое уже давно. Он явно неудобен, о чем тут
уже говорилось, не стоит об этом спорить.
А с plane (behaviorial) HDL - все равно будут проблемы, и в конце
концов проковыряешся больше, что собственно и доказывают посты
в этой ветке.

Нету там никаких особых тонкостей. Только заглянуть пару раз в мануалы,
что никогда не помешает.

А времени потратил до смешного немного. Даже удивительно, отчего это
зайлинкс сам не сделал эту работу, например как альтера.

Но опять же - на вкус и цвет...
Go to the top of the page
 
+Quote Post
des00
сообщение Jul 1 2006, 06:42
Сообщение #15


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



МОЕ ИМХО на весь этот счет, у памяти 2 конфигурации, 1 чистый бехавор для симуляции и первоначальной сборки (1 раз потратил день на изучение как правильно нужно писать память, после этого ни разу не было проблем при синтезе, для симуляции попробуйте на вставленых БРАМАХ при объеме памяти кил в 100-200 симуляться и натравите профайлер).
2 конфигурация это уже конфигурация сборки, с реальными вставленными брамами, к которым к тому же можно и RLOC/LOC пристегнуть.
Выбор конфигурации в ВХДЛ 1 строка. в том же топ файле.


--------------------
Go to the top of the page
 
+Quote Post
qwqw
сообщение Aug 23 2006, 09:08
Сообщение #16


Частый гость
**

Группа: Свой
Сообщений: 192
Регистрация: 23-11-05
Из: г. Москва
Пользователь №: 11 307



У меня Spartan2 а не 3, но думаю это непринципиально.
Мне нужно написать двухпортовую RAM с разными клоками на концах
с одной стороны только запись с we а с другой только чтение.
на сайте Xilinx есть примеры описания
НО мне нужна память с разной разрядностью шин на разных портах, там такого нет.
Есть вариант использовать готовую память типа RAMB4_Sm_Sn или, как говорилось выше, использовать COREGEN, но хочется иметь возможность изменять под себя (выбирать фронты и пр.) ну и по-возможности не использовать черных ящиков. Очевидно, что написать самому возможно, но пока не получается.
Вероятно кто-то уже возился с этим.
Пишу на VHDL, но Verilog тоже прочитаю.

Сообщение отредактировал qwqw - Aug 23 2006, 09:10
Go to the top of the page
 
+Quote Post
BSV
сообщение Aug 23 2006, 19:42
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 541
Регистрация: 11-04-05
Из: Москва
Пользователь №: 4 045



Пытался делать такую штуку в ISE 4.2. Были проблемы с синтезом (надо было писать и читать по обоим портам). Судя по тому, что приводится в Language templates, ситуация мало изменилась, хотя попробовать и не мешает:

Код
process (<clockA>)
begin
   if (<clockA>'event and <clockA> = '1') then
      if (<enableA> = '1') then
         if (<write_enableA> = '1') then
            <ram_name>(conv_integer(<addressA>)) <= <input_dataA>;
         end if;
         <ram_outputA> <= <ram_name>(conv_integer(<addressA>));
      end if;
   end if;
end process;

process (<clockB>)
begin
   if (<clockB>'event and <clockB> = '1') then
      if (<enableB> = '1') then
         <ram_outputB> <= <ram_name>(conv_integer(<addressB>));
      end if;
   end if;
end process;


Единственный выход в данном случае - использовать библиотечные элементы.

По поводу разной разрядности на портах - попробуйте все это описать на поведенческом уровне следующим образом - массив (который память) используйте с минимальной используемой разрядностью, а при описании чтения и записи по другому порту используйте несколько индексов массива. Например так:
Код
  
<ram_outputB> <= <ram_name>(conv_integer(<addressB>*2 + 1)) & <ram_name>(conv_integer(<addressB>*2));

Это в случае, если разрядность различается в 2 раза. Посмотрите, что Вам синтезатор на это скажет. Если схавает - ваша взяла, если нет - ничего не попишешь.

Кстати, тут возможна и другая проблема - в библиотечных элементах может не найтись памяти с нужной комбинацией разрядности портов и/или размером (например мне в Спартане 2е понадобилась память объемом 4КБайт и разрядностью 8 и 32). Тут может оказаться удобным объединение выходов нескольких BRAM при помощи OR или XOR и использовании входов сброса выходных регистров BRAM. Понятно как - на те BRAM, что не используем подаем сигнал сброса, после OR или XOR получаем то, что нужно. Правда, это может оказаться слишком медленно.

Сообщение отредактировал BSV - Aug 23 2006, 19:43


--------------------
Дурак, занимающий высокий пост, подобен человеку на вершине горы - все ему кажется маленьким, а всем остальным кажется маленьким он сам. /Законы Мерфи/
Go to the top of the page
 
+Quote Post
qwqw
сообщение Aug 24 2006, 08:44
Сообщение #18


Частый гость
**

Группа: Свой
Сообщений: 192
Регистрация: 23-11-05
Из: г. Москва
Пользователь №: 11 307



разрядность портов:
A (запись) = 8
B(чтение) = 32
глубина от 1024 байт и выше

ваш вариант (и смежные с ним) я уже пробовал
примерно так:
Код
-------------- A side -------------------------
my_RAM_A_side:process(clkA)
begin
if clkA'event and clkA = '1' then
---
if WEA='1' then ram_block(conv_integer(AddrA))<=DIA;end if;
---
end if; -- clk
end process my_RAM_A_side;
-----------------------------------------------
-------------- B side -------------------------
my_RAM_B_side:process(clkB)
begin
if clkB'event and clkB = '1' then
---
--read_addr<=4*AddrB;--conv_integer(AddrB);
read_addr0<=4*AddrB;
read_addr1<=4*AddrB+1;
read_addr2<=4*AddrB+2;
read_addr3<=4*AddrB+3;
---
end if; -- clk
end process my_RAM_B_side;
----
----
--DOB <= ram_block(read_addr)&ram_block(read_addr+1)&ram_block(read_addr+2)&ram_block(read_addr+3);
DOB( 7 downto  0)<= ram_block(read_addr0);
DOB(15 downto  8)<= ram_block(read_addr1);
DOB(23 downto 16)<= ram_block(read_addr2);
DOB(31 downto 24)<= ram_block(read_addr3);
-----------------------------------------------

но увы не получается
я могу использовать 2 закаскадированых RAMB4_S4_S16, но хочется все же самому закодить
Go to the top of the page
 
+Quote Post
BSV
сообщение Aug 24 2006, 10:59
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 541
Регистрация: 11-04-05
Из: Москва
Пользователь №: 4 045



А синтезатор-то что говорит? В Вашей реализации я вижу ошибку - чтение должно быть обязательно! по фронту клока, а вот адреса чтения как раз и не нужно делать регистровыми.


--------------------
Дурак, занимающий высокий пост, подобен человеку на вершине горы - все ему кажется маленьким, а всем остальным кажется маленьким он сам. /Законы Мерфи/
Go to the top of the page
 
+Quote Post
BSV
сообщение Aug 24 2006, 11:40
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 541
Регистрация: 11-04-05
Из: Москва
Пользователь №: 4 045



Попробовал - таки да, не хавает, говорит, что вместо памяти триггеров навставляет. Ну и шут с ним.
Для вас есть вариант - объединить 4 синтезированных блока xxx_S8_S8 способом, который я описал выше, хотя, вам же по 8-разрядному порту не надо читать - так что это и не нужно. С двумя блоками фокус не пройдет - выравнивание поедет (PORTB(x) /= PORTA(x*4+3) & PORTA(x*4+2) & PORTA(x*4+1) & PORTA(x*4)).


--------------------
Дурак, занимающий высокий пост, подобен человеку на вершине горы - все ему кажется маленьким, а всем остальным кажется маленьким он сам. /Законы Мерфи/
Go to the top of the page
 
+Quote Post
qwqw
сообщение Aug 24 2006, 14:05
Сообщение #21


Частый гость
**

Группа: Свой
Сообщений: 192
Регистрация: 23-11-05
Из: г. Москва
Пользователь №: 11 307



насчет ошибки я не согласен, если посмотрите в примерах там сделано аналогично.
Да и раньше я делал такую память(только с одинаковой разрядностью) и все благополучно паковалось в BRAM.
Цитата
Для вас есть вариант - объединить 4 синтезированных блока xxx_S8_S8 способом, который я описал выше, хотя, вам же по 8-разрядному порту не надо читать - так что это и не нужно. С двумя блоками фокус не пройдет - выравнивание поедет (PORTB(x) /= PORTA(x*4+3) & PORTA(x*4+2) & PORTA(x*4+1) & PORTA(x*4)).

я уже сделал, как говорил выше: каскадировал 2 блока RAMB4_S4_S16 и как раз получается 8/32
и глубина 1024. Соответственно 1-й RAMB4_S4_S16 - на вход младшая тетрада на 2-й - старшая
и выход разобран соответствующим образом.
Все работает и в BRAM упаковалось. Однако камень предкновения во фронтах.
Если не получится с положительными сделать, придется тратить GBUF с CLKDLL (брать противофазный клок), а с ними тоже напряг.
Go to the top of the page
 
+Quote Post
BSV
сообщение Aug 24 2006, 14:46
Сообщение #22


Знающий
****

Группа: Свой
Сообщений: 541
Регистрация: 11-04-05
Из: Москва
Пользователь №: 4 045



Зачем Вам противофазный клок? Если нужен отрицательный фронт - просто заводите на тактовый вход not CLK и все - а синтезатор, маппер или что там еще пусть разбирается (инверторы на тактовом входе имеются в любом блоке, в том числе и в BLOCKRAM).

Сообщение отредактировал BSV - Aug 24 2006, 14:47


--------------------
Дурак, занимающий высокий пост, подобен человеку на вершине горы - все ему кажется маленьким, а всем остальным кажется маленьким он сам. /Законы Мерфи/
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 16:04
Рейтинг@Mail.ru


Страница сгенерированна за 0.01598 секунд с 7
ELECTRONIX ©2004-2016