Skip to main content

Микровычислители

Микросхема 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Ячейка
0FullAngle[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] }
4FullVel[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. При выполнении чтения из памяти данного меньшей разрядности, то его старший разряд разножается до разрядности регистра общего назначения.

КомандаАргументыТактыЯчейкиДиапазон адресовФактический адрес
STORER0 ... R541128...255address_ram + 128
LOADR0 ... R541128...255address_ram + 128
CSTORER0 ... R541128...255address_ram + 128
CLOADR0 ... R541128...255address_ram + 128
STORE32R0 ... R54264...318 (четные)address_ram * 2 + 64
LOAD32R0 ... R54264...318 (четные)address_ram * 2 + 64
CSTORE32R0 ... R54264...318 (четные)address_ram * 2 + 64
CLOAD32R0 ... R54264...318 (четные)address_ram * 2 + 64
STORER6, R76464...318 (четные)address_ram * 2 + 64
LOADR6, R75464...318 (четные)address_ram * 2 + 64
CSTORER6, R76464...318 (четные)address_ram * 2 + 64
CLOADR6, R75464...318 (четные)address_ram * 2 + 64
STORE32R6, R74464...318 (четные)address_ram * 2 + 64
LOAD32R6, R74464...318 (четные)address_ram * 2 + 64
CSTORE32R6, R74464...318 (четные)address_ram * 2 + 64
CLOAD32R6, R74464...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

ПолеБитыДлинаОписание
Sign2710 = +, 1 = −
Exp26..207Порядок, bias = 63
Mant19..020Мантисса (IEEE754 fraction >> 3)

Кодирование (Float32 → Float28)

  1. v = single(x) (IEEE754 float32)
  2. Извлечь поля IEEE754:
    • Sign = bit31
    • Exp32 = bits30..23
    • Frac32 = bits22..0
  3. Порядок:
    • если Exp32 == 0: Exp28 = 0
    • иначе Exp28 = Exp32 − 127
  4. Exp = Exp28 + 63
  5. Mant = Frac32 >> 3
  6. Упаковка: Float28 = (Sign << 27) | (Exp << 20) | Mant

Float28 → Float32

  1. Извлечь поля:
  • Sign = bit27
  • Exp = bits26..20
  • Mant = bits19..0
  1. Восстановление:
  • Exp32 = Exp − 63 + 127
  • Frac32 = Mant << 3
  1. Собрать IEEE754 float32: Value = Sign × (1 + Frac32 / 2^23) × 2^(Exp − 63)

Float28 → Integer

INTvalue = Sign × Mant × 2^(Order - 63)

  • Sign = +1 если бит 27 = 0, иначе -1
  • Mant = целое значение бит 19..0
  • Order = целое значение бит 26..20
  • 63 = смещение порядка

Система команд

ИмяКод операцииАргументАргументАргументОписание
NOP00000000000count ###(2:0)stop cpu DELAY count cycles
CLR00000000001A ###(2:0)A = 0
INC00000000010A ###(2:0)A = A + 1
DEC00000000011A ###(2:0)A = A - 1
ABS00000000100A ###(2:0)A = |A|
SIN00000000101A ###(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
COS00000000110A ###(2:0)A = {{12{cordic_cos[15]}}, cordic_cos[17:0]}
ACC00000000111A ###(2:0)R7 = R7 + A
ACC200000001B ###(5:3)A ###(2:0)R7 = R7 + A + B
ATAN00000010B ###(5:3)A ###(2:0)A[27:0] = {12'b0, atan(B[15:0], A[15:0])}, B - cos argument, A - sin argument
ADD00000011B ###(5:3)A ###(2:0)A = A + B
SUB00000100B ###(5:3)A ###(2:0)A = A - B
ORL00000101B ###(5:3)A ###(2:0)A = A | B
ANL00000110B ###(5:3)A ###(2:0)A = A & B
MOVE00000111B ###(5:3)A ###(2:0)A = B
LSL000010count #####(7:3)A ###(2:0)A = A << (count +1)
ASR000011count #####(7:3)A ###(2:0)A = A >> (count +1)
STORE0001address_ram #### ###(9:3)A ###(2:0)ram[address_ram] = A[13:0]
STORE320010address_ram #### ###(9:3)A ###(2:0)ram[address_ram] = A[13:0], ram[address_ram+1] = A[27:14]
LOAD0011address_ram #### ###(9:3)A ###(2:0)A[27:0] = {{14{T[13]}}, T[13:0]}, where T[13:0] = ram[address_ram]
EQUAL010rel[4:0] #####(10:6)B ###(5:3)A ###(2:0)PC = A == B ? PC + rel : PC, where rel = [-16 … 15]
MORE011rel[4:0] #####(10:6)B ###(5:3)A ###(2:0)PC = A > B ? PC + rel : PC, where rel = [-16 … 15]
CLOAD1000address_ram #### ###(9:3)A ###(2:0)A[27:0] = {{14{T[13]}}, T[13:0]}, где T[13:0] = ram[address_ram + rel]
CSTORE1001address_ram #### ###(9:3)A ###(2:0)ram[address_ram + rel] = A[13:0]
CSTORE321010address_ram #### ###(9:3)A ###(2:0)ram[address_ram + rel] = A[13:0], ram[address_ram + rel + 1] = A[27:14]
CLOAD321011address_ram #### ###(9:3)A ###(2:0)A[27:0] = {ram[address_ram + rel+1], ram[address_ram + rel]}
LOAD321100address_ram #### ###(9:3)A ###(2:0)A[27:0] = {ram[address_ram +1], ram[address_ram]}
CONST1101const ### ####(9:3)A ###(2:0)A[27:0] = {{22{const[6]}}, const[6:0]}
DJNZ11100rel[5:0] ######(8:3)A ###(2:0)PC = A == 0 ? PC : PC + rel, A == 0 ? A = 0 : A = A - 1, rel = [-32 … 31]
CDJNZ111010rel #####(7:3)ch# ###(2:0)PC = ch# == 0 ? PC : PC + rel, ch# == 0 ? ch# = 0 : ch# = ch# - 1, rel = [-16 … 15]
EQUAL0111011rel #####(7:3)A ###(2:0)PC = A == 0 ? PC + rel : PC, rel = [-16…15]
JUMP111100rel #######(7:0)PC = PC + rel
MULTI11110100B ###(5:3)A ###(2:0)R6 = A * B где, A decimal 28bit and B - decimal 24bit, R6 - 52bit
MULTI_ACC11110101B ###(5:3)A ###(2:0)R6 = A * B, R7 = R7 + R6, where A - decimal 28bit and B - decimal 24bit
MULTF11110106B ###(5:3)A ###(2:0)R6 = A * B, where A - decimal 28bit, B = float 28bit, res - decimal int 56 bit
MULTF_ACC11110111B ###(5:3)A ###(2:0)R6 = A * B, R7 = R7 + R6, where A - decimal 28bit, B = float 28bit, res - decimal int 56 bit
MULTK2411111011B ###(5:3)A ###(2:0)A[27:0] = RES[51:22], RES[51:0] = A[27:0] * B[23:0]; integer
MULTK1411111100B ###(5:3)A ###(2:0)A[27:0] = RES[40:13], RES[51:0] = A[27:0] * B[27:0]; integer
MULTCUBE_ACC11111101B ###(5:3)A ###(2:0)R6 = (ch1+1)^(ch7+1) * (B + A), R7 = R7 + R6, int
DEC2FLOAT11111110000A ###(2:0)R6 = float(A)
SET_A_HAND11111110001const ###(2:0)D[180:181] = OWNHAND(const), D[182:183] = EXTHAND(const)
HFIX11111110010A ###(2:0)
REZERVED211111110011A ###(2:0)
CFIX011111110100A ###(2:0)ch0[8:0] = A[8:0]
CFIX111111110101A ###(2:0)ch1[7:0] = A[7:0]
CFIX211111110110A ###(2:0)ch2[6:0] = A[6:0]
CFIX311111110111A ###(2:0)ch3[5:0] = A[5:0]
CFIX411111111000A ###(2:0)ch4[4:0] = A[4:0]
CFIX711111111001A ###(2:0)ch7[1:0] = A[1:0]
CLR_CH11111111010ch# ###(2:0)ch# = 0
CLOAD_CUBE11111111011A ###(2:0)A = (ch1+1)^(ch7+1)
RJUMP11111111100A ###(2:0)PC = A, A = PC+1
STOREPC11111111101A ###(2:0)A = PC + 2
SETB_STP11111111110000STP = 1
CLRB_STP11111111110001STP = 0
SW_HTE111111111110010change sel multiplexer handler1 to another CPU
SW_HTE211111111110011change sel multiplexer handler 2 to another CPU