Скачиваний:
19
Добавлен:
09.05.2014
Размер:
390.66 Кб
Скачать

Министерство образования и науки Российской Федерации

Санкт-Петербургский государственный университет информационных технологий, механики и оптики

Кафедра вычислительной техники

Курсовой проект “Проектирова-

ние ЭВМ”

Выполнили:

студенты группы 2100

Митрофанов А.

Пермяков В.

Проверил:

Скорубский В. И.

Санкт-Петербург 2009г.

Содержание

Постановка исходного задания . . . . . . . . . . . . . . . . . . 2

Формат используемых команд . . . . . . . . . . . . . . . . . . . 2

Структурная схема ЭВМ . . . . . . . . . . . . . . . . . . . . . . . 3

Функциональная схема ЭВМ . . . . . . . . . . . . . . . . . . . . 6

Функциональная и структурная программа,

программа выполнения выбранных команд на С++ . . . 8

Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Постановка исходного задания

Целью курсового проекта является разработка микропрограммного управления и схемы ЭВМ с архитектурой и системой команд MCS51. Микропрограммирование – раздел теории ВМ, в котором разрабатывались методы моделирования и формализации построения схем и управляющих микропрограмм. Для описания микропрограмм можно использовать блок-схемы и средства из процедурных языков программирования (операции, переменные, функции), языков описания аппаратуры (регистры, логика, поля бит) и языков регистровых передач RTL (Registers Tranzactions Language).

Для функционального описания микропрограмм и моделирования могут быть использованы языки программирования, наиболее близким из которых является язык С.

Предлагается список команд, для которых по рассмотренному выше плану разрабатываются – схемы операционного устройства и микропрограммы выполнения команд, программа моделирования на языке С.

• subb a, {@rj, #d}

• rr a

• xch a, {ri, ad}

• acall ad11

Формат используемых команд

Используемые команды имеют следующий формат:

Мнемоника Код команды Примечание

subb A, @Ri 1001 011i i = 0 ... 1

subb A, #data 1001 0100 | #data

rr A 0000 0011

xch A, Rn 1100 1xxx xxx = 000 ... 111

xch A, ad 1100 0101 | direct address

acall ad11 A10 A9 A8 1 0001 | A7 A6 A5 A4 A3 A2 A1 A0

Рассматриваемые команды имеют следующие особенности исполнения:

subb a, @Ri

subb a, #data

Команда «вычитание с заемом» вычитает указанную переменную вместе с флагом переноса из содержимого аккумулятора, засылая результат в аккумулятор. Эта команда устанавливает флаг переноса (заема), если при вычитании для бита 7 необходим заем, в противном случае флаг переноса сбрасывается. Если флаг переноса установлен перед выполнением этой команды, то это указывает на то, что заем необходим при вычитании с увеличенной точностью на предыдущем шаге, поэтому флаг переноса вычитается из содержимого аккумулятора вместе с операндом источника. (АС) устанавливается, если заем необходим для бита 3 и сбрасывается в противном случае. Флаг переполнения (OV) устанавливается, если заем необходим для бита 6, но его нет для бита 7, или есть для бита 7, но нет для бита 6.

При вычитании целых чисел со знаком (OV) указывает на отрицательное число, которое получается при вычитании отрицательной величины из положительной, или положительное число, которое получается при вычитании положительного числа из отрицательного.

rr a

Команда «сдвиг содержимого аккумулятора вправо» сдвигает вправо на один бит все восемь бит аккумулятора. Содержимое бита 0 помещается на место бита 7. На флаги эта команда не влияет.

xch a, Rn

xch a, ad

Команда «обмен содержимого аккумулятора с переменной-байтом» осуществляет обмен содержимого аккумулятора с содержимым источника, указанным в команде.

acall ad11

Команда «абсолютный вызов подпрограммы» вызывает безусловно подпрограмму, размещенную по указанному адресу. При этом счетчик команд увеличивается на 2 для получения адреса следующей команды, после чего полученное 16-битовое значение РС помещается в стек (сначала следует младший байт), и содержимое указателя стека также увеличивается на два. Адрес перехода получается с помощью конкатенации старших бит увеличенного содержимого счетчика команд, битов старшего байта команды и младшего байта команды.

Структурная схема ЭВМ

При построении структурной схемы ЭВМ учтены следующие принципы:

1. Используется шинная архитектура с тремя шинами, достоинствами которой являются:

• максимально параллельное исполнение разнообразных передач между регистрами, регистрами и различными блоками иерархической памяти и выполнение элементарных операций в АЛУ

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

• легко ориентироваться при выборе регистровых передач в микрокомандах преобразования данных

2. Применяются, по возможности, простые регистры-защелки для хранения выбранных из памяти данных и промежуточных результатов. Операции счета и сдвига могут быть выполнены комбинационными схемами при передаче данных между регистрами.

3. Для максимально параллельного выполнения операций счета и сдвига используются накапливающие синхронизированные регистры-счетчики и сдвигатели. Выполнение этих микроопераций часто совмещается с передачами между регистрами и памятью, в которых активно используются шины.

4. К регистрам должен быть обеспечен как адресный доступ, так и непосредственный для контроля и работы с отдельными битами и полями битов.

5. Неявно используемые регистры SFR для сокращения обращения к памяти дублируются с использованием их теневого отображения в памяти и непосредственного доступа в схеме при чтении.

В данном случае блок памяти включает программную память Code и память данных Xdata, которые имеют общую адресную 16-битовую шину ACX[15.0] и слово памяти – байт.

Блок RAM объединяет Data и SFR с общей 8-битовой шиной адреса BasA[7..0] и 8-разрядным словом данных.

Блок 16-битовых адресных регистров-счетчиков с прямым доступом DPTR, PC формируют 16-битовый адрес.

Блок 8-битовых регистров с прямым доступом ACC, B, SP, рабочие Wrk, Wrk1 выполняют разнообразные функции – формируют 8-битовый адрес, хранят операнды и параметры команды, являются счетчиками циклов в операциях умножения и деления и сдвигаетелями.

Арифметико-логический блок включают собственно арифметико-логическое устройство, регистры временного хранения операндов RA, RB и регистр PSW с побитовым доступом к признакам операции.

Блок управления CU содержит регистр команд IR, микропрограммное устройство управления с декодером микрокоманд. Мультиплексор MX выбора битов-признаков с регистра PSW и выходов АЛУ в блок микропрограммного управления.

В схеме выделены специальные функциональные блок формирования констант на шинах (0, -1, -8), блок выборки битов и выполнения битовых операций BIT с прямым доступом к рабочим регистрам Wrk, Wrk1, PSW.

Выделены 8-битовые двунаправленные порты ввода-вывода, имеющие организацию и управление, отличающее их существенно от всех регистров. Порты ввода-вывода P0, P1, P2, P3 представлены в отдельном блоке соответствующими регистрами с теневым отображением в SFR.

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

Каждый мультиплексор BasB, BasC, BasA, ACX позволяет прочитать данные только из одного источника (регистра, памяти), что регулируется соответствующими управляющими сигналами выборки Bi, Ci, Xi.

Запись с мультиплексированных шин в регистры и память выбирается адресным декодером Mi – с шины BasB, декодером Wi – c шины BasC.

Сигнал записи обозначается единицей на одном из 2n выходов декодера, где n – разрядность адреса выбираемого функционального элемента на шинах BasB и/или BasC. При этом нуль на всех остальных выходах декодера обозначает параллельное чтение, но выбор одного из читаемых значений осуществляется мультиплексором.

Функциональная схема ЭВМ

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

Для управления каждым программируемым и управляемым функциональным элементом на функциональной схеме используются структурные микрокоманды. Для кодирования микрокоманд и загрузки в управляющую память используется более простая система обозначений с явным указанием на номер (код) управляющих сигналов.

Функциональная и структурная программа,

программа выполнения выбранных команд на С++

Структурные микрокоманды приведены в комментариях к программе

Программа представляет собой форму, отображающую элементы структурной схемы. Состояние регистров отображается в соотвествующих метках зеленого цвета.

Ниже приводится функция micro (), а также другие функции, используемые в проекте.

#include <iostream>

#include <Math.h>

#pragma once

namespace Kursov {

unsigned char Code[256]; /* память Code */

unsigned char Romm[256]; /* память Romm */

unsigned char IR, /* регистр команд */

C, /* Carry Flag */

ACC, /* аккумулятор */

PSW, /* слово состояния машины */

SP, /* указатель на вершину стека */

Acc, /* указатель на ACC в SFR */

RA, RB, /* регистры-защелки */

Wrk, Wrk1, /* дополнительные регистры */

Ram[256]; /* память Data и SFR */

unsigned char step; /* счетчик тактов */

unsigned short int PC; /* счетчик команд */

unsigned char PCH, PCL; /* старшая и младшая части счетчика команд */

bool flag = true;

void clean ( void )

{

Inst_reg->Text = "00";

Prog_count->Text = "0000";

Carry_flag->Text = "00";

Accum->Text = "00";

Flags->Text = "00";

Stack->Text = "81";

Reg_A->Text = "00";

Reg_B->Text = "00";

Wrk_0->Text = "00";

Wrk_1->Text = "00";

Step_label->Text = "0";

combo_box->SelectedItem = combo_box->Items[0] ;

/* далее сброс глобальных переменных */

IR = 0;

C = 0;

ACC = 0;

PSW = 0;

SP = 0x81;

Acc = 0xe0;

RA = 0;

RB = 0;

Wrk = 0;

Wrk1 = 0;

step = 0;

PC = 0;

b_step->Visible = false;

b_chose->Visible = true;

combo_box->Enabled = true;

/* коды команд */

Romm[0x96] = 0x00; /* subb a, @rj */

Romm[0x97] = 0x00;

Romm[0x94] = 0x01; /* subb a, #data */

Romm[0x03] = 0x02; /* rr a */

Romm[0xc8] = 0x03; /* xch a, rn */

Romm[0xc9] = 0x03;

Romm[0xca] = 0x03;

Romm[0xcb] = 0x03;

Romm[0xcc] = 0x03;

Romm[0xcd] = 0x03;

Romm[0xce] = 0x03;

Romm[0xcf] = 0x03;

Romm[0xc5] = 0x04; /* xch a, ad */

Romm[0xf8] = 0x05; /*acall ad11 */

Romm[0xf9] = 0x05; /*acall ad11 */

Romm[0xfa] = 0x05; /*acall ad11 */

Romm[0xfb] = 0x05; /*acall ad11 */

Romm[0xfc] = 0x05; /*acall ad11 */

Romm[0xfd] = 0x05; /*acall ad11 */

Romm[0xfe] = 0x05; /*acall ad11 */

Romm[0xff] = 0x05; /*acall ad11 */

}

/* У нас функция PSW() применяется только для subb -- пишем PSW() только

* с расчетом на subb.

* --------------------------------------------------------------

*

* -----------------------------------------

* | | | | | | | | |

* | C | AC | F0 | RS1 | RS2 | OV | -- | P |

* | | | | | | | | |

* -----------------------------------------

* 7 0

*/

void Psw(char OP)

{

int i = 0;

char P = 0;

switch (OP) {

case 1:

PSW = ((RA + RB + (PSW >> 7)) >= 0x100) ? PSW | 0x80 :

PSW & 0x7f; /* C */

PSW = (((RA & 0x80) != (RB & 0x80)) & ((ACC & 0x80) ==

(RB & 0x80))) ? PSW | 0x04 : PSW & 0xfb; /* OV */

for (i = 1; i < 8; i++) { /* P */

P += (ACC & (i * 2)) & 0x1;

}

SW = (P % 2) ? PSW | 0x01 : PSW & 0xfe;

C = (PSW & 0x80)>>7;

break;

}

Flags->Text = System::Convert::ToString(PSW);

return;

}

void micro()

{

switch ((int)Romm[(int)IR]) {

case 0: /* subb a, @rj */

switch (step) {

case 0:

RA = ACC; /* BasB = B4, M4 */

step++;

break;

case 1:

Ram[(PSW & 0x18) | (IR & 0x01)] = 0x54;

Wrk = Ram[(PSW & 0x18) | (IR & 0x01)];

/* BasA = A5. BasB = B1, M2 */

step++;

break;

case 2:

Ram[Wrk] = 0x3f;

RB = Ram[Wrk];

/* BasA = A0, BasB = B1, M3, BasC = C4, W5 */

step++;

break;

case 3:

ACC = RA - RB; /* ALU=sub, BasC = C11, W1 */

Psw(1); /* wpsw */

step++;

break;

case 4:

Ram[Acc] = ACC; /* BasA = ACC, BasC = C1, W0 */

IR = Code[PC++] = 0xf4;

/* Acx = PC, BasB = B3, M8, incPC */

step = 0;

flag = true;

break;

} /* switch (step) */

break;

case 1: /* subb a, #data */

switch (step) {

case 0:

RA = ACC; /* BasB = B4, M4 */

step++;

break;

case 1:

Wrk = Code[PC++] = 0xf4;

/* Acx = PC, BasB = B3, M2 */

RB = Wrk; /* BasC = C3, W5 */

step++;

break;

case 2:

ACC = RA - RB; /* ALU=sub, BasC = C11, W1 */

Psw(1); /* wpsw */

step++;

break;

case 3:

Ram[Acc] = ACC; /* BasA = ACC, BasC = C1, W0 */

IR = Code[PC++] = 0x3a;

/* Acx = PC, BasB = B3, M8, incPC */

step = 0;

flag = true;

break;

} /* switch (step) */

break;

case 2: /* rr A */

switch (step) {

case 0:

Wrk = (ACC & 0x01) & 0x01; /* BasB = B4, M2 */

ACC >>= 1; /* srA */

ACC = (ACC & 0xfe) | (Wrk & 0x01);

/* BasC = C3, W1 */

step++;

break;

case 1:

Ram[Acc] = ACC; /* BasA = ACC, BasC = C1, W0 */

IR = Code[PC++] = 0xf4;

/* Acx = PC, BasB = B3, M8, incPC */

step = 0;

flag = true;

break;

} /* switch (step) */

break;

case 3: /* xch a, rn */

switch (step) {

case 0:

Ram[(PSW & 0x18) | (IR & 0x07)] = 0x54;

Wrk = Ram[(PSW & 0x18) | (IR & 0x07)];

/* BasA = A5. BasB = B1, M2 */

step++;

break;

case 1:

Ram[(PSW & 0x18) | (IR & 0x07)] = ACC;

/* BasA = A5, BasC = C1, W0 */

step++;

break;

case 2:

ACC = Wrk; /* BasC = C3, W1 */

step++;

break;

case 3:

Ram[Acc] = ACC; /* BasA = ACC, BasC = C1, W0 */

IR = Code[PC++] = 0xf4;

/* Acx = PC, BasB = B3, M8, incPC */

step = 0;

flag = true;

break;

} /* switch (step) */

break;

case 4: /* xch a, ad */

switch (step) {

case 0:

Wrk1 = Code[PC++] = 0xf4;

/* Acx = PC, BasB = B3, M3, incPC */

step++;

break;

case 1:

Ram[Wrk1] = 0xd2;

Wrk = Ram[Wrk1];

/* BasA = Wrk1, BasB = B1, M2 */

step++;

break;

case 2:

Ram[Wrk1] = ACC;

/* BasA = Wrk1, BasC = C1, W0 */

step++;

break;

case 3:

ACC = Wrk; /* BasC = C3, W1 */

step++;

break;

case 4:

Ram[Acc] = ACC; /* BasA = ACC, BasC = C1, W0 */

IR = Code[PC++] = 0xe2;

/* Acx = PC, BasB = B3, M8, incPC */

step = 0;

flag = true;

break;

} /* switch (step) */

break;

case 5: /* acall ad11 */

switch (step) {

case 0:

Wrk1 = Code[PC++] = 0x04;

/* Acx = PC, BasB = B3, M3, incPC */

step++;

break;

case 1:

PCL = (char)(0x00ff & PC);

Wrk = Code[PC++] = 0x12;

/* Acx = PC, BasB = B3, M2, incPC */

Ram[++SP] = PCL;

/* incSP, BasA = SP, BasC = B6, W0 */

step++;

break;

case 2:

PCH = (char)(0xff00 & PC);

Ram[++SP] = PCH;

/* incSP, BasA = SP, BasC = C4, W0 */

step++;

break;

case 3:

PCH = ((PCH & 0x1f) | (Wrk1 & 0xe0));

/* BasC = C3, W3 */

PCL = Wrk; /* BasB = B10, M8 */

PC = (PCH << 8) | PCL;

step++;

break;

case 4:

IR = Code[PC++] = 0x33;

/* Acx = PC, BasB = B3, M8, incPC */

step = 0;

flag = true;

break;

}

break;

}

return;

}

/* Функция возвращает строку со шестнадцеричным значением переданного в качестве аргумента регистра */

String ^ sw ( unsigned char local )

{

String ^ tmp;

switch (local)

{

case 0: case 1: case 2: case 3: case 4: case 5: case 6: case

7: case 8: case 9: tmp = System::Convert::ToString(local); break;

case 10: tmp = "a"; break;

case 11: tmp = "b"; break;

case 12: tmp = "c"; break;

case 13: tmp = "d"; break;

case 14: tmp = "e"; break;

case 15: tmp = "f"; break;

}

return tmp;

}

String ^ conv_hex ( unsigned char number )

{

String ^ result = "";

unsigned char buf_1 = ( ( number & ( 0xf0 ) ) >> 4 );

unsigned char buf_2 = ( number & ( 0x0f ) );

result+=sw(buf_1)+sw(buf_2);

return result;

}

/* Функция обновления текста в метках полсе выполнения шага микропрограмм */

void refresh (void)

{

PCL = PC & 0x00ff;

PCH = ( PC >> 8 ) & 0x00ff;

Inst_reg->Text = conv_hex(IR);

Prog_count->Text = conv_hex(PCH) + conv_hex(PCL);

Carry_flag->Text = conv_hex(C);

Accum->Text = conv_hex(ACC);

Flags->Text = conv_hex(PSW);

Stack->Text = conv_hex(SP);

Reg_A->Text = conv_hex(RA);

Reg_B->Text = conv_hex(RB);

Wrk_0->Text = conv_hex(Wrk);

Wrk_1->Text = conv_hex(Wrk1);

Step_label->Text = System::Convert::ToString(step);

}

/* Событие - загрузка формы */

private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)

{

clean ();

}

/* Событие - нажатие на кнопку "cброс" */

private: System::Void b_ref_Click(System::Object^ sender, System::EventArgs^ e)

{

clean ();

}

/* Cобытие - нажитие на кнопку "Выбрать команду" */

private: System::Void b_chose_Click(System::Object^ sender, System::EventArgs^ e)

{

int index = combo_box->SelectedIndex;

switch ( index )

{

case 0: Inst_reg->Text = "96"; IR = 0x96; break; /* subb a, @ri */

case 1: Inst_reg->Text = "94"; IR = 0x94; break; /* subb a, #d */

case 2: Inst_reg->Text = "03"; Accum->Text = "04"; IR =

3; ACC = 0x04; break; /* rr a */

case 3: Inst_reg->Text = "c8"; IR = 0xc8; break; /* xch a, ri */

case 4: Inst_reg->Text = "c5"; IR = 0xc5; break; /* xch a, ad */

case 5: Inst_reg->Text = "f8"; IR = 0xf8; break; /* acall ad11 */

}

flag = false;

b_step->Visible = true;

b_chose->Visible = false;

combo_box->Enabled = false;

}

/* Cобытие - нажитие на кнопку "Шаг" */

private: System::Void b_step_Click(System::Object^ sender, System::EventArgs^ e)

{

if ( !flag )

{

micro();

if (step == 0)

{

b_step->Visible = false;

flag = true;

}

}

refresh ();

}

Литература

[1] В.И. Скорубский, П.С. Довгий Методическое пособие по курсовому

проекту “Проектирование ЭВМ”

[2] Э.С. Таненбаум Архитектура ЭВМ