WingLion's Forum

А чего тут только нет?.. и поиска нет, и юзеров нет, и ничего ненужного нет
Текущее время: 24 ноя 2017, 05:53

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 129 ]  На страницу 1, 2, 3, 4, 5 ... 9  След.
Автор Сообщение
 Заголовок сообщения: Forth-CPU (Форт-процессор)
СообщениеДобавлено: 07 июн 2005, 19:50 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Разработка Forth-CPU на ПЛИС фирмы ALTERA.

Некоторые идеи:

1. Регулируемая разрядность 8...32
<dd>можно и больше, но пока не нужно
2. Многостековость (пока - 4-х)
<dd>реализация стеков на внутренних блоках памяти
3. (?)Конвейерный мультипроцессор(?)
<dd>по возможности, если получится
4. Процессор общего назначения.
<dd>добавить спец-функции можно и позже
5. Надо думать, что еще...

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 июн 2005, 19:05 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Итак, начинаем все дело с нуля. В смысле, не совсем с нуля, а с того уровня
знаний, который накоплен к этому моменту времени и с имеющегося опыта.

Для начала, определимся с тем, на какой ПЛИС делать:
Разумеется, выбор падает на ПЛИС фирмы ALTERA, ибо опыт работы у меня
имеется только с ними.

Конкретно выбор падает на микросхему EP1K50QC208-2, которая стоит в
устройстве, что имеется у меня под боком. Чисто принципиально, подойдет и
любая другая ПЛИС семейства ACEX, лишь бы хватило ее объема для реазлизации
процессора и удовлетворила скорость его работы. Speed-Grade = 2 -- это не
самая низкая, но и не самая высокая скорость.

Чтобы уточнить, что же у меня есть под боком, добавлю, что в этом устройстве
кроме ПЛИС есть:
ПЗУ, объемом 512 килобайт, 256Кx16, и временем доступа 70нс;
OЗУ - 256Кб - 128Кx16, 15нс;
полный IDE-интерфейс.
ОЗУ и ПЗУ, имеют общую шину адреса, общую шину данных, к которой подключена
и шина данных IDE (через буферы!). Отдельно от всех устройств подключена
SD-RAM-100MHz, объемом 8Мегабайт - 1Mx8.

Тактовый генератор - 100MHz - Микросхема (однократно)программируемого
генератора фирмы Epson - SG8002.

Из устройств, которые пока не нужны, есть два интерфейса PS/2, через которые
можно подключить клавиатуру и мышь, а так же имеется вторая ПЛИС с VGA
контроллером, который, можно использовать в режиме CGA 80x25 символов.

По мере движения вперед, возможно, всплывет и какая-то новая информация,
необходимая для ведения разработки.

Разумеется, в устройстве есть схема связи с PC (через LPT).


=============================


Начнем с планирования блоков, которые должны быть в процессоре и около него.

1. Тактовый генератор. Вероятность того, что процессор сразу заработает на
100MHz можно исключить, поэтому первым делом в ПЛИС-е устанавливается
тактовый генератор с переменным коэфициентом деления. Для этого тактовая
частота простой схемой умножается на 2, а затем делится на 2N, где N -
заданный коэфициент.
Четное число только для того, чтобы был меандр на выходе, кто захочет, тот
может сделать и деление на нечетное число.

=== GEN.TDF ===
Код:
TITLE "Generator";

-- include "clklock";

PARAMETERS
(
FRQ  = 0
);

SUBDESIGN gen
(
CLK   : INPUT;
CLKF  : BIDIR;
COEF[3..0] : INPUT = GND;
)
VARIABLE

CNT[4..0] : DFF;

CLK100  : NODE;
CLK100X  : NODE;
CLK200  : NODE;

BEGIN



CLK100  = CLK;
CLK100X  = TFF(VCC,CLK200,,);

CLK200  = LCELL(CLK100 xor CLK100X);

-- CLK200  = clklock (CLK100) WITH (CLOCKBOOST=2, INPUT_FREQUENCY=90);

CNT[].clk = CLK200;

IF (FRQ == 0) GENERATE

IF (CNT[3..0] == 0) THEN
  CNT[] = (!CNT4,COEF[]);
ELSE
  CNT[] = CNT[] - 1;
END IF;

ELSE GENERATE

IF (CNT[3..0] == 0) THEN
  CNT[] = (!CNT4,(H"F" & FRQ));
ELSE
  CNT[] = CNT[] - 1;
END IF;

END GENERATE;

CLKF  = TRI(CNT4,VCC);

END;

===

Параметр FRQ указывает, какой коэфициент деления использовать. При FRQ=0
коэфициент берется со входов, иначе, задается значением FRQ+1
Т.е. При FRQ=3 и входной частоте 100MHz, выходная частота 25MHz.

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


=======================


2. Стеки.

Стеки можно реализовывать несколькими способами. Здесь приведу только два из
них:

a) Стек на логических ячейках. Имеет высокую скорость, но малую глубину,
занимает много места в ПЛИС:

=== STACK_LC.TDF ===

Код:
TITLE "Stack_on_lcell";

PARAMETERS
(
WIDTH=16,
DEPTH=8,
FULL = "NO" -- "YES" for 6 bit CMD
);

SUBDESIGN STACK_LC
(
CLK    : INPUT;
DI[WIDTH-1..0] : INPUT;
DO[WIDTH-1..0] : OUTPUT;
AO[WIDTH-1..0] : OUTPUT;
EMPTY   : OUTPUT;
EMPTY1   : OUTPUT;
CMD[1..0]  : INPUT = GND;
COMAND[5..0] : INPUT = GND;
ENA    : INPUT = VCC;
)
VARIABLE

DATA[DEPTH-1..0][WIDTH-1..0] : DFFE;
EMP[DEPTH-1..0] : DFFE;

PUSH/POP  : NODE;
P/P0   : NODE;
P/P1         : NODE;
GO          : NODE;
GO0          : NODE;
GO1          : NODE;

BEGIN

-- 000000 - NOP
-- 000111 - PUSH
-- 111111 - POP/DROP
-- 000110 - DUP
-- 111110 - NIP
-- 001111 - OVER
-- 001011 - SWAP
-- 110111 - DROP/DROP/PUSH - external 2 operand operation
-- 000001 - DROP/PUSH - external 1 operand operation

IF (FULL == "YES") GENERATE
  (PUSH/POP,P/P0,P/P1,GO,GO0,GO1) = COMAND[];
ELSE GENERATE
  (PUSH/POP,P/P0,P/P1,GO,GO0,GO1) = (CMD1,CMD1,CMD1,CMD0,CMD0,CMD0);
END GENERATE;

DATA[][].clk   = CLK;
EMP[].clk    = CLK;
DATA[DEPTH-1..2][].ena = GO & ENA;
EMP[DEPTH-1..2].ena  = GO & ENA;
DATA[1][].ena   = GO1 & ENA;
EMP[1].ena    = GO1 & ENA;
DATA[0][].ena   = GO0 & ENA;
EMP[0].ena    = GO0 & ENA;

FOR i IN DEPTH-1 TO 3 GENERATE
  CASE PUSH/POP IS
   WHEN 0 => DATA[i-1][] = DATA[i-2][]; EMP[i-1] = EMP[i-2];
   WHEN 1 => DATA[i-1][] = DATA[i][]; EMP[i-1] = EMP[i];
  END CASE;
END GENERATE;

CASE PUSH/POP IS
  WHEN 0 => DATA[DEPTH-1][] = DATA[DEPTH-2][]; EMP[DEPTH-1] = EMP[DEPTH-2];
  WHEN 1 => DATA[DEPTH-1][] = GND; EMP[DEPTH-1] = GND;
END CASE;

CASE P/P1 IS
  WHEN 0 => DATA[1][] = DATA[0][]; EMP[1] = EMP[0];
  WHEN 1 => DATA[1][] = DATA[2][]; EMP[1] = EMP[2];
END CASE;

CASE P/P0 IS
  WHEN 0 => DATA[0][] = DI[];
      EMP[0] = VCC;
  WHEN 1 => DATA[0][] = DATA[1][];
      EMP[0] = EMP[1];
END CASE;

AO[] = DATA[1][];
DO[] = DATA[0][];
EMPTY = EMP[0];
EMPTY1 = EMP[1];

END;

===

==========================

б). Стек на внутренних блоках памяти:

=== STACK_M.TDF ===
Код:
TITLE "STACK";

PARAMETERS
(
WIDTH=16
);

INCLUDE "lpm_ram_dq";

