Alikberov 0 1 июля, 2023 Опубликовано 1 июля, 2023 (изменено) · Жалоба Сегодня, на свежую голову, пришла одна любопытная мысль… Процессоры i8085 и i8086 имеют мультиплексированную шину адреса и данных, предназначенную для работы с соответствующими ИМС. Тут подумалось, что везде совмещали именно D0-D7 и A0-A7… А что, если совместить D0-D7 с A8-A15, так как старшая часть адреса меняется относительно реже младшей? То есть, сделать ход конём в рамках конкретной реализации, чтобы сэкономить на тактах: Использовать мелкий внешний регистровый файл, который мог бы переключаясь сам выдавать старшие биты адреса… Вот на этом моменте выясняется, что вся проблема реализации в том, что она затачивается под конкретную шинную архитектуру. Мне нужно разработать сухое ядро, которое уже будет обвешиваться всяческими контроллерами шин. ЯДРО Должно обрабатывать поток машинного кода в формальном виде, как маршрутизатор Должно подключаться к регистровому файлу любого исполнения: Монолитное внутреннее или внешним кэшем Должно только вырабатывать управляющие сигналы для работы всех узлов, входящих в состав процессора Тем самым, параметр разрядности не должен иметь никакого значения (чем-то напоминает процессорную секцию), как и архитектурное исполнение (Гарвардское или Принстонское). На данный момент у меня более-менее разработан и отлажен лишь контроллер шины: Спойлер module bus_control (input wire clk // Clock ,input wire rst // Reset ,input wire bus_save // Machine Cycle: Write/Read ,input wire bus_ready // External Ready Signal ////////////////////////////////// ,output reg bus_read // External Out for Read ,output reg bus_write // External Out for Write ////////////////////////////////// ,output reg bus_measure // Machine Cycle Enable ,output reg bus_translate // Data translation or z-state Data-bus ,output reg bus_receive // Data receiving ,output reg bus_lock // Enable changes for new address ); ////////////////////////// always @* begin bus_translate = bus_write | (bus_save & ~bus_measure); bus_receive = bus_read & ~bus_ready & ~bus_measure; bus_lock = bus_read ~| bus_write; end ////////////////////////// always @(posedge clk) if(~rst) begin bus_read <= 1'b0; bus_write <= 1'b0; bus_measure <= 1'b0; end else begin bus_read <= bus_measure ~| bus_save; bus_write <= ~bus_measure & bus_save; bus_measure <= ~bus_measure & (bus_read | bus_write) & ~bus_ready; end endmodule Здесь: bus_measure - сигнал о разрешении выполнения текущего машинного цикла bus_lock - сигнал о разрешении переключения шины адреса Эти сигналы введены относительно недавно и отвечают за задержки всего остального. Иначе говоря, этот модуль получился основным задающим и остановить его нельзя: Только притормозить. Думаю, именно «bus_measure» должен, в принципе, управлять Ядром в плане скорости, как я понимаю… То есть, по «bus_lock» отдельные исполняющие (Регистровый Файл, Вычислитель Эффективного Адреса и Управление УВВ) архитектуры должны выполнять свой цикл… Вот здесь, как ведущий инженер-конструктор проекта, я чувствую себя никак! У меня нет базовых представлений о маршрутизации. Дешифратор команд также более-менее закончил: Спойлер module command_decoder (input wire [7:0] operation // Instruction ////////////////////////////////////////// ,output reg command_hlt // 00 ,output reg command_bcd // 01::99 ,output reg command_alu // 0A::9F ,output reg command_reg // A0..A9 / B0..B9 / C0..C9 / D0..D9 ,output reg command_arg // AA..AD / BA..BD / CA..CD / DA..DD ,output reg command_cnd // AE..AF / BE..BF / CE..CF / DE..DF ,output reg command_int // E0..FF ); reg hi_reg, lo_reg; reg hi_bcd, lo_bcd; always @(operation) begin hi_reg = operation[7] & ^operation[6:5]; lo_reg = operation[3] & ^operation[2:1]; hi_bcd = operation[7] ~& |operation[6:5]; lo_bcd = operation[3] ~& |operation[2:1]; end // always @* begin command_hlt = ~|operation[7:0]; command_bcd = hi_bcd & lo_bcd & |operation[7:0]; command_alu = hi_bcd & operation[3] & |operation[2:1]; command_reg = hi_reg & lo_bcd; command_arg = hi_reg & lo_reg; command_cnd = hi_reg & &operation[3:1]; command_int = &operation[7:5]; end endmodule Вот на этих трёх узлах (включая вычислитель эффективного адреса, описанный выше) сейчас всё держится и работает (прежде всего, отладчик-дизассемблер на System Verilog). Изменено 1 июля, 2023 пользователем Alikberov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 48 1 июля, 2023 Опубликовано 1 июля, 2023 · Жалоба 16 часов назад, xvr сказал: У автора 'концептуальный' процессор - главное что бы в HEX всё было красиво, работать ему (процессору) не обязательно 🙂 Ну этого уже достаточно, чтобы направить в Сколково на грант по импортозамещению))) Думаю можно на этом еще и бабла нехило срубить,ИМХО... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 173 1 июля, 2023 Опубликовано 1 июля, 2023 · Жалоба 1 час назад, mantech сказал: Думаю можно на этом еще и бабла нехило срубить,ИМХО... Срубить можно, но для этого нужны соответствующие навыки, которые далеко не те, что у технического писатея-изобретателя... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alikberov 0 1 июля, 2023 Опубликовано 1 июля, 2023 (изменено) · Жалоба Вроде бы и отладки не требует такой модуль: И так всё очевидно, понятно… module bcd_accumulator (input wire clk // Clock (positive edge) ,input wire bcd_en // Enable BCD accumulation ,input wire bcd_clr // Clear BCD accumulator ,input wire [7:0] operation // Operation code (BCD only) ,output reg [15:0] bcd_output // Full binary summ from BCD ,output reg bcd_exist // Flag of BCD ); wire [3:0] nibble; assign nibble = &operation[3:0] ? operation[7:4] : operation[3:0]; always @(posedge clk) begin if(bcd_clr) begin bcd_output <= 16'd0; bcd_exist <= 1'd0; end else if(bcd_en) begin bcd_output <= (((bcd_output << 2) + bcd_output) << 1) + {12'd0, nibble}; bcd_exist <= |nibble | bcd_exist; end end endmodule Здесь можно отметить одно важное нововведение: Триггер «bcd_exist»… Сам аккумулятор вектора его не имеет и при указании смещения 65536 оно, естественно, переполняется и становится нулевым. Это - опасная недокументированная ситуация, которая может выработать маргинал! Например: «10» - указатель «[D1+0]» «10 10» - маргинал #1 «10 10 10» - маргинальный указатель «1#[D1+0]» «16» - указатель «[D1+6]» «16 15» - указатель «[D1+65]» «16 15 15» - указатель «[D1+655]» «16 15 15 13» - указатель «[D1+6553]» «16 15 15 13 16» - указатель «[D1+0]», так как 65536 уже 17-битная величина 0x10000 «16 15 15 13 16 10» - побочный маргинал #1: Это уже из разряда эзотерического кодирования «из ряда вон!» - «маргиналище: маргинальный маргинал!» «16 15 15 13 16 10 11» - маргинальный указатель «1#[D1+1]» (концептуальная недопустимость!) Теперь флаг «bcd_exist» будет сигнализировать о наличии в смещении самой ненулевой тетрады, что никак не зависит от переполнения: маргинал посреди указателя не сможет образоваться. Важная модификация: Здесь тетрада «nibble» может использовать как младшие биты кода операции (работает на префиксах и командах REG), так и старшие биты (специально для инструкции FOR/MOV). «AA A1 3F» - команда «MOV A1,A3» «AA A1 A2 3F» - команда «MOV A12,A3» «AA A1 3F 4F» - команда «MOV A1,A34» «AA A1 A2 3F 4F» - команда «MOV A12,A34» «AA A1 A2 A3 A4 A5 6F 7F 8F 9F 0F» - команда «MOV A12345,A67890» В таких ситуациях, так как MOV - не операция АЛУ и может без вреда исполняться много раз, то принято решение ввести такой механизм. Для чего этот модуль должен сам уметь ориентироваться… Изменено 1 июля, 2023 пользователем Alikberov Важная доработка модуля Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 6 3 июля, 2023 Опубликовано 3 июля, 2023 · Жалоба https://github.com/leijurv/Logisim-RISC-V/ может я это уже постил, извиняйте. но вот есть такое. логисим этот "ис коропкм" у меня не заработал, но что-то типа 15 минут понадобилось. (может их несколько таких проектов - что то мне кажется, что я у себя пускал похаотичнее гейты были) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alikberov 0 3 июля, 2023 Опубликовано 3 июля, 2023 (изменено) · Жалоба 18 часов назад, yes сказал: https://github.com/leijurv/Logisim-RISC-V/ может я это уже постил, извиняйте. но вот есть такое. логисим этот "ис коропкм" у меня не заработал, но что-то типа 15 минут понадобилось. (может их несколько таких проектов - что то мне кажется, что я у себя пускал похаотичнее гейты были) Это всё понятно, так как тоже в Logisim в 2019 году и сделал рабочий прототип своего процессора. Сначала Гарвардский, что совсем легко. Потом неделями отлаживал Принстонский, так как пришлось более чётко расписать всё по тактам. Но, так уж сложилось, что о RISC'ах я ещё узнал из статьи «RISC - Путь в будущее» журнала РАДИО (ссылка). Однако, как воспитанный на CISC'ах, консервативно занимаюсь именно этим. К тому же, сам дизайн этого устройства я начинал как шуточную пародию на RISC, типа: А пускай код A1 и выбирает регистр A1 на схеме А пускай код CF инвертирует флаг CF А пускай код BC означает операнды A,B для АЛУ-операций А главное, чтобы код 00 был командой Останова HLT (как Zero-Terminated String) То есть, каждый код делал только одно незаконченное действие и для выполнения одной эффективной операции требовалось как минимум три команды. Но, по мере доработок и наработок, развития JavaScript-эмулятора, оказалось, что теперь можно получить вполне серьёзную модель полноценного процессора… И который год никак не могу его охватить концептуально весь, что не позволяет даже на высоком уровне JavaScript описать эмуляцию на 100%. Его легко эмулировать на i8080 (ссылка запуска) или z80, что позволит исполнять код даже на ZX-Spectrum. Кто работает под Linux, может попробовать эмулятор на Bash'е (пока всё ещё не дописал, но отладчик с ассемблером имеется), который писался под Raspberry Pi для управления периферией. BashEmu.zip Изменено 4 июля, 2023 пользователем Alikberov Перезагрузил файл эмулятора на Bash Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться