|
|
  |
Создание компонета для SOPC Builder с несколькими регистрами ввода/вывода |
|
|
|
Aug 20 2012, 12:35
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Aug 20 2012, 14:48)  Макро IORD(base, n) применяется при адресации типа NATIVE Смотришь через SignalTap? Советую его пользовать. SignalTap загружает проект. Хотелось бы увидеть сигналы вживую. Поставил Код #define IORD_ALTERA_AVALON_RAM_1(base) IORD_16DIRECT(base, 1); В основном цикле просто читаю RAM Код ramres=IORD_ALTERA_AVALON_RAM_1(RAMTEST_0_BASE); Цитата Адрес пользуешь из system.h? Сигнал чтения должен активироваться. Да, адрес компонента (system.h) CODE #define RAMTEST_0_NAME "/dev/ramtest_0" #define RAMTEST_0_TYPE "ramtest" #define RAMTEST_0_BASE 0x00000010 #define RAMTEST_0_SPAN 8 #define RAMTEST_0_TERMINATED_PORTS "" #define ALT_MODULE_CLASS_ramtest_0 ramtest Если у меня на Avalon MM Slave CODE 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_readdata : out std_logic_vector(15 downto 0); -- .readdata 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_chipselect : in std_logic := '0'; -- .chipselect то какой из портов можно наблюдать на осциляторе (если вывести его наружу) при выполнении команды IORD_ALTERA_AVALON_RAM_1(RAMTEST_0_BASE)? Никак не пойму почему простая команда, например IORD_16DIRECT(base, 1) со стороны Nios не активирует ни один из сигналов Avalon MM Slave?
Сообщение отредактировал Acvarif - Aug 20 2012, 12:50
|
|
|
|
|
Aug 20 2012, 14:04
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Aug 20 2012, 16:36)  Вы должны увидеть активацию сигналов avs_s0_read_n (активный 0 ?) и avs_s0_chipselect (активный 1 ?)
Уже при 50MHz тактовой частоты нужен хороший осциллограф, чтобы увидеть импульсы, поэтому я и рекомендовал SignalTap. -------- #define RAMTEST_0_BASE 0x00000010 Подозрительно маленький адрес. Автораспределение адресов в SOPC builder? Можно скриншот системы, c соединениями шин? Понял. Спасибо. Активация имеется. Хорошо, как тогда активировать-деактивировать сигналы программно в цикле? (чтобы увидеть что процесс работает)
С памятью что-то пока не выходит. Попробую создать простой компонент Avalon MM Slave с одним регистром для чтения. При компиляции проекта в Nios создается файл alt_sys_init.c в котором имеется Код ETH_OCM_INSTANCE( ETH_OCM_0, eth_ocm_0 ); ALTERA_AVALON_UART_INSTANCE( UART_0, uart_0 ); ALTERA_AVALON_TIMER_INSTANCE( TIMER_0, timer_0 ); //RAMTEST_INSTANCE( RAMTEST_0, ramtest_0 ); //SD_CONTROLLER_INSTANCE( SD_CONTROLLER_0, sd_controller_0 );
/* * Initialise the devices * */
void alt_sys_init( void ) { ALTERA_AVALON_TIMER_INIT( TIMER_0, timer_0 ); ETH_OCM_INIT( ETH_OCM_0, eth_ocm_0 ); ALTERA_AVALON_UART_INIT( UART_0, uart_0 ); // RAMTEST_INIT( RAMTEST_0, ramtest_0 ); // SD_CONTROLLER_INIT( SD_CONTROLLER_0, sd_controller_0 ); } Строки Код // RAMTEST_INIT( RAMTEST_0, ramtest_0 ); // SD_CONTROLLER_INIT( SD_CONTROLLER_0, sd_controller_0 ); выдают ошибку. Приходся их комментить. Откуда это берется и зачем?
Сообщение отредактировал Acvarif - Aug 20 2012, 14:12
|
|
|
|
|
Aug 20 2012, 17:27
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Aug 20 2012, 19:51)  Вы имеете в виду, что сигналы avs_s0_read_n & avs_s0_chipselect всегда в активном состоянии? Если так, то это неправильно. Может создать простой проект без SD и Ethernet контроллеров и отладить память? Я поторопился. По поводу активации надо будет еще проверить. CD уберу. Ethernet не мешает. Цитата У Вас TimeQuest при компиляции не говорит: "Timing requirements not met."? С этим все впорядке. Код Функции RAMTEST_INIT и SD_CONTROLLER_INIT создаются разработчиком компонентов и относятся к драйверам компонента (каталоги ..\ip\DevName\HAL\inc , ..\ip\DevName\HAL\src) Их наличие или отсутствие задаётся в devname_sw.tcl. Про это есть есть отдельные главы (создание компонентов и драйверов) в документации NiosII Software Developer's Handbook \ Section2 \ SubChapter7 "Developing Device Driver for HAL". Спасибо. Все понятно. Значит перед компиляцией можно закомментить даже в sd_controller_sw.tcl и др. Типа: Код # Initialize the driver in alt_sys_init() # set_sw_property auto_initialize true Попробую упростить компонент и проект...
Сообщение отредактировал Acvarif - Aug 20 2012, 17:29
|
|
|
|
|
Aug 21 2012, 08:07
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Вроде получилось. Для того, чтобы пронаблюдать на осцилляторе сигналы чтения avs_s0_read_n, avs_s0_chipselect пришлось их просто затянуть, примерно так CODE process(clk) begin if (falling_edge(clk)) then if(avs_s0_read_n = '0') then avs_s0_read_n_ext_reg <= '0'; avs_s0_read_n_ext_fl <= '1'; end if; if(avs_s0_read_n_ext_fl = '1') then avs_s0_read_n_ext_cnt <= avs_s0_read_n_ext_cnt + 1; end if; if(avs_s0_read_n_ext_cnt = "11111111") then avs_s0_read_n_ext_fl <= '0'; avs_s0_read_n_ext_reg <= '1'; end if; if(avs_s0_chipselect = '1') then avs_s0_chipselect_ext_reg <= '1'; avs_s0_chipselect_ext_fl <= '1'; end if; if(avs_s0_chipselect_ext_fl = '1') then avs_s0_chipselect_ext_cnt <= avs_s0_chipselect_ext_cnt + 1; end if; if(avs_s0_read_n_ext_cnt = "11111111") then avs_s0_chipselect_ext_fl <= '0'; avs_s0_chipselect_ext_reg <= '0'; end if; end if; end process;
-- внешний контроль сигналов avs_s0_read_n_ext <= avs_s0_read_n_ext_reg; avs_s0_chipselect_ext <= avs_s0_chipselect_ext_reg; При этом IORD и IORD_32DIRECT внешне (по сигналам avs_s0_read_n, avs_s0_chipselect) работают одинаково Теперь остается прописать нормальный механизм чтения данных на Avalon MM Slave из пользовательской двухпортовой памяти . Можно в нескольких словах, как организовать механизм чтения по прерыванию от пользовательской логики?
|
|
|
|
|
Aug 21 2012, 11:10
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Aug 21 2012, 13:35)  Добавляете интерфейс Interrupt sender. У Вас добавится прерывание, которое в SOPC билдере нужно будет подключить к процессору. В пользовательской логике предусмотреть посылку прерывания уровнем или импульсом. Чтение/запись как обычно Avalon MM... Спасибо. Получилось
Чем может грозить предупреждение? Warning: cpu_0.data_master/ramtest_0.s0: ramtest_0.s0 does not have byteenables. Narrow (less than 32-bit) writes from cpu_0.data_master will result in spurious writes to ramtest_0.s0
Сообщение отредактировал Acvarif - Aug 21 2012, 11:13
|
|
|
|
|
Aug 22 2012, 10:13
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Почитал немного букварь "Avalon Interface Specification". Прописал нормально механизм чтения из RAM на Avalon. Чтение из RAM пошло. Но пока какая-то путаница с адресами. Если я определяю Код #define IORD_ALTERA_AVALON_RAM_0(base) IORD_16DIRECT(base, 0); #define IORD_ALTERA_AVALON_RAM_1(base) IORD_16DIRECT(base, 1); #define IORD_ALTERA_AVALON_RAM_2(base) IORD_16DIRECT(base, 2); #define IORD_ALTERA_AVALON_RAM_3(base) IORD_16DIRECT(base, 3); то надеюсь, что IORD_ALTERA_AVALON_RAM_0(base) прочитает данные по базовому адресу без смещения (по нулевому адресу RAM) - таки так оно и есть. далее надеюсь, что IORD_ALTERA_AVALON_RAM_1(base) прочитает данные по адресу базовый плюс 1- а реально читаются данные опять по нулевому адресу RAM. И только IORD_ALTERA_AVALON_RAM_2(base) читает данные по первому адресу RAM. IORD_ALTERA_AVALON_RAM_3(base) тоже читает данные по первому адресу RAM. В чем тут хитрость?
|
|
|
|
|
Aug 22 2012, 14:13
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Aug 22 2012, 16:31)  Предупреждение предупреждает (о как), что устройство не имеет сигнала выбора байта и поэтому, при записи данных шириной меньше полного слова будут изменены соседние байты. Почитайте про режимы адресации. Авалон будет читать целое слово, в вашем случае шириной 32 бита. Поэтому чтение со смещением в 2 байта, приведёт к чтению всё того же 32-битного слова. Спасибо. Понял. Чтение заработало нормально. Перешел к прерываниям (от внешней кнопки). Прерывание срабатывает, но на нем и виснет (не выходит из подпрограммы прерываний) По аналогии с микроконтроллерами полагал, что какой-то флаг прерывания должен автоматом сброситься при входе в обработчик. Получается не не так. Если в двух словах, то как?
|
|
|
|
|
Aug 23 2012, 06:30
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Копейкин @ Aug 22 2012, 18:24)  Нет, автоматом не сбрасывается. Ты должен иметь свой триггер, который устанавливается железом и сбрасывается программой (например, чтением регистра). Спасибо. Понял. Читаю мануалы. Пытаюсь найти простейший пример (программный и аппаратный) реализации обработки прерывания от пользовательской логики. Пока ничего путного не нашел. Также не ясен момент (нигде пока не нашел) как устанавливается как должно срабатывать прерывание (уровень, фронт, спад) В пользовательской логике формирую просто короткий положительный импульс. Вроде и сбрасывать в этом случае ничего не надо. В программе вход в обработчик имеется, но выхода из него нет - виснет на обработчике. В программе при инициализации системы регистрирую обработчик так Код alt_irq_register(RAMTEST_0_IRQ, (void*)RAMTEST_0_BASE, ramtest_isr); Сам обработчик CODE // Обработчик прерываний RAMTEST_0_IRQ static void ramtest_isr() { Start == 0; int ramresult; char uramresult[10] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x00}; ramresult=IORD_ALTERA_AVALON_RAM_0(RAMTEST_0_BASE); uramresult[1] = ramresult; uramresult[0] = ramresult >> 8; .... и т. д. } Если можно в коротком примере как должно быть правильно так, чтобы обработчик по фронту от пользовательской логики выполнил свою задачу однократно и не зависал.?
Сообщение отредактировал Acvarif - Aug 23 2012, 06:31
|
|
|
|
|
Aug 23 2012, 09:05
|
Частый гость
 
Группа: Участник
Сообщений: 190
Регистрация: 7-11-07
Из: С-Петербург
Пользователь №: 32 134

|
У меня примера под рукой нет, но когда разбирался, то отложилось в памяти так: 1) Интерфейс Interrupt sender даёт нам линии irq или irq_n, которые работают по уровню, не фронту. Выбрали, допустим irq - срабатывает на уровень "1". 2) Ставим на линию irq триггер. 3) Триггер взводится в "1" Вашим событием (кнопка, счётчик...) 4) Программа в обработчике прерывания ОБЯЗАТЕЛЬНО должна этот триггер сбросить в "0", иначе из прерывания не выйти. Сбросить можно чтением или записью по адресу, как Вам удобно. Вот таким образом.
Есть ещё компонент - векторизируемый контроллер прерываний - он даёт возможностей побогаче, более предсказуемое время входа в прерывание, но требует существенных ресурсов, для реализации. С ним не разбирался - так, обзорно...
Сообщение отредактировал Копейкин - Aug 23 2012, 09:08
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|