Немного предыстории. Находясь в поездке я узнал о новейшей разработке супер российского смартфона «Р‑фон», а так как делать в тот момент мне было особо нечего я развлекался написанием скриптов на языке Пайтон. И решив, что хуже точно не будет я накатил себе Icarus Verilog на Termux, после чего стал писать свой очередной процессор, так как исходники других моих проектов мне были не доступны.

В итоге это дошло до такого результата...

Немного о том как я работаю с процессором

Тут он в цикле считает до трёх, а затем обнуляет аккумулятор и начинает заново
Тут он в цикле считает до трёх, а затем обнуляет аккумулятор и начинает заново

Немного о том как запускается симуляция. Скрипт создаёт папку для выходного файла, а затем компилирует ядро и тестбенч. После вывода результатов он отчищяет всё за собой. Версия языка - 2005года редкция Систем Верилог, хотя в принципе можно запустить и на любой другой.

mkdir cache
iverilog -o cache/a.out -g2005-sv cpu.sv testbench.sv
vvp cache/a.out
rm -r cache

Тестирование

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

Модуль использует главный модуль процессора. Он генерирует тактовый сигнал CLK и Reset по заданным характеристикам, получая вывод данных и выводя их через модуль $monitor.

module SimpleProcessor_tb;

  // Inputs
  reg clk;
  reg rst;

  // Outputs
  wire [7:0] data_out;

  // Instantiate the SimpleProcessor module
  SimpleProcessor dut (
    .clk(clk),
    .rst(rst),
    .data_out(data_out)
  );

  // Clock generation
    always begin
        #1 clk = ~clk;
    end

    // Monitor the result
    initial begin
        clk = 0;
        $monitor("Time %t | Result: %h",$time, data_out);
        #100 $finish; // Finish the simulation
    end
endmodule

Сам процессор в версии 8

Сам процессор предоставляет пользователю:
-- 8 РОН
-- Аккумулятор
-- 256 Байт = 2048 Бит встроенной памяти
-- 9 инструкций

parameter NOP = 8'h0;
parameter LDA = 8'b001;
parameter MV = 8'b010;
parameter ADD = 8'b011;
parameter SUB = 8'b100;
parameter INC = 8'h85;
parameter DEC = 8'h86;
parameter JMP = 8'h07;
parameter JFZ = 8'h08;
parameter HLT = 8'hFF;

Инструкции версии 8

Организация бит.
Номер 76543210
биты 00000000

LDA - Load Accumulator. Данная команда загружает значение из следующей ячейки памяти в Аккумулятор для дальнейшего использования.

MV - Move. Эта команда выполняет несколько различных действий с регистрами(АtR, RtR, MtR).

//Примеры вариаций использования:
MV A,Рх <= Рх = Acc
76543210
00000ххх
MV Ру,Рх <= Рх = Ру
76543210
10уууххх
MV У,Рх <= Рх = У  Y = Mem[pc+1]
76543210
11000ххх

//У записывается следующим значением ... команда  данные  значение у  ...


ADD - addition. При помощи этой команды происходит сложение регистров, регистра и аккумулятора, регистра и значения из памяти. они работают также как и случаи из команды Move.

//Примеры вариаций использования:
ADD A,Рх <= A = A + Рх
76543210
00000ххх 
ADD Ру,Рх <= Ру = Ру + Рх
76543210
10уууххх 
ADD Рх,У <= Рх = Рх + У Y = Mem[pc+1]
76543210
11000ххх 

//У записывается следующим значением ... команда  данные  значение у  ...

SUB - substraction. При помощи этой команды происходит сложение регистров, регистра и аккумулятора, регистра и значения из памяти. они работают также как и случаи из команды Move.

// Примеры вариаций использования:
SUB A,Рх <= A = A - Рх
76543210
00000ххх 
SUB Ру,Рх <= Ру = Ру - Рх
76543210
10уууххх
SUB Рх,У <= Рх = Рх - У
76543210
11000ххх 

//У записывается следующим значением ... команда  данные  значение у  ...

INC - increment. Прибавляет единицу к аккумулятору. Занимает только один байт памяти.

DEC - decrement. Уменьшает аккумулятор на единицу. Занимает только один байт памяти.

JMP - jump. Безусловный переход. В случае если биты 6-7 равны нулю, то переход осуществляется по адресу из аккумулятора, в ином случае из регистра с адресом из битов 0-2

// Примеры вариаций использования:
JMP A <= PC = Acc
76543210
00000000

JMP Рх <= PC = Pх
76543210
11000ххх

JFZ - jump if zero. Переход если в регистре (с адресом из битов 0-2) или аккумуляторе (если биты 6-7 равны нулю) находится число равное 0

// Примеры вариаций использования:
JFZ A <= PC = Pх если Аккумулятор == 0
76543210
00000ххх

JFZ Ру,Pх <= PC = Pх если Ру == 0
76543210
11yyyххх

HLT - halt. Остановка. Занимает только один байт памяти.

На этом я пожалуй и закончу. Это моя первая статья на Хабре и я буду стараться делать статьи лучше

Если вам не сложно, пожалуйста оставьте комментарий и заходите к нам в чат по разработке этого чуда https://t.me/+hmcaz83QtbJmZjVi