SUBDESIGN STACK_M
(
CLK    : INPUT;
DI[WIDTH-1..0] : INPUT;
DO[WIDTH-1..0] : OUTPUT;
COMAND[1..0] : INPUT;
WRITE   : INPUT;
)
VARIABLE
ADRESS[7..0] : DFF;
ADRESS_NEW[7..0]: NODE;
XX[7..0]  : NODE;

BEGIN

ADRESS[].CLK = CLK;
ADRESS[]  = ADRESS_NEW[];

ADRESS_NEW[] = ADRESS[] + XX[];
XX[7..1]  = COMAND1;
XX0    = COMAND0;

DO[] = lpm_ram_dq(DI[],ADRESS_NEW[],CLK,!CLK,WRITE)
  WITH (lpm_width=WIDTH,lpm_widthad=8,lpm_outdata="REGISTERED");

END;

===

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

====================

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 июн 2005, 23:05 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Частично согласованные по интерфейсу файлы стеков, файлы генератора
и файлы заглушки процессора находятся здесь.
Далее в этом файле будут находиться обновленные версии,
до получения конечного результата.

Stack_lc -- имеет предельную частоту 200MHz с одним тактом задержки,
Stack_m -- 105MHz, при наличии двух тактов задержки.

Имеется в виду задержка появления данных на выходе.
Со входа оба стека данные берут сразу, по очередному такту.

Для работы пока будет использоваться Stack_lc, так как задача
экономии места в ПЛИС не стоит, а скорость лучше иметь побольше
с самого начала.

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 09 июн 2005, 02:33 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Двигаемся дальше.
Следующий необходимый процессору блок - ALU.
Считаем, что нам достаточно 64-х операций, поэтому у
ALU - 6 линий выбора функции, два входа данных, один выход данных и
вход/выход бита переноса.

=== ALU2.TDF ===
Код:

TITLE "ALU";

include "lpm_add_sub";

PARAMETERS
(
MODE=0,
WIDTH=16
);

SUBDESIGN alu2
(
CLK    : INPUT;
ENA    : INPUT = VCC;
A[WIDTH-1..0] : INPUT;
B[WIDTH-1..0] : INPUT;
Q[WIDTH-1..0] : OUTPUT;

COMMAND[5..0] : INPUT;

CI    : INPUT = GND;
CO    : OUTPUT;
COR    : OUTPUT;
)
VARIABLE

CBIT   : DFFE;
LBIT   : DFFE;
ZERO[WIDTH-1..0]: NODE;

IF (MODE == 0) GENERATE
  AX[WIDTH-1..0] : LCELL;
  BX[WIDTH-1..0] : LCELL;
  CX[WIDTH-1..0] : LCELL;
  SX[WIDTH-1..0] : LCELL;
ELSE GENERATE
  AX[WIDTH-1..0] : DFF;
  BX[WIDTH-1..0] : DFF;
  CX[WIDTH-1..0] : DFF;
  SX[WIDTH-1..0] : DFF;
END GENERATE;

ADS    : lpm_add_sub WITH(LPM_WIDTH=WIDTH,LPM_PIPELINE=1);

BEGIN

ZERO[] = GND;

IF (MODE != 0) GENERATE
  AX[WIDTH-1..0].clk = CLK;
  BX[WIDTH-1..0].clk = CLK;
  CX[WIDTH-1..0].clk = CLK;
END GENERATE;

IF COMMAND4 THEN
  Q[] = ADS.result[];
  CO = ADS.cout;
  COR = CBIT;
ELSE
  Q[] = CX[];
  CO  = GND;
  COR = LBIT;
END IF;

ADS.cin  = LCELL((CI & !COMMAND1) or (CBIT & COMMAND1));

ADS.add_sub = !COMMAND0;
ADS.clock = CLK;
ADS.clken = ENA;

ADS.dataa[] = A[];
ADS.datab[] = BX[];

CASE COMMAND[3..2] IS
  WHEN 0 => BX[] = B[];
  WHEN 1 => BX[] = 1;
  WHEN 2 => BX[] = 0;
  WHEN 3 => BX[] = -1;
END CASE;

CBIT.clk = CLK;
CBIT.ena = ENA & COMMAND4;
CBIT  = ADS.cout;

LBIT.clk = CLK;
LBIT.ena = ENA;

CASE COMMAND[1..0] IS
  WHEN 0 => AX[] = !A[];
  WHEN 1 => AX[] = A[] & B[];
  WHEN 2 => AX[]  = A[] or B[];
  WHEN 3 => AX[] = A[] xor B[];
END CASE;

CASE COMMAND[1..0] IS
  WHEN 0 => SX[] = (A[WIDTH-2..0],GND);   LBIT = A[WIDTH-1];
  WHEN 1 => SX[] = (A[WIDTH-2..0],A[WIDTH-1]); LBIT = A[WIDTH-1];
  WHEN 2 => SX[]  = (GND,A[WIDTH-1..1]);          LBIT = A[0];
  WHEN 3 => SX[] = (A[0],A[WIDTH-1..1]);         LBIT = A[0];
END CASE;

CASE COMMAND[3..2] IS
  WHEN 0 => CX[] = AX[];
  WHEN 1 => CX[] = SX[];
  WHEN 2 => CX[] = A[];
  WHEN 3 => CX[] = B[];
END CASE;

END;


===

Можно, конечно, пооптимизировать, но пока не буду.
В конце концов, ALU можно будет изменить и позже,
добавив и другие функции, тем более, что в данной
реализации использованы далеко не 64 функции.

===========================

Итак, почти все блоки готовы, можно приступать и к самому процессору.
Для начала, определимся, какие в процессоре нужны регистры.
1. PC Регистр счетчика команд - обязательно.
2. AR Регистр данных - ну, хоть какой-нибудь.
3. DR Регистр временного хранения данных - нужен именно регистр,
чтобы команда или данные, переданные с шины процессора фиксировались точно.
CMDR - регистр команд (пока оказывается и не нужен)
MR, WMR - триггеры фиксации команды работы с памятью, нужны,
чтобы помнить в течение следующего такта о том, что команды не будет,
а будет передача данных. WMR - определяет, в какую сторону эта передача.

Итак, первый предварительный код собственно процессора:

=== FORTH.TDF ===
Код:

TITLE "Forth-CPU";

include "gen";
include "stack_lc";
include "stack_m";
include "alu2";

PARAMETERS
(
WIDTH = 16
);

SUBDESIGN forth
(
CLK100   : INPUT;
CLKF   : BIDIR;
CLK_CPU   : INPUT;
ENA    : INPUT = VCC;

A[WIDTH-1..0] : OUTPUT;
DI[WIDTH-1..0] : INPUT;
DO[WIDTH-1..0] : BIDIR;

MR    : OUTPUT;
MW    : OUTPUT;
CS    : OUTPUT;

)
VARIABLE

GN    : gen WITH (FRQ=3);
CLK    : NODE;

DOR[WIDTH-1..0] : NODE;
D_OUT   : NODE;

D_Stack   : stack_lc WITH (WIDTH=WIDTH,DEPTH=8,MODE=0);
R_Stack   : stack_lc WITH (WIDTH=WIDTH,DEPTH=8,MODE=0);

ALU    : alu2 WITH (WIDTH=WIDTH,MODE=0);

PC[WIDTH-1..0] : DFFE;
AR[WIDTH-1..0] : DFFE;
DR[WIDTH-1..0] : DFFE;

CMDR[WIDTH-1..0]: DFFE;

RSTC[1..0]  : NODE;
DSTC[1..0]  : NODE;
ALUFN[5..0]  : NODE;

ENA2   : NODE;

RSTD[WIDTH-1..0]: NODE;

MR    : DFFE;
WMR    : DFFE;

BEGIN

GN.clk   = CLK100;
CLKF   = GN.clkf;
-- CLK    = CLKF;
CLK    = CLK_CPU;

ENA2   = DFF(ENA,CLK,,);

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

R_Stack.CLK   = CLK;
R_Stack.DI[]  = RSTD[];
R_Stack.command[] = RSTC[];

D_Stack.CLK   = CLK;
D_Stack.DI[]  = AR[];
D_Stack.command[] = DSTC[];

DOR[]    = ALU.q[];

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

PC[].clk  = CLK;
PC[].ena  = ENA2;

MR.clk   = CLK;
MR.ena   = ENA2;
WMR.clk   = CLK;
WMR.ena   = ENA2;

A[]    = PC[];

