|
|
  |
Память на плис, реализация памяти на VHDL или Coregen |
|
|
|
Sep 17 2015, 12:45
|
Частый гость
 
Группа: Участник
Сообщений: 155
Регистрация: 26-04-12
Пользователь №: 71 584

|
Цитата(iosifk @ Sep 17 2015, 12:29)  Тогда и говорить не о чем... Если данные не согласованы с клоком шины PCI, то результат как раз таким и будет... И еще раз. Я Вам объясняю, что у Ксаййлинкса есть библиотечные компоненты, которые и надо использовать в таких случаях. Без всяких корегенов... А из c:\Xilinx\14.7\ISE_DS\ISE\verilog\src\unisims\.. Сигнал Rd от шины совершенно непричем. Ведь я его использую и с корегеновской коркой. Да и к томуже если я делаю память не на 65536 отсчетов на например 1024 то проблем никаких не возникает. Как я понимаю проблема имеено в размешении блоков памяти по кристалу при большом используемом количестве. Ну может я, конечно, и ошибась где-то. Но на основе своего опыта (довольно большого) могу сказать что элементы сгенерированные корегеном работаю стабильнее будьто память, простые умножители или фильтры построенные на умножителях. Разумного объяснения у меня этому нет. Цитата(Maverick @ Sep 17 2015, 12:25)  пример
[code]-- Following is the equivalent VHDL code for a 4-bit register with a positive-edge clock, asynchronous set and clock enable. library ieee; use ieee.std_logic_1164.all; Вы намекаете что в одном условии нельзя записывать условие клока и разрешения if clk'event and clk='1' and ce='1' then ... а нужно так if ce='1' then if clk'event and clk='1' then ... или о чем речь?
|
|
|
|
|
Sep 17 2015, 13:06
|
Гуру
     
Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369

|
Цитата(Anton1990 @ Sep 17 2015, 15:45)  Сигнал Rd от шины совершенно непричем. Ведь я его использую и с корегеновской коркой. Да и к томуже если я делаю память не на 65536 отсчетов на например 1024 то проблем никаких не возникает. Как я понимаю проблема имеено в размешении блоков памяти по кристалу при большом используемом количестве. Ну может я, конечно, и ошибась где-то. Но на основе своего опыта (довольно большого) могу сказать что элементы сгенерированные корегеном работаю стабильнее будьто память, простые умножители или фильтры построенные на умножителях. Разумного объяснения у меня этому нет. У Вас в виртекс 6 есть блоки 32K × 1... Так вот, возьмите две группы по 16 блоков. И каждый блок - подключите к одному биту данных... По входу данные от АЦП подать параллельно на обе группы, а выбор группы определять по сигналу разрешение записи. А его взять от старшего разряда счетчика. Теперь по выходу FIFO... Поскольку по чтению вообще спешить некуда, то можно блоки прицепить к 32 битам а при чтении учитывать старшее или младшее слово... Или так... учитывая, что чтение идет медленно, то модно сделать и мультиплексор по выходу... Или же брать FIFO с разрядностью 1 на входе и 2 на выходе... При таком раскладе точно не будет мультиплексоров по данным на входе, а значит, что легче будет развести проект по кристаллу. И скорее всего визард так и делает. А компилятор - нет. Посмотрите, что получается после компиляции - оптимизации... Вот потому я всегда такие вещи делаю сам... А если совсем честно, то тут не нужно FIFO, а нужна обычная память с шинами на запись и на чтение... И с одним клоком на 200 Мгц... весь проект сделать на этой частоте. А клок от PCI можно привести к клоку 200 Мгц.
--------------------
www.iosifk.narod.ru
|
|
|
|
|
Sep 17 2015, 13:06
|

я только учусь...
     
Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839

