acvarif 0 4 июля, 2016 Опубликовано 4 июля, 2016 (изменено) · Жалоба Имеется модуль с Avalon Slave присоединенный в систему с Nios 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(7 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(7 downto 0) := (others => '0'); -- .writedata avs_s0_byteenable : in std_logic_vector(0 downto 0) := (others => '0'); avs_s0_readdata : out std_logic_vector(7 downto 0); -- .readdata ins_irq0_irq : out std_logic; В модуле имеется двухпортовая RAM (16 байт) которую необходимо читать по прерыванию ins_irq0_irq В программе обработчика первым делом сбрасываю импульс прерывания чтением по крайнему адресу .... void Irq0Isr(void* context, alt_u32 id) { // сброс сигнала прерывания IORD_8DIRECT(AMULET_0_BASE, 255); Isr0Occur = 1; AllIrq0Count++; } .... В майн читаю память. Данные в памяти заранее известны. 0x55, 0xaa, ... ... if (AllIrq0Count) { RamData = IORD_8DIRECT(AMULET_0_BASE, 0); printf("Прерывание Irq0: N %d \n", AllIrq0Count); printf("Данные: %x \n", RamData[0]); AllIrq0Count = 0; } .... Все работает нормально пока (AMULET_0_BASE, 0) Вопрос как считать данные по следующему адресу RAM? Какое должно быть смещение. Поскольку Nios оперирует байтами, а Avalon имеет ширину 32 бита, то смещение для чтения следующего байта из двухпортовой RAM должно быть 4. Прочитанный байт должет быть 0хaa. На практике читается все то же 0х55. Подскажите пожалуйста в чем загвоздка? Изменено 4 июля, 2016 пользователем Acvarif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 4 июля, 2016 Опубликовано 4 июля, 2016 · Жалоба Поскольку Nios оперирует байтами, а Avalon имеет ширину 32 бита, то смещение для чтения следующего байта из двухпортовой RAM должно быть 4. Нет, это как минимум определяется настройками компонента в Qsys. Там указывается, как интерпретировать адрес - как байтовый или по словам. Если нужно, чтобы первый байт имел адрес 4, то самый простой способ - добить его до 32 бит нулями. Но у вас в компоненте уже есть порт bytenable - тогда м.б. проще сделать именно побайтовый доступ, тогда первый байт будет иметь адрес 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 4 июля, 2016 Опубликовано 4 июля, 2016 (изменено) · Жалоба Нет, это как минимум определяется настройками компонента в Qsys. Там указывается, как интерпретировать адрес - как байтовый или по словам. Если нужно, чтобы первый байт имел адрес 4, то самый простой способ - добить его до 32 бит нулями. Но у вас в компоненте уже есть порт bytenable - тогда м.б. проще сделать именно побайтовый доступ, тогда первый байт будет иметь адрес 1 Понятно. Спасибо. bytenable имеет один разряд. Доступ должен быть побайтовый. Так оно и получилось. Нулевой байт читается по смещению на 0, первый на 1 IORD_8DIRECT(AMULET_0_BASE, 1); и т. д. Изменено 4 июля, 2016 пользователем Acvarif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 4 июля, 2016 Опубликовано 4 июля, 2016 · Жалоба Попутно возник еще вопрос связанный с прерыванием. Почему невозможно добавить к Avalon Slave еще одно прерывание типа ins_irq1_irq? Sopc пишет что позволено только одно. ... avs_s0_byteenable : in std_logic_vector(0 downto 0) := (others => '0'); avs_s0_readdata : out std_logic_vector(7 downto 0); -- .readdata ins_irq0_irq : out std_logic; ins_irq1_irq : out std_logic; ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 5 июля, 2016 Опубликовано 5 июля, 2016 · Жалоба Так а зачем - делаете сколько надо флагов в статусном регистре с соответствующими interrupt_enable в контрольном, а сигнал прерывания будет просто логическим ИЛИ от этих флагов. Обработчик прерывания уже сам разберется в причине, заглянув в статусный регистр перед снятием прерывания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 5 июля, 2016 Опубликовано 5 июля, 2016 · Жалоба Так а зачем - делаете сколько надо флагов в статусном регистре с соответствующими interrupt_enable в контрольном, а сигнал прерывания будет просто логическим ИЛИ от этих флагов. Обработчик прерывания уже сам разберется в причине, заглянув в статусный регистр перед снятием прерывания. Спасибо. Смысл понятен. Не соображу как эти регистры создать. По типу .h фала? #ifndef __ALTERA_AVALON_AMULET_REGS_H__ #define __ALTERA_AVALON_AMULET_REGS_H__ #include <io.h> #define ALTERA_AVALON_AMULET_STATUS_REG 2 #define IOADDR_ALTERA_AVALON_AMULET_STATUS(base) \ __IO_CALC_ADDRESS_NATIVE(base, ALTERA_AVALON_AMULET_STATUS_REG) #define IORD_ALTERA_AVALON_AMULET_STATUS(base) \ IORD(base, ALTERA_AVALON_AMULET_STATUS_REG) #define IOWR_ALTERA_AVALON_AMULET_STATUS(base, data) \ IOWR(base, ALTERA_AVALON_AMULET_STATUS_REG, data) #define ALTERA_AVALON_AMULET_STATUS_IRQ0_MSK (0x1) #define ALTERA_AVALON_AMULET_STATUS_IRQ0_OFST (0) #define ALTERA_AVALON_AMULET_STATUS_IRQ1_MSK (0x2) #define ALTERA_AVALON_AMULET_STATUS_IRQ1_OFST (1) #define ALTERA_AVALON_AMULET_CONTROL_REG 3 #define IOADDR_ALTERA_AVALON_AMULET_CONTROL(base) \ __IO_CALC_ADDRESS_NATIVE(base, ALTERA_AVALON_AMULET_CONTROL_REG) #define IORD_ALTERA_AVALON_AMULET_CONTROL(base) \ IORD(base, ALTERA_AVALON_AMULET_CONTROL_REG) #define IOWR_ALTERA_AVALON_AMULET_CONTROL(base, data) \ IOWR(base, ALTERA_AVALON_AMULET_CONTROL_REG, data) #define ALTERA_AVALON_AMULET_CONTROL_IRQ0_MSK (0x1) #define ALTERA_AVALON_AMULET_CONTROL_IRQ0_OFST (0) #define ALTERA_AVALON_AMULET_CONTROL_IRQ1_MSK (0x2) #define ALTERA_AVALON_AMULET_CONTROL_IRQ1_OFST (1) #endif /* __ALTERA_AVALON_AMULET_REGS_H__ */ Не врубаюсь как в регистрах будут устанавливаться и сбрасываться биты. Очевидно эти регистры (ALTERA_AVALON_AMULET_CONTROL_REG, ALTERA_AVALON_AMULET_STATUS_REG) нужно создать и в самом модуле Amulet? Или нет.. Если не сложно, поясните пожалуйста коротко механизм. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Swup 0 5 июля, 2016 Опубликовано 5 июля, 2016 · Жалоба Не врубаюсь как в регистрах будут устанавливаться и сбрасываться биты. Очевидно эти регистры (ALTERA_AVALON_AMULET_CONTROL_REG, ALTERA_AVALON_AMULET_STATUS_REG) нужно создать и в самом модуле Amulet? Или нет.. Если не сложно, поясните пожалуйста коротко механизм. Пример реализации записи и чтения двух управляющих регистров в модуле. reg [31:0] CSR; reg [31:0] CSR2; /////////// MM CONTROL//////////// always @(posedge clk_cpu) if(reset_cpu) begin CSR <= 32'b0; CSR2 <= 32'b0; end else begin if(!cpu_write_n && (cpu_address == 1'b0)) CSR <= cpu_writedata; if(!cpu_write_n && (cpu_address == 1'b1)) CSR2 <= cpu_writedata; end assign cpu_readdata = !cpu_write_n && cpu_address == 1'b0 ? CSR : !cpu_write_n && cpu_address == 1'b1 ? CSR2 : 32'hzzzz_zzzz; Доступ из ниоса будет вот таким: IOWR(base, 0, data); // запись CSR IOWR(base, 1, data); // запись CSR2 IORD(base, 0); IORD(base, 1); Дальше уже можно сделать обертки макросами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 5 июля, 2016 Опубликовано 5 июля, 2016 · Жалоба Очевидно эти регистры (ALTERA_AVALON_AMULET_CONTROL_REG, ALTERA_AVALON_AMULET_STATUS_REG) нужно создать и в самом модуле Amulet? Или нет.. Если не сложно, поясните пожалуйста коротко механизм. Да, пример выше привели. Эти регистры привязать к MM-слейву, чтобы проц туда доступ имел. Вот еще пример: http://paste.org.ru/?18jxcc Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 13 июля, 2016 Опубликовано 13 июля, 2016 · Жалоба Да, пример выше привели. Эти регистры привязать к MM-слейву, чтобы проц туда доступ имел. Вот еще пример: http://paste.org.ru/?18jxcc Спасибо. Понятно. В тему появилась еще непонятка. При чтении по прерывании (из Nios) данных которые заранее записаны в двухпортовую RAM первое прерывание читает все 0 и только по второму прерыванию читаются верные данные. Ниже обработчик. void Irq0Isr(void* context, alt_u32 id) { alt_u8 i; // сброс сигнала прерывания IORD_8DIRECT(AMULET_0_BASE, 255); // чтение двухпортовой RAM for (i = 0; i < 16; i++) { RamData[i] = IORD_8DIRECT(AMULET_0_BASE, i); } // флаг прерывания FlIrq0 = 1; // счетчик прерываний AllIrq0Count++; // синхро поймано if (RamData[0] == 0x55 && RamData[1] == 0xaa && !BeginTrns) { // начало передачи протокола BeginTrns = 1; // общее количество байт информации о метках AllNbData = (RamData[6] << 8) | RamData[7]; // переключатель банков памяти протокола if(NbTx) NbTx = 0; else NbTx = 1; // флаг для светодиода BeginPr = 1; // фиксация номера прерывания printf("Номер прерывания синхросимволов Irq0: N %d \n", AllIrq0Count); } } Дело в том, что синхросимволы уже имеются в памяти и должны появиться в RamData по первому прерыванию, тоесть когда AllIrq0Count = 1. Но printf принтует в окне терминала N 2. На самом деле так оно и есть. Почему по первому прерыванию из двухпортовой RAM читаются нули, а не реальные данные ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 13 июля, 2016 Опубликовано 13 июля, 2016 · Жалоба надо смотреть, не генерируется ли паразитное прерывание, когда данных еще нет. гляньте signaltap'ом Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 13 июля, 2016 Опубликовано 13 июля, 2016 · Жалоба надо смотреть, не генерируется ли паразитное прерывание, когда данных еще нет. гляньте signaltap'ом Контроль веду по осциллографу. Паразитных всплесков нет. Собственно сама RAM -- карта соединений памяти меток -- принимает (запись) метки от uuartrx_mt -- отправляет (чтение) метки в Nios в кажд. эл. дист -- enable памяти меток s_mtwe <= s_canceler; -- сигнал записи данных в пам. меток s_wrmt <= s_tx_done_tick; -- данные s_datarx на память меток s_d_mtdata_one <= s_datarx; -- адреса чтения 16 байт s_mtraddr <= avs_s0_address(3 downto 0); umtdata : ramdata generic map (8, 4) port map ( rclk => s_rdmt, wclk => s_wrmt, raddr => s_mtraddr, waddr => s_mtwaddr, data => s_d_mtdata_one, we => s_mtwe, q => s_q_mtdata_one ); -- данные на Avalon MM Slave из памяти меток avs_s0_readdata <= s_q_mtdata_one; -- сигнал чтения из Avalon MM Slave на RAM s_rdmt <= (not clk and not avs_s0_read_n and avs_s0_byteenable(0)); Наверное лишним прицеплено avs_s0_byteenable(0) для сигнала чтения Ram. Да и без него все то же самое. Чудес не бывает, но обработчик таки действительно только по второму прерыванию читает реальные данные из двухпортовой RAM. Не связано-ли это с какими-то кешами?... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 14 июля, 2016 Опубликовано 14 июля, 2016 · Жалоба Не связано-ли это с какими-то кешами?... Это легко проверить, отключив кэш данных в настройках процессора Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 14 июля, 2016 Опубликовано 14 июля, 2016 · Жалоба Это легко проверить, отключив кэш данных в настройках процессора Да. Прояснилось. Ошибка в обработчике. В обработчике начинать счет прерываний нужно после того как пойманы синхросимволы по чтению двухпортовой RAM, а не до того. По поводу скорости выполнения операций в main по каждому прерыванию. Время между двумя соседними прерываниями 2 мс. За это время нужно из 16 байт данных сформировать некий протокол и пр. требуха. Как максимально ускорить выполнение операций в main? В смысле какая предпочтительнее конфигурация Nios и что желательно настроить в BSP? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 14 июля, 2016 Опубликовано 14 июля, 2016 · Жалоба Как максимально ускорить выполнение операций в main? В смысле какая предпочтительнее конфигурация Nios и что желательно настроить в BSP? Конфигурация проца - f, опции компилятора -O2 как минимум (и для проекта, и для библиотеки). Но главная проблема тут: Время между двумя соседними прерываниями 2 мс. Нужно искать способ увеличить длину пакета и, соотв., интервал между прерываниями Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться