§ Код ядра

Ядро не завершено и не протестировано.
module cpu
(
    // ---------------------------------------- До 4Гб
    input               clock,          // 25 Mhz
    input               reset_n,        // Сброс процессора
    input               ce,             // Chip Enabled
    output      [31:0]  address,        // Указатель на память программ или данных
    input       [ 7:0]  in,             // Данные из памяти по указателю [address]
    output  reg [ 7:0]  out,            // Запись в память
    output  reg         we,             // Сигнал записи в память
    // ---------------------------------------- 256 x 4 = 1K
    output reg  [ 7:0]  rd,             // Номер регистра destination
    output reg  [ 7:0]  rs,             // Номер регистра source
    input       [31:0]  rd_in,          // Результат чтения из [rd]
    input       [31:0]  rs_in,          // Результат чтения из [rs]
    output reg  [31:0]  rd_out,         // Значение на запись в регистр
    output reg          rdw,            // Сигнал записи в [rd]
    // ---------------------------------------- 1024 x 4 = 4K
    output  reg [ 9:0]  sp,             // Указатель на стек
    input       [31:0]  sp_in,          // Данные из стека
    output  reg [31:0]  sp_out,         // Данные для записи в стек
    output  reg         spw             // Сигнал записи в стек
);

localparam
    ADD = 0, SUB = 1, ADC = 2, SBC = 3, AND = 4, XOR = 5, OR = 6, CMP = 7,
    ROL = 0, ROR = 1, SHL = 2, SHR = 3, RCL = 4, RCR = 5,         SAR = 7,
    OF  = 3, SF  = 2, ZF  = 1, CF  = 0;

// -----------------------------------------------------------------------------
assign address = sw ? cp : pc;
// -----------------------------------------------------------------------------
reg         sw;
reg [ 3:0]  t;
reg [31:0]  pc, cp;
reg [ 3:0]  flags = 4'b0000; // OSZC
reg [ 7:0]  opcode, n;
// -----------------------------------------------------------------------------
wire [31:0] pcn = pc + 1;
wire [31:0] cpn = cp + 1;

// Модуль арифметически-логических операции
// -----------------------------------------------------------------------------

wire [ 2:0] op = opcode[2:0];
wire [32:0] ar =
    op == ADD ? rd_in + rs_in :
    op == ADC ? rd_in + rs_in + flags[CF] :
    op == SBC ? rd_in - rs_in - flags[CF] :
    op == AND ? rd_in & rs_in :
    op == XOR ? rd_in ^ rs_in :
    op == OR  ? rd_in | rs_in :
                         rd_in - rs_in;

wire is_add = op == ADD || op == ADC;
wire is_arh = op != AND && op != XOR && op != OR;

// Флаг переполнения считается определенным образом
wire of = (rd_in[31] ^ rs_in[31] ^ is_add) ^ (rd_in[31] ^ ar[31]);

// Рассчитать флаги (4 флага)
wire [3:0] af = {/*OF*/ of & is_arh, /*SF*/ ar[31], /*ZF*/ ~|ar[31:0], /*CF*/ ar[32] & is_arh};

// Модуль сдвиговых операции
// -----------------------------------------------------------------------------