CASE (MR,DR[15..14]) IS
  WHEN 0 =>  PC[]  = PC[] + 1;
     RSTD[] = AR[];

  WHEN 1 =>  PC[]  = (GND,GND,DR[WIDTH-3..0]);
     RSTD[] = PC[] + 1;

  WHEN 2 =>  PC[]  = R_Stack.DO[];
     RSTD[] = AR[];

  WHEN 3 =>  PC[]  = AR[];
     RSTD[] = PC[] + 1;
  WHEN 4,
   5,6,7 =>PC[]  = R_Stack.DO[];
     RSTD[] = AR[];
END CASE;

CASE (MR,DR[15..14]) IS
  WHEN 0 =>  RSTC[1..0]  = DR[7..6]; -- NEXT
     DSTC[1..0]  = DR[9..8];
     MR    = GND;
     WMR    = GND;
  WHEN 1 =>  RSTC[1..0]  = 1;  -- CALL
     DSTC[1..0]  = 0;
     MR    = GND;
     WMR    = GND;
  WHEN 2 =>  RSTC[1..0]  = 3;  -- RET
     DSTC[1..0]  = DR[9..8];
     MR    = GND;
     WMR    = GND;
  WHEN 3 =>  RSTC[1..0]  = 1;  -- MEM
     DSTC[1..0]  = 3;
     MR    = VCC;
     WMR    = DR[13];
  WHEN 4,
   5,6,7 =>RSTC[1..0]  = 3;  -- RET-MEM
     DSTC[1..0]  = 1;
     MR    = GND;
     WMR    = GND;
END CASE;

CMDR[].clk  = CLK;
CMDR[].ena  = ENA2;
CMDR[]   = DR[];

AR[].clk  = CLK;
AR[].ena  = ENA2;

CASE (MR,WMR) IS
  WHEN 0 => AR[] = ALU.Q[];
  WHEN 1 => AR[] = ALU.Q[];
  WHEN 2 => AR[] = DR[];
  WHEN 3 => AR[] = ALU.Q[];
END CASE;

DR[].clk  = CLK;
-- DR[].clk  = !CLK;
DR[].ena  = ENA;
DR[]   = DI[];

ALUFN[]   = DR[5..0];


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

ALU.clk   = CLK;
ALU.ena   = ENA2;
ALU.command[] = ALUFN[];
ALU.a[]   = AR[];
ALU.b[]   = D_Stack.DO[];

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

D_OUT   = VCC;

FOR i IN 0 TO WIDTH-1 GENERATE
  DO[i] = TRI(DOR[i],D_OUT);
END GENERATE;

(MR,MW,CS) = VCC;

END;


===

Теперь, собственно нужна отладка и добивание необходимой функциональности.

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 09 июн 2005, 02:38 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Собственно, последняя версия исходников на AHDL.

Хм.. с 6-го по 9-е июня - Форт-процессор в 3 дня! :D

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 09 июн 2005, 03:14 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
А теперь о том, что же собственно получилось.

Для начала, система команд:

Изображение

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 09 июн 2005, 03:45 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Tут явно чего-то не хватает, да и полей пустых достаточно.

1. Не хватает условных переходов! (Но это уже не сегодня...)
2. Нет умножения/деления - это для редактирования ALU.


А пока, что же показывает компилятор?..

На EP1K50QC208-2:

Занятых ячеек ПЛИС - 559 - 19%
Максимальная тактовая частота на CLK_CPU - 75.18MHz
При условии, что реально 2 такта на команду - 37.59MHz

Берем самую маленькую EP1K10TC100-1:

LCs - 559 - 97%, CLK_CPU-max=111.11MHz

EP1K10TC100-3:

LCs - 559 - 97%, CLK_CPU-max=66.66MHz

Вполне приличный результат.
Форт-процессор за 12$, с 33млн. оп/сек
Хотя, тут не учтена скорость внешнего ОЗУ, если использовать 15нс микросхемы SRAM, то 20-25MHz, уже можно получить.

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 09 июн 2005, 19:33 
Не в сети
Злой Модерун
Злой Модерун
Аватара пользователя

Зарегистрирован: 05 фев 2005, 04:22
Сообщения: 45
Откуда: с деревни
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Версия совершенно не рабочая.

1. При загрузке данных (команды работы с памятью) регистр команды грузится совершенно левым значением.

2. Нет команд условного перехода.

3. Занимаемый объем, вообще говоря, великоват. На 2 стека уходит 256 ячеек, еще 300 на остальное - много.