|
Цитата(Anton1990 @ Sep 17 2015, 15:45)  Вы намекаете что в одном условии нельзя записывать условие клока и разрешения if clk'event and clk='1' and ce='1' then ... а нужно так if ce='1' then if clk'event and clk='1' then ... или о чем речь? я намекаю на Код if (C'event and C='1')then if (CE='1') then + Код if rd'event and rd='1' then Ard <= Ard + 2; --адреса преребираем через два т.к. шина PCI 32 разряда end if; для синтезатора это счетчик работающий на тактовой частоте rd мне не понятно, например, почему сигнал q_thres окончания наполнения данными в память, не передается на схему вычитки в PCI через синхронизирующие регистры? Как я понял по q_thres начинается вычитка данных из памяти. Мне не понятен обмен готовности выполнения различных процессов и/или синхронизации работы схем: - запись данных в блочную память с АЦП - вычитка данных из блочной памяти для PCI PS Ваше описание мне тяжело читать. Разнесите в разные процессы - запись данных в блочную память с АЦП - вычитка данных из блочной памяти для PCI
--------------------
If it doesn't work in simulation, it won't work on the board.
"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
|
|
|
|
|
Sep 17 2015, 13:12
|
Частый гость
 
Группа: Участник
Сообщений: 155
Регистрация: 26-04-12
Пользователь №: 71 584

|
Цитата(Maverick @ Sep 17 2015, 16:06)  я намекаю на Код if (C'event and C='1')then if (CE='1') then А есть разница ?
|
|
|
|
|
Sep 17 2015, 13:48
|
Частый гость
 
Группа: Участник
Сообщений: 155
Регистрация: 26-04-12
Пользователь №: 71 584

|
Цитата(Maverick @ Sep 17 2015, 16:06)  я намекаю на Код if (C'event and C='1')then if (CE='1') then + Код if rd'event and rd='1' then Ard <= Ard + 2; --адреса преребираем через два т.к. шина PCI 32 разряда end if; для синтезатора это счетчик работающий на тактовой частоте rd мне не понятно почему сигнал q_thres окончания наполнения данными в память, не передается на схему вычитки в PCI через синхронизирующие регистры? Как я понял по q_thres начинается вычитка данных из памяти. Мне не понятен обмен готовности выполнения различных процессов - синхронизации работы: - запись данных в блочную память с АЦП - вычитка данных из блочной памяти для PCI PS Ваше описание мне тяжело читать Все верно счетчик адресов счения радотает по Rd. q_thres записывается в full он и передается в шину для считывания программой. Разумеется читать чужой код с неполными данными об отсутствии окружения данного блока и кода программы верзнего уровня сложно. Тут мне указывают на неправильность конструкций if then.. Если это действительно неправильно то нужно исправить и посмотреть на результат. Я, конечно, давно знаю что VHDL довольно геморойная вешь как бы лесно его не описывали, но это для меня открытие. Цитата(Golikov A. @ Sep 17 2015, 16:25)  есть, потому что синтезаторы анализирует текст на поиск известных им конструкций, с обще принятым описанием. Записав их по другому вы просто мешаете синтезатору понимать что вы хотели. Тут не как в С, тут не компилируется каждый оператор, тут все сложнее... Ну то что здесь все сложнее я знаю, но нужно попробовать исправить и посмотреть. А так вообще спасибо. Если Вы правы то мне много придется исправлять.
|
|
|
|
|
Sep 17 2015, 14:41
|
Частый гость
 
Группа: Участник
Сообщений: 155
Регистрация: 26-04-12
Пользователь №: 71 584

|
Цитата(Golikov A. @ Sep 17 2015, 16:59)  строго говоря я думаю что именно в этом случае синтезатор разберется и так и сяк, они все умнее и умнее становятся. Но на всякий случай проверить стоит.
И по сути проблемы, какой клок на PCI по которому уходят данные? А что значит какой клок на PCI? Это сигнал чтения который поступает в мою ПЛИС от контроллера PCI. По этому сигналу я выбираю данные из памяти на выходную шину и им же открываю выходной bufe. А уже на самой шине PCI данные защелкиваются натуральным клоком от PCI (но это меня уже не касается). У меня в проекте целая куча регистров читается таким образом. Вообще схема отработанная годами. Память в плис с точки зрения логики ее чтения ничем не отличается от большой кучи регистров. А следовательно проблема в правильной записи в эти ''регистры''.
|
|
|
|
|
Sep 17 2015, 18:36
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Вообще схема отработанная годами. Память в плис с точки зрения логики ее чтения ничем не отличается от большой кучи регистров. А следовательно проблема в правильной записи в эти ''регистры''. то есть у вас все работает и проблем никаких нет, да? наводящий вопрос Как вы думаете регистр состоящий из Д триггеров, который может быть размещен в любом месте плис и ячейка памяти расположенная в блоке, с адресацией, имеют одинаковое время распространения сигнала от них до точки где данные захлопнуться? Как вы думаете может такое получиться что вы выставите желаемый адрес по которому хотите считать данные так близко к моменту защелкивания данных, что не все сигналы успели дойти до регистра защелкивающего данные в другой части ПЛИС, к фронту клока управляющего этим регистром?
|
|
|
|
|
Sep 17 2015, 19:16
|
Гуру
     
Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369

|
Цитата(Golikov A. @ Sep 17 2015, 21:36)  то есть у вас все работает и проблем никаких нет, да?
наводящий вопрос Как вы думаете регистр состоящий из Д триггеров, который может быть размещен в любом месте плис и ячейка памяти расположенная в блоке, с адресацией, имеют одинаковое время распространения сигнала от них до точки где данные захлопнуться? Как вы думаете может такое получиться что вы выставите желаемый адрес по которому хотите считать данные так близко к моменту защелкивания данных, что не все сигналы успели дойти до регистра защелкивающего данные в другой части ПЛИС, к фронту клока управляющего этим регистром? Вот две строки: if rd'event and rd='1' then bufDO(15 downto 0) <= Mem(conv_integer(Ard)); --вынимаем из памяти два отсчета данных bufDO(31 downto 16) <= Mem(conv_integer(Ard+1)); Скажите, как происходит Mem(conv_integer(Ard)); --вынимаем из памяти два отсчета данных и Ard+1 Что там с латентностью? И насколько быстро произойдет "Ard+1" и потом Mem(conv_integer(Ard+1)); И все это за один фронт "rd'event and rd='1'" при том, что больше клоков то нет.... Только один этот фронт... Т.е. это скорее всего счетчик, который идет на младшее слово. А с него же адрес идет на сумматор, и после сумматора на старшее??? Или это действительно две ячейки памяти и по выходу мультиплексор? И если сравнивать с регистрами, то память медленнне раза в два....
--------------------
www.iosifk.narod.ru
|
|
|
|
|
Sep 18 2015, 06:08
|
Частый гость
 
Группа: Участник
Сообщений: 155
Регистрация: 26-04-12
Пользователь №: 71 584

|
Цитата(Golikov A. @ Sep 17 2015, 21:36)  то есть у вас все работает и проблем никаких нет, да?
наводящий вопрос Как вы думаете регистр состоящий из Д триггеров, который может быть размещен в любом месте плис и ячейка памяти расположенная в блоке, с адресацией, имеют одинаковое время распространения сигнала от них до точки где данные захлопнуться? Как вы думаете может такое получиться что вы выставите желаемый адрес по которому хотите считать данные так близко к моменту защелкивания данных, что не все сигналы успели дойти до регистра защелкивающего данные в другой части ПЛИС, к фронту клока управляющего этим регистром? По первой части ответ очевиден - время распространения разное. По второй части вопрос не доконца понял. Но отвечу так. Если частота выставления адреса чтения очень низкая, то проблем быть не должно. Наверное. Цитата(iosifk @ Sep 17 2015, 22:16)  Вот две строки:
if rd'event and rd='1' then bufDO(15 downto 0) <= Mem(conv_integer(Ard)); --вынимаем из памяти два отсчета данных bufDO(31 downto 16) <= Mem(conv_integer(Ard+1));
Скажите, как происходит Mem(conv_integer(Ard)); --вынимаем из памяти два отсчета данных
и Ard+1
Что там с латентностью? И насколько быстро произойдет "Ard+1" и потом Mem(conv_integer(Ard+1)); И все это за один фронт "rd'event and rd='1'" при том, что больше клоков то нет.... Только один этот фронт... Т.е. это скорее всего счетчик, который идет на младшее слово. А с него же адрес идет на сумматор, и после сумматора на старшее??? Или это действительно две ячейки памяти и по выходу мультиплексор?
И если сравнивать с регистрами, то память медленнне раза в два.... Mem(conv_integer(Ard)); --вынимаем из памяти два отсчета данных комментарий сразу к двум строкам относиться. Что касается Ard+1, то у меня были по этому поводу сомнения. Взял да убрал чтения сразу двух отсчетов, теперь пишем в память 16 разрядов и читает из памяти 16 разрядов. Ну стало считываться в ПК в 2 раза медленнее ну и пофиг. НО общая проблема осталась.
|
|
|
|
|
Sep 18 2015, 06:25
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Если частота выставления адреса чтения очень низкая, то проблем быть не должно. Наверное. Возможно у вас клоком памяти как раз становиться rd сигнал, клоком второго порта, надо поглядеть разводку. тогда у вас цепочка действий - по сигналу rd защелкиваем в выходной регистр памяти данные по заданному адресу - по какому-то внутреннему вам не известному клоку данные с памяти защелкнули на отправку. эту цепочку можно повторять часто, редко, можно 1 раз и поймать ошибку, важно сколько времени проходит между rd и внутренним клоком, может так оказаться что данные просто не успевают выбраться из памяти и дойти до момента их захвата. Из регистров это все значительно быстрее, а в ФИФО данные к моменту забора на выходе уже готовы.
|
|
|
|
|
Sep 18 2015, 06:56
|

я только учусь...
     
Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839

|
Цитата(Anton1990 @ Sep 18 2015, 09:08)  Общее, что у Вас должно быть: - память двух портовая с двумя клоками (своя тактовая частота для каждого порта памяти): CODE library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity memA0 is generic ( DATA_WIDTH : natural := 4; ADDR_WIDTH : natural := 13 );
port ( clk_a : in std_logic; clk_b : in std_logic; addr_a : in std_logic_vector((ADDR_WIDTH-1) downto 0); addr_b : in std_logic_vector((ADDR_WIDTH-1) downto 0); data_a : in std_logic_vector((DATA_WIDTH-1) downto 0); data_b : in std_logic_vector((DATA_WIDTH-1) downto 0); we_a : in std_logic := '1'; we_b : in std_logic := '1'; q_a : out std_logic_vector((DATA_WIDTH -1) downto 0); q_b : out std_logic_vector((DATA_WIDTH -1) downto 0) ); end memA0;
architecture Behavioral of memA0 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; shared variable ram : memory_t:= (others => (others => '0')); -- signal ram : memory_t := --( -- to initialize memory -- ); signal mem_data : std_logic_vector (14 downto 0);
begin
-- Port A process(clk_a) begin if(rising_edge(clk_a)) then if(we_a = '1') then ram(conv_integer(addr_a)) := data_a; end if; q_a <= ram(conv_integer(addr_a)); end if; end process;
-- Port B process(clk_b) begin if(rising_edge(clk_b)) then if(we_b = '1') then ram(conv_integer(addr_b)) := data_b; end if; q_b <= ram(conv_integer(addr_b)); end if; end process;
end Behavioral;
- схема записи данных с АЦП должна соединяться с одним портом памяти на своей тактовой частоте (у Вас вроде это clk). - схема вычитки данных для PCI должна соединяться с другим портом памяти на своей тактовой частоте (у Вас вроде это rd). - сигналы квитирования или готовности данных должны быть пропущены через синхронизирующую цепочку регистров. Это необходимо когда Вы производите передачу готовности с одной схемы в другую. PS Можно вместо предложенной памяти использовать ФИФО (тоже на 2 клока для входа и выхода).
--------------------
If it doesn't work in simulation, it won't work on the board.
"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|