|
|
  |
DMA: Verilog->Nios |
|
|
|
Mar 31 2010, 17:39
|
Местный
  
Группа: Свой
Сообщений: 317
Регистрация: 25-09-06
Пользователь №: 20 651

|
Цитата(Veg@ @ Mar 31 2010, 19:42)  Начинаю изучать работу с DMA для дальнейшего его применения в качестве способа передачи больших объемов данных из Verilog-модуля в Nios. Подскажите с чего начать, какие посоветуете источники информации по этой теме (сам я ничего подходящего не нашел) и/или, желательно, примеры реализации на Verilog+C? Спасибо. Возможно у Вас не совсем верное представление ... ДМА это модуль у которого есть мастер чтения и мастер записи оба мастера должны подлючаться к соотвествующим слейвам. Процессор это модуль у которого есть мастер чтения инструкций и мастер данных который может либо читать из слейва либо писать в слейв. т.е говорить о том что передавать данные из верилог модуля(я так понимаю слейва) в процессор - некорректно, так как процессор не является слейвом. Если Вы хотите ускорить доступ к порции данных , например из ДДР, то один из вариантов это выкачать с помощью ДМА из ДДР слейва в ончип память обработать процессором эту ончип память и опять с помощью ДМА залить в ДДР из ончип памяти. Суть ускорения в том что ДДР будет работать в бурст режиме , а не в рандом. И когда мастрер данных процессора будет читать из ончип в рандоме то это всёравно как из кеша читать\писать.
|
|
|
|
|
Mar 31 2010, 19:05
|
Частый гость
 
Группа: Участник
Сообщений: 90
Регистрация: 16-09-09
Пользователь №: 52 416

|
2 arexol Уточню: Verilog-код, как я понимаю, находится в ПЛИС, код на C - в sdram. Каким образом я могу обратиться из программы на C (код для Nios) к Verilog-буферу, состоящему из регистров, и нужно ли вообще для этого его предварительно скопировать из ПЛИС, например, в тот же sdram? Сформулирую свой вопрос по-другому: Нужно реализовать такую программу (псевдокод): Код Старт копирования данных из буфера, размещенного в памяти ПЛИС (регистр Verilog)
while(пока не скопировались данные) выполнение полезной работы;
Обработка скопировавшихся данных т.е. обычный асинхронный запрос к памяти, выполняющийся параллельно с основным потоком программы. Корректно ли для этого использовать DMA? В какую сторону копать? Спасибо.
Сообщение отредактировал Veg@ - Mar 31 2010, 19:07
|
|
|
|
|
Apr 1 2010, 02:33
|

Гуру
     
Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988

|
Цитата(Veg@ @ Apr 1 2010, 01:05)  т.е. обычный асинхронный запрос к памяти, выполняющийся параллельно с основным потоком программы. Корректно ли для этого использовать DMA? да, корректно. для этого нужно оснастить verilog-модуль 2-мя интерфейсами Avalon: Avalon-MM-мастер(для доступа к памяти), Avalon-MM-слейв (чтобы NIOS мог управлять модулем и следить за его состоянием). соответственно читать: http://www.altera.com/literature/manual/mnl_avalon_spec.pdf + посмотреть пример http://www.altera.com/support/examples/nio...celeration.html. для устройств с DMA очень важно следить, чтобы они не вылезали за границы, если они имеют доступ на запись.
|
|
|
|
|
Apr 1 2010, 16:39
|
Местный
  
Группа: Свой
Сообщений: 317
Регистрация: 25-09-06
Пользователь №: 20 651

