Создание проекта для iCE5 (iCE40 Ultra) в среде iCEcube2

Есть такая фирма Lattice, которая производит микросхемы FPGA (некоторые из них тут продаются, некоторые — фиг). Самое интересное их отличительное качество — размер. Например, серия iCE5 (iCE40 Ultra), имеет вариант корпуса QFN48 7х7мм:
STM32F303 + ice5 Development Board
Вторая микросхема — это stm32f303. Сама плата: STM32F303 + ice5 Development Board. iCE5LP4K не удалось найти, потому поставили iCE5LP2K, да и слот под sd-карты решили не паять.

У микросхемы iCE5LP2K в этом корпусе на борту есть:
  • 2048 логических ячеек;
  • Генератор 48 МГц и 10 кГц, раздельные;
  • Один PLL;
  • Встроенные блоки два I2C и два SPI;
  • 80 кбит набортной оперативной памяти в блоках по 4 кбит;
  • 4 блока DSP (там умножатор с накоплением и что-то такое);
  • Силовой выход с током от 50 мА до 500 мА для ИК-светодиода (с шагом в 50 мА);
  • Три специализированных выхода с током от 4 мА до 24 мА (с шагом в 4 мА) для RGB-светодиодика;
  • Модуль восьмибитного ШИМа (для того же RGB-светодиодика), в iCE5LP4К его, кстати, нет;
  • Конфигурация по SPI или из внутренней одноразовой памяти;
  • 39 доступных ножек.
Это из плюсов. Из минусов — малая распространённость и доступность в России, да и примеров очень мало. Вроде, какие-то мануалы присутствуют, но не сказать, чтоб супер понятные.

Конфигурируется эта FPGA по SPI (~70 КБ), так что в качестве мастера надо или использовать контроллер с достаточной памятью, либо хранить прошивку во внешней какой-нибудь микросхеме. Есть вариант и прошить конфигурацию в сам FPGA, не знаю как, но только один раз. И, конечно, можно хранить прошивку в SPI-флеш 25 серии и подобных. Выбор режима загрузки осуществляется при запуске (ресете), если на ноге CS низкий уровень, то SPI работает в режиме слейва и получает конфигурацию из внешнего контроллера или программатора, если высокий — он становится в режим мастера и загружает конфигурацию из SPI флеш (без дополнительного МК).

Алгоритм загрузки по SPI простой:
  1. CS в низкий уровень
  2. CRST в низкий уровень
  3. Подождать сброса CDONE в низкий уровень
  4. CRST в высокий уровень
  5. Чуток подождать, пока FPGA очухается
  6. Отправить по SPI прошивку (8 бит, MSB, CPHA=0, CPOL=0), все 70 килобайт (в начале прошивки есть какой-то странный заголовок на 80 байт, это норм, так и должно быть, загружать вместе с ним)
  7. После загрузки прошивки в цикле с таймаутом посылаем 0xFF и ждём высокого уровня на CDONE.
  8. После появления CDONE надо отправить ещё зачем-то как минимум 49 клоков (7 байт) и поднять CS.
Конфигурация завершена и FPGA должен работать. Пример кода можно посмотреть в исходниках проекта от этой платы на гитхабе.

А теперь посмотрим, как эту самую прошивку получить, хотя бы в самом минимальном варианте: моргалка светодиодом!

Среда, которая будет заниматься сборкой и склейкой всего этого дела, называется Lattice iCEcube2. Она вообще бесплатная, но лицензию к ней надо получать.
www.latticesemi.com/Support/Licensing.aspx — На офсайте в разделе лицензирования есть ссылка на получение лицензии для iCEcube2. Для лицензии надо указать МАС-адрес сетевой карточки, видимо, привязка к нему идёт.
Эта среда, что странно, не имеет редактора кода. Точнее, там есть подобие блокнота, но редактировать можно только включённые в проект файлы. Создавать новые нельзя. Так что сразу лучше подыскать нормальный редактор для Verilog или VHDL.
Для начала работы в нём хорошо бы ознакомиться с инструкцией: iCEcube201612UserGuide.pdf, там показано очень подробно, как создавать проект и всё такое.
внешний вид

