count_enable 0 21 января, 2014 Опубликовано 21 января, 2014 · Жалоба Сейчас перекраиваю пример код от Xilinx под себя, и идёт мне... ну в общем медленно дело движется. Нужен простой мастер, который по получении внешнего прерывания читает данные из внешней памяти. Т.е. алгоритм такой. 0-Резет 1-Код, исполняемый на процессоре записывает в мастер адрес, откуда мастер будет брать данные и адрес, куда мастер будет писать флаг конца чтения. 2-Мастер заполняет флаг паттерном типа АВАВАВАВ 3-Мастер ждёт прерывания на внешнем порту. 4-После прерывания мастер читает слово из адреса в DDR3 и записывает флаг другим паттерном - 0С0С0С0С 5-GOTO 3. Буду весьма признателен за простой код мастера на AXI4, потому что в примере от Хилинха и слейв, и locallink, и фифо, и куча внутренних флагов, и всё в одном файле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 21 января, 2014 Опубликовано 21 января, 2014 · Жалоба Сейчас перекраиваю пример код от Xilinx под себя, и идёт мне... ну в общем медленно дело движется. Нужен простой мастер, который по получении внешнего прерывания читает данные из внешней памяти. Т.е. алгоритм такой. 0-Резет 1-Код, исполняемый на процессоре записывает в мастер адрес, откуда мастер будет брать данные и адрес, куда мастер будет писать флаг конца чтения. 2-Мастер заполняет флаг паттерном типа АВАВАВАВ 3-Мастер ждёт прерывания на внешнем порту. 4-После прерывания мастер читает слово из адреса в DDR3 и записывает флаг другим паттерном - 0С0С0С0С 5-GOTO 3. Буду весьма признателен за простой код мастера на AXI4, потому что в примере от Хилинха и слейв, и locallink, и фифо, и куча внутренних флагов, и всё в одном файле. поиск не пробовали делать по форуму? (Сообщение #7) Ваш алгоритм не делает, но пример мастера там человек дает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
count_enable 0 21 января, 2014 Опубликовано 21 января, 2014 · Жалоба Большое спасибо за ссылку! Не догадался посмотреть в разделе SoPC. К сожалению, там Верилог (забыл уточнить - ищу VHDL), но даёт понятие о порядке работы с шиной. Всё же, если у кого завалялся AXI Lite мастер на VHDL - буду весьма признателен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 22 января, 2014 Опубликовано 22 января, 2014 · Жалоба Большое спасибо за ссылку! Не догадался посмотреть в разделе SoPC. К сожалению, там Верилог (забыл уточнить - ищу VHDL), но даёт понятие о порядке работы с шиной. Всё же, если у кого завалялся AXI Lite мастер на VHDL - буду весьма признателен. именно VHDL ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
count_enable 0 22 января, 2014 Опубликовано 22 января, 2014 (изменено) · Жалоба Ааа, Вы про m_axi_user_bridge.vhd ? Я не сразу понял, что он делает и смотрел на код _4afc_ из архива. Для будущих поколений, есть Xilinx AR http://www.xilinx.com/support/answers/37425.htm на тему, с очень хорошими примерами - но на Верилоге. Когда пробую подключить m_axi_user_bridge.vhd - требует сигналов ARADDR, ARSIZE и других, не описанных в дизайне. Подключаю через Create or Import Peripheral Wizard. Можно ли его как-то обойти? Полный DMA_controller тащить не хочу. Изменено 22 января, 2014 пользователем count_enable Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
count_enable 0 24 января, 2014 Опубликовано 24 января, 2014 · Жалоба Разобрался. Создал код с нуля и спецификации шины. Очень помог комментарий RobFPGA из этой шины http://electronix.ru/forum/index.php?showtopic=116819 . Но пока не могу разобраться с таймаутами шины. Если моя корка неправильно написана, даже слейв, она вешает шину намертво и всю систему тоже. Кто может вкратце разъяснить как ведёт себя AXI_interconnect если слейв не отвечает или завис в момент транзакции? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 24 января, 2014 Опубликовано 24 января, 2014 · Жалоба Разобрался. Создал код с нуля и спецификации шины. Очень помог комментарий RobFPGA из этой шины http://electronix.ru/forum/index.php?showtopic=116819 . Но пока не могу разобраться с таймаутами шины. Если моя корка неправильно написана, даже слейв, она вешает шину намертво и всю систему тоже. Кто может вкратце разъяснить как ведёт себя AXI_interconnect если слейв не отвечает или завис в момент транзакции? я точно не скажу, но вроде слейв должен начинать транзакцию передачи пакета когда будут собраны данные для всего пакета (пакет = "длине" фифо). И не начинать транзакцию передачи пока фифо не будет полным (имеются все данные для пакета). Причины зависания в момент транзакции? Слейв используете свой или корка от Xilinx? upd только что перешел по ссылке, там в принципе тоже самое пишет RobFPGA Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
count_enable 0 24 января, 2014 Опубликовано 24 января, 2014 (изменено) · Жалоба Конечно поделюсь, только закончу еще слейв-часть. Пока что виснет, паскуда и не могу понять почему. В Isim все работает, но не использую Xilinxoвую модель, а дергаю шину вручную. Слейв Акси-лайт, т.е одно слово. Два регистра. В симуляторе норм, вживую не поднимается в 1 S_AXI_AWREADY. Таймаут по шине не приходит, система тупо висит. --------------------------------------------------------- WRITE_PROC: process(M_AXI_ACLK) is begin if M_AXI_ARESETN='0' then conf_reg<=(others=>'0'); addr_reg<=(others=>'0'); else if M_AXI_ACLK'event and M_AXI_ACLK='1' then case W_state is when ST_IDLE=> if S_AXI_AWVALID='1' then S_AXI_AWREADY<='1'; W_state<=ST_WRITE; end if; when ST_WRITE=> S_AXI_AWREADY<='0'; S_AXI_WREADY<='1'; if S_AXI_WVALID='1' then if S_AXI_AWADDR(0)='0' then conf_reg<=S_AXI_WDATA; else addr_reg<=S_AXI_WDATA; end if; W_state<=ST_CONFIRM; end if; when ST_CONFIRM=> S_AXI_BRESP<="00"; S_AXI_WREADY<='0'; S_AXI_BVALID<='1'; if S_AXI_BREADY='1' then S_AXI_BVALID<='0'; W_state<=ST_IDLE; end if; end case; end if; end if; end process; ДОБАВЛЕНО: Ёрш твою медь, есть ли где-то вменяемая времянка записи в Axi-lite? У меня проц почему-то первым делом BREADY поднимает. Изменено 24 января, 2014 пользователем count_enable Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 24 января, 2014 Опубликовано 24 января, 2014 · Жалоба ДОБАВЛЕНО: Ёрш твою медь, есть ли где-то вменяемая времянка записи в Axi-lite? У меня проц почему-то первым делом BREADY поднимает. вот это не подойдет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
count_enable 0 24 января, 2014 Опубликовано 24 января, 2014 · Жалоба Хош сделать хорошо- сделай сам: Вот времянки записи и чтения процессора из Xilinxoвой корки, т.е. самые правильные. Запись: Чтение: На выходных постараюсь сложить всю инфу в кучу. Я в курсе, что есть AXI4-IPIF, но чтобы разобраться надо работать на самом нижнем уровне. IPIF может оказаться излишним. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
count_enable 0 27 января, 2014 Опубликовано 27 января, 2014 (изменено) · Жалоба Как и обещал, выкладываю свои шаблоны. Мастер пишет по фиксированному адресу 4 фиксированных слова, потом их читает и отправляет во внешний порт. Проверка на ошибки шины не производится, поэтому виснет при неправильном адресе! ------------------------------------------------------------------------------- -- -- AXI4-Lite Master -- Simplified IP-core that performs 32-byte write to fixed address and reads it back -- Does not perform error check on write and read!!! -- -- VHDL-Standard: VHDL'93 ---------------------------------------------------------------------------- -- -- Structure: -- axi_lite_master -- ---------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_misc.all; --library unisim; --use unisim.vcomponents.all; entity AXI4_master_lite is generic( C_M_AXI_ADDR_WIDTH : integer := 32; C_M_AXI_DATA_WIDTH : integer := 32 ); port( STATUS: out std_logic_vector(31 downto 0); -- output for debug purposes -- System Signals M_AXI_ACLK : in std_logic; M_AXI_ARESETN : in std_logic; -- Master Interface Write Address M_AXI_AWADDR : out std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0); M_AXI_AWPROT : out std_logic_vector(3-1 downto 0); M_AXI_AWVALID : out std_logic; M_AXI_AWREADY : in std_logic; -- Master Interface Write Data M_AXI_WDATA : out std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); M_AXI_WSTRB : out std_logic_vector(C_M_AXI_DATA_WIDTH/8-1 downto 0); M_AXI_WVALID : out std_logic; M_AXI_WREADY : in std_logic; -- Master Interface Write Response M_AXI_BRESP : in std_logic_vector(2-1 downto 0); M_AXI_BVALID : in std_logic; M_AXI_BREADY : out std_logic; -- Master Interface Read Address M_AXI_ARADDR : out std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0); M_AXI_ARPROT : out std_logic_vector(3-1 downto 0); M_AXI_ARVALID : out std_logic; M_AXI_ARREADY : in std_logic; -- Master Interface Read Data M_AXI_RDATA : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); M_AXI_RRESP : in std_logic_vector(2-1 downto 0); M_AXI_RVALID : in std_logic; M_AXI_RREADY : out std_logic ); end AXI4_master_lite; ------------------------------------------------------------------------------- -- Architecture ------------------------------------------------------------------------------- architecture implementation of AXI4_master_lite is signal testreg: std_logic_vector (C_M_AXI_DATA_WIDTH-1 downto 0); signal counter, ctrread: integer range 0 to 32; type state_type is (ST_IDLE, ST_WRITE,ST_DWRITE,ST_DACK, ST_ACK,ST_BREADY); signal state, next_state : state_type; type Rstate_type is (ST_IDLE, ST_RADDR,ST_RDATA); signal Rstate:Rstate_type; signal start_read:std_logic; begin M_AXI_AWPROT<=(others=>'0'); M_AXI_ARPROT<=(others=>'0'); WRITE_SM: process (M_AXI_ACLK) is begin if M_AXI_ARESETN='0' then testreg<=x"A5A5A5A5"; M_AXI_AWVALID<='0'; M_AXI_WVALID<='0'; M_AXI_BREADY<='0'; counter<=0; state<=ST_IDLE; start_read<='0'; STATUS(15 downto 0)<=(others=>'0'); else if M_AXI_ACLK'event and M_AXI_ACLK='1' then case state is when ST_IDLE => M_AXI_AWVALID<='0'; M_AXI_WVALID<='0'; M_AXI_BREADY<='0'; if counter<31 then state<=ST_WRITE; STATUS(15 downto 0)<=x"0001"; else state<=state; start_read<='1'; -- after writes we initiate reading end if; when ST_WRITE => M_AXI_AWADDR(31 downto 8)<=x"A800F0"; M_AXI_AWADDR(7 downto 0)<=std_logic_vector(to_unsigned(counter,8)); M_AXI_WDATA<=testreg; M_AXI_WSTRB<="1111"; M_AXI_AWVALID<='1'; M_AXI_WDATA<=testreg; M_AXI_WSTRB<="1111"; M_AXI_WVALID<='1'; state<=ST_ACK; STATUS(15 downto 0)<=x"0002"; when ST_ACK => if M_AXI_AWREADY='1' then M_AXI_AWVALID<='0'; counter<=counter+4; state<=ST_DACK; STATUS(15 downto 0)<=x"0003"; else next_state<=state; end if; when ST_DWRITE => M_AXI_WDATA<=testreg; M_AXI_WSTRB<="1111"; M_AXI_WVALID<='1'; state<=ST_DACK; STATUS(15 downto 0)<=x"0004"; when ST_DACK => if M_AXI_WREADY='1' then M_AXI_WVALID<='0'; M_AXI_BREADY<='1'; state<=ST_BREADY; STATUS(15 downto 0)<=x"0005"; else state<=state; end if; when ST_BREADY => if M_AXI_BVALID='1' then M_AXI_BREADY<='0'; state<=ST_IDLE; STATUS(15 downto 0)<=x"0006"; else state<=state; end if; end case; end if; end if; end process; READ_SM: process(M_AXI_ACLK) is begin if M_AXI_ARESETN='0' then M_AXI_ARVALID<='0'; M_AXI_RREADY<='0'; Rstate<=ST_IDLE; ctrread<=0; STATUS(31 downto 16)<=(others=>'0'); else if M_AXI_ACLK'event and M_AXI_ACLK='1' then case Rstate is when ST_IDLE => if start_read='1' and ctrread<31 then Rstate<=ST_RADDR; M_AXI_ARVALID<='1'; M_AXI_ARADDR(31 downto 8)<=x"A800F0"; M_AXI_ARADDR(7 downto 0)<=std_logic_vector(to_unsigned(ctrread,8)); end if; when ST_RADDR => M_AXI_ARVALID<='0'; M_AXI_RREADY<='1'; if M_AXI_RVALID='1' then ctrread<=ctrread+4; STATUS(31 downto 16)<=M_AXI_RDATA(15 downto 0); Rstate<=ST_RDATA; end if; when ST_RDATA => M_AXI_RREADY<='0'; Rstate<=ST_IDLE; end case; end if; end if; end process; end implementation; Слейв это 2 регистра, ошибок не возвращает (всегда можно прочитать). Проверка на валидность адреса тоже рудиментарная. ------------------------------------------------------------------------------- -- -- AXI4-Lite Slave -- -- VHDL-Standard: VHDL'93 ---------------------------------------------------------------------------- -- -- Structure: -- axi_lite_slave -- ---------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_misc.all; --library unisim; --use unisim.vcomponents.all; entity axi_paer_router is generic( C_M_AXI_ADDR_WIDTH : integer := 32; C_M_AXI_DATA_WIDTH : integer := 32; C_S_AXI_ADDR_WIDTH : integer := 32; C_S_AXI_DATA_WIDTH : integer := 32; C_S_AXI_MIN_SIZE : std_logic_vector := X"000001FF"; C_USE_WSTRB : integer := 0; C_DPHASE_TIMEOUT : integer := 8; C_BASEADDR : std_logic_vector := X"00000000"; C_HIGHADDR : std_logic_vector := X"00000010"; C_FAMILY : string := "spartan6"; C_NUM_REG : integer := 1; C_NUM_MEM : integer := 1; C_SLV_AWIDTH : integer := 32; C_SLV_DWIDTH : integer := 32 ); port( -- System Signals M_AXI_ACLK : in std_logic; -- это еще остались от мастер-слейва, поэтому не переименовал M_AXI_ARESETN : in std_logic; -- это еще остались от мастер-слейва, поэтому не переименовал -- Slave Interface Write Address Ports S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); S_AXI_AWPROT : in std_logic_vector(3-1 downto 0); S_AXI_AWVALID : in std_logic; S_AXI_AWREADY : out std_logic; -- Slave Interface Write Data Ports S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); S_AXI_WSTRB : in std_logic_vector(C_S_AXI_DATA_WIDTH/8-1 downto 0); S_AXI_WVALID : in std_logic; S_AXI_WREADY : out std_logic; -- Slave Interface Write Response Ports S_AXI_BRESP : out std_logic_vector(2-1 downto 0); S_AXI_BVALID : out std_logic; S_AXI_BREADY : in std_logic; -- Slave Interface Read Address Ports S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); S_AXI_ARPROT : in std_logic_vector(3-1 downto 0); S_AXI_ARVALID : in std_logic; S_AXI_ARREADY : out std_logic; -- Slave Interface Read Data Ports S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); S_AXI_RRESP : out std_logic_vector(2-1 downto 0); S_AXI_RVALID : out std_logic; S_AXI_RREADY : in std_logic ); end axi_paer_router; ------------------------------------------------------------------------------- -- Architecture ------------------------------------------------------------------------------- architecture implementation of axi_paer_router is signal conf_reg: std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); -- вот и память слейва, 2 регистра signal addr_reg: std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); type Rstate_type is (ST_IDLE, ST_READ); signal R_state : Rstate_type; type Wstate_type is (ST_IDLE,ST_WRITE, ST_CONFIRM); signal W_state : Wstate_type; begin --------------------------------------------------------- WRITE_PROC: process(M_AXI_ACLK) is begin if M_AXI_ARESETN='0' then conf_reg<=(others=>'0'); addr_reg<=(others=>'0'); else if M_AXI_ACLK'event and M_AXI_ACLK='1' then case W_state is when ST_IDLE=> S_AXI_BVALID<='0'; if S_AXI_AWVALID='1' then S_AXI_AWREADY<='1'; W_state<=ST_WRITE; end if; when ST_WRITE=> S_AXI_AWREADY<='0'; if S_AXI_WVALID='1' then S_AXI_WREADY<='1'; if S_AXI_AWADDR(2)='0' then -- every 4th byte (either XXXXXXX0 or XXXXXXX4) conf_reg<=S_AXI_WDATA; else addr_reg<=S_AXI_WDATA; -- вот такая примитивная адресация - все адреса мапированы в 2 рег end if; W_state<=ST_CONFIRM; end if; when ST_CONFIRM=> S_AXI_BRESP<="00"; S_AXI_WREADY<='0'; S_AXI_BVALID<='1'; if S_AXI_BREADY='1' then W_state<=ST_IDLE; end if; end case; end if; end if; end process; --------------------------------------------------------- READ_PROC: process (M_AXI_ACLK) is begin if M_AXI_ARESETN='0' then R_state<=ST_IDLE; else if M_AXI_ACLK'event and M_AXI_ACLK='1' then S_AXI_ARREADY<='0'; S_AXI_RVALID<='0'; S_AXI_RRESP<="00"; case R_state is when ST_IDLE=> if S_AXI_ARVALID='1' then S_AXI_ARREADY<='1'; R_state<=ST_READ; else R_state<=R_state; end if; when ST_READ => S_AXI_ARREADY<='0'; S_AXI_RVALID<='1'; S_AXI_RRESP<="00"; if S_AXI_ARADDR(2)='0' then -- every 4th byte (either XXXXXXX0 or XXXXXXX4) S_AXI_RDATA<=conf_reg; else S_AXI_RDATA<=addr_reg; end if; if S_AXI_RREADY ='1' then R_state<=ST_IDLE; else R_state<=R_state; end if; end case; end if; end if; end process; end implementation; Если кто-то не хочет использовать Xilinx IPIF, может воспользоваться вышеприведенными шаблонами для собственных корок. Лицензия WTFPL :). Обе корки протестированы в железе, собирались на xc6slx45 с микроблейзом в ИСЕ 14.2. Помогла документация: http://www.xilinx.com/support/documentatio..._ipif_ds765.pdf http://www.xilinx.com/support/documentatio...master_lite.pdf http://home.mit.bme.hu/~feher/MSC_RA/ARM/A...otocol_spec.pdf По возможности постараюсь помочь, если у кого-то будут вопросы. На самом деле шина значительно проще чем кажется - глаза боятся, а руки делают. Изменено 27 января, 2014 пользователем count_enable Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться