Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Память на плис
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
Anton1990
Все добрый день.
Использую виртекс6. Реализую промежуточный накопитель оцифрованного сигнала (16 бит) с АЦП с дискретизацией 200 МГц. и последующим сливом в ПК.
На VHDL реализовал накопитель. Вродебы все просто: в массив длинной 65536 загоняю сигнал и останавливаю запись. Далее медленно по PCI скачиваю данные. Сигнал тактирования разумеется законстрейнил (задал period). При компиляции не ругается. Вся конструкция работает, но наблюдается нестабильность от разводки к разведке проекта. При использовании FIFO созданного в Coregeneratore результат значительно лучше (практически нет глюков).
Вопрос: в чем отличие? Может я чего то незнаю? Какая нибудь потаенная галочка, констрейн или еще что?
Кстати памяти в плис используется немного всего 20 %.
Заранее спасибо за ответы.
Maverick
Цитата(Anton1990 @ Sep 17 2015, 08:21) *
Все добрый день.
Использую виртекс6. Реализую промежуточный накопитель оцифрованного сигнала (16 бит) с АЦП с дискретизацией 200 МГц. и последующим сливом в ПК.
На VHDL реализовал накопитель. Вродебы все просто: в массив длинной 65536 загоняю сигнал и останавливаю запись. Далее медленно по PCI скачиваю данные. Сигнал тактирования разумеется законстрейнил (задал period). При компиляции не ругается. Вся конструкция работает, но наблюдается нестабильность от разводки к разведке проекта. При использовании FIFO созданного в Coregeneratore результат значительно лучше (практически нет глюков).
Вопрос: в чем отличие? Может я чего то незнаю? Какая нибудь потаенная галочка, констрейн или еще что?
Кстати памяти в плис используется немного всего 20 %.
Заранее спасибо за ответы.

предположение:
переходы из одного клокового домена в другой - двух клоковое FIFO решает как раз эту проблему...
blackfin
Цитата(Anton1990 @ Sep 17 2015, 08:21) *
Сигнал тактирования разумеется законстрейнил (задал period). При компиляции не ругается. Вся конструкция работает, но наблюдается нестабильность от разводки к разведке проекта.
Вопрос: в чем отличие? Может, я чего-то не знаю? Какая-нибудь потаенная галочка, констрейн или еще что?

Просто задать период клока недостаточно. Необходимо задать задержки по всем входам и выходам.

Для SDC это команды типа:

set_input_delay -clock clk -min 1.000 [all_inputs]
set_input_delay -clock clk -max 2.000 [all_inputs]

set_output_delay -clock clk -min 0.000 [all_outputs]
set_output_delay -clock clk -max 1.000 [all_outputs]

Для UCF (в ISE) есть похожие команды (См., UG612).
Krys
Цитата(Maverick @ Sep 17 2015, 12:28) *
двух клоковое FIFO решает как раз эту проблему...
на двухпортовой памяти с независимыми клоками
Golikov A.
Цитата
на двухпортовой памяти с независимыми клоками

для которой ксалинкс честно пишет, что писать по одному порту и читать по другому по разным клокам из одного и того же адреса некорректно, данные на выходе будут не определены.
Одной памяти мало, в фифо еще встроен правильный переход между клоковыми доменами с правильной синхронизацией
blackfin
Цитата(Golikov A. @ Sep 17 2015, 09:18) *
для которой ксалинкс честно пишет, что писать по одному порту и читать по другому по разным клокам из одного и того же адреса некорректно, данные на выходе будут не определены.

Так и ТС честно пишет: "в массив длиной 65536 загоняю сигнал и останавливаю запись. Далее медленно по PCI скачиваю данные."

В чем проблема?
Golikov A.
в том что скачиваться данные из памяти могут на одном клоке, а отправляться на другом. Среда следит чтобы данные выставляемые по переднему фронту первого клока, были валидны к следующему переднему фронту (констраины только на период), Но среда совершенно не следит чтобы они были валидны к фронту того клока по которому они отправляются.
В случае фифо данные, наверняка забираются по фронту по которому отправляются и там среда опять следит.

Но это все предположения, правду от нас скрываютsm.gif
Anton1990
Цитата(Golikov A. @ Sep 17 2015, 09:52) *
в том что скачиваться данные из памяти могут на одном клоке, а отправляться на другом. Среда следит чтобы данные выставляемые по переднему фронту первого клока, были валидны к следующему переднему фронту (констраины только на период), Но среда совершенно не следит чтобы они были валидны к фронту того клока по которому они отправляются.
В случае фифо данные, наверняка забираются по фронту по которому отправляются и там среда опять следит.

Но это все предположения, правду от нас скрываютsm.gif


Еще раз. В память данные пишутся на 200 МГц. По заполнению запись ОСТАНАВЛИВАЕТСЯ. Далее по сигналу чтения из шины PCI данные медленно выбираются. Как только выбрал все, по программно формируемому сигналу сброса память снова начинает заполняться. Т.е. процесс записи и чтения во времени строго разделены, одновременного чтения и записи одного адреса НЕТ. Ошибки в логике построения записи-чтения нет. Ведь иной раз все работает нормально. Меняю что либо в другой части проекта, перекомпилирую и ВСЕ глюки и не работает.

Цитата(Golikov A. @ Sep 17 2015, 09:52) *
в том что скачиваться данные из памяти могут на одном клоке, а отправляться на другом. Среда следит чтобы данные выставляемые по переднему фронту первого клока, были валидны к следующему переднему фронту (констраины только на период), Но среда совершенно не следит чтобы они были валидны к фронту того клока по которому они отправляются.
В случае фифо данные, наверняка забираются по фронту по которому отправляются и там среда опять следит.

Но это все предположения, правду от нас скрываютsm.gif


Высказывается много предположений почему не работает. Подскажите что делать чтоб работало.
Golikov A.
Цитата
Еще раз. В память данные пишутся на 200 МГц

как они из памяти читаются.
Приведите кусок кода.

Цитата
Подскажите что делать чтоб работало.

если правильно угадали почему не работает, то нужно описать констрейны и доделать междоменный переход
Anton1990
Цитата(Golikov A. @ Sep 17 2015, 11:22) *
как они из памяти читаются.
Приведите кусок кода.

если правильно угадали почему не работает, то нужно описать констрейны и доделать междоменный переход

Ниже привожу полный текст модуля. Критикуйте. А лучше исправляйте. Подсказывайте.

entity MemSV_vhdl is
generic (Nbit : integer := 16;
N : integer := 65536;
BitSignal : integer := 16
);
Port ( I : in STD_LOGIC_VECTOR (BitSignal-1 downto 0);
clk : in STD_LOGIC;
reset : in STD_LOGIC;
rd : in STD_LOGIC;
DO : out STD_LOGIC_VECTOR (31 downto 0);
full : out STD_LOGIC);
end MemSV_vhdl;

architecture Behavioral of MemSV_vhdl is

type TMemory is array (0 to N-1) of std_logic_vector(BitSignal-1 downto 0);
signal Mem : TMemory;
signal Ard, Awr: std_logic_vector(Nbit-1 downto 0);
signal ce, q_thres : std_logic;
signal bufDO : std_logic_vector(2*BitSignal-1 downto 0);
signal bufI : std_logic_vector(BitSignal-1 downto 0);
begin
process (clk, Reset, rd)
begin
if clk'event and clk='1' then
bufI <= I; --просто регистр на входе
end if;
if Reset='1' then
Awr <= Conv_Std_Logic_Vector(0, Nbit); --если сброс то обнуляет счетчик адреса записи
q_thres <= '0';
else
if clk'event and clk='1' and ce='1' then
Awr <= Awr + 1;
if Awr=Conv_Std_Logic_Vector(N-1, Nbit) then
q_thres <='1';
end if;
end if;
end if;
ce <= not q_thres; --останавливаем запись когда заполниться память
full <= q_thres; --тут все и так понятно

if clk'event and clk='1' and q_thres='0' then
Mem(conv_integer(Awr))(BitSignal-1 downto 0) <= bufI; --собственно заполняем память
end if;
if Reset='1' then
Ard <= Conv_Std_Logic_Vector(0, Nbit); --при сбросе обнуляет счетчик адреса чтения
else
if rd'event and rd='1' then
Ard <= Ard + 2; --адреса преребираем через два т.к. шина PCI 32 разряда
end if;
end if;
if rd'event and rd='1' then
bufDO(15 downto 0) <= Mem(conv_integer(Ard)); --вынимаем из памяти два отсчета данных
bufDO(31 downto 16) <= Mem(conv_integer(Ard+1));
end if;
DO <= bufDO;
end process;
end Behavioral;
Maverick
Цитата(Anton1990 @ Sep 17 2015, 11:36) *
Ниже привожу полный текст модуля. Критикуйте. А лучше исправляйте. Подсказывайте.

