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

 
 
> Чтение/Запись из HPS в FPGA и наоборот
chipmasta
сообщение Nov 13 2017, 19:18
Сообщение #1





Группа: Участник
Сообщений: 6
Регистрация: 13-11-17
Пользователь №: 100 178



Всем привет! Я только начал вникать в мир ПЛИС но столкнулся со слишком уж большим количеством входных данных) Сам программист, решил вот с железом "пообщаться"
Задача стоит, как мне казалась простая - из HPS записать данные в RAM FPGA, в FPGA эти данные прочитать, и записать туда же в RAM "ответ".
Имеем : De0 Nano SoC, за основу взять проект который идёт в комплекте GHRD. Квартус 17.
Смотрим в Qsys, там уже имеется блок onchip_memory2_0, который даст нашему HPS доступ к RAM. С этим доступом вроде как всё ясно - в Си приложении работаем с /dev/mem, базовый адрес у нас по 0xC0000000. И действительно - работает. Если в блоке onchip_memory2_0 постаивть галочку "доступно для In-System memory Editor" то можно посмотреть этот RAM, увидеть и изменения сделанные со сторны HPS. Здесь всё хорошо.
А вот с чтением этих байтов в ПЛИС у меня полный ступор, от слова совсем) Я нашел в soc_system.v (который я так понял генерится из Qsys) как инстанцируется модуль onchip_memory2_0. Дальше что?

Я пробовал инстанцировать свой onchip_memory2_0 и даже записать туда данные -

Код
soc_system_onchip_memory2_0 m(.address(0)
, .byteenable(4'b1111)
, .chipselect(1)
, .clk(FPGA_CLK1_50)
, .clken(1'b1)
, .reset(hps_fpga_reset_n)
, .reset_req(1'b0)
, .write(1'b1)
, .writedata(32'hF0F0F0F0)
, .readdata(datain)
);


в таком случае я вижу два инстанса в эдиторе, и даже вижу записанные байты, НО к этому инстансу не могу достучаться из HPS...

Люди добрые, подскажите, как реализовывать в Верилоге... как будет выглядеть код который запишет/прочитает данные в этот, доступный для HPS, RAM ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Golikov A.
сообщение Nov 14 2017, 06:46
Сообщение #2


Гуру
******

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



Цитата
в блоке always плис мониторит флаг впамяти, назовём его requestReady

Эта фраза выдает что вы немного не понимаете как оно все устроено. Блок алвайс в плис это не совсем while в С.

В целом кроме памяти в ПЛИС есть еще и регистры, которые для проца выглядят как память, а для плис как удобные сигналы, но это детали.
Попробуем поработать с решением в вашей постановке.

Вам нужен конечный автомат FSM по буржуйски. У него должны быть состояния
IDLE - в этом состоянии ПЛИС читает ячейку памяти с флагом и если видит флаг переходит в READ
READ - в этом состоянии плис перебирает адреса памяти, чтобы на шине появлялись данные, которые забирает блок обработки. Прочитав нужное количество переходит в PROCESS
PROCESS - в этом состоянии плис ждет когда блок обработки закончит обработку и сформирует ответ. Дождавшись переходит в WRITE
WRITE - в этом состоянии плис перебирает адреса для записи памяти, а блок обработки отдает данные, они попадаю в память. Записав нужное количество плис переходит в DONE
DONE - в этом состоянии плис ставит флаг готовности данных, записывает его в нужную ячейку памяти и переходит в IDLE

Конечный автомат описывается так.

Код
localparam IDLE = 0;
localparam READ = 1;
....

always @(posedge clk)
begin
   if(reset) State <= IDLE;
   else State <= NextState;
end

always @(*)
begin
  if((State == IDLE) && (requestReady == 1'b1))         NextState = READ;
  if((State == READ) && (RCounter == 0))                  NextState = PROCESS;
  if((State == PROCESS) && (ProcessDone == 1'b1))   NextState = WRITE;
  if((State == WRITE) && (WCounter == 0))               NextState = DONE;
  if(State == DONE)                                                   NextState = IDLE;
end


выше приведенный код ходит по состояниям, переводя автомат из одного в другое. Теперь вам надо описать действия внутри этих состояний, например

Код
always @(posedge clk)
begin
if(State == IDLE)
    begin
      MemAddr <= FlagAddr;
      if(MemAddr == FlagAddr)
        requestReady <= MemData[0];
      RCounter <= 10;
      WCoutner <= 10;
    end
end

always @(posedge clk)
begin
if(State == READ)
    begin
      MemAddr <= MemAddr  + 1'b1;
      RCounter <= RCounter  - 1'b1;
    end
end


и так далее...


Обратите внимание что часто нужны какие-то однобитные сигналы, желательно появляющиеся сразу, без необходимости что-то делать, выставлять адрес и так далее... Поэтому обычно это решают не через память, а через регистры. Делают блок который висит на вашей шине и когда видит обращение по определенному адресу сохраняет данные с шины в регистры, которые доступны другим блокам как сигналы или команды. В ПЛИС все происходит параллельно и у нее есть альтернативные варианты хранения нежели память, нет абсолютно никакой необходимости вести управляющий обмен через блоки памяти.

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



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

 


RSS Текстовая версия Сейчас: 25th July 2025 - 17:49
Рейтинг@Mail.ru


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