Автор: Бортников Анатолий Юрьевич, генеральный директор компании ООО “РСВ ЭЛЕКТРОНИКС”, кандидат физ.- мат. наук.

Введение

Шина Avalon-MM является одной из стандартных шин передачи данных, используемых в ПЛИС фирмы Intel. Использование этой шины в своих модулях для передачи данных существенно повышает их возможность повторного применения и повышает надежность проектов. Также упрощается интеграция модулей в проект с помощью Platform Designer.

Принципы работы шины Avalon-MM

Шина Avalon-MM используется для передачи данных между модулями проекта. Она позволяет выполнять запись данных в модуль либо чтение данных из модуля обращаясь к нему как к блоку памяти.

На шине Avalon-MM существует определенная иерархия модулей. Обязательно должен быть контроллер - Master, который управляет всеми транзакциями передачи данных по шине. Остальные модули выступают в роли подчиненных - Slave. Каждый Slave на шине имеет определенный адрес или диапазон адресов, в которые Master может писать данные или читать из этих адресов. На рис. 1 представлен вариант конфигурации шины Avalon-MM.

Рис 1. Вариант конфигурации шины Avalon-MM

В качестве мастера часто выступает процессор NIOS II либо может использоваться другой модуль в качестве процессора. Если использовать NIOS II то проблем с подключением к шине Avalon-MM не возникает. Так как он уже имеет встроенный интерфейс Avalon-MM Master. Если же есть необходимость использовать процессор без интерфейса Avalon-MM (например когда процессор пишется пользователем под конкретную задачу) то для его подключения к шине Avalon-MM требуется реализация интерфейса Avalon-MM Master.

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

Таблица 1. Сигналы шины Avalon-MM, минимальный набор

Название

разряды

направление

описание

address

1-32

выход

address представляет адрес байта независимо от ширины шины данных. Значение адреса должно быть выровнено по ширине шины данных. Для записи отдельных байтов с шины данных требуется использовать сигналы byteenable. Мастер всегда выставляет адрес независимо от ширины шины данных. Система межсоединений конвертирует этот адрес в адрес слов в адресном пространстве Slave-модуля.

read, read_n

1

выход

Сигнал запроса операции чтения. Не требуется, если Master никогда не инициализирует операцию чтения. Но если есть сигналы read/read_n то readdata обязательны.

readdata

8, 16, 32, 64, 128, 256, 512, 1024

вход

Сигналы для чтения данных.

write write_n

1

выход

Сигнал запроса операции записи. Не требуется, если Master никогда не инициализирует операцию записи данных. Но если есть write/write_n то сигналы writedata обязательны.

writedata

8, 16, 32, 64, 128, 256, 512, 1024

вход

Сигналы для передачи данных для записи в Slave. Если присутствуют writedata и readdata, то они должны быть одинаковой разрядности.

byteenable byteenable_n

1, 2, 4, 8, 16, 32, 64, 128

выход

Сигналы активизируют отдельные байты данных при передаче, если разрядность шины данных больше 8. Каждый бит в byteenable соответствует отдельному байту в шине данных как при чтении так и при записи. Единица в бите byteenable показывает, будет ли передан этот байт по шине данных. Остальные байты в шине данных должны игнорироваться Slave-ом. Если требуется передать больше чем 1 байт по шине данных, то все байты должны быть выставлены. Количество передаваемых байт должно быть равно степени 2. Доступны следующие варианты значения сигналов byteenable и количество передаваемых байт: 1111 - передача 4-х байтов (32 бита); 0011 - передача младших двух байт (16 бит); 1100 - передача старших двух байт (16 бит); 0001 - передача младшего (первого) байта; 0010 - передача второго байта; 0100 - передача третье байта; 1000 - передача четвертого байта;

waitrequest waitrequest_n

1

вход

Сигнал ожидания завершения транзакции. waitrequest выставляется Svale-ом, в случае, если он не может в данный момент принять входные данные или выдать данные для чтения. Master ожидает пока waitrequest не сбросится, чтобы завершить транзакцию. В это время Master не должен переключать сигналы на шине Avalon-MM.

Как было упомянуто выше, все передачи данных инициализирует Master. Передачи данных осуществляется словами. Разрядность слов настраивается дискретными значениями в диапазоне от 8 бит до 1024 бит. Активные байты в передаваемых словах обозначаются маской в сигналах byteenable или byteenable_n.

Slave может приостановить передачу данных выставив в единицу сигнал waitrequest. Тогда, пока сигнал waitrequest равен 1, Master находится в режиме ожидания и не имеет права переключать сигналы интерфейса. Транзакция может завершиться только когда Slave сбросит сигнал waitrequest в 0 на рис. 2 представлены временные диаграммы записи и чтения данных.

Рис. 2 Временные диаграммы записи и чтения данных по шине Avalon-MM.

  1. Master начинает чтение данных выставляя сигналы address, byteenable и read. Slave выдает данные на readdata в течение следующего такта clk.

  2. Master считывает данные с readdata и сбрасывает сигнал read, заканчивая тем самым операцию чтения данных. И тут же начинает операцию записи данных выставляя сигналы address, byteenable, write и данные на writedata.

  3. Сигнал waitrequest не выставляется в единицу по следующему фронту clk, следовательно по этому фронту заканчивается операция записи. Master сбрасывает сигнал write.

  4. Master выставляет address, byteenable, writedata и write начиная следующую операцию записи. Тут же Slave поднимает сигнал waitrequest, сообщая, что он не готов в данный момент обрабатывать данные. Поэтому Master удерживает без изменения все сигналы шины Avalon-MM.

  5. waitrequest сброшен, и тут операция записи завершается. И сразу Master начинает следующую операцию чтения выставляя сигналы read, address, byteenable. Slave, в свою очередь, поднимает сигнал waitrequest, сообщая, что он занят выполнением другой операции и не может в данный момент выставить данные на выход readdata. На следующем такте Slave выставляет данные на шину readdata и сбрасывает сигнал waitrequest.

  6. waitreqiuest сброшен на следующем фронте сигнала clk, следовательно на этом фронте clk операция чтения завершается.

Реализация интерфейса Avalon-MM Master в виде конечного автомата

Если посмотреть внимательно на временные диаграммы записи чтения данных изображенных на рис. 2, то можно увидеть, что интерфейс при каждой транзакции проходит одни и те же состояния. Следовательно его можно реализовать в виде конечного автомата. Но сначала определим порты для нашего интерфейса Avalon-MM Master.

Порты интерфейса Avalon-MM Master

Представим наш интерфейс Avalon-MM Master как отдельный модуль, встраиваемый в какой-либо процессор или контроллер в следующем виде рис. 3.

Рис. 3 Графическое обозначение модуля Avalon-MM Master.

Описание портов ввода-вывода на языке VHDL для компонента Avalon-MM Master, графическое представление которого изображено на рис. 3, приведено ниже в листинге 1.

Листинг 1: Описание портов ввода\вывода для Avalon-MM Master

PORT(
	nReset 				: IN STD_LOGIC;
	Clock 				: IN STD_LOGIC;
	
	------------ Processor Interface --------------------
	
	CPU_WrEn 			: IN STD_LOGIC;
	CPU_RdEn 			: IN STD_LOGIC;
	CPU_AddrIn 			: IN STD_LOGIC_VECTOR( 7 DOWNTO 0 );
	CPU_WrDataIn 		: IN STD_LOGIC_VECTOR( 31 DOWNTO 0 );
	CPU_ByteEnCode 		: IN STD_LOGIC_VECTOR( 3 DOWNTO 0 );
	CPU_Ready 			: OUT STD_LOGIC;
	CPU_RdDataOut 		: OUT STD_LOGIC_VECTOR( 31 DOWNTO 0 );
	
	---------- Avalon-MM Master interface --------------
	
	avm_readdata 		: IN STD_LOGIC_VECTOR( 31 DOWNTO 0 );
	avm_readdatavalid 	: IN STD_LOGIC;
	avm_address 		: OUT STD_LOGIC_VECTOR( 7 DOWNTO 0 );
	avm_byteenable 		: OUT STD_LOGIC_VECTOR( 3 DOWNTO 0 );
	avm_read 			: OUT STD_LOGIC;
	avm_write 			: OUT STD_LOGIC;
	avm_writedata 		: OUT STD_LOGIC_VECTOR( 31 DOWNTO 0 )
);

Согласно таблице 1, разрядность и шин данных avm_writedata и avm_readdata равны между собой. Разрядность сигналов avm_byteenable равна разрядность шин данных деленной на 8. Каждый бит в avm_byteenable ставится в соответствии байту на шине данных.

Разрядность шина адреса avm_address составляет в данном случае 8 бит. Разрядность шины адреса выбирается в зависимости от того, насколько большие области адресов памяти выделяются для компонентов периферии.

Если в проекте не используются модули встроенной памяти или контроллеры доступа к внешней памяти SDRAM, DDR-DDR3, то скорее всего большая разрядность шины адреса не потребуется.

Однако, если предполагается работа с перечисленными выше контроллера доступа к памяти, то может потребоваться достаточно большая разрядность шины адреса: 8, 16, 24, 32 бита.

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

  • регистр записи данных;

  • регистр чтения данных

  • регистр управления и настройки

  • регистр статуса

Для модулей работы с памятью, в свою очередь, выделяются гораздо большие массивы памяти, что требует большей разрядности шины адреса.

Описание конечного автомата

На рис. 4 представлена диаграмма состояний конечного автомата интерфейса Avalon-MM Master.

Рис. 4 Диаграмма состояний конечного автомата интерфейса Avalon-MM Master

После подачи питания конечный автомат попадает в состояние сброса FSM_RESET. Где сбрасываются в исходные состояния все внутренние переменные и сигналы шины Avalon-MM.

На следующем такте конечный автомат переходит в состояние ожидания FSM_IDLE. Это исходное состояние автомата для работы с шиной Avalon-MM. В этом состоянии автомат ожидает команду от процессора. В листинге 2 представлен исходный код, описывающий это состояние на VHDL.

Листинг 2. Исходный код реализации состояния FSM_IDLE

WHEN FSM_IDLE =>
	IF( CPU_WrEn = '1' ) THEN
		MasterAddr      <= CPU_AddrIn;
		MasterData      <= CPU_WrDataIn;
		FSM_MasterState <= FSM_WRITE;
	ELSIF( CPU_RdEn = '1' ) THEN
		MasterAddr      <= CPU_AddrIn;
		FSM_MasterState <= FSM_READ;
	ELSE
		MasterAddr <= ( OTHERS => '0' );
		MasterData <= ( OTHERS => '0' );
		avm_write  <= '0';
		avm_read   <= '0';
		avm_byteenable <= ( OTHERS => '0' );
		ReadyTmp <= '0';
	END IF;

По сигналам CPU_WrEn и CPU_RdEn происходит предварительное защелкивание адреса и данных с процессора во внутренние переменные конечного автомата.

При появлении единицы на линии CPU_RdEn, конечный автомат переходит в состояние FSM_READ - состояние чтения данных по шине Avalon-MM. Процессор должен вместе с единицей на линии CPU_RdEn выставить адрес на входные линии CPU_AddrIn, с которого он запрашивает чтение данных. И в это же время процессор должен задать код на шине CPU_ByteEnCode, чтобы определить, какие байты на шине данных будут активны.

В состоянии FSM_READ конечный автомат дублирует адрес на шину avm_address, повторяет код с CPU_ByteEnCode на линии avm_byteenable и выставляет единицу на линию avm_read, в соответствии с временными диаграммами на рис. 2. В листинге 3 показан исходный код этого состояния на VHDL

Листинг 3. Исходный код реализации состояния FSM_READ

WHEN FSM_READ =>
	avm_write 		<= '0';
	avm_read 		<= '1';
	avm_address 	<= MasterAddr;
	avm_byteenable 	<= CPU_ByteEnCode;
	FSM_MasterState <= FSM_ACK_READ;

На следующем такте конечный автомат переходит в состояние FSM_ACK_READ - подтверждение чтения данных. В этом состоянии автомат проверяет значение на линии avm_readdatavalid.

Если значение avm_readdatavalid равно единице, значит на линии avm_readdata доступны верные данные. В таком случае эти данные дублируются на выход CPU_RdDataOut и на линию CPU_Ready выставляется единица, как сигнал для процессора, что c интерфейса Avalon-MM Master доступны новые данные для чтения. На следующем такте автомат переходит в исходное состояние FSM_IDLE.

Если же значение avm_readdatavalid равно нулю, то на линию CPU_Ready выставляется ноль и на следующем такте автомат переходит также в исходное состояние FSM_IDLE.

В листинге 4 представлен исходный код реализации состояния FSM_ACK_READ на VHDL.

Листинг 4. Исхjдный код реализации состояния FSM_ACK_READ

WHEN FSM_ACK_READ =>
	IF( avm_readdatavalid = '1' ) THEN
		ReadyTmp 		<= '1';
		RdDataOutTmp 	<= avm_readdata;
		FSM_MasterState <= FSM_IDLE;
	ELSE
		FSM_MasterState <= FSM_IDLE;
		ReadyTmp 		<= '0';
		RdDataOutTmp 	<= ( OTHERS => '0' );
	END IF;

Из состояние FSM_IDLE конечный автомат по единице на входной линии CPU_WrEn переходит в состояние FSM_WRITE. В этом состоянии дублируется значение адреса с линии CPU_AddrIn и код с линии CPU_ByteEnCode на выходные линии avm_address и avm_byteenable соответственно. И выставляется единица на линию avm_write. Исходный код реализации этого состояния представлен в листинге 5.

Листинг 5: Исходный код реализации состояния FSM_WRITE.

WHEN FSM_WRITE =>
	avm_write 		<= '1';
	avm_read 		<= '0';
	avm_address 	<= MasterAddr;
	avm_byteenable 	<= CPU_ByteEnCode;
	avm_writedata 	<= MasterData;
	FSM_MasterState <= FSM_ACK_WRITE;

На следующем такте автомат переходит в состояние FSM_ACK_WRITE, в котором сбрасывается в 0 сигнал на линии avm_write. Это приводит к завершению операции записи данных в периферийный модуль. Исходный код реализации состояния FSM_ACK_WRITE представлен в листинге 7.

Листинг 7. Исходный код реализации состояния FSM_ACK_WRITE.

WHEN FSM_ACK_WRITE =>
	avm_write 		<= '0';
	FSM_MasterState <= FSM_IDLE;

На следующем такте автомат переходит в исходное состояние FSM_IDLE для ожидания новой команды от процессора.

Обработка waitrequest

Конечно не всегда периферийный модуль может за один такт успеть защелкнуть записываемые в него данные либо успеть выдать на следующем такте запрашиваемые в него данные. На этот случай шина Avalon-MM имеет сигнал waitrequest.

Сигнал waitrequest управляется интерфейсом Avalon-MM Slave на периферийном модуле (см. рис. 2). Если периферийный модуль не может в данный момент отреагировать на запрос от Avalon-MM Master, то он выставляет 1 на линию waitrequest. Это приводит к тому, что Avalon-MM Master должен удерживать все сигналы на линии Avalon-MM в текущем состоянии, пока периферийный модуль не сбросить waitrequest в 0. И только тогда Avalon-MM Master сможет завершить текущую операцию записи или чтения.

Обработку сигнала waitrequest лучше всего добавить в состояния FSM_ACK_READ и FSM_ACK_WRITE. Так как в этих состояниях автомат уже выставил все сигналы на шине Avalon-MM, то тут нам только потребуется проверять значения сигнала waitrequest. Пока он равен 1, автомат должен находиться в текущем состоянии, а как только waitrequest будет сброшен в 0, автомат сможет завершить текущую операцию и перейти в состояние FSM_IDLE. Исходные коды реализации состояний FSM_ACK_READ и FSM_ACK_WRITE с обработкой сигнала waitrequest представлены в листинге 8 и 9 соответственно.

Листинг 8. Исходный код реализации сосотяния FSM_ACK_READ с обработкой сигнала waitrequest.

WHEN FSM_ACK_READ =>
	IF( avm_readdatavalid = '1' ) THEN
		ReadyTmp 		<= '1';
		RdDataOutTmp 	<= avm_readdata;
		avm_read 		<= '0';
		FSM_MasterState <= FSM_IDLE;
	ELSE
		ReadyTmp 		<= '0';
		RdDataOutTmp 	<= ( OTHERS => '0' );
		IF( avm_waitrequest = '0' ) THEN
			IF (wait_cycle > 0) THEN
				wait_cycle <= wait_cycle - 1;
			ELSE
				FSM_MasterState <= FSM_IDLE;
			END IF;
		ELSE
			IF( AckCounter > 0 )THEN
				AckCounter := ( AckCounter - 1 );
			ELSE
				FSM_MasterState <= FSM_IDLE;
			END IF;
		END IF;
	END IF;

Листинг 9. Исходный код реализации сосотяния FSM_ACK_WRITE с обработкой сигнала waitrequest.

WHEN FSM_ACK_WRITE =>
	IF( avm_waitrequest = '0' ) THEN
		avm_write		<= '0';
		FSM_MasterState <= FSM_IDLE;
	ELSE
		IF( AckCounter > 0 )THEN
			AckCounter := ( AckCounter - 1 );
		ELSE
			avm_write 		<= '0';
			FSM_MasterState <= FSM_IDLE;
		END IF;
	END IF;

Нужно отметить, что в условие проверки сигнала waitrequest полезно добавить счетчик-таймер, по истечению которого, если периферийный модуль так и не сбросит сигнал waitrequest в 0, то автомат вернется в исходное состояние FSM_IDLE. Таким образом возможное зависание периферийного модуля не приведет к зависанию интерфейса Avalon-MM Master.

В нашем случае мы добавили счетчик AckCounter, который считает от 15 до 0. В состоянии FSM_IDLE значение этого счетчика выставляется равное 15.

Так же нужно отметить, что в состояние FSM_ACK_READ была добавилена задержка в 1 такт на счетчике wait_cycle. Это было сделано для того, чтобы автомат задержался в состоянии FSM_ACK_READ на 1 такт дольше, чтобы дождаться появления 1 на линии avm_readdatavalid.

Отладка конечного автомата Avalon-MM Master

Для отладки работы конечного автомата был написан testbench, достаточно простой. Все окружение, кроме тестируемого интерфейса Avalon-MM Master состояло из конечного автомата, который эмулировал команды процессора - FSM_CPU и модуля встроенной памяти On-Chip Memory с интерфейсом Avalon-MM Slave.

Автомат процессора последовательно задавал команды на запись и чтение данных. Встроенная память была изначально проинициализирована тестовыми данными.

На рис. 5 представлены временные диаграммы работы компонента Avalon-MM Master с встроенной памятью через шину Avalon-MM.

Рис. 5 временные диаграммы работы компонента Avalon-MM Master с встроенной памятью через шину Avalon-MM (приставка TB_ обозначает сигналы из testbench)

Когда процессор начинает операцию записи, он выставляет на линии TB_CPU_WrEn, TB_CPU_AddrIN, TB_CPU_WrDataIn соответсвенно сигнал записи, адрес ячейки (0xAD) и данные, которые требуется записать в память (0xDADA0505).

В свою очередь автомат интерфейса Avalon-MM Master переходит в состояние FSM_WRITE и выставляет на шину Avalon-MM сигнал TB_avm_write равный 1 и дублирует адрес и данные на линии TB_avm_address и TB_avm_writedata соответвтенно.

На следующем такте On-Chip Memory выдает 1 на линию TB_waitrequest, сигнализируя о процессе записи данных в память. После чего процедура записи заканчивается. Автомат интерфейса Avalon-MM Master переходит в состояние FSM_IDLE.

Для начала операции чтения процессор выставляет на линии TB_CPU_RdEn интерфейса Avalon-MM Master единицу и на линии TB_CPU_AddrIN адрес ячейки (0xBB) для чтения данных.

Автомат интерфейса Avalon-MM Master переходит в состояние FSM_READ и выставляет единицу на линии TB_avm_read а так же дублирует адрес ячейки на шину адреса TB_avm_address и выставляет код активных байтов (0xF) на линии TB_avm_byteenable.

На следующем такте On-Chip Memory выдает 1 на линию TB_waitrequest, сигнализируя о процессе чтения данных из памяти. И в следюущий такт считаные данные выставыляются на линию TB_avm_readdata (0x1A2B3C4D) и одновременно с этим выставляется единица на линию TB_avm_readdatavalid, сигнализирующая, что выставлены валидные данные. После чего автомат интерфеса Avalon-MM Master выставляет единицу на линию TB_CPU_Ready, показывая что доступны новые данные для процессора и дублирует данные с линии TB_avm_readdata на выход TB_CPU_RdDataOut. После чего операция чтения завершается.

Заключение

В данной статье был рассмотрен вариант реализации конечного автомата для интерфейса Avalon-MM Master. Данная реализация позволяет встраивать этот интерфейс в свои компоненты, что приводит к повышению степени их повторного использования и упрощает проектирование систем на ПЛИС с использованием инструмента Platform Designer.

Комментарии (0)