4. Двухтакное время исполнения команды наталкивает на мысль подключить стек на внутренней памяти. Все равно, стек простаивает лишний такт без дела, а так будет хотя бы экономия объема ПЛИС.

5. У стека нет команды SWAP - для нее надо использовать код NOP* (исправлено)

А пока начну с устранения проблемы 1.

_________________
Всех сгым, а кого нэ сгым, того пынадкусаю!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 09 июн 2005, 20:49 
Не в сети
Аватара пользователя

Зарегистрирован: 05 фев 2005, 14:50
Сообщения: 144
Откуда: Сфероид.
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Поглядим чем оное дело закончится.
А вообще - ты делаеш CPU с вшытым языком ФОРТ или просто свой CPU оптимизированный на работу с кодом скомпилированным с языка ФОРТ? Или что?
А то в моём представлении ФОРТ процессор - процессор ориентированный на работус с кодом скопилированным с ФОРТа.

_________________
Дракон-киборг.
Хочеш веселья? - Дёрни кольцо! (Надпись на гранате).
Танки грязи не боятся! - Особенно Т-3200!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 09 июн 2005, 21:27 
А систему команд лучше со слабым кодированием. У стековой машины опкодов очень немного, с приведенным вариантом системы команд будет много незадействованных или бессмысленных сочетаний полей.


Вернуться к началу
  
 
 Заголовок сообщения:
СообщениеДобавлено: 10 июн 2005, 01:32 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Цитата:
А вообще - ты делаеш CPU с вшытым языком ФОРТ или просто свой CPU оптимизированный на работу с кодом скомпилированным с языка ФОРТ? Или что?


Форт-процессор, это такой процессор, у которого ассемблер совпадает с неким набором примитовов языка FORTH.

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


Цитата:
А систему команд лучше со слабым кодированием. У стековой машины опкодов очень немного, с приведенным вариантом системы команд будет много незадействованных или бессмысленных сочетаний полей.


О кодировании буду позже думать, когда понадобится делать реализацию с 8-ю битами или с 32-мя. В первом случае кодирование нужно, т.к. 8-ми бит не хватит, во втором 32 - излишние, надо подумать, как в одно слово несколько команд ужать.

А пока работа продолжается...
Сейчас появится новый блок.

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 10 июн 2005, 01:44 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Блок управления памятью.

=== MDB.TDF ===
Код:

   Title "Memory direction block";

PARAMETERS
   (
   WIDTH = 16
   );

CONSTANT CMD_CALL = 2^(WIDTH-2) + 64;
CONSTANT CMD_RET = 2^(WIDTH-1) + 192;
--CONSTANT CMD_CALL = 2^(WIDTH-2);
--CONSTANT CMD_RET = 2^(WIDTH-1);

SUBDESIGN MDB
   (
   CLK               : INPUT;
   ENA               : INPUT = VCC;
   ENA2            : OUTPUT;

   DI[WIDTH-1..0]      : INPUT;
   DO[WIDTH-1..0]      : OUTPUT;
   COMMAND[WIDTH-1..0]   : OUTPUT;
   MEM               : OUTPUT;


   MR,MW,CS         : OUTPUT;
   READY            : INPUT = VCC;

   AO[WIDTH-1..0]      : OUTPUT;

   RSTO[WIDTH-1..0]   : INPUT = VCC;
   AR[WIDTH-1..0]      : INPUT = GND;

   PCI[WIDTH-1..0]      : OUTPUT;

   )
VARIABLE

   CMDR[WIDTH-1..0]   : DFFE;
   MEM               : DFFE;

   iPC[WIDTH-1..0]      : DFF;
   PC[WIDTH-1..0]      : DFFE;
   ENA2            : NODE;

   DR[WIDTH-1..0]      : DFFE;

BEGIN

   DR[].clk      = CLK;
   DR[].ena      = ENA;
   DR[]         = DI[];
   DO[]         = DR[];

   CMDR[].clk      = CLK;
   CMDR[].ena      = ENA;
   MEM.clk      = CLK;
   MEM.ena      = ENA;

   CASE (MEM,DI[WIDTH-1..WIDTH-2]) IS

      -- NEXT
      WHEN 0 =>    CMDR[] = DI[]; MEM = GND;

      -- CALL
      WHEN 1 =>    CMDR[] = CMD_CALL; MEM = GND;

      -- RET
      WHEN 2 =>    CMDR[] = (DI[]); MEM = GND;

      -- MEM READ
      WHEN 3 =>    CMDR[] = (DI[]); MEM = VCC;

      -- MEM READ-next
      WHEN 4,5,6,7 => CMDR[] = CMD_RET; MEM = GND;

   END CASE;

   COMMAND[]   = CMDR[];

   MR   = !MW;
   MW   = !DFFE((MEM & CMDR[WIDTH-3]),CLK,,,ENA2);
   CS   = GND;

   ENA2         = DFF(ENA,CLK,,);

   iPC[].clk      = CLK;
   iPC[]         = PC[] + 1;
   PCI[]         = iPC[];

   PC[].clk      = CLK;
   PC[].ena      = ENA2;

   CASE (MEM,CMDR[WIDTH-1..WIDTH-2]) IS

      WHEN 0 => PC[]   = iPC[];
      WHEN 1 => PC[]   = (GND,GND,DR[WIDTH-3..0]);
      WHEN 2 => PC[]   = RSTO[];
      WHEN 3 => PC[]   = AR[];

      WHEN 4 => PC[]   = RSTO[];
      WHEN 5 => PC[]   = RSTO[];
      WHEN 6 => PC[]   = RSTO[];
      WHEN 7 => PC[]   = AR[];
   END CASE;

   AO[]   = PC[];

END;


===

Блок принимает данные с шины данных и начинает декодирование команды. Старшими битами определяется, какого типа следующая команда.

[два старших бита команды - 16-й и 15-й в 16-битном варианте]

00 - простая команда, код команды в младших битах
01 - вызов подпрограммы, с адресом заданным в младших битах команды.
10 - возврат иь подпрограммы, код в младших битах так же представляет часть команды, т.е. возврат происходит одновременно с исполнением последней инструкции подпрограммы.
11 - команда работы с памятью. 14 бит определяет направление:
0 - читать данные из памяти,
1 - писать данные в память

Команда работы с памятью исполняется как короткая (на 1 инструкцию) попрограмма. При этом в стеке возвратов сохраняется счетчик команд, а в счетчик грузится вершина стека данных - регистр AR, следующая команда жестко задана в блоке - команда возврата. При этом счетчик команд возвращается к адресу следующей команды, а регистр AR грузится либо с шины данных (форт-команда @), либо со стека данных (форт-команда !).

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 10 июн 2005, 01:50 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
Собственно, обновленный код процессора:

=== FORTH.TDF ===
Код:

   TITLE "Forth-CPU";

include "gen";
include "stack_lc";
include "stack_m";
include "alu2";
include "mdb";

PARAMETERS
   (
   WIDTH = 16
   );

SUBDESIGN forth
   (
   CLK100         : INPUT;
   CLKF         : BIDIR;
   CLK_CPU         : INPUT;
   ENA            : INPUT = VCC;

   A[WIDTH-1..0]   : OUTPUT;
   DI[WIDTH-1..0]   : INPUT;
   DO[WIDTH-1..0]   : BIDIR;

   MR            : OUTPUT;
   MW            : OUTPUT;
   CS            : OUTPUT;

   )
VARIABLE

   GN            : gen WITH (FRQ=3);
   CLK            : NODE;

   DOR[WIDTH-1..0]   : NODE;
   D_OUT         : NODE;

   D_Stack         : stack_lc WITH (WIDTH=WIDTH,DEPTH=8,MODE=0);
   R_Stack         : stack_lc WITH (WIDTH=WIDTH,DEPTH=8,MODE=0);

   ALU            : alu2 WITH (WIDTH=WIDTH,MODE=0);

   PROC         : mdb WITH (WIDTH=WIDTH);

--   iPC[WIDTH-1..0]   : DFF;
--   PC[WIDTH-1..0]   : DFFE;

   AR[WIDTH-1..0]   : DFFE;

   DR[WIDTH-1..0]   : NODE;
   MR            : NODE;
   CMDR[WIDTH-1..0]: NODE;

--   DR[WIDTH-1..0]   : DFFE;
--   DR[WIDTH-1..0]   : NODE;

--   CMDR[WIDTH-1..0]: DFFE;

   RSTC[1..0]      : NODE;
   DSTC[1..0]      : NODE;
   ALUFN[5..0]      : NODE;

   ENA2         : NODE;

   RSTD[WIDTH-1..0]: NODE;

BEGIN

   GN.clk         = CLK100;
   CLKF         = GN.clkf;
--   CLK            = CLKF;
   CLK            = CLK_CPU;

--   ENA2         = DFF(ENA,CLK,,);

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

   R_Stack.CLK         = CLK;
   R_Stack.ENA         = ENA2;
   R_Stack.DI[]      = RSTD[];
--   R_Stack.command[]   = RSTC[];
   R_Stack.command[]   = CMDR[7..6];

   D_Stack.CLK         = CLK;
   D_Stack.ENA         = ENA2;
   D_Stack.DI[]      = AR[];
--   D_Stack.command[]   = DSTC[];
   D_Stack.command[]   = CMDR[9..8];

   DOR[]            = AR[];

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

   PROC.clk      = CLK;
   PROC.ena      = ENA;
   PROC.di[]      = DI[];
   PROC.AR[]      = AR[];
   PROC.RSTO[]      = R_Stack.DO[];

   ENA2         = PROC.ena2;
   A[]            = PROC.AO[];

   CMDR[]         = PROC.command[];

   DR[]         = PROC.DO[];

   MR            = PROC.MEM;
--   *****************************

   IF CMDR[14] THEN
      RSTD[]         = PROC.PCI[];
   ELSE
      RSTD[]         = AR[];
   END IF;

%
   CASE (MR,CMDR[15..14]) IS
      WHEN 0 =>    RSTC[1..0]      = CMDR[7..6]; -- NEXT
               DSTC[1..0]      = CMDR[9..8];
               RSTD[]         = AR[];

      WHEN 1 =>    RSTC[1..0]      = 1;      -- CALL
               DSTC[1..0]      = 0;
               RSTD[]         = PROC.PCI[];

      WHEN 2 =>    RSTC[1..0]      = 3;      -- RET
               DSTC[1..0]      = CMDR[9..8];
               RSTD[]         = AR[];

      WHEN 3 =>    RSTC[1..0]      = 1;      -- MEM
               DSTC[1..0]      = 3;
               RSTD[]         = PROC.PCI[];
      WHEN 4,
         5,6,7 =>RSTC[1..0]      = 3;      -- RET-MEM
               DSTC[1..0]      = 1;
               RSTD[]         = AR[];
   END CASE;
%

   AR[].clk      = CLK;
   AR[].ena      = ENA2;

   CASE (MR,CMDR[WIDTH-3]) IS
      WHEN 0 => AR[] = ALU.Q[];
      WHEN 1 => AR[] = ALU.Q[];
      WHEN 2 => AR[] = DR[];
      WHEN 3 => AR[] = ALU.Q[];
   END CASE;

   ALUFN[]         = CMDR[5..0];

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

   ALU.clk         = CLK;
   ALU.ena         = ENA2;
   ALU.command[]   = ALUFN[];
   ALU.a[]         = AR[];
   ALU.b[]         = D_Stack.DO[];

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

   D_OUT         = VCC;

   FOR i IN 0 TO WIDTH-1 GENERATE
      DO[i]   = TRI(DOR[i],D_OUT);
   END GENERATE;

   (MR,MW,CS)   = VCC;

END;


===

Полностью все AHDL исходники тут

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 10 июн 2005, 21:12 
Не в сети
Аватара пользователя

Зарегистрирован: 05 фев 2005, 14:50
Сообщения: 144
Откуда: Сфероид.
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Спасибо за пояснение. По сути получается что форт-процессор - процессор с зашитым в него фортом в качестве ассемблера?

_________________
Дракон-киборг.
Хочеш веселья? - Дёрни кольцо! (Надпись на гранате).
Танки грязи не боятся! - Особенно Т-3200!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 10 июн 2005, 21:34 
Не в сети
Добрый Админ
Добрый Админ
Аватара пользователя

Зарегистрирован: 04 фев 2005, 06:45
Сообщения: 616
Откуда: St.Petersburg
Благодарил (а): 1 раз.
Поблагодарили: 32 раз.
falanger писал(а):
Спасибо за пояснение. По сути получается что форт-процессор - процессор с зашитым в него фортом в качестве ассемблера?


Именно так, за исключением того, что ассемблер равен не полному форту, а только его некоему подмножеству.

_________________
Дракон всегда прав. Даже, когда он Лев - он прав!


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 129 ]  На страницу 1, 2, 3, 4, 5 ... 9  След.

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения

Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB