Полигон для творчества за 1500 р. Часть 2. Структура платы, 256 UARTов и расширение спектра

l7eqdvsckkjfihk4qsyie7rgl-8.png

Приветствую вас, друзья!

Продолжаем знакомство с платой SX100. Рассмотрим структуру и некоторые любопытные особенности платы, узнаем, как улучшить ЭМС с помощью расширения спектра. Сделаем пару сотен UARTов и доработаем плату.

Вперёд к экспериментам!


В прошлый раз мы познакомились с платой SX100, рассмотрели способы определения распиновки микросхем в корпусах BGA. Один из вариантов — повесить по UART передатчику на выводы и слушать. Пришло время провести этот любопытный эксперимент!

Делаем сотни UARTов


Выводы в корпусах с матрицей шариков (BGA) называются по строке и столбцу, на пересечении которых находятся. Например, например, А5, W22, P7, AA15… Можно попробовать реализовать UART как кольцевой регистр сдвига, передающий нужную строку с именем вывода, разделённую на байты с добавлением старт- и стоп-битов.

z92njff2ahvdfhktvydy38ntxeo.png

Сделаем проще: будем передавать не строки (коды символов) с именами выводов, а числа. Это облегчит генерацию экземпляров UART передатчиков.

Числа сделаем от 0 до 255, чтобы уложиться в 8 бит и посылать 1 байт, а не 2.

Получается, что передатчиков у нас столько же, сколько щупальцев у тридцати двух осьминогов ☺.

u2mkas3rwxs9nmrs_czwm0sijbm.png

Добавим 1 старт-бит, 1 стоп-бит. Поскольку регистр закольцованный, он будет передавать одну и ту же 10-битную посылку постоянно.

Делать скорость UART стандартной необязательно. Сделаем любую удобную, а потом просто впишем её в терминале:

avwdpyxfbprv816jtzi-1vwlub4.png

Поделим частоту 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


Файлы проекта:

qoeabyjm4fh4dcezrur3ucwc6zi.png
Синтезируем наш проект, выводим сигналы на разъёмы. Для быстроты выборочно выведем часть из 256 сигналов: с конца, с середины и начала шины UART_OUT. 

8tq0-u0irjpgmxigobav3ykzlkg.png

Компилируем. Ресурсов проект занимает очень мало. В основном, выводы.

gsd2cjsjk168e-9cyl6gytelzh8.png

Смотрим, что на CLK_100k:

4sbcg_vc-ex67rnzsxojj3xrjzo.png

Выборочно смотрим, что на разъёмах, куда мы вывели наши числа.
R9, число 253.

x_3cjylxv-9bkax9jhzsmeblp1u.png

uvuieasm6mqpab-imnwv1juotbq.png

Число 0. Хорошо видны стоп-бит, старт-бит, 8 бит данных, 1 стоп-бит и 1 старт-бит следующего кадра.

ld681zzzuldu3nnzsyiqoal4sky.png

swk2ia21xnfy98wygsperwdaoly.png

Интересно, что число 85 = 0b0101_0101 выглядит как меандр.

q_b4ekzwwksp5xmdhphdegry5sy.png

Но терминал принимает верно.

uibrmt6jnmszzjyqo79otxacq5g.png

А вот число 170 = 0b1010_1010 терминал принимает неправильно.

wlohql1oprry7sdle6hekkdpgou.png

ekrcn3wcsd6t4xukbaeqwyj5qdk.png

Мы передаём одну за одной посылки вида:

0 (старт-бит) | 8 бит данные | 1 (стоп-бит) | 0 (старт-бит) | 8 бит данные | 1 (стоп-бит) |… И они сливаются в меандр. Можно добавить в наш кадр по одному стоп-биту (лог. 1) или временную задержку в начале и конце.

При необходимости можно добавить передатчикам разные функции. Мы же будем двигаться дальше — нас ждёт ещё много интересного!

Вот она, разница между ПЛИС и микроконтроллером!

Структурная схема платы


Для удобства работы сделаем структурную схему. По мере поступления информации схема может дополняться. Сейчас она имеет такой вид:

7nprvfsqjwlbfysz7jjhsf4vppw.png

В центре схемы ПЛИС. К ней подключено больше всего устройств.
Прошивка загружается в 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.

s55dy20bcs9fmm5shq4rlyzt-c0.png

Вывод выбора канала S1 подключен к земле (низкий уровень), а S0 управляется STM32.

5qjdh2d2baxxyozi5oh9i7z6owk.png

К 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).

mvyzukjvl3rpwxe4fbmugolcdrw.png

