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

 
 
 
Reply to this topicStart new topic
> DMA: Verilog->Nios
Veg@
сообщение Mar 31 2010, 16:42
Сообщение #1


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

Группа: Участник
Сообщений: 90
Регистрация: 16-09-09
Пользователь №: 52 416



Начинаю изучать работу с DMA для дальнейшего его применения в качестве способа передачи больших объемов данных из Verilog-модуля в Nios. Подскажите с чего начать, какие посоветуете источники информации по этой теме (сам я ничего подходящего не нашел) и/или, желательно, примеры реализации на Verilog+C? Спасибо.

Сообщение отредактировал Veg@ - Mar 31 2010, 16:43
Go to the top of the page
 
+Quote Post
arexol
сообщение Mar 31 2010, 17:39
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 317
Регистрация: 25-09-06
Пользователь №: 20 651



Цитата(Veg@ @ Mar 31 2010, 19:42) *
Начинаю изучать работу с DMA для дальнейшего его применения в качестве способа передачи больших объемов данных из Verilog-модуля в Nios. Подскажите с чего начать, какие посоветуете источники информации по этой теме (сам я ничего подходящего не нашел) и/или, желательно, примеры реализации на Verilog+C? Спасибо.


Возможно у Вас не совсем верное представление ...

ДМА это модуль у которого есть мастер чтения и мастер записи
оба мастера должны подлючаться к соотвествующим слейвам.

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

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

Если Вы хотите ускорить доступ к порции данных , например из ДДР, то один из вариантов это выкачать с помощью ДМА из ДДР слейва в ончип память
обработать процессором эту ончип память и опять с помощью ДМА залить в ДДР из ончип памяти.

Суть ускорения в том что ДДР будет работать в бурст режиме , а не в рандом.
И когда мастрер данных процессора будет читать из ончип в рандоме то это всёравно как из кеша читать\писать.
Go to the top of the page
 
+Quote Post
Veg@
сообщение Mar 31 2010, 19:05
Сообщение #3


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

Группа: Участник
Сообщений: 90
Регистрация: 16-09-09
Пользователь №: 52 416



2 arexol
Уточню: Verilog-код, как я понимаю, находится в ПЛИС, код на C - в sdram. Каким образом я могу обратиться из программы на C (код для Nios) к Verilog-буферу, состоящему из регистров, и нужно ли вообще для этого его предварительно скопировать из ПЛИС, например, в тот же sdram?

Сформулирую свой вопрос по-другому:
Нужно реализовать такую программу (псевдокод):
Код
Старт копирования данных из буфера, размещенного в памяти ПЛИС (регистр Verilog)

while(пока не скопировались данные)
выполнение полезной работы;

Обработка скопировавшихся данных

т.е. обычный асинхронный запрос к памяти, выполняющийся параллельно с основным потоком программы. Корректно ли для этого использовать DMA? В какую сторону копать? Спасибо.

Сообщение отредактировал Veg@ - Mar 31 2010, 19:07
Go to the top of the page
 
+Quote Post
vadimuzzz
сообщение Apr 1 2010, 02:33
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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 очень важно следить, чтобы они не вылезали за границы, если они имеют доступ на запись.
Go to the top of the page
 
+Quote Post
arexol
сообщение Apr 1 2010, 16:39
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Veg@
сообщение Apr 8 2010, 19:05
Сообщение #6


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

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
vadimuzzz
сообщение Apr 9 2010, 01:18
Сообщение #7


Гуру
******

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



1. делать так можно, но это не айс. в данном случае лучше использовать memory to memory транзакции. тогда адреса сами будут инкрементиться.
2. похоже на фокусы с data cache. попробуйте воткнуть alt_dcache_flush_all() в функцию done().
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 08:57
Рейтинг@Mail.ru


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