Микровычислители
Микросхема 5400ТР065А-022 содержит два независимых специализированных микровычислителя (CPU), разработанных для выполнения следующих целей:
- Упрощение настройки коэффициентов за счет буфферизации внутренних сигналов преобразователей
- Согласование отсчетов в многополюсных датчиках
- Корректировка статических нелинейностей датчика угла
- Расчет угловой скорости, ускорения, фильтрация угла
Наличие двух CPU (вместо одного) обусловлено оптимизацией производительности вычислений под средний темп расчета управления электроприводом 50-150мкс, для чего один CPU выполняет роль исправления нелинейностей, а второй - роль рассчета скорости и ускорения. Аналоговая база кристалла и используемая в микросхеме радиационно-стойкая технология обсловили жетскую оптимизацию ресурсвов CPU - нестандартную разрядность в 14 бит, сокращенный набор команд (48), сокращенный набор регистров общего назначения(8 штук 28-56 бит), и экстремально малый объем памяти программ/данных(240 ячеек 14бит для каждого CPU + буффер на 128 ячеек).
Чтение данных с преобразователя
Подключение СPU1 CPU2 к преобразователям (HAND1 HAND2) осуществляется симметрично: для cpu1 "родным" (или "own") является HAND1, а внешним ("ext") является HAND2, для cpu2 родным является HAND2, а ext является HAND1. Считывание данных производится с двойной шириной слова (28 бит): c own по адресам 252 253, а с ext по адресам 254 255. Выбор номера паря ячеек преобразователя выполняется командой SET_A_HAND #ADDR.
| #ADDR | Ячейка |
|---|---|
| 0 | FullAngle[27:0] |
| 1 | { Wca[11:0], BScos[12], ex_shifted, Wsa[11:0], BSsin[12], ex_ref } |
| 2 | { VirtualS[12:0], ex_recovered, BSsin[12:0], ex_recovered_90dgr } |
| 3 | { Amp_metric[11:0], Err_metric[15:0] } |
| 4 | FullVel[27:0] |
| 5 | { PhiC[15:2], PhiS[15:2] } |
| 6 | { VirtualC[12:0], ex_recovered, BScos[12:0], ex_recovered_90dgr } |
| 7 | { Pole_addi, STAT } |
Запись данных в преобразователь
Доступ к записи в каждый преобразователь данных есть только у одного CPU. Выбор какой именно CPU имеет доступ на запись определяется конфигурационным битом HandToEXT у каждого преобразователя. CPU может инвертировать действие флага HandToEXT с помощью команд SW_HTE1 или SW_HTE2 где цифра в команде обозначает номер преобразователя.
Запись Coord Vel
Результаты вычислений CPU могут быть записаны в блок гистериза скорости и координаты (для эмуляции энкодера, сэмплирования и т.п.). Для этого в конфигурации требуется установить соответствующий флаг Coord_from_cpu, Vel_from_cpu (или оба) и произвести запись установив командой SET_A_HAND соответствующий адрес (0 для координаты, 4 для скорости).
Запись Pole_addi
Для записи добавочного значения полюса Pole_addi требуется выставить командой SET_A_HAND адрес 3. Запись будет возможна если источник записи определен как CPU c помощью установки бита PoleAddi_src.
Структура памяти/программ

