![](https://habrastorage.org/webt/fo/th/9n/foth9n1n9wwqidtad13fodcaxxm.jpeg)
Часть I
Часть II
Часть III
Часть IV
Часть V
На данном ресурсе уже была опубликована статья, посвящённая RAM-машине
Wikipedia также содержит статью об этой вычислительной модели
RAM-машина, которая упоминается в книге «Построение и анализ вычислительных алгоритмов» (авторы: Ахо, Хопкрофт, Ульман) имеет ограниченный набор арифметических команд (сложение, вычитание, умножение, деление), команду безусловного перехода, две команды условных переходов. Здесь же из арифметических команд присутствуют только сложение и вычитание, команды ветвления (переходов) будут идентичными командам, приведённым в книге
LIttle Man Computer ссылка обладает схожим набором команд
Online симулятор LMC находится здесь
Схема АЛУ представлена ниже.
Шина соединяет память данных с сумматором (обозначен плюсом), вычитателем (обозначен минусом) и мультиплексором MUX.
Переключение между сумматором и вычитателем производится мультиплексором.
Также в мультиплексор загружаются числовые данные из устройства ввода data_input (в физическом воплощении — это набор переключателей).
Флаги состояния Acc>=0 и Acc=0, а также устройство вывода подключены к выводу аккумулятора
![image](https://habrastorage.org/webt/mx/mv/eu/mxmveuu6yw0mzsn86w6xakho5sy.gif)
Отличием LIttle Man Computer от RAM-машины является механизм, обеспечивающий косвенную адресацию (возможность работать с числом, хранящемся в памяти, как с адресом).
Для того, чтобы работать с числом, хранящимся в памяти, как с адресом, подключим к адресному входу Памяти Данных мультиплексор MUX, осуществляющий выборку между, собственно, адресом (поступающим из Памяти Команд) и числом, представляющем адрес и хранящемся в Памяти Данных.
![](https://habrastorage.org/webt/sk/6a/7y/sk6a7y2qvdunwxrlppbreubshhy.jpeg)
Будем загружать число из памяти в регистр каждый раз, когда происходит выборка новой команды из Памяти команд. При переключении мультиплексора MUX происходит переход на адрес, записанный в адресный регистр.
![](https://habrastorage.org/webt/7k/k_/xb/7kk_xbldx4vggzaebcyfqeccxnm.gif)
Также будем загружать загружать адрес команды в аккумулятор Acc как число, для этого увеличим разрядность адресного входа мультиплексора, производящего выборку данных для загрузки в аккумулятор Асс. Адрес загружается на 4ый вход мультиплексора.
![](https://habrastorage.org/webt/4c/v-/_l/4cv-_l8vkeqgfd9ujkh2rooi7vy.jpeg)
Пусть бработка команды производится в два такта: подключим к тактовому генератору два D-триггера, которые будут переключать друг друга при поступлении тактового сигнала.
![](https://habrastorage.org/webt/xx/0f/3n/xx0f3nv9gdqgleplfan3tp7_kzi.gif)
1ый такт осуществляет загрузку адреса в адресный регистр, 2ой такт осуществляет загрузку числа в аккумулятор Acc или в Память данных.
Подключим к аккумулятору 2 флага:
1. Флаг Acc = 0. Флаг поднимается, если содержимое Асс равно нулю.
2. Флаг Acc > 0. Флаг поднимается, если содержимое Асс больше нуля.
![](https://habrastorage.org/webt/av/2m/32/av2m32fmfxqkv4f6eecbaarz66s.jpeg)
Получилась вот такая схема, которую можно скачать отсюда
![](https://habrastorage.org/webt/lt/hw/_o/lthw_ou3mjjlswhj08hx7iw32lo.jpeg)
Линия, идущая на разрешающий вход аккумулятора, нужна для того, чтобы схема не глючила.
Отключим некоторые команды и напишем программу, которая загружает нулевую ячейку Памяти данных по адресу, хранящемуся в нулевой ячейке. Будем в цикле увеличивать значение нулевой ячейки на единицу. Т.о. мы заполним Память данных порядковыми номерами.
1401 загружаем в Acc число 1
1100 прибавляем число в Acc к числу в нулевой ячейке
2000 сохраняем результат в нулевой ячейке
2080 загружаем число из Acc по адресу, на который ссылается нулевая ячейка
0010 прыгаем в начало программы
![](https://habrastorage.org/webt/jh/sr/ic/jhsricpjdwfv8bjztng2-v8kxso.gif)
Напишем программу, суммирующую
Будем записывать натуральные числа в 1ой ячейке, а их сумму в 0ой ячейке.
Для начала напишем программу, загружающую натуральные числа в первую ячейку
1401 загружаем в Acc число 1
1101 прибавляем число в Acc к числу в 1ой ячейке
2001 сохраняем результат в 1ой ячейке
В 0ой ячейке будем производить суммирование. После увеличения числа в 1ой ячейке надо прибавить это число к 0ой ячейке.
1300 загружаем в Acc число из ячейки 0
1101 прибавляем число в Acc к числу в 1ой ячейке
2000 сохраняем результат в 0ой ячейке
0010 прыгаем в начало программы
Полный текст программы
1401
1101
2001
1300
1101
2000
0010
Для того, чтобы вычислить
Далее необходимо произвести суммирование:
1300 загружаем в Acc число из ячейки 0
1101 прибавляем число в Acc к числу в 1ой ячейке
2000 сохраняем результат в 0ой ячейке
Далее необходимо прыгнуть на 3 команды назад и повторить этот набор операций
Эмулятор классической RAM-машины (с раздельными лентами чтения/записи) можно скачать отсюда.
Проверим как работает схема, состоящая из двух d-триггеров. Эта схема обеспечивает двух-тактовый режим.
Напишем схему обычного d-триггера (без reset и enable). У него будет два входных порта — порт данных и тактовый порт.
module dff
(
input [1:0] key,
output led
);
wire clk;
assign clk = key [0]; // тактовый вход
wire d = key [1]; // вход данных
reg q;
always @(posedge clk)
q <= d;
assign led = q;
endmodule
Светодиод led показывает состояние d-триггера.
Подключим два dff в общую схему.
Состояние первого d-триггера будет показывать светодиод q1_led.
Состояние второго d-триггера будет показывать светодиод q2_led.
Выведем тактовый сигнал на отдельный светодиод q3_led.
module dff_dff
(
input clk,
output q1_led, q2_led,q3_led
);
assign q3_led = clk;
wire d1_in;
assign d1_in=~q2_led;
dff dff1(
.clk(clk),
.d(d1_in),
.q(q1_led)
);
wire d2;
assign d2=q1_led;
dff dff2(
.clk(clk),
.d(d2),
.q(q2_led)
);
endmodule
RTL-модель модуля dff_dff выглядит так
![](https://habrastorage.org/webt/g5/kq/hg/g5kqhgy5dxzupyxyipw2lgb179u.jpeg)
Работоспособность схемы можно проверить, непосредственно загрузив программу в ПЛИС.
Эта схема будет работать не на всех платах, на некоторых платах необходимо производить инициализацию d-триггеров. По этой же причине такая схема не будет симулироваться в ModelSim.