entity MemSV_vhdl is
generic (Nbit : integer := 16;
N : integer := 65536;
BitSignal : integer := 16
);
Port ( I : in STD_LOGIC_VECTOR (BitSignal-1 downto 0);
clk : in STD_LOGIC;
reset : in STD_LOGIC;
rd : in STD_LOGIC;
DO : out STD_LOGIC_VECTOR (31 downto 0);
full : out STD_LOGIC);
end MemSV_vhdl;

architecture Behavioral of MemSV_vhdl is

type TMemory is array (0 to N-1) of std_logic_vector(BitSignal-1 downto 0);
signal Mem : TMemory;
signal Ard, Awr: std_logic_vector(Nbit-1 downto 0);
signal ce, q_thres : std_logic;
signal bufDO : std_logic_vector(2*BitSignal-1 downto 0);
signal bufI : std_logic_vector(BitSignal-1 downto 0);
begin
process (clk, Reset, rd)
begin
if clk'event and clk='1' then
bufI <= I; --просто регистр на входе
end if;
if Reset='1' then
Awr <= Conv_Std_Logic_Vector(0, Nbit); --если сброс то обнуляет счетчик адреса записи
q_thres <= '0';
else
if clk'event and clk='1' and ce='1' then
Awr <= Awr + 1;
if Awr=Conv_Std_Logic_Vector(N-1, Nbit) then
q_thres <='1';
end if;
end if;
end if;
ce <= not q_thres; --останавливаем запись когда заполниться память
full <= q_thres; --тут все и так понятно

if clk'event and clk='1' and q_thres='0' then
Mem(conv_integer(Awr))(BitSignal-1 downto 0) <= bufI; --собственно заполняем память
end if;
if Reset='1' then
Ard <= Conv_Std_Logic_Vector(0, Nbit); --при сбросе обнуляет счетчик адреса чтения
else
if rd'event and rd='1' then
Ard <= Ard + 2; --адреса преребираем через два т.к. шина PCI 32 разряда
end if;
end if;
if rd'event and rd='1' then
bufDO(15 downto 0) <= Mem(conv_integer(Ard)); --вынимаем из памяти два отсчета данных
bufDO(31 downto 16) <= Mem(conv_integer(Ard+1));
end if;
DO <= bufDO;
end process;
end Behavioral;



Описание желает лучшего...
iosifk
Цитата(Anton1990 @ Sep 17 2015, 08:21) *
При использовании FIFO созданного в Coregeneratore результат значительно лучше (практически нет глюков).


Я для таких целей применяю библиотечный компонент Ксайлинкса. Он легко устанавливается в проект и он достаточно описан... Да и текста в проекте значительно меньше...
Про клоки в Вашем тексте все понятно, а вот про rd'event не понятно... Что это? Это частота или внешние сигналы? Для PCI Вы должны иметь их клоки и сигналы чтения. Так вот, сигналы чтения надо применить как "разрешение", а не как тактовые. Иначе и пойдут глюки...
Еще где-то надо учесть латентность...

А еще взять FIFO у которого с одной стороны 16 бит, а с другой 32... Это тоже очень просто...
Maverick
Цитата(iosifk @ Sep 17 2015, 12:06) *
Про клоки в Вашем тексте все понятно, а вот про rd'event не понятно... Что это? Это частота или внешние сигналы? Для PCI Вы должны иметь их клоки и сигналы чтения. Так вот, сигналы чтения надо применить как "разрешение", а не как тактовые. Иначе и пойдут глюки...
Еще где-то надо учесть латентность...

там кроме rd'event
есть еще
if clk'event and clk='1' and q_thres='0' then
if clk'event and clk='1' and ce='1' then

я понимаю что q_thres, се - сигналы разрешения, но нужно соблюдать правила...
Посмотрите как описывается триггер с сигналом разрешения и сбросом

Anton1990
Цитата(iosifk @ Sep 17 2015, 12:06) *
Я для таких целей применяю библиотечный компонент Ксайлинкса. Он легко устанавливается в проект и он достаточно описан... Да и текста в проекте значительно меньше...
Про клоки в Вашем тексте все понятно, а вот про rd'event не понятно... Что это? Это частота или внешние сигналы? Для PCI Вы должны иметь их клоки и сигналы чтения. Так вот, сигналы чтения надо применить как "разрешение", а не как тактовые. Иначе и пойдут глюки...
Еще где-то надо учесть латентность...

