§ Код ядра

Ядро было начало в 2020, а закончено 11.09.2025. Как долго я его... ждал, чтобы сделать за 5 часов.
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off WIDTHEXPAND */
/* verilator lint_off CASEINCOMPLETE */

module core
(
    input               clock,
    input               reset_n,
    input               ce,
    // Программа ----------------------------
    output      [31:0]  A,      // Указатель на память
    input       [ 7:0]  I,      // Входящие данные из памяти
    output reg  [ 7:0]  O,      // Исходящние данные
    output reg          W,      // Сигнал на запись
    // Регистры A, B ------------------------
    output reg  [ 7:0]  Ap,     // Адрес A
    input       [31:0]  Ai,     // Значение A
    output reg  [31:0]  Ao,     // Значение на запись
    output reg          Aw,     // Запись A
    output reg  [ 7:0]  Bp,     // Адрес B
    input       [31:0]  Bi,     // Значение B
    // Стек ---------------------------------
    output reg  [ 7:0]  Sp,     // Значение стека
    input       [31:0]  Si,     // Чтение
    output reg  [31:0]  So,     // Запись
    output reg          Sw      // Сигнал записи
);

// Флаги
localparam OF=3, SF=2, ZF=1, CF=0;

// Остановка выполнения инструкции
`define TERM begin cp <= 0; t <= 0; end
`define OP20 opcode[2:0]

assign A = cp ? ap : pc;

// -----------------------------------------------------------------------------
reg             cp;             // Указатель на память программ=0 или данных=1
reg     [31:0]  pc, ap;         // Программный счетчик и адрес в памяти (данные)
reg     [31:0]  ax, bx, cx;     // Перемещение памяти
reg     [ 3:0]  flags;          // Флаги OSZC
reg     [ 7:0]  opcache;        // Сохранение в кеш опкода
reg     [ 4:0]  t;              // Фаза выполнения инструкции
// -----------------------------------------------------------------------------
wire    [ 7:0]  opcode  = t ? opcache : I;
wire    [31:0]  pcn     = pc + 1;
wire    [31:0]  apn     = ap + 1;
wire    [31:0]  sign    = {{24{I[7]}}, I};
// -----------------------------------------------------------------------------
wire    [32:0]  Aluo =

    `OP20 == 3'h0 ? Ai + Bi :
    `OP20 == 3'h1 ? Ai + Bi + flags[CF] :
    `OP20 == 3'h3 ? Ai - Bi - flags[CF] :
    `OP20 == 3'h4 ? Ai & Bi:
    `OP20 == 3'h5 ? Ai ^ Bi:
    `OP20 == 3'h6 ? Ai | Bi:
                    Ai - Bi; // SUB, CMP

// Расчет переполнения результата при вычислении
wire    is_add   = opcode[2:1] == 2'b00;
wire    overflow = (Ai[31] ^ Bi[31] ^ is_add) & (Ai[31] ^ Aluo[31]);

// Вычисление конечных флагов
wire    [ 3:0]  Aluf = {overflow, Aluo[31], Aluo[31:0] == 0, Aluo[32]};
wire    [ 7:0]  cond = {
   (flags[SF] ^ flags[OF]) | flags[ZF],
    flags[SF] ^ flags[OF],
    flags[SF],
    flags[CF] & flags[ZF],
    flags[ZF],
    flags[CF],
    2'b00
};

// -----------------------------------------------------------------------------
// Инструкции, которые не имеют цикличности
wire        rr_nocycle = opcode[2:1] == 2'b01 || opcode[2:0] == 3'h7;

// Выбор источника для сдвига
wire [66:0] rr_in =

    `OP20 == 3'h0 ? {flags[CF], Ai[31:0], Ai[31:0]}   :           // ROL
    `OP20 == 3'h1 ? {Ai[31:0],  Ai[31:0], flags[CF]}  :           // ROR
    `OP20 == 3'h2 ? {flags[CF], Ai[31:0]}             :           // SHL <<
    `OP20 == 3'h3 ? {Ai[31:0],  flags[CF]}             :          // SHR >>
    `OP20 == 3'h4 ? {flags[CF], Ai[31:0], flags[CF], Ai[31:0]} :  // RCL
    `OP20 == 3'h5 ? {Ai[31:0],  flags[CF], Ai[31:0], flags[CF]} : // RCR
    `OP20 == 3'h7 ? {{33{Ai[31]}}, Ai[31:0], flags[CF]} : 0;      // SAR

// 0..31|32
wire [ 5:0] rr_sh = Bi[31:5] && rr_nocycle ? 33 : Bi[4:0];

// Сдвиг налево или направо
wire [66:0] rr_lf = rr_in << rr_sh;
wire [66:0] rr_rt = rr_in >> rr_sh;

// Результаты сдвига
wire [31:0] rr_rs =

    `OP20 == 3'h0 ? rr_lf[63:32]  :     // ROL
    `OP20 == 3'h2 ? rr_lf[31:0]   :     // SHL
    `OP20 == 3'h4 ? rr_lf[64:33]  :     // RCL
                    rr_rt[32:1];        // ROR, SHR, SAR, RCR