Из отличий с квартусом я заметил только отсутствие атрибутов у сигналов ('left, 'right — ничего этого нет почему-то).

Создание проекта. Выбирается название, тип FPGA, количество ячеек, тип корпуса. Дальше можно добавить файлы или закрыть окно и добавить потом.
создание проекта

Добавим два файла VHDL, один из которых подключит внутренний генератор на 48 МГц (на плате, для которой я пишу тестовый код, нет входа тактирования от стмки, либо его надо пробрасывать проводом), а другой, главный, будет моргать светодиодом.
Не скажу, что я знаток этого дела, так что код может быть весьма так себе, но тем не менее, он работает.

Файл osc.vhd:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity osc is
    port (
        clkhf_pu : in std_logic;
        clkhf_en : in std_logic;
        clkhf : out std_logic
    );
    attribute VPP_2V5_TO_1P8V :boolean;
    attribute VPP_2V5_TO_1P8V of osc : entity is true; --true or false
end osc;

architecture behavior of osc is
    component SB_HFOSC is
        port(CLKHFEN, CLKHFPU : in std_logic;
        CLKHF: out std_logic);
    end component;
    begin
        HFOSCinst0 : SB_HFOSC
        port map
        (
            CLKHFEN => clkhf_en,
            CLKHFPU => clkhf_pu,
            CLKHF => clkhf
        );
end behavior;

Два входа: включение питания генератора clkhf_pu и включение выхода генератора clkhf_en; и один выход — clkhf, тактовый сигнал на 48 МГц.
У компонента SB_HFOSC можно ещё указать две опции, предделитель (выход 48, 24, 12, 6 МГц) и ещё что-то. По умолчанию предделитель /1 и всё работает. Он будет пребупреждать варнингами, что опции не указаны, но это не страшно.

Файл main.vhd:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test is
port (
led1     : out std_logic
);
end test;

architecture RTL of test is
 signal test_cnt : integer range 0 to 23999999 := 0;
 signal test_led : std_logic;

 signal clk : std_logic;

 begin
    osc_inst : entity osc
    port map(clkhf => clk, clkhf_en => '1', clkhf_pu => '1');

    process (clk)
     begin
        if rising_edge(clk) then
            if(test_cnt = 23999999) then
                test_led <= not test_led; 
                test_cnt <= 0;
            else
                test_cnt <= test_cnt + 1;
            end if;  
        end if;
    end process;

    led1 <= test_led;
    
end RTL;

Всего один выход — led1 для светодиода.
После половины секунды переключаем состояние выхода. Получим частоту 1 Гц. Примерно, фз, какая там точность у генератора.

Дальше надо дважды щёлкнуть Run Symplify Pro Synthesis. Если всё ок, то он соберёт и сделает доступным первый пункт в P&R: Import P&R Input Files.
Щёлкаем его. После этого этапа можно указать ножку, куда же выведем моргательный сигнал. Меню: Tool -> Package View.
Tool-Package View

Щёлкаем правой кнопкой по названию сигнала и выбираем пункт Edit Pin Constraint.
Edit Pin Constraint

Там надо указать номер вывода, к которому подцепляем (23, например), тип вывода (SB_LVCMOS, там больше нет вариантов) и отсутствие подтяжки — т.к. выход, подтяжка тут лишняя.
Pin constraint
На плате есть встроенные светодиоды, но они подключены на модуль токовых драйверов, а я пока не знаю, как с ними быть, потому светодиод внешний, на штырьках.

Далее Ctrl-S и сохраняем под каким-нибудь именем файл ограничений, и соглашаемся включить его в проект (он окажется в меню P&R Flow->Add P&R Files->Constraint Files).
Далее щёлкаем Run Placer. Впрочем, если выводы не указывать, то на этом этапе они будут расположены случайным образом.
Пинчики, которые помечены красным крестиком и замочком (переключается в контекстном меню Lock/Unlock) показывают, что их положение задано извне и они не будут скакать куда попало. Просто зелёные — они никуда не были назначены вручную и встали куда сами захотели.


Потом щёлкаем Run Router. И Generate Bitmap. В этот момент в папке ledex\ledex_Implmnt\sbt\outputs\bitmap появились файлы test_bitmap.bin и test_bitmap.hex с прошивкой FPGA, которую можно попробовать закатать в микросхему.

