Category: FPGA

Ноя 23 2015

Проект видеоадаптера. Часть 3

Продолжение. Часть 2.

Структурная схема видеоадаптера приведена на рис. 1 (кликабельно)

vga-card-big

 

Рис. 1. Структурная схема видеоадаптера.

 

Пояснения к схеме:

В первой версии видеоадаптер будет иметь только текстовый режим EGA, 80 * 25 символов 8 * 14 пикселов каждый символ. Таким образом, экранное разрешение составит 8 * 80 = 640 пикселов по горизонтали и 14 * 25 = 350 пикселов по вертикали. Частота пикселов в этом режиме составляет, по стандарту 25,175 МГц, фактическая частота будет 25 МГц, в связи с тем, что частота тактирования ПЛИС составляет 50 МГц. При этом на любом мониторе происходит нормальная синхронизация.

Read more »

Ноя 05 2015

Проект видеоадаптера. Часть 2

Продолжение. Начало.

Проект видеоадаптера переделан под использование видео ЦАП ADV7123. Схема подключения приведена на рисунке:

VGA_DAC

(по клику откроется полный размер).

Код проекта приведён на гитхабе (ссылка). Это тестовый код, который выводит на монитор поле разноцветных квадратов.

По сравнению с предыдущей версией, в которой использовался резистивный ЦАП, увеличена разрядность с 2-х до 8-и бит на цвет, и существенно улучшилось качество изображения.

Фото тестовой картинки:

pic

 

Окт 02 2015

Драйвер для Linux: первый шаг

Продолжаю эксперименты с Altera Cyclone V. На этот раз объектом эксперимента стал драйвер для той прошивки FPGA, про которую я писал ранее. Сама прошивка простейшая: она просто мигает светодиодами с частотой, которую можно задавать программно. В прошлом посте на эту тему я сделал управление частотой мигания из обычной (user-space) программы, которая получает доступ к физической памяти через функции open(«/dev/mem») и mmap().
Однако такой путь считается «hacky and unsafe». Поэтому следующим логичным шагом должно стать написание драйвера.

Tux-linux-and-ARM-multiplatform-support

Я воспользовался готовым исходником драйвера (ссылка) за авторством Howard Mao (он на самом деле не Howard, а Zhe Hao Mao). Конечно, для того, чтобы разобраться в работе кода, почитал отдельные главы книги Linux Device Drivers (есть русский перевод).

Для компиляции пришлось вытаскивать архив Arrow SocKit 13.1 GSRD Linux отсюда: http://releases.rocketboards.org/release/2013.11/gsrd/src, файл linux-socfpga-gsrd-13.1-src.bsx. Объем архива около 1.1 Гб, но сервер очень медленный, качается несколько часов. Честно говоря, я впервые увидел файл с расширением bsx, оказалось, что это самораспаковывающийся архив. Просто запускаем его и он разворачивается в указанную папку. В ней в папке sources находится файл linux-socfpga.tgz. Его тоже нужно распаковать, естественно. Это и есть как таковое ядро системы, которое нужно указывать при компиляции драйвера.

Однако всё не так просто. После компиляции записываем скомпилированный драйвер blinker.ko на SD-карту, после загрузки Linux пишем insmod blinker.ko и получаем следующее: «blinker: version magic ‘3.9.0-00161-ged01b8c SMP mod_unload ARMv7 p2v8 ‘ should be ‘3.9.0 SMP mod_unload ARMv7 p2v8’«. Не совпали волшебные номерки. Причем версия одна и та же, просто зачем-то к ней приделан какой-то добавочный номер.

Решений может быть три: 1. Скомпилировать Linux именно из этого скачанного исходника (очень неохота) или 2. Подправить номер в исходниках ядра Linux. 3. Использовать команду modprobe с ключом -f, который заставляет систему игнорировать «волшебные цифры».  Однако этот способ почему-то не заработал.
Итак, способ номер 2, подправить номер в исходнике ядра. Данный номер записан в файле /include/generated/utsrelease.h. Исправляем то, что там было, на «3.9.0», и перекомпилируем драйвер. На всякий случай смотрим hex-редактором файл blinker.ko, чтобы убедиться, что волшебные циферки такие, как нужно. Снова записываем драйвер на SD-карту, запускаем insmod, всё прошло гладко. Теперь можно проверить работу драйвера, посылая ему числа от 1 до 15 для управления частотой миганий: echo 1 > blinker — мигает быстро, echo 15 > blinker — мигает медленно. Пока всё. Немного, но путь в тысячу ли начинается с одного шага.

Эксперименты продолжаются.

Сен 23 2015