// Результаты вычисления флага CF
wire rr_cf =

    `OP20 == 3'h0 ? rr_lf[64] :         // ROL
    `OP20 == 3'h2 ? rr_lf[32] :         // SHL
    `OP20 == 3'h4 ? rr_lf[66] :         // RCL
                    rr_rt[0];           // ROR, SHR, SAR, RCR
// -----------------------------------------------------------------------------
wire [63:0] mul = Ai * Bi;
wire [32:0] div = bx - Bi;
wire [31:0] est = div[32] ? bx : div;
// -----------------------------------------------------------------------------

always @(posedge clock)
// Сброс процессора
if (reset_n == 1'b0) begin

    pc <= 0;
    Sp <= 0;
    {cp, t} <= 0;

    //          OSZC
    flags <= 4'b0001;

end
// Активация
else if (ce) begin

    W  <= 1'b0;
    Aw <= 1'b0;
    Sw <= 1'b0;
    t  <= t + 1;

    // Зафиксировать опкод
    if (t == 0) begin opcache <= I; pc <= pcn; end

    // Выполнение инструкции
    case (opcode)

    // [6T] MOV A, u32 :: 00 AA IMM32
    8'h00: case (t)

        1:      begin pc <= pcn; Ap <= I; end
        2,3,4:  begin pc <= pcn; Ao <= {I, Ao[31:8]}; end
        5:      begin pc <= pcn; Ao <= {I, Ao[31:8]}; Aw <= 1; t <= 0; end

    endcase

    // [3T] MOV A, B :: 01 BB AA
    8'h01: case (t)

        1: begin pc <= pcn; Bp <= I; end
        2: begin pc <= pcn; Ap <= I; Ao <= Bi; Aw <= 1; t <= 0; end

    endcase

    // [3T] MOV A, u8/s8 :: 02 AA **
    8'h02, 8'h03: case (t)

        1: begin pc <= pcn; Ap <= I; end
        2: begin pc <= pcn; Ao <= opcode[0] ? sign : I; Aw <= 1; t <= 0; end

    endcase

    // 4T MOVB A,[B] :: 04 BB AA
    // 5T MOVW A,[B] :: 05 BB AA
    // 6T MOVD A,[B] :: 06 BB AA
    8'h04, 8'h05, 8'h06: case (t)

        1: begin pc <= pcn;      Bp <= I;   end
        2: begin pc <= pcn;      Ap <= I;   ap <= Bi; cp <= 1; end
        3: begin Ao <= I;        ap <= apn; if (opcode == 8'h04) begin Aw <= 1; `TERM; end end
        4: begin Ao[15:8]  <= I; ap <= apn; if (opcode == 8'h05) begin Aw <= 1; `TERM; end end
        5: begin Ao[23:16] <= I; ap <= apn; end
        6: begin Ao[31:24] <= I; Aw <= 1; cp <= 0; t <= 0; end

    endcase

    // 5T MOVB [A],B :: 07 BB AA
    // 6T MOVW [A],B :: 08 BB AA
    // 8T MOVD [A],B :: 09 BB AA
    8'h07, 8'h08, 8'h09: case (t)

        1: begin pc <= pcn; Bp <= I; end
        2: begin pc <= pcn; Ap <= I; ap <= Bi; end
        3: begin O <= Ai[ 7:0];  W <= 1; cp <= 1; end
        4: begin O <= Ai[15:8];  W <= (opcode != 8'h07); ap <= apn; if (opcode == 8'h07) `TERM end
        5: begin O <= Ai[23:16]; W <= (opcode != 8'h08); ap <= apn; if (opcode == 8'h08) `TERM end
        6: begin O <= Ai[31:24]; W <= 1; ap <= apn; end
        7: begin t <= 0; cp <= 0; end

    endcase

    // 6T+2T*C :: COPY A,B,C
    8'h0A: case (t)

        // Загрузка значений регистров
        1: begin pc <= pcn; Ap <= I; end
        2: begin pc <= pcn; Ap <= I; ax <= Ai; end
        3: begin pc <= pcn; Ap <= I; bx <= Ai; end
        4: begin cx <= Ai;  cp <= 1; end
        // Чтение-запись (2T)
        5: begin ap <= ax; W <= 0; ax <= ax + 1; if (cx == 0) `TERM; end
        6: begin ap <= bx; W <= 1; bx <= bx + 1; O <= I; cx <= cx - 1; t <= 5; end

    endcase

    // 5T :: MUL умножение
    8'h0B: case (t)

        1: begin pc <= pcn; Ap <= I; end
        2: begin pc <= pcn; Bp <= I; end

        // Запись младшего результата
        3: begin

            Aw <= 1;
            Ao <= mul[ 31:0];
            ax <= mul[63:32];

            flags[ZF] <= mul[31:0]  ? 0 : 1;
            flags[SF] <= mul[31];

        end

        // Запись старшего результата
        4: begin

            Aw <= 1;
            Ao <= ax;
            Ap <= Bp;

            flags[OF] <= mul[63:32] ? 1 : 0;
            t <= 0;

        end

    endcase

    // 32+4 :: DIV беззнаковое деление
    8'h0C: case (t)

        1: begin pc <= pcn; Ap <= I; end
        2: begin pc <= pcn; Bp <= I; ax <= Ai; bx <= 0; cx <= 32; end
        3: begin

            if (cx == 0) begin

                Ap <= Bp;
                Bp <= Ap;
                Ao <= est;
                Aw <= 1;

            end

            ax <= {ax[30:0], ~div[32]};
            bx <= {est[30:0], ax[31]};
            cx <= cx - 1;
            t  <= cx ? 3 : 4;

        end
        // Результат доступен здесь, на последнем такте
        4: begin Ap <= Bp; Ao <= ax; Aw <= 1; t <= 0; end

    endcase

    // 4T :: *ALU* AA BB :: Арифметическое Логическое Устройство
    8'h10, 8'h11, 8'h12, 8'h13,
    8'h14, 8'h15, 8'h16, 8'h17: case (t)

        1: begin pc <= pcn; Ap <= I; end
        2: begin pc <= pcn; Bp <= I; end
        3: begin Ao <= Aluo[31:0]; Aw <= `OP20 != 7; flags <= Aluf; t <= 0; end

    endcase

    // 4T :: Инструкции сдвига
    8'h18, 8'h19, 8'h1A, 8'h1B,
    8'h1C, 8'h1D,        8'h1F: case (t)

        1: begin pc <= pcn; Ap <= I; end
        2: begin pc <= pcn; Bp <= I; end
        3: begin Ao <= rr_rs; Aw <= 1; flags <= {flags[OF], rr_rs[31], rr_rs[31:0] == 0, rr_cf}; t <= 0; end

    endcase

    // 3T :: 1E AA s8 :: INC A, s8
    8'h1E: case (t)

        1: begin pc <= pcn; Ap <= I; end
        2: begin pc <= pcn; Ao <= Ai + sign; Aw <= 1; t <= 0; end

    endcase

    // 2T Безусловные переходы
    8'h20: case (t)

        1: begin pc <= pcn + sign; t <= 0; end

    endcase

    // 3T Переход на 16 бит
    8'h21: case (t)

        1: begin pc <= pcn; ax <= I; end
        2: begin pc <= pcn + {{16{I[7]}}, I, ax[7:0]}; t <= 0; end

    endcase

    // 5T Абсолютный переход на 32х битный
    8'h22: case (t)

        1,2,3: begin pc <= pcn; ax <= {I, ax[31:8]}; end
        4:     begin pc <= {I, ax[31:8]}; t <= 0; end

    endcase

    // 3T Косвенный переход по значению указанного регистра
    8'h23: case (t)

        1: begin Ap <= I; end
        2: begin pc <= Ai; t <= 0; end

    endcase

    // 1T / 2T Условный переход
    8'h24, 8'h25, 8'h26, 8'h27,
    8'h28, 8'h29, 8'h2A, 8'h2B,
    8'h2C, 8'h2D, 8'h2E, 8'h2F: case (t)

        0: begin if (cond[ opcode[3:1] ] == opcode[0]) begin pc <= pcn + 1; t <= 0; end end
        1: begin pc <= pcn + sign; t <= 0; end

    endcase

    // 4T + n :: PUSH r=(0..255) ...
    8'h30: case (t)

        1: begin pc <= pcn; cx <= I; end
        2: begin pc <= pcn; Ap <= I; end
        3: begin

            t  <= cx ? 3 : 0;
            pc <= cx ? pcn : pc;
            Sp <= Sp - 1;
            Sw <= 1;
            So <= Ai;
            Ap <= I;
            cx <= cx - 1;

        end

    endcase

    // 3T + n :: POP r=(0..255) ...
    8'h31: case (t)

        1: begin pc <= pcn; cx <= I; end
        2: begin

            t  <= cx ? 2 : 0;
            pc <= pcn;
            Ap <= I;
            Ao <= Si;
            Aw <= 1;
            Sp <= Sp + 1;
            cx <= cx - 1;

        end

    endcase

    // 5T CALL u32
    8'h32: case (t)

        1,2,3: begin pc <= pcn; ax <= {I, ax[31:8]}; end
        4:     begin pc <= {I, ax[31:8]}; So <= pcn; Sw <= 1; Sp <= Sp - 1; t <= 0; end

    endcase

    // 3T CALL A
    8'h33: case (t)

        1: begin Ap <= I; end
        2: begin pc <= Ai; So <= pcn; Sw <= 1; Sp <= Sp - 1; t <= 0; end

    endcase

    // 1T RET
    8'h34: begin

        pc <= Si;
        Sp <= Sp + 1;
        t  <= 0;

    end

    endcase

end

endmodule