И при изменении VHDL-файлов все этапы должны быть пройдены заново. Очень долго и печально. Вывод ошибок тоже не блещет удобством, но хотя бы по двойному клику может перенести на строку с ошибкой.

Первый проект готов и Lattice iCE5LP2K весело моргает светодиодом. В файле test_bitmap.zip лежит бинарник.

Ссылки:
Файлы в топике: ledex.zip, test_bitmap.zip

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

RSS свернуть / развернуть
Жду, пока в продаже появятся ICE5UP5K, в которой 8 умножителей и 5К ячеек. Вполне вероятно, что туда можно будет вместить весь процессинг OFDM-сигналов (синхронизатор, эквалайзер iFFT и демаппер)…
0
А как вы думаете, на какой частоте возможна работа типовых ЦОС-систем на семействе ICE5UP?
0
Думаю, стабильная работа должнна быть на частоте не выше 50МГц (тот-же внутренний тактовый генератор и SPI расчитаны на 48МГц), это для мультиплексоров и DSP. Память и счётчики можно и до 70-100 МГц разгонять.
www.latticesemi.com/~/media/LatticeSemi/Documents/DataSheets/iCE/iCE40%20UltraPlus%20Family%20Data%20Sheet.pdf?document_id=51968 (раздел 4.19)
0
Не совсем понял с подключением SB_HFOSC. В заголовках нету никаких специфических библиотек. Получается что латтисовские элементы включены в проект по умолчанию? Очень нелогичная и плохая практика.
Вообще печально видеть что софт для ПЛИС застрял в году этак 1998 и никуда двигаться не собирается.
0
Да, я долго тупил и гуглил, в какой же библиотеке латтисовские блоки прописаны, если об этом нигде не сказано, а примеры использования есть в юзермануалах, но обрывками, без указания всего причитающегося к ним.

Но, похоже, что да, как-то их влепили по умолчанию :<
0
Вообще печально видеть что софт для ПЛИС застрял в году этак 1998 и никуда двигаться не собирается.

Вообще для синтеза они дают нахаляву пользоваться Синплифаем — а это что 10лет назад, что сейчас — лучшее что есть для синтеза для ПЛИС.
0
На фоне инструментов для разработки софта или веба, инструментарий для ПЛИС это даже не каменный век, это мезозой. На сушу уже вылезли, но думать еще не особо получается. И даже «принципиально новый» Vivado изнутри оказывается монстром франкенштейна, писанным инопланетными аутсорсерами из всей галактики.
0
Кстати, предлагаю взглянуть на проект SpinalHDL — новый язык, основанный на Scala. Есть куча высокоуровневых плюшек, причём не просто синтаксический сахар, а полезные вещи типа очередей или интерфейсов шин в одну-две строчки. На нём уже написан вполне серьезный SoC c процом Risc-V. Конечно это не решает проблему нехватки нормального IDE, но уже на голову выше допотопного VHDL.
0
Конфигурируется эта FPGA по SPI (~70 КБ), так что в качестве мастера надо или использовать контроллер с достаточной памятью, либо хранить прошивку во внешней какой-нибудь микросхеме.
А это уже сжатый поток, который разжимает сама ПЛИС?
т.е. полученный файл можно сжать дополнительно любым архиватором — размер уменьшается?
0
Это не сжатый поток, просто маска внутренней коммутации. Да, прекрасно сжимается, особенно, если схема нехитрая — почти всё место занимают нули. Тут зипчик 2 кБ вместо 70 =)

В принципе да, в контроллер можно даже RLE какое забабахать или какой-нибудь другой алгоритм сжатия, и получить изрядно сжатый образ.
0
Можно нечто из группы LZ взять. Оно, правда, обычно требует чтобы буфер распакованных данных был доступен, нельзя просто распаковать байт и отправить в SPI. Так что придется лимитировать длину окна, ориентируясь на доступную RAM. Сжатие пострадает, но на таких мелких файлах это не должно быть сильно существенно, а распаковщик компактный, быстрый и простой.
0
P.S. Можно даже взять блочные алгоритмы вроде NRV2E, лимитировать в настройках компрессора окно и переделать декомпрессор под скользящее окно.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.