БЭСМ-6 HDL

23 views
Skip to first unread message

Alex Loktionoff

unread,
Sep 7, 2025, 4:19:18 AM (2 days ago) Sep 7
to БЭСМ-6
В этой теме хотелось бы собрать знания и опыт реализации БЭСМ-6 на языке описания аппаратуры.
Вопросы по реализации на современных аппаратных платформах Рассыпуха/FPGA/ASIC.

Alex Loktionoff

unread,
Sep 7, 2025, 4:55:00 AM (2 days ago) Sep 7
to БЭСМ-6
Первое, что я столкнулся когда только попробовал - это сумматор в АЛУ БЭСМ6.
Хотя есть и микросхемы сумматоров с быстрым переносом и в FPGA есть готовые блоки DSP, но все-же они не безразмерные и объединить их хочется как в БЕСМ6 с синхронным переносом за один (короткий!) такт.
И сразу напоролся на грабли - по документации операция сложения в среднем происходит за 9 тактов (да по статистике в среднем 9 переносов если брать случайные числа). Но у меня выходит даже без переносов, на выходе будет значение не раньше чем на 3-ем такте:
1- запись значения в регистр В (и если нужно сброс регистра А) на выходе при это еще старое значение А!
2 - неполное суммирование  A ^ B и формирования переносов (A & B)<<1. В при этом еще не 0 поэтому результат еще не готов.
3 - то-же, что и в 2, только В уже новый 0-вый (у нас самый простой пример без переносов), тут уже формируется сигнал готовности, но доступен он будет на выходе, только в следующем такте!
4 - сумма на выходе сумматора и данные готовы, аккумулятор может в этом такте уже принимать новые данные, поэтому этот так уже не считается.

Вопрос, что я делаю не так?
Вроде идея понятная: 
 - реализовать именно аккумулятор, в который можно либо загрузить значение либо добавить/накопить. так как и команды одноадресные и мультиплексор для выбора значения для В лучше ставить только в одном "плече", там где только быстрая "операция" И, при этом оба  "плеча" И и  XOR по времени прохождения становятся более-менее сбалансированными. И время такта можно сократить до минимума, выжав максимум из железа.
Но:
- почему 3 такта на ровном месте?
- подозреваю, что XOR в "парафазной" логике реализуется быстрее чем обычной с дополнительными инверторами.
- в FPGA борще по барабану что AND что XOR там все на LUTах сделано и задержка теоретически одинакова, в зависимости от количества входов, там и мультиплексоры сольются в один каскад комбинаторной логики.
- а в ASIC-е еще можно городить этажерки мосфетов и склеить   НЕИНЕ в один каскад с задержкой распространения примерно как у И и еще подкорректировать площадь затворов, подгоняя время фронтов чтоб вообще сровнять 1:1 скорости. 
Тогда вопрос как писать HDL код ? Для рассыпухи один, для ASIC другой а для  FPGA вообще третий? А чем нам тогда вообще HDL код на FPGA поможет в разработке ASIC-а если он вообще другой и тайминг другие?

Вот схемка в digit, примерчик аккумулятора, я даже индикаторы пририсовал с права внизу для наглядности:
Снимок 9-6-25 в 11.33 PM.jpg 

Буду благодарен если меня кто-то просветит.

Leo B.

unread,
Sep 7, 2025, 12:45:37 PM (2 days ago) Sep 7
to БЭСМ-6
Для простоты, чтобы не надо было учитывать нормализацию, рассмотрим длительность выполнения команды 013 (циклическое сложение). Её длительность в АУ такова: минимальная - 3 такта, средняя - 6 тактов, максимальная - 27 тактов. Из этого следует, что приведение переносов выполнялось 2 раза за такт (27 = 48/2 + 3) благодаря парафазности. На какой смеси тестовых данных у разработчиков получилось, что в среднем для команды 013 нужно 6 приведений переносов (6 = (6-3)*2), а не 9, неясно. 

Массовая цепь сравнения регистра переноса с нулём была асинхронная. Цепи приведения переносов были активны, и могли последние несколько полутактов работать вхолостую, пока не вырабатывался признак окончания переноса, а это могло занимать разное время в зависимости от того, какие разряды в регистре переноса перешли из 1 в 0 последними.

Кстати говоря, в зависимости от того, что мы хотим получить, сначала дизайн может быть полезно иметь на уровне RTL (регистровых передач). На этом уровне всё пишется за один такт, и в явном представлении парафазности пока нет необходимости. На этом уровне написан mesm6. 

Грубо говоря, на Верилоге

always_comb begin
    acc_next = (новое значение сумматора в зависимости от текущей выполняемой команды, изменяющей сумматор, например, acc_reg + input_reg)
    acc_hold = (условие неизменности сумматора на следующем такте, например, если текущая команда не изменяет сумматор, или если БАК пуст, и т. п.)
end

always @(posedge clk) begin
    if (!acc_hold)
        acc_reg <= acc_next;
end


Leo B.

unread,
Sep 8, 2025, 2:23:33 AM (yesterday) Sep 8
to БЭСМ-6
Тестирование на случайных данных показало, что среднее количество приведений переносов при сложении 48-битных целых не 9, а даже меньше 6 (5.89):

#include <random>
#include <cstdint>
#include <iostream>

uint64_t getRandomInt64() {
    static std::random_device rd;  // Non-deterministic seed
    static std::mt19937_64 gen(rd());  // 64-bit Mersenne Twister engine
    static std::uniform_int_distribution<uint64_t> dist;

    return dist(gen);
}

int trial() {
        uint64_t sum = getRandomInt64() >> 16;
        uint64_t carry = getRandomInt64() >> 16;
        int steps = 0;
        do {
                uint64_t new_sum, new_carry;
                new_sum = sum ^ carry;
                new_carry = (sum & carry) << 1;
                ++steps;
                sum = new_sum;
                carry = new_carry;
        } while (carry);
        return steps;
}

int main() {
        uint64_t total = 0;
        for (int i = 0; i < 1000000; ++i) {
                total += trial();
        }
        std::cout << "Average " << total / 1000000.0 << '\n';
}

Alex Loktionoff

unread,
Sep 8, 2025, 2:33:01 PM (12 hours ago) Sep 8
to БЭСМ-6
Леонид, огромное спасибо, это была моя ошибка, не могу уже найти исходников где я ошибся, у меня был цикл, а не случайные числа, и где-то дал маху.
Ну если в среднем 9 а минимально 3 то с моей схемой сходиться, значит я на правильном пути. Читать формулы из тех описания БЭСМ сил нету, мне легче заново изобрести...
Вот только сегодня вечером нашел тему "Ардуино БЭСМ-6" где обещали помочь в разъяснении :)

В этой теме и хотелось бы собрать "базу знаний" чтоб написать "almost cycle-accurate" /* чтоб не слишком замахиваться */ симулятор БЭСМ-6 и Э1-КБ в первую очередь для пользовательского режима /* и быстрее получить какой-то полезный инструмент */. 

Меня терзают смутные сомнения что на более чем "almost cycle-accurate" замахиваться при современной стандартной синхронной логике, лучше не надо, иначе где-то что-то порвется.
Красные и синие каскады мне не кажутся такой уж проблемой, можно просто считать что тактовая частота в 2 раза выше. Как я и предполагал в элементной базе БЭСМ при монтажном ИЛИ и парафазный логике реализация XOR может быть по скорости сравнима с AND. Но на FPGA мы и так будем иметь иные времянки... Так что только  "almost cycle-accurate". Но все-равно хотелось бы понимать как это работало.

Вы писали, про регистры АУМ, РС1, РС2,  РП1 , РП2, ВР, ПР, ВРУ, ПРУ, РОМ, РСМ. Можно как-то схематично их соединить, чтоб понять как это связано и еще с БАК? /* а как это описать на HDL уж можно придумать*/ Как реализацию задокументировать это другой вопрос, хотя интересный и трудный. В свое время было закодировано "формулами", которые мало кто может декодировать, теперь есть system verilog, но как я понял описание на нем должно быть разным для разной элементной базы, но как я говорил это уже другой вопрос.


понедельник, 8 сентября 2025 г. в 08:23:33 UTC+2, Leo B.:

Alex Loktionoff

