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

Простой шаблон AXI4-lite master

Сейчас перекраиваю пример код от Xilinx под себя, и идёт мне... ну в общем медленно дело движется. Нужен простой мастер, который по получении внешнего прерывания читает данные из внешней памяти. Т.е. алгоритм такой.

0-Резет

1-Код, исполняемый на процессоре записывает в мастер адрес, откуда мастер будет брать данные и адрес, куда мастер будет писать флаг конца чтения.

2-Мастер заполняет флаг паттерном типа АВАВАВАВ

3-Мастер ждёт прерывания на внешнем порту.

4-После прерывания мастер читает слово из адреса в DDR3 и записывает флаг другим паттерном - 0С0С0С0С

5-GOTO 3.

 

Буду весьма признателен за простой код мастера на AXI4, потому что в примере от Хилинха и слейв, и locallink, и фифо, и куча внутренних флагов, и всё в одном файле.

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


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

Сейчас перекраиваю пример код от Xilinx под себя, и идёт мне... ну в общем медленно дело движется. Нужен простой мастер, который по получении внешнего прерывания читает данные из внешней памяти. Т.е. алгоритм такой.

0-Резет

1-Код, исполняемый на процессоре записывает в мастер адрес, откуда мастер будет брать данные и адрес, куда мастер будет писать флаг конца чтения.

2-Мастер заполняет флаг паттерном типа АВАВАВАВ

3-Мастер ждёт прерывания на внешнем порту.

4-После прерывания мастер читает слово из адреса в DDR3 и записывает флаг другим паттерном - 0С0С0С0С

5-GOTO 3.

 

Буду весьма признателен за простой код мастера на AXI4, потому что в примере от Хилинха и слейв, и locallink, и фифо, и куча внутренних флагов, и всё в одном файле.

поиск не пробовали делать по форуму? (Сообщение #7)

Ваш алгоритм не делает, но пример мастера там человек дает...

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


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

Большое спасибо за ссылку! Не догадался посмотреть в разделе SoPC. К сожалению, там Верилог (забыл уточнить - ищу VHDL), но даёт понятие о порядке работы с шиной.

Всё же, если у кого завалялся AXI Lite мастер на VHDL - буду весьма признателен.

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


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

Большое спасибо за ссылку! Не догадался посмотреть в разделе SoPC. К сожалению, там Верилог (забыл уточнить - ищу VHDL), но даёт понятие о порядке работы с шиной.

Всё же, если у кого завалялся AXI Lite мастер на VHDL - буду весьма признателен.

именно VHDL ...

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


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

Ааа, Вы про 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 тащить не хочу.

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

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


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

Разобрался.

Создал код с нуля и спецификации шины.

Очень помог комментарий RobFPGA из этой шины http://electronix.ru/forum/index.php?showtopic=116819 .

 

Но пока не могу разобраться с таймаутами шины. Если моя корка неправильно написана, даже слейв, она вешает шину намертво и всю систему тоже. Кто может вкратце разъяснить как ведёт себя AXI_interconnect если слейв не отвечает или завис в момент транзакции?

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


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

Разобрался.

Создал код с нуля и спецификации шины.

Очень помог комментарий RobFPGA из этой шины http://electronix.ru/forum/index.php?showtopic=116819 .

 

Но пока не могу разобраться с таймаутами шины. Если моя корка неправильно написана, даже слейв, она вешает шину намертво и всю систему тоже. Кто может вкратце разъяснить как ведёт себя AXI_interconnect если слейв не отвечает или завис в момент транзакции?

я точно не скажу, но вроде слейв должен начинать транзакцию передачи пакета когда будут собраны данные для всего пакета (пакет = "длине" фифо). И не начинать транзакцию передачи пока фифо не будет полным (имеются все данные для пакета).

Причины зависания в момент транзакции?

Слейв используете свой или корка от Xilinx?

 

upd

 

только что перешел по ссылке, там в принципе тоже самое пишет RobFPGA

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


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

Конечно поделюсь, только закончу еще слейв-часть. Пока что виснет, паскуда и не могу понять почему. В 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 поднимает.

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

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


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

ДОБАВЛЕНО:

Ёрш твою медь, есть ли где-то вменяемая времянка записи в Axi-lite? У меня проц почему-то первым делом BREADY поднимает.

вот это не подойдет?

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


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

Хош сделать хорошо- сделай сам:

Вот времянки записи и чтения процессора из Xilinxoвой корки, т.е. самые правильные.

Запись:

im86j8.png

Чтение:

xms9is.png

 

На выходных постараюсь сложить всю инфу в кучу.

Я в курсе, что есть AXI4-IPIF, но чтобы разобраться надо работать на самом нижнем уровне. IPIF может оказаться излишним.

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


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

Как и обещал, выкладываю свои шаблоны.

Мастер пишет по фиксированному адресу 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

По возможности постараюсь помочь, если у кого-то будут вопросы. На самом деле шина значительно проще чем кажется - глаза боятся, а руки делают.

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

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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