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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> АЦП+FPGA+NIOS
Dootch
сообщение Oct 17 2013, 06:36
Сообщение #1


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

Группа: Свой
Сообщений: 76
Регистрация: 12-02-10
Из: Хабаровск
Пользователь №: 55 441



Доброго времени суток. Прошу посоветовать оптимальный вариант для решения моей задачи.
Имеется 14-битный АЦП ad9649. Данные с АЦП оцифровываются с частотой 5 МГц и поступают на вход ПЛИС. В работе используется отладочная плата altera de0 с Cyclone III на борту. Для выделения полезного сигнала на фоне шума необходимо использовать метод усреднения периодического сигнала (в английской википедии Signal averaging). Период сигнала составляет 100 мс, что требует 500 000 14 битных слов в памяти для записи одной реализации. Усреднение проводится по методу экспоненциального скользящего среднего. Для работы требуется за период 200 нс извлечь из памяти 14-битное слово, сдвинуть его и сложив со вновь поступившими данными записать обратно. Сначала была мысль использовать софт-процессор, который по прерыванию от АЦП будет проводить усреднение и записывать данные в SDRAM память, которая есть на плате. Но оказалось, что на переход к обработке прерывания уходит слишком много времени.
Теперь вот не знаю как подступиться к решению задачи.
Go to the top of the page
 
+Quote Post
lekintr
сообщение Oct 17 2013, 07:12
Сообщение #2


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

Группа: Участник
Сообщений: 112
Регистрация: 10-10-13
Пользователь №: 78 684



Напишите отдельный модуль, который забирает данные с АЦП, обрабатывает их и кладет в свою память. На выходе поставьте FIFO, которое подключено к шине NIOS. Размер FIFO позволит отработать любые разумные задержки, главное чтобы в среднем время чтения из FIFO было меньше времени его заполнения. Задачка несложная..
Go to the top of the page
 
+Quote Post
Dootch
сообщение Oct 17 2013, 08:15
Сообщение #3


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

Группа: Свой
Сообщений: 76
Регистрация: 12-02-10
Из: Хабаровск
Пользователь №: 55 441



Цитата(lekintr @ Oct 17 2013, 10:12) *
Напишите отдельный модуль, который забирает данные с АЦП, обрабатывает их и кладет в свою память. На выходе поставьте FIFO, которое подключено к шине NIOS. Размер FIFO позволит отработать любые разумные задержки, главное чтобы в среднем время чтения из FIFO было меньше времени его заполнения. Задачка несложная..

Правильно ли я вас понял?
Мне надо написать например на VHDL модуль памяти длиной n 14-битных слов в который будут записываться данные с АЦП. Этот модуль будет промежуточным буфером. Поскольку длина n намного меньше 500000, то модуль будет использовать только внутреннюю память ПЛИС. Вместе с тем, модуль должен быть подключен к софт-процессору с FIFO интерфейсом на борту. В программе софт процессора посредством функций вроде altera_avalon_fifo_read_fifo я смогу быстро читать содержимое буфера и обработав его, писать в SDRAM, подключенную к процессор?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Oct 17 2013, 17:37
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



не селен в альтерах, но по сути
вам предлагают сделать АЦП + модуль первичной обработки, как раз ваше скользящую экспоненту. Результат работы этого модуля - выдавать в ФИФО, а уж оттуда уже забирать процессором и класть в память.


единственное что не понятно зачем для скользящей экспоненты вам хранить n слов, ну если оно так, то да в вашем модуле должен быть 14 битный сдвиговый регистр на n позиций
Go to the top of the page
 
+Quote Post
Andrey S
сообщение Oct 20 2013, 09:52
Сообщение #5





Группа: Новичок
Сообщений: 5
Регистрация: 20-10-13
Пользователь №: 78 808



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

X - вход 500 000 слов
Y - выход 500 000 слов

Y(n) = А*X + (1 - А)*Y(n - 1)

Понятно, что у Cyclone III не хватит внутренней памяти и надо использовать внешнюю.

Почти со 100% уверенностью заявляю, что NIOS не справится с обработкой сигнала с дискретизацией 5МГц. Надо делать хардовую обработку.
В приложении мои мысли на этот счет.

На словах: нужны два компонента (чтения/записи) для доступа к SDRAM через Avalon MM (доступ следует делать с brust), работающих на частоте шины (зеленая рамка),
две FIFO которые развяжут clock АЦП и clock шины, и будут служить буфером для доступа к SDRAM, ну и собственно усредняющий блок, который берет значение с АЦП с
FIFO умножает/складыет и кладет в другое FIFO. Все пишется ручками и вставляется в SoPC, для FIFO берется MegaFunction.


Прикрепленное изображение
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Oct 20 2013, 11:27
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Цитата(Andrey S @ Oct 20 2013, 13:52) *
X - вход 500 000 слов
Y - выход 500 000 слов
Y(n) = А*X + (1 - А)*Y(n - 1)



Прикрепленное изображение


Я вижу что в один момент используется прошлое измерение и текущее. Другими словами не надо хранить 500 000 входных и выходных слов.
надо на лету читать и класть в память. 5 МГц на 100 МГц это 20 тактов, с 1 тактовыми умножителями (пусть с конвеером 3 тактовые) вполне можно уложится. ДСП модули есть в ПЛИС?
Go to the top of the page
 
+Quote Post
Andrey S
сообщение Oct 20 2013, 13:09
Сообщение #7





Группа: Новичок
Сообщений: 5
Регистрация: 20-10-13
Пользователь №: 78 808



Цитата(Golikov A. @ Oct 20 2013, 15:27) *
Я вижу что в один момент используется прошлое измерение и текущее. Другими словами не надо хранить 500 000 входных и выходных слов.
надо на лету читать и класть в память. 5 МГц на 100 МГц это 20 тактов, с 1 тактовыми умножителями (пусть с конвеером 3 тактовые) вполне можно уложится. ДСП модули есть в ПЛИС?

Надо хранить 500 000 выходных слов, X и Y - вектор. Усреднение не между отсчетами, а между векторами,
в Y(n) = a*X + (1 - a)*Y(n - 1) n - индекс вектора(а не отсчета).

А насчет производительности NIOS, нужно пробовать...
Go to the top of the page
 
+Quote Post
Dootch
сообщение Oct 22 2013, 12:07
Сообщение #8


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

Группа: Свой
Сообщений: 76
Регистрация: 12-02-10
Из: Хабаровск
Пользователь №: 55 441



Прикрепленное изображение
Цитата(Andrey S @ Oct 20 2013, 12:52) *
нужны два компонента (чтения/записи) для доступа к SDRAM через Avalon MM (доступ следует делать с brust), работающих на частоте шины (зеленая рамка),
две FIFO которые развяжут clock АЦП и clock шины, и будут служить буфером для доступа к SDRAM, ну и собственно усредняющий блок, который берет значение с АЦП с
FIFO умножает/складыет и кладет в другое FIFO. Все пишется ручками и вставляется в SoPC, для FIFO берется MegaFunction.


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

Мне схема работы видится как на приложенной картинке.
Если кратко:
АЦП пишет данные поочередно в буферы. Выбор буфера осуществляют сигналы заполненности. Буфер представляет собой сдвиговый регистр длиной n слов (на картинке n=1024). После заполнения одного буфера АЦП переключается на другой, а в процессор подается сигнал о готовности порции данных. За время заполнения второго буфера проводится быстрая передача данных в процессор где все аккуратно складывается с усреднением в SDRAM.
Есть ли компонент для быстрой передачи порции данных длиной n слов в процессор?
Могу ли я так рассчитать размер буфера, что времени его заполнения хватит на обработку в софте?
Go to the top of the page
 
+Quote Post
Andrey S
сообщение Oct 22 2013, 18:06
Сообщение #9





Группа: Новичок
Сообщений: 5
Регистрация: 20-10-13
Пользователь №: 78 808



Цитата(Dootch @ Oct 22 2013, 16:07) *
Есть ли компонент для быстрой передачи порции данных длиной n слов в процессор?

Не понимаю, что значит передать порцию данных длиной n слов в процессор... Процессор берет данные из памяти загружает в регистры, выполняет операцию, записывает результат в память.

Вместо памяти он может читать из FIFO, к которой вы сделаете avalon slave интерфейс (без brust, это проще чем мастер, если решитесь - я подскажу).
Прикрепленное изображение

Можно обойтись одним FIFO, скажем 2048 слов, начинаете читать из него когда в нем больше половины заполнено в этом случаи вы гарантировано можете последовательно прочитать 1024 слова не тратя время на опрос на наличие слова в очереди при каждом чтении.

Т.е. описываете устройство с avalon slave интерфейсом для доступа к регистрам, у которого внутри FIFO куда пишутся данные с АЦП.
Мин. набор регистров:
control - здесь либо ресет, либо разрешение на захвата данный с АЦП, чтобы иметь возможность управлять стартом
status - флаг - число слов в очереди больше половины, флаг - очередь заполнена (в этом случаи пиши пропал, проц. не успевает)
read_data - отсюда читается слово из очереди.

В nios примерно след:
CODE

while (1) {
if ( iord(reg_status) & FIFO_FULL ) {
Panik!!!
}

if ( iord(reg_status) & FIFO_HALF_FULL ) {
for ( int i = 0; i < 1024; i++ ) {
int x = iord(reg_read_data);
int y = ...

y = ( a * x + b * y ) >> ...;

y в память...
}
}
}

Если АЦП знаковое расширение знака лучше сделать в хардваре при чтении из FIFO, что бы проц. сэкономить.

Как писалось выше при 100МГц у вас есть 20 тактов на отсчет, что очень немного. Само собой в цикле никаких вызовов функций, принтфов, арифметика целочисленная, полная оптимизация, на SDRAM включенный кэш. Если процессор справится, то никакие другие задачи он уже не потянет. Какова последующая обработка, после фильтрации?...

Цитата(Dootch @ Oct 22 2013, 16:07) *
Могу ли я так рассчитать размер буфера, что времени его заполнения хватит на обработку в софте?

С включенным кэшем при чтении из SDRAM задержка будет только при чтении первого слова, последующие будут в кэше и так каждые 500000. Т.е. длина очереди должна скомпенсировать это время, я думаю что 1024 хватит за глаза.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Oct 22 2013, 20:59
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Не надо хранить 2 вектора по 500 000 слов.

надо читать очередное значение с АЦП, складывать - фильтровать с соотвествующим сохраненным значением, и пихать обратно, но успевать надо за 20 тактов. Боюсь что только выбор данных из памяти и запись обратно сожрет тактов 14, за 6 тактов посчитать умножение и 2 сложения, теоретически возможно, но это реально предел...
Go to the top of the page
 
+Quote Post
Dootch
сообщение Oct 29 2013, 07:36
Сообщение #11


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

Группа: Свой
Сообщений: 76
Регистрация: 12-02-10
Из: Хабаровск
Пользователь №: 55 441



Пошерстил литературу, кажется начинаю разбираться понемногу. Поправьте если ошибаюсь.
Собрал ФИФО в MegaWizard-e. Основные параметры:
2048 слов длиной 14 бит (УГО прикреплено).
Соответственно у меня создался vhd файл с описанием моего ФИФО.
Далее по методу, описанному в ftp://ftp.altera.com/up/pub/Altera_Materi..._components.pdf я прикручиваю к моему ФИФО интерфейс Avalon-ST и создаю на основе своих vhd файлов компонент в SOPC builder или Qsys. Цепляю полученный компонент к соф-процессору, после чего начинается программный прием и обработка как указал Andrey S.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Andrey S
сообщение Oct 29 2013, 18:38
Сообщение #12





Группа: Новичок
Сообщений: 5
Регистрация: 20-10-13
Пользователь №: 78 808



Avalon-ST - это Avalon Streaming Interfaces, нужен Avalon-MM (Memory-Mapped), в помощь Avalon Interface Specifications .
Компонент для SOPC builder или Qsys описывается в *_hw.tcl, рекомендую отказаться от мастера и почитать описание для Qsys.

Как подсказку, даю пример от которого можно отталкиваться (извиняюсь писал без проверки), к компоненту подсоединяется NIOS, внутри 4 регистра: 0 - status (очередь пуста, заполнена, заполнена на половину), при чтении из 1-го происходит чтение из очереди, 2 - тестовый регистр из него всегда читается 0xAAAAAAAA, 3 - тестовый регистр в него можно писать и читать.

test_component будет виден в Qsys с версии 12.0

test_component_hw.tcl
CODE
package require -exact qsys 12.0

#------------------------------------------------------------------------------
# module
#------------------------------------------------------------------------------
set_module_property NAME test_component
set_module_property VERSION 1.0
set_module_property AUTHOR "Andrey S"
set_module_property EDITABLE false
set_module_property HIDE_FROM_SOPC true

#------------------------------------------------------------------------------
# file sets
#------------------------------------------------------------------------------
add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" ""
set_fileset_property QUARTUS_SYNTH TOP_LEVEL test_component_top

add_fileset_file "test_component.vhd" VHDL PATH "test_component.vhd"

#---------------------------------------------------------------------
# Clock & Reset connection points
#---------------------------------------------------------------------
add_interface "clk" clock end
add_interface "reset" reset end
# <interface> <property> <value>
set_interface_property "reset" associatedClock "clk"
set_interface_property "reset" synchronousEdges DEASSERT
# <interface> <port> <type> <dir> <width>
add_interface_port "clk" clk clk Input 1
add_interface_port "reset" reset reset Input 1

#---------------------------------------------------------------------
# AVALON
#---------------------------------------------------------------------
add_interface "csr" avalon slave
# <interface> <property> <value>
set_interface_property "csr" associatedClock "clk"
set_interface_property "csr" associatedReset "reset"
# <interface> <port> <type> <dir> <width>
add_interface_port "csr" bus_address address Input 2
add_interface_port "csr" bus_waitrequest waitrequest Output 1
add_interface_port "csr" bus_readdata readdata Output 32
add_interface_port "csr" bus_read read Input 1
add_interface_port "csr" bus_writedata writedata Input 32
add_interface_port "csr" bus_write write Input 1

test_component.vhd
CODE
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test_component_top is
port (
clk : in std_logic;
reset : in std_logic;
bus_address : in std_logic_vector(1 downto 0);
bus_read : in std_logic;
bus_readdata : out std_logic_vector(31 downto 0);
bus_waitrequest : out std_logic;
bus_write : in std_logic;
bus_writedata : in std_logic_vector(31 downto 0)
);
end entity test_component_top;

architecture rtl of test_component_top is
signal rdreq : std_logic;
signal wrreq : std_logic;
signal rdresp : std_logic;
signal wrresp : std_logic;

-- REGS
constant C_REG_STATUS : natural := 0;
constant C_REG_RDDATA : natural := 1;
constant C_REG_TEST_AA : natural := 2;
constant C_REG_TEST : natural := 3;

signal reg_test : std_logic_vector(31 downto 0);

-- FIFO (need show-ahead)
signal fifo_q : std_logic_vector(13 downto 0);
signal fifo_rdusedw : std_logic_vector(10 downto 0);
signal fifo_rdfull : std_logic;
signal fifo_rdempty : std_logic;
signal fifo_rdreq : std_logic;

begin
process( clk, reset )
begin
if ( reset = '1' ) then
rdreq <= '0';
wrreq <= '0';
state <= ST_WAIT_REQUEST;
elsif rising_edge(clk) then
-- Default
rdreq <= '0';
wrreq <= '0';

-- State
case state is
when ST_WAIT_REQUEST =>
if ( bus_read = '1' ) then
rdreq <= '1';
state <= ST_WAIT_RESPONSE;
elsif ( bus_write = '1' ) then
wrreq <= '1';
state <= ST_WAIT_RESPONSE;
end if;

when ST_WAIT_RESPONSE =>
if ( rdresp = '1' or wrresp = '1' ) then
state <= ST_WAIT_REQUEST;
end if;

when others =>
state <= ST_WAIT_REQUEST;
end case;
end if;
end process;
bus_waitrequest <= ( bus_read or bus_write ) when ( state = ST_WAIT_REQUEST ) else not( rdresp or wrresp );

-- Write
wrresp <= wrreq;

process( clk, reset )
begin
if ( reset = '1' ) then
reg_test <= ( others => '0' );
elsif rising_edge(clk) then
if ( wrreq = '1' ) then
if ( unsigned(bus_address) = C_REG_STATUS ) then
-- Read only
elsif ( unsigned(bus_address) = C_REG_RDDATA ) then
-- Read only
elsif ( unsigned(bus_address) = C_REG_TEST_AA ) then
-- Read only
elsif ( unsigned(bus_address) = C_REG_TEST ) then
reg_test <= bus_writedata;
end if;
end if;
end if;
end process;

-- Read
process( clk, reset )
begin
if ( reset = '1' ) then
rdresp <= '0';
bus_readdata <= ( others => '0' );
elsif rising_edge(clk) then
rdresp <= rdreq;
bus_readdata <= ( others => '0' );
if ( unsigned(bus_address) = C_REG_STATUS ) then
bus_readdata(0) <= fifo_rdempty
bus_readdata(1) <= fifo_rdfull;
bus_readdata(2) <= fifo_rdusedw(fifo_rdusedw'length - 1);
elsif ( unsigned(bus_address) = C_REG_RDDATA ) then
bus_readdata(fifo_q'range) <= fifo_q;
elsif ( unsigned(bus_address) = C_REG_TEST_AA ) then
bus_readdata <= x"AAAA_AAAA";
elsif ( unsigned(bus_address) = C_REG_TEST) ) then
bus_readdata <= reg_test;
end if;
end if;
end process;
fifo_rdreq <= rdreq when ( unsigned(bus_address) = C_REG_RDDATA ) else '0';

end architecture rtl;

успехов...

Сообщение отредактировал Andrey S - Oct 29 2013, 18:40
Go to the top of the page
 
+Quote Post
Dootch
сообщение Oct 30 2013, 10:06
Сообщение #13


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

Группа: Свой
Сообщений: 76
Регистрация: 12-02-10
Из: Хабаровск
Пользователь №: 55 441



Andrey S, большое спасибо за полезную литературу и примеры.
Для проверки быстродействия по примеру, описанному в ftp://ftp.altera.com/up/pub/Altera_Materi..._components.pdf я собрал регистр для чтения и записи с Avalon-MM интерфейсом.
В Eclipse запущен простой код
CODE
int z;
while(1)
{
IOWR(0x11048,0,z);
z++;
}

где по кругу в регистр выводится значение переменной z.
Младший разряд регистра выведен на ногу ПЛИС для мониторинга осциллографом.
При частоте NIOS 100 МГц максимальная частота переключения регистра составляет 1,7 МГц при использовании оптимизации Level 3. Такой частоты явно недостаточно. По моим скромным подсчетам необходима скорость около 7 МГц.
На плате стоит ПЛИС Altera EP3C16F484C6, Speed Grade 6. Пробовал увеличивать частоту работы процессора до 150 и 200 МГц, процессор генерируется, компиляция в Quartus проходит успешно, но запустить код в Eclipse не выходит. Возможно я что-то делаю не так.
Есть ли способ повышения скорости работы процессора?
Возможно есть смысл писать код на ассемблере?
Go to the top of the page
 
+Quote Post
DASM
сообщение Oct 30 2013, 11:10
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Зачем вам программно дергать регистр ? Делайте аппаратно, своим верилог модулем, для чего это ? Повышать не стоит тактовую, нестабилен этот НИОС на таких частотах. На асме писать - тем более. Может Циклон 5 / Zynq 7010/20 поглядеть ?
Go to the top of the page
 
+Quote Post
Dootch
сообщение Oct 30 2013, 11:34
Сообщение #15


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

Группа: Свой
Сообщений: 76
Регистрация: 12-02-10
Из: Хабаровск
Пользователь №: 55 441



Цитата(DASM @ Oct 30 2013, 14:10) *
Зачем вам программно дергать регистр ? Делайте аппаратно, своим верилог модулем, для чего это ? Повышать не стоит тактовую, нестабилен этот НИОС на таких частотах. На асме писать - тем более. Может Циклон 5 / Zynq 7010/20 поглядеть ?

В данном случае я проверяю быстродействие чтения процессором данных из будущего FIFO модуля, то есть вместо IOWR(0x11048,0,z) будет чтение данных и их обработка. Скорость выборки из FIFO должна быть выше скорости записи туда.

Начинаю задумываться о написании аппаратного модуля сбора и обработки данных с последующей записью в SDRAM минуя процессор. Пока трудно оценить трудоемкость такой работы. С SDRAM не дружил пока что.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 29th April 2024 - 01:29
Рейтинг@Mail.ru


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