При включенной функции инициализации (бит INIT_on) в первые 232 ячейки обоих CPU переписываются данные из ПЗУ с последовательным доступом. В остальные ячейки с адресами доступными для записи\чтения по SPI записываются нули. Первые 96 ячеек доступны только для чтения ядром CPU. Ячейки с адресами в диапазоне [96 ... 239] доступны как для чтения, так и для записи.
Ячейки обмена данными CPU
Ячейки с адресами 240...247 предназначены для передачи данных между CPU. Шины чтения у этих ячеек подключены к неродным ядрам CPU, так что чтение по адресам 240..247 одним CPU будет тех значений что записаны другим CPU и наоборот.
Ячейки обмена с интерфейсом SPI
Ячейки с адресами 240...247 предназначены для передачи данных между CPU. Шины чтения у этих ячеек подключены к неродным ядрам CPU, так что чтение по адресам 240..247 одним CPU будет тех значений что записаны другим CPU и наоборот.
Буфферы
В микросхему добавлены два допольнительных куска памяти BUF1 BUF2 по 64 ячейки каждый. По умолчанию BUF1 расширяет память CPU1, а BUF2 - CPU2; адреса ячеек в диапазоне 256..319. При необходимости буффер может быть переключен на неродной CPU с помощью установки битов SHRD_RAM и SHRD_CPU2 в соответствии с их описанием. В этом случае для работы у одного из CPU добавляется 128 ячеек данных, доступных по адресам 256 ... 383.
Регистры общего назначения
Для реализации микропрограмм CPU содержит 8 регистров. Первые 6 R0...R5 имеют разрядность 28 бит, последние два R6, R7 -разрядность 56 бит. R6 всегда перезаписывается результатом выполнения подфукнции умножения/сдвига при выполнении команд MULTI, MULTI_ACC, MULTF, MULTF_ACC, MULTCUBE_ACC, DEC2FLOAT. R7 всегда используется и перезаписывается при реализации команд ACC, ACC2, MULTI_ACC, MULTF_ACC, MULTCUBE_ACC. Загрузка/сохранение R6 или R7 доступна только в 28 битном и 56 формате (сразу из/в 2 или 4 последовательные ячейки), загрузить/сохранить младшие 14 бит R6 R7 одну ячейку невозможно. Для 56 битных операции доступа с памятью использовать команды CLOAD, LOAD, STORE,CSTORE c аргументом R6 или R7. При выполнении чтения из памяти данного меньшей разрядности, то его старший разряд разножается до разрядности регистра общего назначения.
| Команда | Аргументы | Такты | Ячейки | Диапазон адресов | Фактический адрес |
|---|---|---|---|---|---|
| STORE | R0 ... R5 | 4 | 1 | 128...255 | address_ram + 128 |
| LOAD | R0 ... R5 | 4 | 1 | 128...255 | address_ram + 128 |
| CSTORE | R0 ... R5 | 4 | 1 | 128...255 | address_ram + 128 |
| CLOAD | R0 ... R5 | 4 | 1 | 128...255 | address_ram + 128 |
| STORE32 | R0 ... R5 | 4 | 2 | 64...318 (четные) | address_ram * 2 + 64 |
| LOAD32 | R0 ... R5 | 4 | 2 | 64...318 (четные) | address_ram * 2 + 64 |
| CSTORE32 | R0 ... R5 | 4 | 2 | 64...318 (четные) | address_ram * 2 + 64 |
| CLOAD32 | R0 ... R5 | 4 | 2 | 64...318 (четные) | address_ram * 2 + 64 |
| STORE | R6, R7 | 6 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
| LOAD | R6, R7 | 5 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
| CSTORE | R6, R7 | 6 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
| CLOAD | R6, R7 | 5 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
| STORE32 | R6, R7 | 4 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
| LOAD32 | R6, R7 | 4 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
| CSTORE32 | R6, R7 | 4 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
| CLOAD32 | R6, R7 | 4 | 4 | 64...318 (четные) | address_ram * 2 + 64 |
Адрес команд загрузки/сохранения с префиксом C суммируется с регистром rel = ch0 + ch1 * 2 + ch2 * 4 + ch3 * 8;
Регистр ch7 используется для команд MULTCUBE_ACC,CLOAD_CUBE. Значения ch0..ch3, ch7 устанавливаются командами CFIX.
Адрес команд чтения/загрузки пары ячеек всегда умножается на 2, в результате ячейка с четным адресом заносится/считывается в/из младшую часть регистра общего назначения, а нечетная ячейка (с адресом +1) в сташую часть регистра общего назначения 28 бит. Для команд чтения/загрузки 4 ячеек формат аналогичен : {data[addr+3], data[addr+2], data[addr+1], data[addr]}
Система команд
Выполнение команд
Каждая операция выполняется 4 такта FINT. Операции умножения/сдвига и аккумулятора MULTF, MULTF_ACC, MULTCUBE_ACC, DEC2FLOAT выполняются больше 4 тактов, но не блокируют выполнение других операций только если аргумент последних не перезаписывается операцией умножения/сдвига или аккумулятора.
28-битный формат с плавающей запятой
- Формат является усечённым IEEE754 float32
- Нет NaN / Inf / denormal
Структура форматаs
| Поле | Биты | Длина | Описание |
|---|---|---|---|
| Sign | 27 | 1 | 0 = +, 1 = − |
| Exp | 26..20 | 7 | Порядок, bias = 63 |
| Mant | 19..0 | 20 | Мантисса (IEEE754 fraction >> 3) |
Кодирование (Float32 → Float28)
v = single(x)(IEEE754 float32)- Извлечь поля IEEE754:
Sign = bit31Exp32 = bits30..23Frac32 = bits22..0
- Порядок:
- если
Exp32 == 0:Exp28 = 0 - иначе
Exp28 = Exp32 − 127
- если
Exp = Exp28 + 63Mant = Frac32 >> 3- Упаковка:
Float28 = (Sign << 27) | (Exp << 20) | Mant
Float28 → Float32
- Извлечь поля:
Sign = bit27Exp = bits26..20Mant = bits19..0
- Восстановление:
Exp32 = Exp − 63 + 127Frac32 = Mant << 3
- Собрать IEEE754 float32:
Value = Sign × (1 + Frac32 / 2^23) × 2^(Exp − 63)
Float28 → Integer
INTvalue = Sign × Mant × 2^(Order - 63)
Sign = +1если бит 27 = 0, иначе-1Mant= целое значение бит 19..0Order= целое значение бит 26..2063= смещение порядка
Система команд
| Имя | Код операции | Аргумент | Аргумент | Аргумент | Описание |
|---|---|---|---|---|---|
| NOP | 00000000000 | count ###(2:0) | stop cpu DELAY count cycles | ||
| CLR | 00000000001 | A ###(2:0) | A = 0 | ||
| INC | 00000000010 | A ###(2:0) | A = A + 1 | ||
| DEC | 00000000011 | A ###(2:0) | A = A - 1 | ||
| ABS | 00000000100 | A ###(2:0) | A = |A| | ||
| SIN | 00000000101 | A ###(2:0) | A = {{12{cordic_sin[15]}}, cordic_sin[15:0]}, cordic_sin = sin(A[17:0]), cordic_cos = sin(A[17:0]), where result - signed 16bit, argument - unsigned 18bit | ||
| COS | 00000000110 | A ###(2:0) | A = {{12{cordic_cos[15]}}, cordic_cos[17:0]} | ||
| ACC | 00000000111 | A ###(2:0) | R7 = R7 + A | ||
| ACC2 | 00000001 | B ###(5:3) | A ###(2:0) | R7 = R7 + A + B | |
| ATAN | 00000010 | B ###(5:3) | A ###(2:0) | A[27:0] = {12'b0, atan(B[15:0], A[15:0])}, B - cos argument, A - sin argument | |
| ADD | 00000011 | B ###(5:3) | A ###(2:0) | A = A + B | |
| SUB | 00000100 | B ###(5:3) | A ###(2:0) | A = A - B | |
| ORL | 00000101 | B ###(5:3) | A ###(2:0) | A = A | B | |
| ANL | 00000110 | B ###(5:3) | A ###(2:0) | A = A & B | |
| MOVE | 00000111 | B ###(5:3) | A ###(2:0) | A = B | |
| LSL | 000010 | count #####(7:3) | A ###(2:0) | A = A << (count +1) | |
| ASR | 000011 | count #####(7:3) | A ###(2:0) | A = A >> (count +1) | |
| STORE | 0001 | address_ram #### ###(9:3) | A ###(2:0) | ram[address_ram] = A[13:0] | |
| STORE32 | 0010 | address_ram #### ###(9:3) | A ###(2:0) | ram[address_ram] = A[13:0], ram[address_ram+1] = A[27:14] | |
| LOAD | 0011 | address_ram #### ###(9:3) | A ###(2:0) | A[27:0] = {{14{T[13]}}, T[13:0]}, where T[13:0] = ram[address_ram] | |
| EQUAL | 010 | rel[4:0] #####(10:6) | B ###(5:3) | A ###(2:0) | PC = A == B ? PC + rel : PC, where rel = [-16 … 15] |
| MORE | 011 | rel[4:0] #####(10:6) | B ###(5:3) | A ###(2:0) | PC = A > B ? PC + rel : PC, where rel = [-16 … 15] |
| CLOAD | 1000 | address_ram #### ###(9:3) | A ###(2:0) | A[27:0] = {{14{T[13]}}, T[13:0]}, где T[13:0] = ram[address_ram + rel] | |
| CSTORE | 1001 | address_ram #### ###(9:3) | A ###(2:0) | ram[address_ram + rel] = A[13:0] | |
| CSTORE32 | 1010 | address_ram #### ###(9:3) | A ###(2:0) | ram[address_ram + rel] = A[13:0], ram[address_ram + rel + 1] = A[27:14] | |
| CLOAD32 | 1011 | address_ram #### ###(9:3) | A ###(2:0) | A[27:0] = {ram[address_ram + rel+1], ram[address_ram + rel]} | |
| LOAD32 | 1100 | address_ram #### ###(9:3) | A ###(2:0) | A[27:0] = {ram[address_ram +1], ram[address_ram]} | |
| CONST | 1101 | const ### ####(9:3) | A ###(2:0) | A[27:0] = {{22{const[6]}}, const[6:0]} | |
| DJNZ | 11100 | rel[5:0] ######(8:3) | A ###(2:0) | PC = A == 0 ? PC : PC + rel, A == 0 ? A = 0 : A = A - 1, rel = [-32 … 31] | |
| CDJNZ | 111010 | rel #####(7:3) | ch# ###(2:0) | PC = ch# == 0 ? PC : PC + rel, ch# == 0 ? ch# = 0 : ch# = ch# - 1, rel = [-16 … 15] | |
| EQUAL0 | 111011 | rel #####(7:3) | A ###(2:0) | PC = A == 0 ? PC + rel : PC, rel = [-16…15] | |
| JUMP | 111100 | rel #######(7:0) | PC = PC + rel | ||
| MULTI | 11110100 | B ###(5:3) | A ###(2:0) | R6 = A * B где, A decimal 28bit and B - decimal 24bit, R6 - 52bit | |
| MULTI_ACC | 11110101 | B ###(5:3) | A ###(2:0) | R6 = A * B, R7 = R7 + R6, where A - decimal 28bit and B - decimal 24bit | |
| MULTF | 11110106 | B ###(5:3) | A ###(2:0) | R6 = A * B, where A - decimal 28bit, B = float 28bit, res - decimal int 56 bit | |
| MULTF_ACC | 11110111 | B ###(5:3) | A ###(2:0) | R6 = A * B, R7 = R7 + R6, where A - decimal 28bit, B = float 28bit, res - decimal int 56 bit | |
| MULTK24 | 11111011 | B ###(5:3) | A ###(2:0) | A[27:0] = RES[51:22], RES[51:0] = A[27:0] * B[23:0]; integer | |
| MULTK14 | 11111100 | B ###(5:3) | A ###(2:0) | A[27:0] = RES[40:13], RES[51:0] = A[27:0] * B[27:0]; integer | |
| MULTCUBE_ACC | 11111101 | B ###(5:3) | A ###(2:0) | R6 = (ch1+1)^(ch7+1) * (B + A), R7 = R7 + R6, int | |
| DEC2FLOAT | 11111110000 | A ###(2:0) | R6 = float(A) | ||
| SET_A_HAND | 11111110001 | const ###(2:0) | D[180:181] = OWNHAND(const), D[182:183] = EXTHAND(const) | ||
| HFIX | 11111110010 | A ###(2:0) | |||
| REZERVED2 | 11111110011 | A ###(2:0) | |||
| CFIX0 | 11111110100 | A ###(2:0) | ch0[8:0] = A[8:0] | ||
| CFIX1 | 11111110101 | A ###(2:0) | ch1[7:0] = A[7:0] | ||
| CFIX2 | 11111110110 | A ###(2:0) | ch2[6:0] = A[6:0] | ||
| CFIX3 | 11111110111 | A ###(2:0) | ch3[5:0] = A[5:0] | ||
| CFIX4 | 11111111000 | A ###(2:0) | ch4[4:0] = A[4:0] | ||
| CFIX7 | 11111111001 | A ###(2:0) | ch7[1:0] = A[1:0] | ||
| CLR_CH | 11111111010 | ch# ###(2:0) | ch# = 0 | ||
| CLOAD_CUBE | 11111111011 | A ###(2:0) | A = (ch1+1)^(ch7+1) | ||
| RJUMP | 11111111100 | A ###(2:0) | PC = A, A = PC+1 | ||
| STOREPC | 11111111101 | A ###(2:0) | A = PC + 2 | ||
| SETB_STP | 11111111110000 | STP = 1 | |||
| CLRB_STP | 11111111110001 | STP = 0 | |||
| SW_HTE1 | 11111111110010 | change sel multiplexer handler1 to another CPU | |||
| SW_HTE2 | 11111111110011 | change sel multiplexer handler 2 to another CPU |