Управление FPGA из программы

Приведённый ниже код писал не я, он взят отсюда: https://zhehaomao.com/blog/fpga/2013/12/27/sockit-3.html, но я решил оставить его здесь, т.к. он пригодится для дальнейших экспериментов.

Напоминаю, что данная программа работает в ОС Linux GSRD на SoC Altera Cyclone V (ядро ARM Cortex A9). Компилятор Linaro GCC, берём здесь: http://releases.linaro.org/latest/components/toolchain/binaries/4.8/arm-linux-gnueabihf/

#include ;
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PAGE_SIZE 4096
#define LWHPS2FPGA_BRIDGE_BASE 0xff200000
#define BLINK_OFFSET 0x0

volatile unsigned char *blink_mem;
void *bridge_map;

int main(int argc, char *argv[])
{
	int fd, ret = EXIT_FAILURE;
	unsigned char value;
	off_t blink_base = LWHPS2FPGA_BRIDGE_BASE;

	if (argc < 2) {
		fprintf(stderr, "Usage: %s number\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	/* check the bounds of the value being set */
	value = atoi(argv[1]);
	if (value < 1 || value > 15) {
		fprintf(stderr, "Invalid delay setting."
				"Delay must be between 1 and 15, inclusive.\n");
		exit(EXIT_FAILURE);
	}

	/* open the memory device file */
	fd = open("/dev/mem", O_RDWR|O_SYNC);
	if (fd < 0) {
		perror("open");
		exit(EXIT_FAILURE);
	}

	/* map the LWHPS2FPGA bridge into process memory */
	bridge_map = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED,
				fd, blink_base);
	if (bridge_map == MAP_FAILED) {
		perror("mmap");
		goto cleanup;
	}

	/* get the delay_ctrl peripheral's base address */
	blink_mem = (unsigned char *) (bridge_map + BLINK_OFFSET);

	/* write the value */
	*blink_mem = value;

	if (munmap(bridge_map, PAGE_SIZE) < 0) {
		perror("munmap");
		goto cleanup;
	}

	ret = 0;

cleanup:
	close(fd);
	return ret;
}

Программа управляет частотой мигания светодиода, сам делитель частоты расположен в FPGA, частота задаётся регистром.

Read more »

Авг 21 2015

Прошиваем FPGA в run-time

В общем, ничего сложного.
Для того, чтобы заливать прошивку в FPGA из процессорного ядра, нужно сделать следующее:
1. Подготовить файл rbf, это и есть файл прошивки. Он делается из файла sof с помощью утилиты Quartus:

quartus_cpf -c output_files/sockit_test.sof output_files/sockit_test.rbf

Положить этот файл в основной раздел SD-карты, например, в корень.

2. После загрузки linux, отключить мосты между FPGA и HPS (HPS — это процессорное ядро):

echo 0 > /sys/class/fpga-bridge/fpga2hps/enable
echo 0 > /sys/class/fpga-bridge/hps2fpga/enable
echo 0 > /sys/class/fpga-bridge/lwhps2fpga/enable

И заливаем файл в FPGA:

dd if=/sockit_test.rbf of=/dev/fpga0 bs=1M

Собственно, всё. Мосты можно включить обратно, если нужно:

echo 1 > /sys/class/fpga-bridge/fpga2hps/enable
echo 1 > /sys/class/fpga-bridge/hps2fpga/enable
echo 1 > /sys/class/fpga-bridge/lwhps2fpga/enable

Разумеется, всё это можно делать скриптом.
Пишем файл gsrd_init.sh:

#!/bin/sh

echo 0 > /sys/class/fpga-bridge/fpga2hps/enable
echo 0 > /sys/class/fpga-bridge/hps2fpga/enable
echo 0 > /sys/class/fpga-bridge/lwhps2fpga/enable
dd if=/sockit_test.rbf of=/dev/fpga0 bs=1M
echo 1 > /sys/class/fpga-bridge/fpga2hps/enable
echo 1 > /sys/class/fpga-bridge/hps2fpga/enable
echo 1 > /sys/class/fpga-bridge/lwhps2fpga/enable

Кладём его в /etc/init.d. Теперь после загрузки Linux прошивка FPGA будет загружаться автоматически.

Июл 28 2015

SoCKit Lab Instructions

Прочитал и освоил на практике воркбенч SoCKit Lab, две части, Hardware и Software.
Данная программа лабораторных работ основана на системе на кристалле (SoC) Altera Cyclone V. SoC состоит из двух процессорных ядер ARM Cortex A9 и FPGA, которые соединены мостами и могут взаимодействовать друг с другом. Первое руководство, Hardware, выполняется в Quartus II, и описывает конфигурирование и подключение периферии к процессору, а также симуляцию системы в ModelSim.
Вторая часть, Software, описывает процесс загрузки Linux, компиляцию простейшей программы (мигание светодиодом), отладку программы в ARM DS-5 Embedded Development Suite, и основы работы с SignalTap II Logic Analyzer в режиме совместной отладки программного кода и FPGA-проекта.

pic1

Июн 21 2015

Генерация файлов .mif и case-конструкций

Пусть в проекте FPGA необходимо ПЗУ, в которое записана определённая информация, имеющаяся у нас в виде бинарного файла. ПЗУ, как правило, реализуются на блоках BRAM, в которые при инициализации FPGA записывается требуемое содержимое.
Файлы инициализации памяти BRAM для FPGA, могут иметь формат MIF (Memory Initialization File) или формат HEX.

DSC_0522_EDIT

Нужный модуль памяти можно сгенерировать в Quartus II с помощью MegaWizard, в ISE — с помощью Xilinx Core Generator. Кроме этого, в QuartusII возможно использование специальной директивы:

reg [7:0] mem[0:2047] /* synthesis ram_init_file = "test.mif" */;

Эта директива позволяет создать RAM, инициированную значениями из файла .MIF. Использование RAM с предустановленными значениями, это очень плохая идея, но в качестве ROM такую память использовать вполне можно. Проблема в том, что эту директиву понимает только Quartus II, никакой кроссплатформенности.

Quartus II предоставляет редактор файлов памяти, и возможность загрузки файлов .mif и .hex, Xilinx Core Generator требует загрузки файла .coe, имеющего другой формат, нежели MIF. Однако хочется иметь кроссплатформенное решение, которое не зависело бы от платформы. Таким вариантом является генерация ROM в виде case-конструкции:

always@(posedge clk)
begin
  case(in)
  ...
  11'h00d: out = 8'h99;
  11'h00e: out = 8'h81;
  11'h00f: out = 8'h7e;
  11'h010: out = 8'h7e;
  11'h011: out = 8'hff;
  11'h012: out = 8'hdb;
  11'h013: out = 8'hff;
  11'h014: out = 8'hc3;
  11'h015: out = 8'he7;
  11'h016: out = 8'hff;
  ...
  endcase
end

Полезная ссылка: различные конструкции для генерации разных типов RAM, ROM и других модулей можно найти в руководстве Altera «Recommended HDL Coding Styles»: https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/qts/qts_qii51007.pdf
Я написал две простые утилиты, которая преобразует бинарный файл в MIF и в тело конструкции case.

Read more »

Июн 19 2015

FPU. Часть 5. Сумматор, тест и RTL

Итак, сумматор чисел в формате IEEE 754 с разрядностью 32 или 64 бита.
Исходники можно скачать на Github: https://github.com/arktur04/FPU.

КДПВ (кликабельно):

pic1

Read more »

Июн 12 2015

О подсчете нулей

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

Итак, вариант 1:

function [ZERO_DATA_WIDTH - 1: 0] zero_cnt;
input [DATA_WIDTH - 1: 0] in;
integer i;
begin
  zero_cnt = DATA_WIDTH;
  for(i = DATA_WIDTH - 1; i >= 0; i = i - 1)
  begin
    if(in[i] && zero_cnt == DATA_WIDTH)
	   zero_cnt = DATA_WIDTH - i - 1;
  end
end
endfunction

Read more »

Май 28 2015

Книга Pong P. Chu «FPGA prototyping by Verilog examples»

Прочитал книгу «FPGA prototyping by Verilog examples», очень понравилось.
Обычно в таких книгах приводится синтаксис языка и какие-либо примеры проектов, часто далёкие от практики. В этой книге описываюься примеры взаимодействия с периферийными устройствами: клавиатурой, мышью, VGA-мониторм, памятью SRAM. Примеры приведены в расчёте на плату фирмы Digilent с FPGA семейства Spartan-3, но приведённые примеры практически не содержат чего-то специфического именно для данного семейства FPGA.

fpga_vlog_front

Во второй половине книги рассмотрен встраиваемый микроконтроллер PicoBlaze, его ассемблер, и приводятся примеры программ на нём.

В книге рассматривается метод синтеза RTL-кода из ASMD-диаграмм (представление алгоритма, сочетающее в себе графическую блок-схему алгоритма и граф конечного автомата).

Также в книге рассматривается проект простой видеоигры, которую можно сделать на плате Digilent (или на любой другой, если позволяют аппаратные возможности).