|
Ваш верилог модуль из которого можно прочитать процессором что либо должен иметь слейв интерфейс (читайте спецификацию). Грубо говоря это набор сигналов и правил для этих сигналов. простой слейв будет выгляеть примерно вот так Код module MyModule ( input clk; input reset; input chipselect; input read; input [3:0] adress; output reg [31:0] readdata; input write; input [31:0] writedata; );
reg [31:0] buffer;
always @(posedge clk or posedge reset ) begin if (reset) begin readdata<=0; buffer<=5; end else begin if (chipselect & write) begin buffer<=writedata; // writing end if (chipselect & read) begin if (adress==2) readdata<=buffer; else readdata<=0; end end end
endmodule обратите внимание на адрес - 5 бит в соотв разрядности будет выделено адресное пространство когда Вы сделаете указатель на это адресное пространство в Си коде то при чтении или записи по этому указателю будет инициироваться транзакция чтения или записи мастером данных процессора ну и вот если вы запишете в это адресное пространство число то оно попадёт в регистр буффер чтобы считать записанное значение надо будет потом обратиться к адресу базовый + 2 ps. если есть ошибки то прошу прощения - не компилировал вот нашёл ещё мелкий слейв для учебных целей Код module MyModule( clk, chipselect, reset, address, read, readdata, write, writedata, irq
);
input clk; input chipselect; input reset; input [3:0]address; input read; output [31:0]readdata; reg [31:0]readdata; input write; input [31:0]writedata; output irq; reg irq; // internal regs reg [31:0]reg0; reg [31:0]reg1; reg [31:0]reg2; reg [31:0]reg3;
always @(posedge clk or posedge reset) begin if(reset) begin irq<=1'b0; readdata<=32'b0; reg0=32'd0; reg1=32'd1; reg2=32'd2; reg3=32'd3; end else begin
if (chipselect & read) // ANALON READING TO CPU case (address) 4'd0: readdata<=reg0; 4'd1: readdata<=reg1; 4'd2: readdata<=reg2; 4'd3: readdata<=reg3; endcase
if (chipselect & write) //AVALON WRITING FROM CPU case(address) 4'd0: reg0<=writedata; 4'd1: reg1<=writedata+reg0; 4'd2: reg2<=writedata-reg1; 4'd3: reg3<=writedata*reg2; endcase
if (reg0==32'd12) // IRQ PROCESSING irq<=1; else irq<=0;
end end
endmodule
|
|
|
|
|
Apr 8 2010, 19:05
|
Частый гость
 
Группа: Участник
Сообщений: 90
Регистрация: 16-09-09
Пользователь №: 52 416

|
1. Понемногу разбираюсь с DMA. Инициализировал прием следующим образом: Код rxchan = alt_dma_rxchan_open("/dev/dma"); alt_dma_rxchan_ioctl(rxchan, ALT_DMA_RX_ONLY_ON, (void *)(TEST_COMPONENT_BASE); alt_dma_rxchan_ioctl(rxchan, ALT_DMA_SET_MODE_32, NULL); alt_dma_rxchan_prepare (rxchan,rx_buffer,16,done,NULL); В результате происходит чтение по адресу TEST_COMPONENT_BASE с нулевым смещением. Т.е., насколько я понял, для того, чтобы принять из этого компонента объем данных >4Б (напр., массив регистров), необходимо в нем хранить указатель на следующую порцию отправляемых данных и после каждой отправки 4Б увеличивать его соответственно на 4Б. Думаю, это будет работать, но верное и стандартное ли это решение? (все примеры, которые я рассматривал, принимали данные в компонент по DMA, но не отправляли). 2. Реализованный мной пример чтения данных из TEST_COMPONENT верно работает при их копировании в onchip_memory. Мне же, в конечном итоге, нужно их доставить в SDRAM, где находится программа на Си. В приведенном ниже коде я попытался это реализовать, но данные в массив data не попадают. В чем ошибка: в коде или SOPC ?  Код #include <stdio.h> #include <stdlib.h> #include <sys/alt_dma.h> #include "system.h" #include "io.h"
static volatile int rx_done = 0; alt_dma_txchan txchan; alt_dma_rxchan rxchan; int rc; static void done (void* handle, void* data) { rx_done++; }
void init_dma() { if ((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL) { printf ("Failed to open the DMA transmit channel\n"); exit(1); } if ((rc = alt_dma_rxchan_ioctl(rxchan, ALT_DMA_RX_ONLY_ON, (void *)(TEST_COMPONENT_BASE))) < 0) { printf ("Failed to set the DMA channel to transmit only, reason = %i\n", rc); exit(1); } if ((rc = alt_dma_rxchan_ioctl(rxchan, ALT_DMA_SET_MODE_32, NULL)) < 0) { printf ("Failed to set the DMA channel to word access, reason = %i\n", rc); exit(1); } }
int main() { unsigned long data[7]; void* rx_buffer = data;
init_dma(); if ((rc = alt_dma_rxchan_prepare (rxchan,rx_buffer,4,done,NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); }
while (!rx_done);
printf ("\nTransfer successful!\n"); printf ("0x%X\n0x%X\n0x%X\n0x%X\n",data[0],data[1],data[2],data[3]); return 0; }
Сообщение отредактировал Veg@ - Apr 8 2010, 19:15
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|