Перейти к содержанию
    

Nios II обращение к внешней памяти как к массиву

Доброго времени суток.

В процессе работы возник следующий вопрос:

В квартусе создаю Simple Dual-Port RAM (dual clock), прямо из темплейта.

 

-- Quartus II VHDL Template
-- Simple Dual-Port RAM with different read/write addresses and
-- different read/write clock

library ieee;
use ieee.std_logic_1164.all;

entity simple_dual_port_ram_dual_clock is

generic 
(
	DATA_WIDTH : natural := 32;
	ADDR_WIDTH : natural := 6
);

port 
(
	rclk	: in std_logic;
	wclk	: in std_logic;
	raddr	: in natural range 0 to 2**ADDR_WIDTH - 1;
	waddr	: in natural range 0 to 2**ADDR_WIDTH - 1;
	data	: in std_logic_vector((DATA_WIDTH-1) downto 0);
	we		: in std_logic := '1';
	q		: out std_logic_vector((DATA_WIDTH -1) downto 0)
);

end simple_dual_port_ram_dual_clock;

architecture rtl of simple_dual_port_ram_dual_clock 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;

-- Declare the RAM signal.	
signal ram : memory_t;

begin

process(wclk)
begin
if(rising_edge(wclk)) then 
	if(we = '1') then
		ram(waddr) <= data;
	end if;
end if;
end process;

process(rclk)
begin
if(rising_edge(rclk)) then 
	q <= ram(raddr);
end if;
end process;

end rtl;

 

Запись в память производит отдельный автомат со своим клоком.

Есть ли возможность подключить память к процессору таким образом, чтобы объявить ее обычным const unsigned int ARRAY[2**ADDR_WIDTH - 1] и читать из нее как из обычного массива?

Моя цель - это отдельный сбор данных с АЦП в память в хардваре, и отдельная асинхронная математическая обработка этих же данных в софтваре.

Изменено пользователем Dootch

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В квартусе создаю Simple Dual-Port RAM (dual clock), прямо из темплейта.

как показала практика фигово он это создает, лучше явно через мегафункцию описать....

 

Есть ли возможность подключить память к процессору таким образом, чтобы объявить ее обычным const unsigned int ARRAY[2**ADDR_WIDTH - 1] и читать из нее как из обычного массива?

можно. Надо 1 подключить эту память к шине через подходящий переходник (это должен быть готовый модуль).

Переходник выделит вашей памяти адресное пространство и дальше у вас 2 пути

1. это создать указатель unsigned int *MyPointer = MEM_ADDR; и обращаться в память через MyPointer = 10 или *MyPointer = 10; *(MyPointer + i) = 10;

2. это создать переменную массив, и договориться с линкером чтобы он ее разместил точно в этой памяти, тогда будет точно ваш вариант const unsigned int ARRAY[2**ADDR_WIDTH - 1], как в ниосе договариваться с линкером надо читать.... но это уже нюансы.

 

То есть основная ваша задача это через переходник подключить память к шине и выдать ей адресное пространство.

 

Но по мне это надо делать со стороны НИОСА, то есть делать модуль памяти для него через встроенный IP core генератор (или как там он у квартуса называется), а уж потом к нему цеплятся периферией, может даже через еще какие то стандартные блоки...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

можно. Надо 1 подключить эту память к шине через подходящий переходник (это должен быть готовый модуль).

Переходник выделит вашей памяти адресное пространство и дальше у вас 2 пути

1. это создать указатель unsigned int *MyPointer = MEM_ADDR; и обращаться в память через MyPointer = 10 или *MyPointer = 10; *(MyPointer + i) = 10;

2. это создать переменную массив, и договориться с линкером чтобы он ее разместил точно в этой памяти, тогда будет точно ваш вариант const unsigned int ARRAY[2**ADDR_WIDTH - 1], как в ниосе договариваться с линкером надо читать.... но это уже нюансы.

 

То есть основная ваша задача это через переходник подключить память к шине и выдать ей адресное пространство.

 