// Подготовить данные
wire [64:0] srd =
    op == ROR ? {rd_in,                 rd_in, rd_in[0]} :                  // Вращение вправо
    op == ROL ? {rd_in[31],             rd_in, rd_in} :                     // Вращение влево
    op == SAR ? {{32{rd_in[31]}},       rd_in, rd_in[0]} :                  // Арифметический вправо
    op == SHR ? {32'b0,                 rd_in, rd_in[0]} :                  // Сдвиг влево
    op == RCR ? {rd_in[30:0],flags[CF], rd_in, rd_in[0]} :                  // Вращение вправо через флаг CF
    op == RCL ? {rd_in[31],             rd_in, flags[CF], rd_in[31:1]} :    // Вращение влево через флаг CF
                {rd_in[31],             rd_in, 32'b0};                      // Сдвиг вправо

// Сдвиг вправо или влево (до 32 сдвигов)
wire [32:0] shr = srd >> rs_in[3:0];
wire [63:0] shl = srd << rs_in[3:0];

// -----------------------------------------------------------------------------

always @(posedge clock)
if (reset_n == 1'b0) begin

    sw  <= 0;
    pc  <= 0;
    sp  <= 0;
    t   <= 0;
    out <= 0;

end else if (ce) begin

    we  <= 0;
    rdw <= 0;
    spw <= 0;
    t   <= t + 1;

    // Чтение опкода
    if (t == 0) begin opcode <= in; pc <= pcn; end

    // Выполнение операции
    casex (t ? opcode : in)

        // 6T MOV R, i32 -- Прочитать непосредственное значение 32х бит в регистр
        8'h00:
        case (t)
        1: begin rd <= in; pc <= pcn; end
        2: begin rd_out[  7:0] <= in; pc <= pcn; end
        3: begin rd_out[ 15:8] <= in; pc <= pcn; end
        4: begin rd_out[23:16] <= in; pc <= pcn; end
        5: begin rd_out[31:24] <= in; pc <= pcn; rdw <= 1; t <= 0; end
        endcase

        // 3T MOV A, B -- Скопировать регистр B -> A
        8'h01:
        case (t)
        1: begin rs <= in; pc <= pcn; end
        2: begin rd <= in; rd_out <= rs_in; rdw <= 1; t <= 0; end
        endcase

        // 4,5,7T MOV A, [B] -- Читать из памяти [B] и запись в регистр A
        8'h02, // BYTE
        8'h03, // WORD
        8'h04: // DWORD
        case (t)
        1: begin rs <= in; pc <= pcn; end
        2: begin rd <= in; pc <= pcn; cp <= rs_in; sw <= 1; end
        3: begin rd_out        <= in; cp <= cpn; rdw <= 1; if (opcode == 8'h02) begin t <= 0; sw <= 0; end end
        4: begin rd_out[ 15:8] <= in; cp <= cpn; rdw <= 1; if (opcode == 8'h03) begin t <= 0; sw <= 0; end end
        5: begin rd_out[23:16] <= in; cp <= cpn; end
        6: begin rd_out[31:24] <= in; cp <= cpn; rdw <= 1; t <= 0; sw <= 0; end
        endcase

        // 5,6,8T MOV [B], A -- Запись в память B из регистра A
        8'h05, // BYTE
        8'h06, // WORD
        8'h07: // DWORD
        case (t)
        1: begin rs <= in; pc <= pcn; end
        2: begin rd <= in; pc <= pcn; cp <= rs_in; sw <= 1; end
        3: begin out <= rd_in[  7:0]; we <= 1;            if (opcode == 8'h05) t <= 7; end
        4: begin out <= rd_in[ 15:8]; we <= 1; cp <= cpn; if (opcode == 8'h06) t <= 7; end
        5: begin out <= rd_in[23:16]; we <= 1; cp <= cpn; end
        6: begin out <= rd_in[31:24]; we <= 1; cp <= cpn; end
        7: begin t <= 0; sw <= 0; end
        endcase

        // 3T MOV A, i8
        8'h20, // Unsigned
        8'h21: // Signed
        case (t)
        1: begin rd <= in; pc <= pcn; end
        2: begin rd_out <= {{24{in[7] & opcode[0]}}, in}; rdw <= 1; pc <= pcn; t <= 0; end
        endcase

        // 5T CALL i32
        8'h0C:
        case (t)
        1: begin rd_out[  7:0] <= in; pc <= pcn; end
        2: begin rd_out[ 15:8] <= in; pc <= pcn; end
        3: begin rd_out[23:16] <= in; pc <= pcn; end
        4: begin pc <= {in, rd_out[23:0]}; sp_out <= pcn; spw <= 1; sp <= sp - 1; t <= 0; end
        endcase

        // 1T RET
        8'h0D:
        case (t)
        0: begin pc <= sp_in; sp <= sp + 1; t <= 0; end
        endcase

        // 4T+ PUSH nn ...
        8'h0E:
        case (t)
        1: begin n  <= in; pc <= pcn; end
        2: begin rs <= in; pc <= pcn; end // Предварительное считывание
        3: begin

            sp_out  <= rs_in;
            sp      <= sp - 1;
            spw     <= 1;
            rs      <= in;
            pc      <= n ? pcn : pc;
            n       <= n - 1;
            t       <= n ? 3 : 0;

        end
        endcase

        // 3T+ POP nn ...
        8'h0F:
        case (t)
        1: begin n <= in; pc <= pcn; end
        2: begin

            rd      <= in;
            pc      <= pcn;
            rd_out  <= sp_in;
            rdw     <= 1;
            n       <= n - 1;
            sp      <= sp + 1;
            t       <= n ? 2 : 0;

        end
        endcase

        // 4T [ALU] A, B, C
        8'b0001_0xxx:
        case (t)
        1: begin rd <= in; pc <= pcn; end
        2: begin rs <= in; pc <= pcn; end
        3: begin rd <= in; pc <= pcn; rd_out <= ar; flags <= af; rdw <= 1; t <= 0; end
        endcase

        // 4T ROL, ROR, SHL, SHR, RCL, RCR, SAR A, B
        8'b0001_1xxx:
        case (t)
        1: begin pc <= pcn; rd <= in; end
        2: begin pc <= pcn; rs <= in; end
        3: begin rd_out <= opcode[0] ? shr[32:1] : shl[64:32]; rdw <= 1; t <= 0; end
        endcase

        // JMP [ccc]

    endcase

end

endmodule