unread,
Sep 8, 2025, 2:45:35 PM (12 hours ago) Sep 8
to БЭСМ-6


воскресенье, 7 сентября 2025 г. в 18:45:37 UTC+2, Leo B.:
Для простоты, чтобы не надо было учитывать нормализацию, рассмотрим длительность выполнения команды 013 (циклическое сложение).
Согласен, вот с нее и начнем.
 
Её длительность в АУ такова: минимальная - 3 такта, средняя - 6 тактов, максимальная - 27 тактов. Из этого следует, что приведение переносов выполнялось 2 раза за такт (27 = 48/2 + 3)
2 раза за такт? Это значит было две стадии конвейера с промежуточной защелкой?
Вот тогда я не понимаю, у меня минимум 3 такта, при одной стадии конвейера, тоесть вообще без конвейеризации.
 
благодаря парафазности. На какой смеси тестовых данных у разработчиков получилось, что в среднем для команды 013 нужно 6 приведений переносов (6 = (6-3)*2), а не 9, неясно. 

 
Массовая цепь сравнения регистра переноса с нулём была асинхронная.
Вот тут у меня прокол, 48ИЛИНЕ в один каскад не удастся реализовать не на одной элементной базе, фронты поплывут... /*  а хочется раскачегарить до предела */
 
Цепи приведения переносов были активны, и могли последние несколько полутактов работать вхолостую, пока не вырабатывался признак окончания переноса, а это могло занимать разное время в зависимости от того, какие разряды в регистре переноса перешли из 1 в 0 последними.
Вот тут не понял от слова совсем, можно сравнить с моей схемой или фрагмент верилога или на пальцах как-то?  


Кстати говоря, в зависимости от того, что мы хотим получить, сначала дизайн может быть полезно иметь на уровне RTL (регистровых передач). На этом уровне всё пишется за один такт, и в явном представлении парафазности пока нет необходимости. На этом уровне написан mesm6. 
Но mesm6 он весь микрокодовый, и реализован на sliced  ALU от AMD, тоесть времянки совсем не те.
  

Грубо говоря, на Верилоге

always_comb begin
    acc_next = (новое значение сумматора в зависимости от текущей выполняемой команды, изменяющей сумматор, например, acc_reg + input_reg)
    acc_hold = (условие неизменности сумматора на следующем такте, например, если текущая команда не изменяет сумматор, или если БАК пуст, и т. п.)
end

always @(posedge clk) begin
    if (!acc_hold)
        acc_reg <= acc_next;
end

Ну это как-то на TLS смахивает, "это-ж не наши методы". Тут мне хотелось бы собрать базу  "almost cycle-accurate"...

Serge Vakulenko

unread,
Sep 8, 2025, 2:58:11 PM (12 hours ago) Sep 8
to БЭСМ-6
On Monday, September 8, 2025 at 11:45:35 AM UTC-7 oxy...@gmail.com wrote:
Но mesm6 он весь микрокодовый, и реализован на sliced  ALU от AMD, тоесть времянки совсем не те.
  
Вы путаете микро-бэсм и мэсм6. 

Leo B.

unread,
Sep 8, 2025, 6:03:53 PM (9 hours ago) Sep 8
to БЭСМ-6
On Monday, September 8, 2025 at 11:33:01 AM UTC-7 oxy...@gmail.com wrote:

Меня терзают смутные сомнения что на более чем "almost cycle-accurate" замахиваться при современной стандартной синхронной логике, лучше не надо, иначе где-то что-то порвется.

Пожалуй. Или всё надо реализовать в стандартных флип-флопах сначала однофазно, потом на posedge/negedge, а когда заработает, тогда можно подумать и о преобразовании в схему "L1L2"  на защёлках.
 
Красные и синие каскады мне не кажутся такой уж проблемой, можно просто считать что тактовая частота в 2 раза выше. Как я и предполагал в элементной базе БЭСМ при монтажном ИЛИ и парафазный логике реализация XOR может быть по скорости сравнима с AND. Но на FPGA мы и так будем иметь иные времянки... Так что только  "almost cycle-accurate". Но все-равно хотелось бы понимать как это работало.

Забудьте пока про времянки, про картинки  со схематикой, про разные реализации между FPGA и ASIC... Рассуждайте исключительно в терминах RTL, пока дизайн на уровне RTL не заработает. 

Вы писали, про регистры АУМ, РС1, РС2,  РП1 , РП2, ВР, ПР, ВРУ, ПРУ, РОМ, РСМ. Можно как-то схематично их соединить, чтоб понять как это связано и еще с БАК? /* а как это описать на HDL уж можно придумать*/ Как реализацию задокументировать это другой вопрос, хотя интересный и трудный. В свое время было закодировано "формулами", которые мало кто может декодировать, теперь есть system verilog, но как я понял описание на нем должно быть разным для разной элементной базы, но как я говорил это уже другой вопрос.

Обилие регистров связано, в частности, с парафазностью. На уровне RTL, например, двойное приведение переносов вполне можно написать без дополнительного регистра - пусть синтезатор строит логику, как сумеет.

Просто берите https://github.com/besm6/mesm6/blob/master/rtl/mesm6_alu.sv, который работает (и потому любые изменения поддаются regression testing), и начинайте делать инкрементные изменения, приводя реализацию к похожей по количеству тактов на АУ БЭСМ-6.
В первую очередь, например, нужно ликвидировать явную операцию умножения. 
Потом все явные сложения-вычитания сумматора нужно превратить в приведение переносов (а также логическое ИЛИ в однократное приведение переносов без сдвига carry - см. разницу в длительности выполнения НТЖ и ИЛИ), и т.п. 
Как там делать многотактные операции путем введения дополнительных состояний автомата, надеюсь, понятно.
Самым интересным будет аутентичная реализация деления (существующая, хотя и проходит тест АУ, на самом деле иногда даёт результат, отличающийся от БЭСМовского в младшем разряде - как, впрочем, и на софтверном эмуляторе). 

Leo

Leo B.

unread,
Sep 8, 2025, 6:47:40 PM (8 hours ago) Sep 8
to БЭСМ-6
On Monday, September 8, 2025 at 11:45:35 AM UTC-7 oxy...@gmail.com wrote:


воскресенье, 7 сентября 2025 г. в 18:45:37 UTC+2, Leo B.:
Для простоты, чтобы не надо было учитывать нормализацию, рассмотрим длительность выполнения команды 013 (циклическое сложение).
Согласен, вот с нее и начнем.
 
Её длительность в АУ такова: минимальная - 3 такта, средняя - 6 тактов, максимальная - 27 тактов. Из этого следует, что приведение переносов выполнялось 2 раза за такт (27 = 48/2 + 3)
2 раза за такт? Это значит было две стадии конвейера с промежуточной защелкой?
Вот тогда я не понимаю, у меня минимум 3 такта, при одной стадии конвейера, тоесть вообще без конвейеризации.

Так это нормально. В mesm6, где сумма вырабатывается комбинационно, ее длительность уже 2 такта. Если делать двухрядный код, по-видимому, как раз 3 и получится.

 
благодаря парафазности. На какой смеси тестовых данных у разработчиков получилось, что в среднем для команды 013 нужно 6 приведений переносов (6 = (6-3)*2), а не 9, неясно. 

 
Массовая цепь сравнения регистра переноса с нулём была асинхронная.
Вот тут у меня прокол, 48ИЛИНЕ в один каскад не удастся реализовать не на одной элементной базе, фронты поплывут... /*  а хочется раскачегарить до предела */
 
Цепи приведения переносов были активны, и могли последние несколько полутактов работать вхолостую, пока не вырабатывался признак окончания переноса, а это могло занимать разное время в зависимости от того, какие разряды в регистре переноса перешли из 1 в 0 последними.
Вот тут не понял от слова совсем, можно сравнить с моей схемой или фрагмент верилога или на пальцах как-то?  

Строго говоря, сравнение с нулём делается с помощью монтажного ИЛИ, но я не знаю, были ли в этом ИЛИ на 48 разрядов какие-то дополнительные  усилители, и насколько сбалансировано было это дерево. Но да, по сравнению с любой современной элементной базой эта операция, скорее всего, была относительно более быстрой.  О времянках пока заботиться не надо, всему своё время.

Leo


Reply all
Reply to author
Forward
0 new messages