Приветствую вас, друзья!
Продолжаем знакомство с платой SX100. Рассмотрим структуру и некоторые любопытные особенности платы, узнаем, как улучшить ЭМС с помощью расширения спектра. Сделаем пару сотен UARTов и доработаем плату.
Вперёд к экспериментам!
В прошлый раз мы познакомились с платой SX100, рассмотрели способы определения распиновки микросхем в корпусах BGA. Один из вариантов – повесить по UART передатчику на выводы и слушать. Пришло время провести этот любопытный эксперимент!
❯ Делаем сотни UARTов
Выводы в корпусах с матрицей шариков (BGA) называются по строке и столбцу, на пересечении которых находятся. Например, например, А5, W22, P7, AA15… Можно попробовать реализовать UART как кольцевой регистр сдвига, передающий нужную строку с именем вывода, разделённую на байты с добавлением старт- и стоп-битов.
Сделаем проще: будем передавать не строки (коды символов) с именами выводов, а числа. Это облегчит генерацию экземпляров UART передатчиков.
Числа сделаем от 0 до 255, чтобы уложиться в 8 бит и посылать 1 байт, а не 2.
Получается, что передатчиков у нас столько же, сколько щупальцев у тридцати двух осьминогов ☺.
Добавим 1 старт-бит, 1 стоп-бит. Поскольку регистр закольцованный, он будет передавать одну и ту же 10-битную посылку постоянно.
Делать скорость UART стандартной необязательно. Сделаем любую удобную, а потом просто впишем её в терминале:
Поделим частоту 25 МГц с генератора на 250 и получим 100 кГц. Этот сигнал будет тактировать наши UART передатчики. Для деления используем счётчик по модулю 125. Ещё 2 добавит инвертирование.
Код делителя частоты
module clk_div_250(
input clk_in,
output reg clk_out
);
//Инвертируем состояние выхода дважды за период. Получается частота ниже в 2 раза. Поэтому 250/2=125
parameter MODULE = 125;
reg [7:0]count = 1'b0; //счетчик
always @(posedge clk_in)
begin
if(count==MODULE-1)
begin
count <= 0; //обнуляем счетчик
clk_out <= ~clk_out; //Инвертируем состояние выхода
end
else
count <= count + 1'b1; //увеличиваем счетчик
end
endmodule
Код одного экземпляра UART передатчика
//Модуль для постоянной передачи по Юарт пакетов
//вида 1 старт-бит =0, 8 бит данных, 1 стоп-бит =1
module cycled_uart_transmitter(
input clk, //Тактовый сигнал
output reg Tx //Информационный выход
);
// Данные. Максимум 255
parameter data = 8'b1010_1010;
// хранилище данных 10 бит.
reg [9:0] uart_data;
reg [3:0]i= 1'b0; //счетчик битов = 0
always @ (posedge clk) //с каждым тактом
begin
//Записываем начальное значение регистра
uart_data[0] <= 0;//1 старт-бит = 0,
uart_data[8:1] <= data;//8 бит данных,
uart_data[9] <= 1;//1 стоп-бит = 1
Tx <= uart_data[i]; //отправили 1 бит данных
i <= i + 1'b1; //перешли к следующему биту данных
if(i==9) // если все 10 бит отправлены
begin
i <= 0; //обнулить счетчик битов
end
end
endmodule
Теперь нам нужно создать схему, в которой мы установим 1 делитель частоты на 250 и 256 экземпляров UART передатчиков. Если рисовать это на схеме, будет ооочень долго. Можно прописывать соединения на языке Verilog, описывая каждый модуль вручную. Это быстрее, но тоже долго.
Поэтому мы используем цикл и конструкцию «generate». Здесь нам будет проще из-за передачи чисел, а не строк. Мы просто передадим передатчикам в качестве параметра текущее значение счётчика цикла генерации. Получается вот такое небольшое описание. Красота!
Штампуем 256 передатчиков
//Модуль создания сотен Юартов. В данном случае будет 256.
module top_100s_of_UARTs(
input CLK_IN,
output CLK_100k,//Выведем сигнал, чтобы проверить осциллографом
output [255:0]UART_OUT//Шина 256-ти выходов UART
);
wire clk_100k;//Выход частоты 100 кГц
clk_div_250 clk_div_250_0(//Счётчик-делитель на 250
.clk_in(CLK_IN),
.clk_out(clk_100k)
);
//Далее создаём 256 экземпляров UART передатчика (cycled_uart_transmitter)
genvar n;//Счётчик для цикла
generate
for(n = 0; n < 256; n = n + 1 )
begin : cycled_uart_transmitter_generation
//имя экземпляра не имеет значения в дальнейшем
//Здесь переопределяем параметр каждого экземпляра Юарт знаком #
//Все юарты передают число n от 0 до 255.
//Каждый новый Юарт будет передавать своё число.
cycled_uart_transmitter #(n) cycled_uart_transmitter_insts
(
.clk(clk_100k),//На вход подаём 100 кГц
.Tx(UART_OUT[n]) //Выход UART
);
end
endgenerate
assign CLK_100k = clk_100k;
endmodule
Файлы проекта:
Синтезируем наш проект, выводим сигналы на разъёмы. Для быстроты выборочно выведем часть из 256 сигналов: с конца, с середины и начала шины UART_OUT.
Компилируем. Ресурсов проект занимает очень мало. В основном, выводы.
Смотрим, что на CLK_100k:
Выборочно смотрим, что на разъёмах, куда мы вывели наши числа.
R9, число 253.
Число 0. Хорошо видны стоп-бит, старт-бит, 8 бит данных, 1 стоп-бит и 1 старт-бит следующего кадра.
Интересно, что число 85 = 0b0101_0101 выглядит как меандр.
Но терминал принимает верно.
А вот число 170 = 0b1010_1010 терминал принимает неправильно.
Мы передаём одну за одной посылки вида:
0 (старт-бит) | 8 бит данные | 1 (стоп-бит) | 0 (старт-бит) | 8 бит данные | 1 (стоп-бит) | … И они сливаются в меандр. Можно добавить в наш кадр по одному стоп-биту (лог. 1) или временную задержку в начале и конце.
При необходимости можно добавить передатчикам разные функции. Мы же будем двигаться дальше – нас ждёт ещё много интересного!
Вот она, разница между ПЛИС и микроконтроллером!
❯ Структурная схема платы
Для удобства работы сделаем структурную схему. По мере поступления информации схема может дополняться. Сейчас она имеет такой вид:
В центре схемы ПЛИС. К ней подключено больше всего устройств.
Прошивка загружается в FPGA микроконтроллером Nuvoton NUC123LD4AN0 из flash-памяти 128 Мбит по SPI1 в пассивном последовательном (PS) режиме. Нувотон можно сбросить, и загружать конфигурацию ПЛИС по JTAG, что мы и делаем в процессе экспериментов.
Соответствующие выводы RGB HDMI приёмника и передатчика соединены между собой. Например, Hsync микросхемы ADV7612 соединён с Hsync ADV7511, R0…R7 – c R0…R7 и т д. Получается, принятый HDMI –> RGB сигнал можно подать на ПЛИС и HDMI передатчик одновременно. Другой вариант – отключить HDMI приёмник и подавать на передатчик сигнал с ПЛИС.
А ещё на плате необычное подключение между микроконтроллерами STM32 и Nuvoton NUC123LD4AN0: не напрямую по UART, а через HC4052.
Вывод выбора канала S1 подключен к земле (низкий уровень), а S0 управляется STM32.
К nY1 подключен UART STM32. Что подключено к nY0?
Можно подумать, что к микроконтроллеру Нувотон подключается какое-то ещё устройство по UART0. Но почему тогда не он переключает каналы с помощью S0, а STM32? Выходит другого устройства нет и STM32 просто отключает внука от своего UART1. Только зачем?
Если бы к UART1 STM32 было подключено ещё какое-то устройство, то при таком подключении HC4052 и выбора канала с Нувотоном, к UART1 STM32 оказались бы подключены сразу 2 устройства. Видимо, кроме Нувотона к UART1 STM32 ничего не подключено, а STM32 просто иногда хочет побыть наедине. Немного странное решение.
Выводы 86 (USART2_TX), 87 (USART2_RX) STM32 выведены на гребёнку, но ничего интересного там не происходит.
❯ Схема тактирования и расширение спектра
Колебание 25 МГц генерируется микросхемкой с маркировкой X2 A0KGF. Найти точно такую же не удалось, но корпусом и распиновкой похоже на SiT2024B.
Сигнал 25 МГц (c выв 5 Х2) через резистор R180 = 33 Ом идёт к ПЛИС (на AA12) и на clock buffer/multiplier U41 (на вывод 1-in).
С вывода 6-out U41 колебание идёт через R108 = 33 Ом к ПЛИС (на АВ11).
Вывод 5-FS CDCS503 сидит на земле, поэтому умножения нет. Напрашивается вопрос: зачем тогда эта деталь? В названии есть слово «buffer», поэтому можно предположить, что выполняется какая-то изоляция источника синхросигнала от ПЛИС.
Выводы SSC_SEL0, SSC_SEL1 не соединены с землёй, значит, на них высокий уровень, так как есть внутренние подтяжки.
Значит есть расширение спектра +-2%.
Интересно, что на выходе генератора (левая часть рисунка) не меандр, а треугольный сигнал. Мне казалось, что на выходе буфера CDCS503 (правая часть рисунка) сигнал будет более красивым (может, для этого микросхему и поставили), но нет. Видно некоторое фазовое дрожание (jitter).
Дрожание в тактовый сигнал добавляется специально, чтобы расширить спектр. Но оно может быть неприемлемым для некоторых периферийных устройств, таких как АЦП, ЦАП и таймеры.
Расширение спектра (SSCG – spread spectrum clock generation) уменьшает пиковую энергию на основной частоте и на её гармониках, что помогает выполнить требования ЭМС. (AN4850 STM32 MCUs spread-spectrum clock generation principles, properties and implementation)
На картинке хорошо видно разницу.
Уровень излучения на частоте 120 МГц снизился примерно на 20 дБ или в 100 раз!
На ПЛИС идёт сигнал с генератора без расширения спектра и с расширением после CDCS503. Можно выбрать любой.
❯ Что делать с 74HC245?
Особенность большинства подобных плат в том, что на них установлены микросхемы 74HC245, настроены они на работу в одном направлении (от ПЛИС к разъёмам) и питаются от 5 В, что много для ПЛИС и не позволяет просто изменить направление с помощью вывода DIR. Можно попробовать отпаять вывод Vcc микросхемы 74HC245, изолировать его от пада термоскотчем или соплеклеем и питать от нужного уровня напряжения. C выводом DIR поступить также.
Если нужно убрать 74HC245:
- Отпаять и заменить проволочками/кусочком шлейфа fpc с нужным шагом или платкой, как на картинке:
- Использовать гибкие печатные платы:
Симпатично. Подробнее здесь. - Встречал вариант замены микросхемы на двунаправленный вариант SN74CBT3245APW. Только смысла большого здесь не вижу: хоть у микросхемы вместо вывода direction (выбор направления) и not connected, но Vcc то всё равно сидит на 5В. Разве что изолировать его от 5 В и подавать нужное напряжение.
Для большей универсальности платы решил отпаять 74HC245 и заменить их перемычками:
Сначала я не очень хотел это делать, ведь мне казалось, что будет долго. Но потом решился, так как это даёт больше возможностей. Сперва я возился с каждой проволочкой и припаял так штук 10. Потом взял правильный пинцет, поменял жало у паяльника на «миниволну», немного приноровился и процесс просто полетел. Всё оказалось не сложнее, чем припаять какой-нибудь резистор 0805. Снизу пинцет «до», а сверху уже удобный для этого случая пинцет «после»:
А отпаивать микросхемы очень удобно сразу двумя паяльниками в две руки. В каждом установить жало «косой нож». Остаётся только отмыть флюс, проверить пайку и можно защищать соплеклеем. Или как-то ещё.
Кому-то нравится ремонтировать технику, узнавая при этом что-то новое и изучая, как оно устроено. Мне же нравится обратная разработка – ощутимо повышается мастерство.
Продолжение следует…