А еще взять FIFO у которого с одной стороны 16 бит, а с другой 32... Это тоже очень просто...


Ну с коркой фифо я уже говорил работает лучше. Хочу узнать свои проблемы. Сигнал Rd это клок - по преднему фронту данные выставляются на шину PCI. Как таковой клок шины я не использую.

Цитата(Maverick @ Sep 17 2015, 12:10) *
там кроме rd'event
есть еще
if clk'event and clk='1' and q_thres='0' then
if clk'event and clk='1' and ce='1' then

я понимаю что q_thres, се - сигналы разрешения, но нужно соблюдать правила...

из-за этого и спрашиваю что ТС описал или хотел описать


А что собственно в этих строчках ненравиться? О каких правилах речь?
Maverick
Цитата(Anton1990 @ Sep 17 2015, 12:21) *
А что собственно в этих строчках ненравиться? О каких правилах речь?

пример

Код
-- 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;  

entity flop is  
  port(C, CE, PRE : in std_logic;  
        D : in  std_logic_vector (3 downto 0);  
        Q : out std_logic_vector (3 downto 0));  
end flop;
architecture archi of flop is  
  begin  
    process (C, PRE)  
      begin  
        if (PRE='1') then  
          Q <= "1111";  
        elsif (C'event and C='1')then  
          if (CE='1') then  
            Q <= D;  
          end if;  
        end if;  
    end process;  
end archi;


Вот здесь Вы найдете больше описаний простых элементов цифровой схемы

В Xilinx ISE есть Template Language - посмотрите еще туда...
iosifk
Цитата(Anton1990 @ Sep 17 2015, 12:21) *
Ну с коркой фифо я уже говорил работает лучше. Хочу узнать свои проблемы. Сигнал Rd это клок - по преднему фронту данные выставляются на шину PCI. Как таковой клок шины я не использую.

Тогда и говорить не о чем... Если данные не согласованы с клоком шины PCI, то результат как раз таким и будет...
И еще раз. Я Вам объясняю, что у Ксаййлинкса есть библиотечные компоненты, которые и надо использовать в таких случаях. Без всяких корегенов... А из c:\Xilinx\14.7\ISE_DS\ISE\verilog\src\unisims\..
Anton1990
Цитата(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 ...
или о чем речь?
iosifk
Цитата(Anton1990 @ Sep 17 2015, 15:45) *
Сигнал Rd от шины совершенно непричем. Ведь я его использую и с корегеновской коркой. Да и к томуже если я делаю память не на 65536 отсчетов на например 1024 то проблем никаких не возникает. Как я понимаю проблема имеено в размешении блоков памяти по кристалу при большом используемом количестве. Ну может я, конечно, и ошибась где-то. Но на основе своего опыта (довольно большого) могу сказать что элементы сгенерированные корегеном работаю стабильнее будьто память, простые умножители или фильтры построенные на умножителях. Разумного объяснения у меня этому нет.

У Вас в виртекс 6 есть блоки 32K × 1... Так вот, возьмите две группы по 16 блоков. И каждый блок - подключите к одному биту данных... По входу данные от АЦП подать параллельно на обе группы, а выбор группы определять по сигналу разрешение записи. А его взять от старшего разряда счетчика.
Теперь по выходу FIFO... Поскольку по чтению вообще спешить некуда, то можно блоки прицепить к 32 битам а при чтении учитывать старшее или младшее слово...
Или так...
учитывая, что чтение идет медленно, то модно сделать и мультиплексор по выходу... Или же брать FIFO с разрядностью 1 на входе и 2 на выходе...
При таком раскладе точно не будет мультиплексоров по данным на входе, а значит, что легче будет развести проект по кристаллу.
И скорее всего визард так и делает. А компилятор - нет. Посмотрите, что получается после компиляции - оптимизации...
Вот потому я всегда такие вещи делаю сам...
А если совсем честно, то тут не нужно FIFO, а нужна обычная память с шинами на запись и на чтение... И с одним клоком на 200 Мгц... весь проект сделать на этой частоте.
А клок от PCI можно привести к клоку 200 Мгц.
Maverick
Цитата(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
Anton1990
Цитата(Maverick @ Sep 17 2015, 16:06) *
я намекаю на
Код
if (C'event and C='1')then  
          if (CE='1') then

А есть разница ?
Maverick
Цитата(Anton1990 @ Sep 17 2015, 16:12) *
А есть разница ?

есть
Golikov A.
есть, потому что синтезаторы анализирует текст на поиск известных им конструкций, с обще принятым описанием. Записав их по другому вы просто мешаете синтезатору понимать что вы хотели. Тут не как в С, тут не компилируется каждый оператор, тут все сложнее...
Anton1990
Цитата(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) *
есть, потому что синтезаторы анализирует текст на поиск известных им конструкций, с обще принятым описанием. Записав их по другому вы просто мешаете синтезатору понимать что вы хотели. Тут не как в С, тут не компилируется каждый оператор, тут все сложнее...


Ну то что здесь все сложнее я знаю, но нужно попробовать исправить и посмотреть. А так вообще спасибо. Если Вы правы то мне много придется исправлять.
Golikov A.
строго говоря я думаю что именно в этом случае синтезатор разберется и так и сяк, они все умнее и умнее становятся. Но на всякий случай проверить стоит.

И по сути проблемы, какой клок на PCI по которому уходят данные?
Anton1990
Цитата(Golikov A. @ Sep 17 2015, 16:59) *
строго говоря я думаю что именно в этом случае синтезатор разберется и так и сяк, они все умнее и умнее становятся. Но на всякий случай проверить стоит.

И по сути проблемы, какой клок на PCI по которому уходят данные?


А что значит какой клок на PCI? Это сигнал чтения который поступает в мою ПЛИС от контроллера PCI. По этому сигналу я выбираю данные из памяти на выходную шину и им же открываю выходной bufe. А уже на самой шине PCI данные защелкиваются натуральным клоком от PCI (но это меня уже не касается). У меня в проекте целая куча регистров читается таким образом. Вообще схема отработанная годами. Память в плис с точки зрения логики ее чтения ничем не отличается от большой кучи регистров. А следовательно проблема в правильной записи в эти ''регистры''.
Golikov A.
Цитата
Вообще схема отработанная годами. Память в плис с точки зрения логики ее чтения ничем не отличается от большой кучи регистров. А следовательно проблема в правильной записи в эти ''регистры''.

то есть у вас все работает и проблем никаких нет, да?

наводящий вопрос
Как вы думаете регистр состоящий из Д триггеров, который может быть размещен в любом месте плис и ячейка памяти расположенная в блоке, с адресацией, имеют одинаковое время распространения сигнала от них до точки где данные захлопнуться?
Как вы думаете может такое получиться что вы выставите желаемый адрес по которому хотите считать данные так близко к моменту защелкивания данных, что не все сигналы успели дойти до регистра защелкивающего данные в другой части ПЛИС, к фронту клока управляющего этим регистром?
iosifk
Цитата(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'" при том, что больше клоков то нет.... Только один этот фронт...
Т.е. это скорее всего счетчик, который идет на младшее слово. А с него же адрес идет на сумматор, и после сумматора на старшее??? Или это действительно две ячейки памяти и по выходу мультиплексор?

И если сравнивать с регистрами, то память медленнне раза в два....
Anton1990
Цитата(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 раза медленнее ну и пофиг. НО общая проблема осталась.
Golikov A.
Цитата
Если частота выставления адреса чтения очень низкая, то проблем быть не должно. Наверное.


Возможно у вас клоком памяти как раз становиться rd сигнал, клоком второго порта, надо поглядеть разводку.

тогда у вас цепочка действий

- по сигналу rd защелкиваем в выходной регистр памяти данные по заданному адресу
- по какому-то внутреннему вам не известному клоку данные с памяти защелкнули на отправку.

эту цепочку можно повторять часто, редко, можно 1 раз и поймать ошибку, важно сколько времени проходит между rd и внутренним клоком, может так оказаться что данные просто не успевают выбраться из памяти и дойти до момента их захвата. Из регистров это все значительно быстрее, а в ФИФО данные к моменту забора на выходе уже готовы.
Maverick
Цитата(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 клока для входа и выхода).
Krys
Цитата(Anton1990 @ Sep 17 2015, 20:48) *
Тут мне указывают на неправильность конструкций if then.. Если это действительно неправильно то нужно исправить и посмотреть на результат. Я, конечно, давно знаю что VHDL довольно геморойная вешь как бы лесно его не описывали, но это для меня открытие.
Да тут не в языке особо дело, а в синтезаторе. На верилоге тоже подобные вещи в 2 оператора записывать принято, так же, как и в VHDL.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.