|
|
  |
Запись по базовому адресу пользовательской логики |
|
|
|
Dec 4 2012, 11:46
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Имеется пользовательская логика с базовым адресом 0x00000010 подключенная к шине Avalon в SOPC с портами Код port ( -- Avalon Slave clk : in std_logic := '0'; -- clock.clk reset_n : in std_logic := '0'; -- .reset_n avs_s0_address : in std_logic_vector(1 downto 0) := (others => '0'); -- s0.address avs_s0_read_n : in std_logic := '0'; -- .read_n avs_s0_write_n : in std_logic := '0'; -- .write_n avs_s0_writedata : in std_logic_vector(15 downto 0) := (others => '0'); -- .writedata avs_s0_byteenable : in std_logic_vector(1 downto 0) := (others => '0'); avs_s0_readdata : out std_logic_vector(15 downto 0); -- .readdata ins_irq0_irq : out std_logic;
-- Avalon Source aso_out0_ready : in std_logic := '0'; -- .ready aso_out0_data : out std_logic_vector(15 downto 0); -- out0.data aso_out0_valid : out std_logic; -- .valid ......................................................и т. д. В пользовательской логике имеется такая конструкция (VHDL) Код process(clk) begin if (falling_edge(clk)) then if(avs_s0_address = "00" and avs_s0_write_n = '0') then if(avs_s0_writedata = "0000000000000001") then s_aso_out0_ready <= '1'; elsif (avs_s0_writedata = "0000000000000000") then s_aso_out0_ready <= '0'; end if; end if; end if; end process; В программе Nios запись для установки s_aso_out0_ready в 1 делаю так Код #define IOWR_ALTERA_AVALON_PUSK(base) IOWR_32DIRECT(base, 0, 0x0001); #define IOWR_ALTERA_AVALON_STOP(base) IOWR_32DIRECT(base, 0, 0x0000);
IOWR_ALTERA_AVALON_PUSK(0x00000010); Delay(0x0002); IOWR_ALTERA_AVALON_STOP(0x00000010); Delay(0x000f); Все работает. Но как теперь сделать то же только по адресу avs_s0_address = "01" ? Не врубаюсь, что теперь нужно менять в IOWR_ALTERA_AVALON_PUSK(base) IOWR_32DIRECT(base, 0, 0x0001); смещение или базовый адрес...или еще как-то
Сообщение отредактировал Acvarif - Dec 4 2012, 11:48
|
|
|
|
|
Dec 5 2012, 12:44
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Dec 4 2012, 18:18)  Используется режим адресации DYNAMIC. Вы пишите 32-битное слово, которое занимает диапазон адресов BASE+0 - BASE+3. Адресация побайтная. Поэтому если вы желаете записать байт BASE+1, то нужно использовать сигнал byteenable[1]. Если нужно смещение + одно 32-битное слово, то нужно записать: IOWR_32DIRECT( base, 4, value ); Не совсем понял avs_s0_writedata : in std_logic_vector(15 downto 0) слово у меня 16 битное Тоесть в моей пользовательской лолгике (с базовым адресом 0x00000010) имеются 4 (четыре avs_s0_address : in std_logic_vector(1 downto 0)) 16 битных регистра. В нулевой регистр все пишется непосредственно по базовому адресу. А как записать данные в первый...третий регистры? Как это будет выглядеть в коде Nios? Цитата Когда с 32 разрядами работаешь, бывает такое. может адреса стоит подцепить к более старшим (кстати а сейчас они куда подцеплены на шине, к а0,а1?) А если все нормально, то адрес выставляете в base+свое значение адреса*4. Короче, лучше выровнять слова по 32-битной (4-х байтной) границе и не морочиться с BE Пользовательский модуль подцеплен к s0.
|
|
|
|
|
Dec 7 2012, 07:43
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Dec 5 2012, 19:47)  Выглядеть будет так: IOWR_16DIRECT( base, reg * 2, val); где номер регистра reg = 0, 1, 2, 3...n reg - 16-битный регистр. Так как адресация процессора всё равно байтовая. В железе младший адрес адресной шины будет выбран автоматически, согласно разрядности шины данных. Поэтому в железе смещение будет на 1. reg0 - 0x00 reg1 - 0x01 reg2 - 0x02 ... Спасибо. Работает. Тоесть чтобы записать данные в пользовательский регистр 01 нужно выполнить IOWR_16DIRECT( base, 2, val); не совсем понятны рассуждения. Команда IOWR_16DIRECT( base, reg * 2, val); пишет данные val в 16 битный регистр по базовому адресу base со смещением относительно базового адреса на reg * 2 Тоесть если бы в пользовательской логике был регистр 8 разрядный то смещение нужно было-бы делать reg * 4 и команда должна быть IOWR_8DIRECT( base, 4, val); . Это верно? Или все же reg + 4, а в предыдущем случае reg + 2?
Сообщение отредактировал Acvarif - Dec 7 2012, 07:57
|
|
|
|
|
Dec 7 2012, 08:30
|
Частый гость
 
Группа: Участник
Сообщений: 190
Регистрация: 7-11-07
Из: С-Петербург
Пользователь №: 32 134

|
Нужно просто уложить в голове, что у процессора адресация всегда побайтная. А вот шина Avalon-MM использует в качестве самого младшего адреса для слейва: 8 бит - A[0] 16 бит - A[1] 32 бит - A[2] Я привел пример для записи в 16-битный слейв, где смещение reg * 2, так как A[0] не используется, а самый младший используемый адрес A[1]. Для 8-битного слейва (reg * 1) т.е. IOWR_8DIRECT( base, reg, val ). Для 32-битного, соответственно (reg *4) т.е. IOWR_32DIRECT( base, reg*4, val). Собственно макросы IOWR_ это ассемблерные команды STBIO, STHIO, STWIO (store byte/halfword/word in IO space) Так яснее?
|
|
|
|
|
Dec 7 2012, 13:07
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Dec 7 2012, 11:30)  Нужно просто уложить в голове, что у процессора адресация всегда побайтная. А вот шина Avalon-MM использует в качестве самого младшего адреса для слейва: 8 бит - A[0] 16 бит - A[1] 32 бит - A[2] Я привел пример для записи в 16-битный слейв, где смещение reg * 2, так как A[0] не используется, а самый младший используемый адрес A[1]. Для 8-битного слейва (reg * 1) т.е. IOWR_8DIRECT( base, reg, val ). Для 32-битного, соответственно (reg *4) т.е. IOWR_32DIRECT( base, reg*4, val). Собственно макросы IOWR_ это ассемблерные команды STBIO, STHIO, STWIO (store byte/halfword/word in IO space) Так яснее? Спасибо. Понятно.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|