Но по мне это надо делать со стороны НИОСА, то есть делать модуль памяти для него через встроенный IP core генератор (или как там он у квартуса называется), а уж потом к нему цеплятся периферией, может даже через еще какие то стандартные блоки...

 

Спасибо за разъяснение, думаю вариант со стороны Nios действительно лучше. Нашел на альтеровском форуме вот это. Думаю как раз похожий случай.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спустя 2 года опять вернулся к вопросу.

 

Собрал процессор. Помимо on_chip memory для данных и кода добавил еще один модуль test_onchip на 4096 байт с параметрами, приведенными на картинке.

image.png

 

В получившемся модуле имеется 2 Avalon MM Slave интерфейса, 2 клока и 2 резета.

 

Один интерфейс я подключаю к CPU, второй экспортирую.

 

Таким образом, собранный процессор содержит следующие порты:

 

test_onchip_s2_address : in std_logic_vector(11 downto 0); -- address

test_onchip_s2_chipselect : in std_logic; -- chipselect

test_onchip_s2_clken : in std_logic; -- clken

test_onchip_s2_write : in std_logic; -- write

test_onchip_s2_readdata : out std_logic_vector(7 downto 0); -- readdata

test_onchip_s2_writedata : in std_logic_vector(7 downto 0); -- writedata

test_onchip_clk2_clk : in std_logic; -- clk

test_onchip_reset2_reset : in std_logic; -- reset

test_onchip_reset2_reset_req : in std_logic; -- reset_req

 

Правильно ли я понимаю, если теперь какой-либо мой аппаратный модуль запишет данные по адресу от 0 до 4095 через экспортированный интерфейс, то в коде процессора я смогу к ним обращаться как к переменной?

 

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Правильно ли я понимаю, если теперь какой-либо мой аппаратный модуль запишет данные по адресу от 0 до 4095 через экспортированный интерфейс, то в коде процессора я смогу к ним обращаться как к переменной?

Именно "как с переменной", строго говоря, нет. Т.к. размещением переменных в памяти занимается линкер, а тут у вас адрес фиксируется в момент генерации в QSys. Но если имеется в виду "завести в коде указатель на подходящий тип, нацелить его руками на соотв. адрес, а затем читать данные по указателю, используя в том числе оператор [] или поля структур", то таки да.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Именно "как с переменной", строго говоря, нет. Т.к. размещением переменных в памяти занимается линкер, а тут у вас адрес фиксируется в момент генерации в QSys. Но если имеется в виду "завести в коде указатель на подходящий тип, нацелить его руками на соотв. адрес, а затем читать данные по указателю, используя в том числе оператор [] или поля структур", то таки да.

 

Такой вариант подходит. Вот только экспортированный интерфейс кажется оказался не так прост.

Попытался повесить на

входы test_onchip_s2_chipselect, test_onchip_s2_clken, test_onchip_s2_write единицу

на test_onchip_s2_address выставил ноль

на test_onchip_s2_writedata подал 0xAA

после чего дернул клоком test_onchip_clk2_clk

 

В ниосе память после этоо все равно пустая. test_onchip_reset2_reset пробовал задавать и прямой и инверсный.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Такой вариант подходит. Вот только экспортированный интерфейс кажется оказался не так прост.

Попытался повесить на

входы test_onchip_s2_chipselect, test_onchip_s2_clken, test_onchip_s2_write единицу

на test_onchip_s2_address выставил ноль

на test_onchip_s2_writedata подал 0xAA

после чего дернул клоком test_onchip_clk2_clk

 

В ниосе память после этоо все равно пустая. test_onchip_reset2_reset пробовал задавать и прямой и инверсный.

Я бы сказал, что дело не в экспортированном интерфейсе, а в особенности 2-портовой памяти. Конкретно режима "read-during-write". Меня в частности смущает, что по сути у вас транзакция записи бесконечная. Если хочется сделать однократную запись, то дергать надо именно cselect и write, а clock д.б. постоянным. Вообще это можно и без ниоса в моделсиме проверить (2-портовую память).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...