§ Код ядра
Ядро было начало в 2020, а закончено 9 фев 2025. Как долго я его... ждал, чтобы сделать за 5 часов.История версии
- Версия 16.02.2025, добавлены инструкции FINT, FLD для преобразования чисел в Int32 < — > Float32
/* verilator lint_off WIDTHTRUNC */ /* verilator lint_off WIDTHEXPAND */ /* verilator lint_off CASEINCOMPLETE */ module core ( input CLK, input RST_N, input ENA, output DBG, // Программа ------------------------ 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; assign A = cp ? ap : pc; assign DBG = (t == 0); // --------------------------------------------------------------------- reg cp; reg [31:0] pc, ap, si, di, cx; reg [ 3:0] flags; reg [ 7:0] opcache; reg [ 2:0] alu; reg [ 4:0] t; // --------------------------------------------------------------------- wire [ 7:0] opcode = t ? opcache : I; wire [31:0] pcn = pc + 1; wire [31:0] apn = ap + 1; wire cf = flags[CF]; wire zf = flags[ZF]; wire sf = flags[SF]; wire of = flags[OF]; wire [ 7:0] cond = {zf | (sf ^ of), (sf ^ of), 1'b0, sf, (cf | zf), zf, cf, 1'b0}; wire [63:0] mul = Ai * Bi; wire mulf = {|mul[63:32], mul[31], mul == 0, flags[CF]}; wire [31:0] diva = {si[30:0], di[31]}; wire [32:0] divb = diva - Bi; wire [63:0] divc = {divb[32] ? diva : divb[31:0], di[30:0], ~divb[32]}; // Вычисление значения АЛУ // --------------------------------------------------------------------- wire [32:0] Ri = alu == 0 ? Ai + Bi : alu == 1 ? Ai + Bi + flags[CF] : alu == 3 ? Ai - Bi - flags[CF] : alu == 4 ? Ai & Bi : alu == 5 ? Ai ^ Bi : alu == 6 ? Ai | Bi : Ai - Bi; // Результат отфлаговывания wire add_i = alu == 0 || alu == 1; wire lgc_i = alu == 4 || alu == 5 || alu == 6; wire flg_o = (Ai[31] ^ Bi[31] ^ add_i) & (Ai[31] ^ Ri[31]); // Знаковое сложение wire [31:0] S8 = {{24{I[7]}}, I}; wire [32:0] As = Ai + S8; wire Aso = (Ai[31] ^ I[7] ^ 1) & (Ai[31] ^ As[31]); // Общая функция вычисления флагов после выполнения АЛУ wire [3:0] Rf = {lgc_i ? flags[OF] : flg_o, Ri[31], Ri[31:0] == 0, lgc_i ? cf : Ri[32]}; // Сдвиговые инструкции // --------------------------------------------------------------------- wire [ 5:0] mxr = (Bi[31:5] ? 32 : Bi[4:0]); wire [64:0] rol = {cf, Ai, Ai} << Bi[4:0]; wire [64:0] ror = {Ai, Ai, cf} >> Bi[4:0]; wire [32:0] shl = {Ai} << mxr; wire [32:0] shr = {Ai, cf} >> mxr; wire [65:0] rcl = {cf, Ai, cf, Ai} << Bi[4:0]; wire [65:0] rcr = {Ai, cf, Ai, cf} >> Bi[4:0]; wire [64:0] sar = {{32{Ai[31]}}, Ai, cf} >> mxr; // Результат сдвига wire [31:0] rrr = alu == 0 ? rol[63:32] : alu == 1 ? ror[ 32:1] : alu == 2 ? shl[ 31:0] : alu == 3 ? shr[ 32:1] : alu == 4 ? rcl[64:33] : alu == 5 ? rcr[ 32:1] : sar[ 32:1]; // Значение флага C после сдвига wire rrc = alu == 0 ? rol[64] : alu == 1 ? ror[0] : alu == 2 ? shl[32] : alu == 3 ? shr[0] : alu == 4 ? rcl[32] : alu == 5 ? rcr[0] : sar[0]; // Float Point Unit // --------------------------------------------------------------------- // Определить количество лидирующих нулей wire [31:0] fldsv = Ai[31] ? -Ai : Ai; wire [ 4:0] fldsx = {|fldsv[31:16], |flds0[31:24], |flds1[31:28], |flds2[31:30], flds3[31]}; // Передвинуть влево на количество бит 16,8,4,2,1 wire [31:0] flds0 = fldsx[4] ? fldsv : {fldsv[15:0], 16'b0}; wire [31:0] flds1 = fldsx[3] ? flds0 : {flds0[23:0], 8'b0}; wire [31:0] flds2 = fldsx[2] ? flds1 : {flds1[27:0], 4'b0}; wire [31:0] flds3 = fldsx[1] ? flds2 : {flds2[29:0], 2'b0}; wire [31:0] flds4 = fldsx[0] ? flds3 : {flds3[30:0], 1'b0}; wire [ 7:0] fldp = 127 + fldsx; wire [ 7:0] filp = Ai[30:23] - 127; // Преобразование числа int в float wire [31:0] fld = fldsv ? {Ai[31], fldp[7:0], flds4[30:8]} : 32'b0; // Из float -> integer wire [53:0] fildt = filp < 30 ? {1'b1, Ai[22:0]} << filp : (filp[7] ? 0 : 31'h7FFFFFFF); wire [31:0] fild = Ai[31] ? -fildt[53:23] : fildt[53:23]; // --------------------------------------------------------------------- always @(posedge CLK) // Сброс процессора if (RST_N == 1'b0) begin pc <= 0; Sp <= 0; {cp,t} <= 0; flags <= 4'b0000; end // Активация else if (ENA) begin Aw <= 0; Sw <= 0; W <= 0; t <= t + 1; // Защелкивание опкода if (t == 0) begin opcache <= I; pc <= pcn; end case (opcode) // [6T] MOV A, u32 -- загрузка 32х битного значения в регистр 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 -- скопировать 32х битный регистр B -> A 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 // [4T] MOVB A, [B] -- получение BYTE из памяти // [5T] MOVW A, [B] -- получение WORD из памяти // [7T] MOVD A, [B] -- получение DWORD из памяти 8'h02, 8'h03, 8'h04: case (t) 1: begin pc <= pcn; Bp <= I; end 2: begin pc <= pcn; Ap <= I; ap <= Bi; cp <= 1; end 3: begin Ao[ 31:0] <= I; Aw <= 1; ap <= apn; if (opcode == 2) {t,cp} <= 0; end 4: begin Ao[ 15:8] <= I; Aw <= 1; ap <= apn; if (opcode == 3) {t,cp} <= 0; end 5: begin Ao[23:16] <= I; Aw <= 1; ap <= apn; end 6: begin Ao[31:24] <= I; Aw <= 1; cp <= 0; t <= 0; end endcase // [5T] MOVB [A], B -- сохранение BYTE в память // [6T] MOVW [A], B -- сохранение WORD в память // [8T] MOVD [A], B -- сохранение DWORD в память 8'h05, 8'h06, 8'h07: case (t) 1: begin pc <= pcn; Bp <= I; end 2: begin pc <= pcn; Ap <= I; end 3: begin ap <= Ai; O <= Bi[7:0]; W <= 1; cp <= 1; end 4: begin ap <= apn; O <= Bi[15:8]; W <= 1; if (opcode == 5) {t,cp,W} <= 0; end 5: begin ap <= apn; O <= Bi[23:16]; W <= 1; if (opcode == 6) {t,cp,W} <= 0; end 6: begin ap <= apn; O <= Bi[31:24]; W <= 1; end 7: begin cp <= 0; t <= 0; end endcase // [3T] MOVU A,u8 // [3T] MOVS A,s8 8'h08, 8'h09: case (t) 1: begin pc <= pcn; Ap <= I; end 2: begin pc <= pcn; Ao <= opcode == 9 ? {{24{I[7]}}, I} : I; Aw <= 1; t <= 0; end endcase // 5T+2C MOVS S,D,C -- блочное копирование памяти 8'h1E: case (t) 1: begin pc <= pcn; Ap <= I; end 2: begin pc <= pcn; Bp <= I; si <= Ai; end 3: begin pc <= pcn; Bp <= I; di <= Bi; end 4: begin cx <= Bi; cp <= 1; end // Запрос чтения и запрос записи 5: begin ap <= si; si <= si + 1; if (cx == 0) {t,cp} <= 0; end 6: begin ap <= di; di <= di + 1; cx <= cx - 1; O <= I; W <= 1; t <= 5; end endcase // [5T] MUL A,B => H,L -- Умножение 8'h0A: case (t) 1: begin pc <= pcn; Ap <= I; end 2: begin pc <= pcn; Bp <= I; end 3: begin pc <= pcn; Ap <= I; Aw <= 1; Ao <= mul[63:32]; di <= mul[31:0]; flags <= mulf; end 4: begin pc <= pcn; Ap <= I; Aw <= 1; Ao <= di; t <= 0; end endcase // [36T] DIV A,B => H,L -- Деление 8'h0B: case (t) 1: begin pc <= pcn; Ap <= I; end 2: begin pc <= pcn; Bp <= I; end 3: begin pc <= pcn; cx <= 31; {si, di} <= {32'b0, Ai}; end 4: begin {si, di} <= divc; cx <= cx - 1; t <= cx ? 4 : 5; end 5: begin pc <= pcn; Ap <= I; Ao <= si; Aw <= 1; end 6: begin Aw <= 1; Ap <= I; Ao <= di; t <= 0; end endcase // [5T] CALL u32 -- вызов процедуры 8'h0C: case (t) 1,2,3: begin ap <= {I, ap[31:8]}; pc <= pcn; end 4: begin pc <= {I, ap[31:8]}; Sp <= Sp - 1; So <= pcn; Sw <= 1; t <= 0; end endcase // [1T] RET -- возврат из процедуры 8'h0D: case (t) 0: begin pc <= Si; Sp <= Sp + 1; t <= 0; end endcase // [4T+n] PUSH n regs -- запись в стек потока регистров, n=0 это 1 регистр 8'h0E: case (t) 1: begin pc <= pcn; cx <= I; end 2: begin pc <= pcn; Ap <= I; end // Предзагрузка значения 3: begin pc <= cx ? pcn : pc; Ap <= I; Sw <= 1; So <= Ai; Sp <= Sp - 1; cx <= cx - 1; t <= cx ? 3 : 0; end endcase // [3T+n] POP n regs -- чтение из стека потока регистров 8'h0F: case (t) 1: begin pc <= pcn; cx <= I; end 2: begin pc <= pcn; Ap <= I; Aw <= 1; Ao <= Si; Sp <= Sp + 1; cx <= cx - 1; t <= cx ? 2 : 0; end endcase // [4T] (ADD|ADC|SUB|SBC|AND|XOR|OR) A,B,C 8'h10, 8'h11, 8'h12, 8'h13, 8'h14, 8'h15, 8'h16: case (t) 1: begin pc <= pcn; Ap <= I; alu <= opcode[2:0]; end 2: begin pc <= pcn; Bp <= I; end 3: begin pc <= pcn; Ap <= I; Ao <= Ri; Aw <= 1; flags <= Rf; t <= 0; end endcase // [3T] ADDS A,s8 8'h2B: case (t) 1: begin pc <= pcn; Ap <= I; alu <= 0; end 2: begin pc <= pcn; Ao <= As; Aw <= 1; flags <= {Aso, As[31], As[31:0] == 0, As[32]}; t <= 0; end endcase // [4T] (ROL|ROR|SHL|SHR|RCL|RCR|SAR) A,B 8'h18, 8'h19, 8'h1A, 8'h1B, 8'h1C, 8'h1D, 8'h1F: case (t) 0: begin alu <= opcode[2:0]; end 1: begin pc <= pcn; Ap <= I; end 2: begin pc <= pcn; Bp <= I; end 3: begin Ao <= rrr; Aw <= 1; flags <= {flags[OF], rrr[31], rrr == 0, rrc}; t <= 0; end endcase // [2T] JR b8 8'h20: case (t) 1: begin pc <= pcn + S8; t <= 0; end endcase // [5T] JMP u32 8'h21: case (t) 1,2,3: begin pc <= pcn; ap <= {I, ap[31:8]}; end 4: begin pc <= {I, ap[31:8]}; t <= 0; end endcase // [3T] JMP AA 8'h2A: case (t) 1: begin Ap <= I; pc <= pcn; end 2: begin pc <= Ai; t <= 0; end endcase // [1/2T] JUMP COND b8 8'h22, 8'h23, // JC, JNC 8'h24, 8'h25, // JZ, JNZ 8'h26, 8'h27, // JBE, JA 8'h28, 8'h29, // JS, JNS 8'h2C, 8'h2D, // JL, JNL 8'h2E, 8'h2F: // JLE, JG case (t) 0: if (cond[opcode[3:1]] == opcode[0]) begin pc <= pcn + 1; t <= 0; end 1: begin pc <= pcn + S8; t <= 0; end endcase // [4T] (ADD|ADC|SUB|SBC|AND|XOR|OR|CMP) A,B 8'h30, 8'h31, 8'h32, 8'h33, 8'h34, 8'h35, 8'h36, 8'h37: case (t) 0: begin alu <= opcode[2:0]; end 1: begin pc <= pcn; Ap <= I; end 2: begin pc <= pcn; Bp <= I; end 3: begin Ao <= Ri; Aw <= ~&alu; flags <= Rf; t <= 0; end endcase // [3T] 3C FINT A,B -- преобразование числа FLOAT -> INT // [3T] 3D FLD A,B -- преобразование числа INT -> FLOAT 8'h3C, 8'h3D: case (t) 1: begin pc <= pcn; Ap <= I; end 2: begin pc <= pcn; Ap <= I; Aw <= 1; Ao <= opcode == 8'h3D ? fld : fild; t <= 0; end endcase endcase end endmodule