Вот поделюсь первыми результаты по проекту USBTerm.
Проект в плате Марсоход3bis стартует, программируется SDRAM, во фреймбуффер экрана записываются несколько вертикальных полос, включается видео развертка, отображается изображение из памяти.
Коротко расскажу, как я веду разработку.
Обычно мои инструменты - это текстовый редактор notepad++, симулятор icarus verilog, программа для просмотра временных диаграмм GtkWave, gitbash.
Проект состоит из многих текстовых верилоговских файлов. Я их исправляю в текстовом редакторе notepad++. Он поддерживает много открытых файлов и я могу легко переключаться между ними, просматривать исправлять. При этом, еще я держу открытое окно командной строки cmd. Из него я запускаю BAT файл test.bat, который компилирует верилог файлы компилятором icarus verilog. Это дело пары секунд.
Кроме этого, в моем проекте есть тестбенч tb.v, который как бы представляет из себя всю плату:
Тестбенч создает тактовую частоту clk_100Mhz, которая идет к модулю top (имитация кварцевого генератора платы), модуль top - определяет поведение ПЛИС на плате, а модуль mt48lc4m16a2 - имитирует поведение микросхемы памяти SDRAM платы.
После того, как проект скомпилирован с помощью icarus verilog его довольно просто симулировать. Результат компиляции - файл qqq (задается через параметр "-o" к iverilog). Запускаю симулятор икаруса: vvp qqq. Собственно симуляция проекта - это у меня довольно долгий процесс.
Симуляция идет примерно минут десять, так как мой тестбенч охватывает почти два кадра вертикальной развертки.
Зато потом я могу посмотреть любые интересующие меня временный диаграммы с помощью GtkWave.
Команда из консоли: gtkwave out.vcd.
GtkWave после очередной симуляции не перезапускаю. Просто перезагружаю файл фвременных диаграмм из меню File => Reload Waveform.
Таким образом, весь процесс разработки состоит из простых этапов:
- редактирование текста verilog модулей
- запуск компилятора icarus verilog из консоли BAT файлом test.bat
- запуск симулятора: vvp qqq
- перезагрузка временных диаграмм в GtkWave, просмотр временных диаграмм.
Почему я выбираю icarus? Просто и легковесно. Сам компилятор и симулятор занимает мало места, работа с ними проста и понятна и выполняется легко из командной строки. Icarus Verilog бесплатен и работает с проектами любого размера. Напомню, что входящий в состав Altera Quartus Web Edition симулятор ModelSim Altera имеет ограничение до 10 тысяч строк исполняемого кода. Еще бы понять, что такое "исполняемая строка"... Честно сказать даже не могу сказать 10 тысяч строк - это много или мало.. Хорошо они хоть убрали ограничение и теперь можно симулировать проект содержащий одновременно и Verilog и VHDL..
Однако, есть у iverilog и недостатки:
- с icarus verilog я могу сделать только функциональную симуляцию проекта. Временную сделать невозможно, так как временная симуляция зависит от модели микросхемы ПЛИС и от трассировки сигналов внутри ПЛИС.
- iverilog симулирует только verilog проекты, в то время как последняя версия ModelSim Altera из Quartus Prime Lite Edition уже может симулировать и смешанные проекты Verilog+VHDL
- с iverilog я не могу симулировать модули созданные с Altera Megafunction Wizard, например, модули PLL или модуль FIFO..
Последний пункт конечно досадный. Из за него у меня в проекте есть условная компиляция по переменной __ICARUS__.
Если она определена (а она определена при компиляции с iverilog), то в проект вставляются прототипы модулей, а не реальные модули созданные в Altera Quartus Wizard. Например, вот модуль clocks.v
Этот модуль создает сигнал сброса для всей схемы и выдает три тактовые частоты: частоту mem_clk для контроллера ОЗУ, video_clk - частота пикселов для отображения видео и частота video_clk5 - частота для HDMI видеосигналов tmds (в пять раз больше, чем video_clk):
///////////////////////////////////////////////////////////////
//module which generates all necessary clocks in system
///////////////////////////////////////////////////////////////
module clocks (
input wire clk_100Mhz,
output reg reset,
output reg mem_clk,
output reg video_clk = 0,
output reg video_clk5 = 0
);
`ifdef __ICARUS__
//simplified reset and clock generation for simulator
reg [3:0]rst_delay = 0;
always @(posedge clk_100Mhz)
rst_delay <= { rst_delay[2:0], 1'b1 };
always @*
reset = ~rst_delay[3];
always @*
mem_clk = clk_100Mhz;
always
#6.7 video_clk = ~video_clk;
always
#1.34 video_clk5 = ~video_clk5;
`else
//use Quartus PLLs for real clock and reset synthesis
wire w_locked;
wire w_video_clk;
wire w_video_clk5;
wire w_mem_clk;
mypll u_mypll0(
.inclk0(clk_100Mhz),
.c0(w_video_clk),
.c1(w_video_clk5),
.c2(w_mem_clk),
.locked(w_locked)
);
always @*
begin
reset = ~w_locked;
mem_clk = w_mem_clk;
video_clk = w_video_clk;
video_clk5 = w_video_clk5;
end
`endif
endmodule
Экземпляр модуля mypll вставляется в проект только для реальной компиляции в среде Альтера для ПЛИС. А иначе все частоты просто создаются через временные задержки #6.7 video_clk = ~video_clk; - такие конструкции языка verilog не могут быть синтезированы для реальных чипов, но широко используются во время симуляции проектов.
Кроме PLL у меня в проекте еще есть места, где во время условной компиляции проекта используются альтернативные модули - например, это generic_fifo_dc_gray. Я взял его с opencores и он работает практически так же, как и родное FIFO от Altera. Но, когда я уже делаю сборку проекта в квартусе - естественно используются родные квартусовские FIFO и PLL и ALTDDIO..
Покажу некоторые временные диаграммы.
Инициализация памяти SDRAM.
Это самый первый этап, после включения платы. Контроллер памяти должен настроить микросхему SDRAM в нужный режим работы. При этом назначаются CAS latency, Burst length, Operation mode и прочие параметры. Я использую SDRAM контроллер взятый с opencores.org. Документация к контроллеру и описание принципов работы SDRAM есть в проекте. Я программирую память на burst length = 8, все чтения и запись будут происходить блоками по 8 слов. Планируемая тактовая частота на микросхему SDRAM 148 MHz.
Вот так работает генератор строчных и кадровых импульсов видео сигнала:
Виден кадровый импульс, строчные импульсы, сигнал active показывает, когда на дисплей должны отображаться реальные данные из видеопамяти.
Глядя на эти временные диаграммы можно убедиться, что видеосигнал соответствует спецификации VESA для видео режима 1280x720, 60Hz.
Чтение памяти и отображение пикселов на экране производится через FIFO.
Изначально FIFO пустое. По заднему фронту сигнала кадровой развертки начинается процесс чтения видеопамяти и все, считанные пикселы помещается в FIFO пока оно не заполнится хотя бы на три четверти. Когда заполнилось на 3/4 - read_request уходит в y ноль и чтение из памяти прекращается. Сигнал active от видеосинхронизатора наоборот действует для FIFO как запрос на чтение. Во время отображения пикселов FIFO начинает опустошаться. Как только FIFO опустошается до уровня одной четверти процесс чтения возобновляется. Задача модуля videomem_rd_req поддерживать уровень наполненности фифо. За время развертки оно не должно опустошаться. Добавлю, что разные концы FIFO работают на разной частоте. Запись в фифо идет на частоте работы SDRAM 148MHz. Чтение из фифо идет с частотой pixel_clock 74MHz связанной разверткой. Чем больше разница частот тем лучше - ведь мне еще придется писать в видеопамять. А запись в моем проекте будет иметь меньший приоритет, чем чтение. Чтение нельзя отменить - иначе FIFO пикселов станет пустым. Значит писать в память можно только во время окошек, когда read_request=0.
У нас как-то была статья про использование FIFO с разными частотами на запись и чтение. Вот в этом проекте так же будет несколько частот и для синхронизации потоков данных используется FIFO.
Вы можете взять весь проект с GITHUB https://github.com/marsohod4you/UsbHwThinClient4Vm и используя симулятор icarus verilog и GtkWave посмотреть все другие интересующие вас сигналы.
Следующий этап проекта - нужно сделать запись в видео память из компьютера. Сейчас как раз занимаюсь этим..
Подробнее...