С вывода 6-out U41 колебание идёт через R108 = 33 Ом к ПЛИС (на АВ11).
Вывод 5-FS CDCS503 сидит на земле, поэтому умножения нет. Напрашивается вопрос: зачем тогда эта деталь? В названии есть слово «buffer», поэтому можно предположить, что выполняется какая-то изоляция источника синхросигнала от ПЛИС.

Выводы SSC_SEL0, SSC_SEL1 не соединены с землёй, значит, на них высокий уровень, так как есть внутренние подтяжки.

eo7q_ob6dmqksmrsps-qlkler5w.png

Значит есть расширение спектра ±2%.

dgx3xftbgxbglbbmagfmrqhvlvo.png

Интересно, что на выходе генератора (левая часть рисунка) не меандр, а треугольный сигнал. Мне казалось, что на выходе буфера CDCS503 (правая часть рисунка) сигнал будет более красивым (может, для этого микросхему и поставили), но нет. Видно некоторое фазовое дрожание (jitter).

pyevkorda9otm8ontk2230fspke.png

Дрожание в тактовый сигнал добавляется специально, чтобы расширить спектр. Но оно может быть неприемлемым для некоторых периферийных устройств, таких как АЦП, ЦАП и таймеры.
Расширение спектра (SSCG — spread spectrum clock generation) уменьшает пиковую энергию на основной частоте и на её гармониках, что помогает выполнить требования ЭМС. (AN4850 STM32 MCUs spread-spectrum clock generation principles, properties and implementation)
На картинке хорошо видно разницу.

9s6i3mgqdxn41qorsajr_nkbdhc.png

Уровень излучения на частоте 120 МГц снизился примерно на 20 дБ или в 100 раз!

znhvzjoumjchqqm3xqdksb5dc-e.jpeg

На ПЛИС идёт сигнал с генератора без расширения спектра и с расширением после CDCS503. Можно выбрать любой.

Что делать с 74HC245?


Особенность большинства подобных плат в том, что на них установлены микросхемы 74HC245, настроены они на работу в одном направлении (от ПЛИС к разъёмам) и питаются от 5 В, что много для ПЛИС и не позволяет просто изменить направление с помощью вывода DIR. Можно попробовать отпаять вывод Vcc микросхемы 74HC245, изолировать его от пада термоскотчем или соплеклеем и питать от нужного уровня напряжения. C выводом DIR поступить также.
Если нужно убрать 74HC245:

  1. Отпаять и заменить проволочками/кусочком шлейфа fpc с нужным шагом или платкой, как на картинке:

    avdpp0jmdpch_j0oyfhvdd72e0g.png

  2. Использовать гибкие печатные платы:

    7yndlzd3fxo0bo-vej_z7p7a0sm.jpeg

    wcn6mfqxbpsukwabuwlb0jcf_yu.jpeg

    Симпатично. Подробнее здесь.

  3. Встречал вариант замены микросхемы на двунаправленный вариант SN74CBT3245APW. Только смысла большого здесь не вижу: хоть у микросхемы вместо вывода direction (выбор направления) и not connected, но Vcc то всё равно сидит на 5В. Разве что изолировать его от 5 В и подавать нужное напряжение.


Для большей универсальности платы решил отпаять 74HC245 и заменить их перемычками:

09uaq9crjrdt5j3pwmusjj_zgfc.jpeg

Сначала я не очень хотел это делать, ведь мне казалось, что будет долго. Но потом решился, так как это даёт больше возможностей. Сперва я возился с каждой проволочкой и припаял так штук 10. Потом взял правильный пинцет, поменял жало у паяльника на «миниволну», немного приноровился и процесс просто полетел. Всё оказалось не сложнее, чем припаять какой-нибудь резистор 0805. Снизу пинцет «до», а сверху уже удобный для этого случая пинцет «после»:

edp0zldfcswrlc3epdyqxppukfs.jpeg

А отпаивать микросхемы очень удобно сразу двумя паяльниками в две руки. В каждом установить жало «косой нож». Остаётся только отмыть флюс, проверить пайку и можно защищать соплеклеем. Или как-то ещё.

efnzuktlo3z9asgr9lwt2pgc9fs.jpeg

Кому-то нравится ремонтировать технику, узнавая при этом что-то новое и изучая, как оно устроено. Мне же нравится обратная разработка — ощутимо повышается мастерство.

Продолжение следует…


Возможно, захочется почитать и это:

Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале


b5pjofdoxth14ro-rjsrn7sbmiy.png

© Habrahabr.ru