Автор |
Сообщение |
|
|
Заголовок сообщения: |
|
|
|
Сделал одноядерный вариант процессора с максимально быстрым исполнением инструкций. Команды, не требующие обращения к памяти, выполняются за 1 такт.
Текущий вариант процессора (1E16 - одно ядро, 16 бит) работает на частоте 100MHz. Цикл обращения к внутренней памяти - 3 такта. Так же 3 такта на загрузку слова команд.
"Предельно низкие скорости"
1. - идущие подряд команды NOP (формально - это операция загрузки следующей команды) - 33миллиона команд в секунду.
Предельно низкая скорость при работе с памятью - загрузка литералов LIT - каждая команда требует обращения к памяти - скорость исполнения - 3 такта + "3/4 такта" на выборку кода - 15/4 тактов на команду - 100*4/15 = 26 миллионов инструкций в секунду.
2. Команды @ и ! - работают по времени чуть дольше чем LIT, т.к. исполняются за два машинных цикла, один из которых имеет длительность 1 такт, как команда не требующая обращения к памяти, а второй - 3 такта - обращение к памяти. Итого - 4 такта + "3/4" такта на выборку команды - 19/4 тактов - 100*4/19=21 миллионов инструкций в секунду.
3. Работу команды MOVE - не рассматриваю - ее исполнение зависит от числа пересылаемых слов - по 6 тактов на одну пересылку.
4. Предельно высокая скорость - идущие подряд команды NOP* (коды 14 и 15 - ничего не делают вообще) - 1 такт на "исполнение" + 3/4 такта на загрузку кода - 7/4 тактов на команду - 100*4/7 = 57 миллионов команд в секунду.
Аналогичная скорость будет при исполнении идущих подряд команд R> >R
Идущие подряд префиксные команды - команды исполняются за 1 такт, но выбирается только по 2 команды, т.е. на одну команду приходится 1+3/2 такта - 2.5 такта - 100/2.5 = 40 миллионов инструкций в секунду.
Усреднять эти цифры смысла нет, но можно утверждать, что процессор 1E16 имеет среднюю скорость в пределах от 21MIPS до 57MIPS при тактовой частоте 100MHz и при работе на внутренней памяти ПЛИС.
CALL исполняется за "3/4"+3 = 15/4 такта
RET - "3/4"+1 = 7/4 такта
NEXT - связка RET+CALL - "3/4"+3 = 14/4 такта
Доли тактов имеют смысл только для усредненных величин.
Сделал одноядерный вариант процессора с максимально быстрым исполнением инструкций. Команды, не требующие обращения к памяти, выполняются за 1 такт.
Текущий вариант процессора (1E16 - одно ядро, 16 бит) работает на частоте 100MHz. Цикл обращения к внутренней памяти - 3 такта. Так же 3 такта на загрузку слова команд.
"Предельно низкие скорости"
1. - идущие подряд команды NOP (формально - это операция загрузки следующей команды) - 33миллиона команд в секунду.
Предельно низкая скорость при работе с памятью - загрузка литералов LIT - каждая команда требует обращения к памяти - скорость исполнения - 3 такта + "3/4 такта" на выборку кода - 15/4 тактов на команду - 100*4/15 = 26 миллионов инструкций в секунду.
2. Команды @ и ! - работают по времени чуть дольше чем LIT, т.к. исполняются за два машинных цикла, один из которых имеет длительность 1 такт, как команда не требующая обращения к памяти, а второй - 3 такта - обращение к памяти. Итого - 4 такта + "3/4" такта на выборку команды - 19/4 тактов - 100*4/19=21 миллионов инструкций в секунду.
3. Работу команды MOVE - не рассматриваю - ее исполнение зависит от числа пересылаемых слов - по 6 тактов на одну пересылку.
4. Предельно высокая скорость - идущие подряд команды NOP* (коды 14 и 15 - ничего не делают вообще) - 1 такт на "исполнение" + 3/4 такта на загрузку кода - 7/4 тактов на команду - 100*4/7 = 57 миллионов команд в секунду.
Аналогичная скорость будет при исполнении идущих подряд команд R> >R
Идущие подряд префиксные команды - команды исполняются за 1 такт, но выбирается только по 2 команды, т.е. на одну команду приходится 1+3/2 такта - 2.5 такта - 100/2.5 = 40 миллионов инструкций в секунду.
Усреднять эти цифры смысла нет, но можно утверждать, что процессор 1E16 имеет среднюю скорость в пределах от 21MIPS до 57MIPS при тактовой частоте 100MHz и при работе на внутренней памяти ПЛИС.
CALL исполняется за "3/4"+3 = 15/4 такта
RET - "3/4"+1 = 7/4 такта
NEXT - связка RET+CALL - "3/4"+3 = 14/4 такта
Доли тактов имеют смысл только для усредненных величин.
|
|
|
|
Добавлено: Пт апр 02, 2010 22:07 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Предположу, что в этом случае пропорция могла бы быть меньше (1/3 что-то уж много на любой взгляд)
Предположу, что в этом случае пропорция могла бы быть меньше (1/3 что-то уж много на любой взгляд)
|
|
|
|
Добавлено: Вс окт 04, 2009 16:17 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Не при каждой... только в операциях работы с памятью и еще один раз на каждые четыре команды
Не при каждой... только в операциях работы с памятью и еще один раз на каждые четыре команды
|
|
|
|
Добавлено: Вс окт 04, 2009 16:02 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Цитата: Теоретические цифры получались для разводки голого процессора без подключения к памяти. обращение к памяти происходит при каждой операции?
[quote]Теоретические цифры получались для разводки голого процессора без подключения к памяти.[/quote] обращение к памяти происходит при [b]каждой [/b]операции?
|
|
|
|
Добавлено: Вс окт 04, 2009 15:54 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
вопрос писал(а): Если 3 такта на обращение к памяти - порядок (т.е. стандартно), то как получались "теоретические цифры" лучше, чем 60MHz... а если количество тактов варьируется, то от чего это может зависеть?
Теоретические цифры получались для разводки голого процессора без подключения к памяти.
[quote="вопрос"]Если 3 такта на обращение к памяти - порядок (т.е. стандартно), то как получались "теоретические цифры" лучше, чем 60MHz... а если количество тактов варьируется, то от чего это может зависеть?[/quote]
Теоретические цифры получались для разводки голого процессора без подключения к памяти.
|
|
|
|
Добавлено: Вс окт 04, 2009 15:19 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
WingLion писал(а): Kрасивые теоретические цифирьки с частотами, а реально, в железяке процессор сегодня заработал на частоте 60MHz... С памятью внутри ПЛИС, которая работает на частоте 180MHz - три такта для обращения к альтеровской памяти ;(
Если 3 такта на обращение к памяти - порядок (т.е. стандартно), то как получались "теоретические цифры" лучше, чем 60MHz... а если количество тактов варьируется, то от чего это может зависеть?
[quote="WingLion"]Kрасивые теоретические цифирьки с частотами, а реально, в железяке процессор сегодня заработал на частоте 60MHz... С памятью внутри ПЛИС, которая работает на частоте 180MHz - три такта для обращения к альтеровской памяти ;([/quote]
Если 3 такта на обращение к памяти - порядок (т.е. стандартно), то как получались "теоретические цифры" лучше, чем 60MHz... а если количество тактов варьируется, то от чего это может зависеть?
|
|
|
|
Добавлено: Вс окт 04, 2009 15:08 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Что-то странное для памяти получается. Дело в том, что Post Place&Route Static Timing у Xilinx - вещь на удивление точная и ответственная. Причем взятая с запасом на наихудшие условия по температуре и питанию. Вплоть до того, что проект, для которого ISE показывал 65 МГц, устойчиво работал на 80 (в комнатных условиях). Так что можно считать, что ~100 МГц у дешевых спартанов на этот процессор есть
Что-то странное для памяти получается. Дело в том, что Post Place&Route Static Timing у Xilinx - вещь на удивление точная и ответственная. Причем взятая с запасом на наихудшие условия по температуре и питанию. Вплоть до того, что проект, для которого ISE показывал 65 МГц, устойчиво работал на 80 (в комнатных условиях). Так что можно считать, что ~100 МГц у дешевых спартанов на этот процессор есть :)
|
|
|
|
Добавлено: Вс окт 04, 2009 13:40 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Kрасивые теоретические цифирьки с частотами, а реально, в железяке процессор сегодня заработал на частоте 60MHz...
С памятью внутри ПЛИС, которая работает на частоте 180MHz - три такта для обращения к альтеровской памяти ;(
Kрасивые теоретические цифирьки с частотами, а реально, в железяке процессор сегодня заработал на частоте 60MHz...
С памятью внутри ПЛИС, которая работает на частоте 180MHz - три такта для обращения к альтеровской памяти ;(
|
|
|
|
Добавлено: Вс окт 04, 2009 02:47 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Да, 10.542 - это "автоматически примененная спецификация". Можно и меньше, но я не стал.
В третьем спартане уже нет трехстабильных шин, они потеряли актуальность на 90 нм и глубже (мультиплексоры быстрее). Я его не пытался вытягивать по частоте, там настройки "усредненные" получились. Плюс к этому можно наложить топологические ограничения, при достаточном навыке 30-40% можно получить дополнительно. Плюс ко всему код не учитывает возможностей делать стеки на распределенной памяти - стеки сейчас все улеглись в триггеры, а это немного расточительно для спартанов.
Вообще, циклоны весьма сильный конкурент спартанам. Особенно третьи циклоны, которые 65 нм, против 90-нм спартанов. Если рассматривать high-end сегмент, то тут Virtex должен быть существенно лучше.
Вот попробовал Virtex-5 - 3,57 нс (280 МГц). Есть сильное ощущение, что 300 вполне достижимы.
Да, 10.542 - это "автоматически примененная спецификация". Можно и меньше, но я не стал.
В третьем спартане уже нет трехстабильных шин, они потеряли актуальность на 90 нм и глубже (мультиплексоры быстрее). Я его не пытался вытягивать по частоте, там настройки "усредненные" получились. Плюс к этому можно наложить топологические ограничения, при достаточном навыке 30-40% можно получить дополнительно. Плюс ко всему код не учитывает возможностей делать стеки на распределенной памяти - стеки сейчас все улеглись в триггеры, а это немного расточительно для спартанов.
Вообще, циклоны весьма сильный конкурент спартанам. Особенно третьи циклоны, которые 65 нм, против 90-нм спартанов. Если рассматривать high-end сегмент, то тут Virtex должен быть существенно лучше.
Вот попробовал Virtex-5 - 3,57 нс (280 МГц). Есть сильное ощущение, что 300 вполне достижимы.
|
|
|
|
Добавлено: Вт сен 29, 2009 19:10 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Хищник писал(а): Using target part "3s700afg484-4". Number of occupied Slices: 475 out of 5,888 8% Autotimespec constraint for clock net clk 10.542ns
10.542нс - это минимальный период clk? т.е. ~95MHz на циклончике побыстрее получилось (сегодня до 149MHz выжал на лицензионном квартусе) хотя и пообъемнее.
Видимо, объем меньше за счет трехстабильных шин внутри спартана
[quote="Хищник"]Using target part "3s700afg484-4". Number of occupied Slices: 475 out of 5,888 8% Autotimespec constraint for clock net clk 10.542ns [/quote]
10.542нс - это минимальный период clk? :) т.е. ~95MHz на циклончике побыстрее получилось (сегодня до 149MHz выжал на лицензионном квартусе) ;) хотя и пообъемнее.
Видимо, объем меньше за счет трехстабильных шин внутри спартана ;)
|
|
|
|
Добавлено: Вт сен 29, 2009 18:32 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
WingLion писал(а): Интересно, что скажет ISE на счет этого кода? Прожует или будет плеваться?
Using target part "3s700afg484-4".
Number of occupied Slices: 475 out of 5,888 8%
Autotimespec constraint for clock net clk 10.542ns
[quote="WingLion"]Интересно, что скажет ISE на счет этого кода? Прожует или будет плеваться?[/quote]
Using target part "3s700afg484-4".
Number of occupied Slices: 475 out of 5,888 8%
Autotimespec constraint for clock net clk 10.542ns
:)
|
|
|
|
Добавлено: Вт сен 29, 2009 14:26 |
|
|
|
|
|
Заголовок сообщения: |
[VHDL] И снова форт-процессор (все тот же самый) |
|
|
Но теперь на VHDL...
Код: LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all;
-- Forth-CPU ver.8
ENTITY fcpu IS
GENERIC ( widtx : integer :=16; Ddepth : integer :=5; Rdepth : integer :=5);
Port( rst : in std_logic; clk : in std_logic; all_ena : in std_logic; addr : out std_logic_vector (widtx-1 downto 0); data_in : in std_logic_vector (widtx-1 downto 0); data_out : out std_logic_vector (widtx-1 downto 0); rd_ram : out std_logic; wr_ram : out std_logic; cs_ram : out std_logic; command : out std_logic_vector (3 downto 0); addr_fix : out std_logic_vector (widtx-1 downto 0) );
END fcpu;
ARCHITECTURE RTL OF fcpu IS
TYPE TstackD IS array (Ddepth-1 downto 0 ) of std_logic_vector (widtx-1 downto 0); TYPE TstackR IS array (Rdepth-1 downto 0 ) of std_logic_vector (widtx-1 downto 0); -- TYPE comands IS (NOP,LIT,CALL,RET,BRANCH,DUP,SWAP,DROP,RAZIM,PRISV,toR,fromR,MOVE,NEXXT);
signal RESET : std_logic; signal PC : std_logic_vector (widtx-1 downto 0); signal newPC : std_logic_vector (widtx-1 downto 0); signal TOP : std_logic_vector (widtx-1 downto 0); signal newTOP : std_logic_vector (widtx-1 downto 0); signal BOT : std_logic_vector (widtx-1 downto 0); signal newBOT : std_logic_vector (widtx-1 downto 0); signal CMD : std_logic_vector (widtx-1 downto 0); signal newCMD : std_logic_vector (widtx-1 downto 0); signal rrd : std_logic; signal rwr : std_logic; signal rcs : std_logic; signal CMD4shr : std_logic_vector (widtx-1 downto 0); signal CMD8shr : std_logic_vector (widtx-1 downto 0); signal RStack : TstackR; -- array (depth-1 downto 0) of std_logic_vector (widtx-1 downto 0); signal DStack : TstackD; -- array (depth-1 downto 0) of std_logic_vector (widtx-1 downto 0); signal newRStack : TstackR; -- std_logic_vector (widtx-1 downto 0); signal newDStack : TstackD; -- std_logic_vector (widtx-1 downto 0); signal alu1_resT : std_logic_vector (widtx-1 downto 0); signal alu1_resB : std_logic_vector (widtx-1 downto 0); signal alu2_resT : std_logic_vector (widtx-1 downto 0); signal alu2_resB : std_logic_vector (widtx-1 downto 0); signal alu3_resT : std_logic_vector (widtx-1 downto 0); signal alu3_resB : std_logic_vector (widtx-1 downto 0); signal mul_res : std_logic_vector (widtx+widtx-1 downto 0); signal pre_mul : std_logic_vector (widtx+widtx-1 downto 0); signal enaX : std_logic; signal xSWAP : std_logic; signal DStackRD : std_logic_vector (widtx-1 downto 0); signal DStackWR : std_logic_vector (widtx-1 downto 0); signal RStackRD : std_logic_vector (widtx-1 downto 0); signal RStackWR : std_logic_vector (widtx-1 downto 0); signal DStackPUSH : TstackD; signal DStackPOP : TstackD; signal DStackSWAP : TstackD; signal RStackPUSH : TstackR; signal RStackPOP : TstackR; signal RStackSWAP : TstackR; signal zero : std_logic_vector (widtx-1 downto 0);
BEGIN zero <= (others => '0'); -- вспомогательные сигналы: -- регистр команд, сдвинутый на 4 бита (для большинства команд) CMD4shr(widtx-5 downto 0) <= (CMD(widtx-1 downto 4)); CMD4shr(widtx-1 downto widtx-4)<=zero(widtx-1 downto widtx-4); -- регистр команд, сдвинутый на 8 бит для дкоманд-префиксов CMD8shr(widtx-9 downto 0) <= (CMD(widtx-1 downto 8)); CMD8shr(widtx-1 downto widtx-8)<=zero(widtx-1 downto widtx-8); -- стек данных DStackRD <= DStack(0); DStackPUSH(0) <= DStackWR; DStackPUSH(Ddepth-1 downto 1) <= DStack(Ddepth-2 downto 0); DStackPOP(Ddepth-2 downto 0) <= DStack(Ddepth-1 downto 1); DStackPOP(Ddepth-1) <= zero; DStackSWAP(Ddepth-1 downto 1) <= DStack(Ddepth-1 downto 1);DStackSWAP(0) <= DStackWR; -- стек возвратов RStackRD <= RStack(0); RStackPUSH(0) <= RStackWR; RStackPUSH(Rdepth-1 downto 1) <= RStack(Rdepth-2 downto 0); RStackPOP(Rdepth-2 downto 0) <= RStack(Rdepth-1 downto 1); RStackPOP(Rdepth-1) <= zero; RStackSWAP(Rdepth-1 downto 1) <= RStack(Rdepth-1 downto 1); RStackSWAP(0) <= RStackWR; -- результат умножения -- mul_res <= TOP * BOT; -- mul_res <= (others => '0'); mul_res <= pre_mul; -- ALU для команд типа DUP#, SWAP#, DROP# process (CMD) begin case conv_integer(CMD(7 downto 4)) is when 0 => -- DUP alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= TOP; -- caaeooea aey DUP -- SWAP alu2_resB <= TOP; -- caaeooea aey SWAP alu2_resT <= BOT; -- caaeooea aey SWAP -- DROP alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT; -- caaeooea aey DROP when 1 => -- OVER alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= BOT; -- caaeooea aey DUP -- INC alu2_resB <= BOT; -- caaeooea aey SWAP alu2_resT <= TOP+1; -- caaeooea aey SWAP -- ADD alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT+TOP; -- caaeooea aey DROP when 2 => -- TRUE alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= zero; -- caaeooea aey DUP -- DEC alu2_resB <= BOT; -- caaeooea aey SWAP alu2_resT <= TOP-1; -- caaeooea aey SWAP -- SUB alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT-TOP; -- caaeooea aey DROP when 3 => -- FALSE alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= (others => '1'); -- caaeooea aey DUP -- MUL alu2_resB <= mul_res(widtx+widtx-1 downto widtx); alu2_resT <= mul_res(widtx-1 downto 0); --alu2_resB <= BOT; -- caaeooea aey SWAP --alu2_resT <= TOP-1; -- caaeooea aey SWAP -- AND alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT and TOP; -- caaeooea aey DROP when 4 => -- ONE alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= (0 => '1',others => '0'); -- caaeooea aey DUP -- MUL alu2_resB <= mul_res(widtx+widtx-1 downto widtx); alu2_resT <= mul_res(widtx-1 downto 0); --alu2_resB <= BOT; -- caaeooea aey SWAP --alu2_resT <= TOP-1; -- caaeooea aey SWAP -- OR alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT or TOP; -- caaeooea aey DROP when others => alu1_resB <= TOP; -- заглушка для DUP alu1_resT <= TOP; -- заглушка для DUP alu2_resB <= TOP; -- заглушка для SWAP alu2_resT <= BOT; -- заглушка для SWAP alu3_resB <= DStackRD; -- заглушка для DROP alu3_resT <= BOT; -- заглушка для DROP end case; end process;
-- вся логика процессора process (RESET,CMD) begin -- установки при сбросе if RESET = '0' then
newPC <= zero; newBOT <= BOT; newTOP <= TOP; DStackWR <= DStackRD; RStackWR <= RStackRD; newRStack <= RStack; -- RStack-NOP newDStack <= DStack; -- DStack-NOP enaX <= '0'; rrd <= '1'; rcs <= '1'; rwr <= '1'; newCMD <= zero; else -- система команд здесь! case conv_integer(CMD(3 downto 0)) is -- NOP when 0 => newPC <= PC+1; enaX <= '0'; newCMD <= data_in; newBOT <= BOT; newTOP <= TOP; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newRStack <= RStack; newDStack <= DStack; rrd <= '0'; rcs <= '0'; rwr <= '1'; enaX <= '0'; -- LIT when 1 => enaX <= '0'; newBOT <= TOP; newTOP <= data_in; newPC <= PC+1; rrd <= '0'; rcs <= '0'; rwr <= '1'; newDStack <= DStackPUSH; DStackWR <= BOT; newRStack <= RStack; RStackWR <= RStackRD; newCMD <= CMD4shr; -- CALL when 2 => enaX <= '0'; newBOT <= BOT; newTOP <= TOP; newPC <= data_in; rrd <= '0'; rcs <= '0'; rwr <= '1'; DStackWR <= DStackRD; newRStack <= RStackPUSH; RStackWR <= PC+1; newDStack <= DStack; newCMD <= zero; -- RET when 3 => enaX <= '0'; newBOT <= BOT; newTOP <= TOP; newPC <= RStackRD; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStack; newRStack <= RStackPOP; -- RStack-POP newCMD <= CMD4shr; -- IF when 4 => enaX <= '0'; if (conv_integer(TOP) = 0) then newPC <= PC+1; newCMD <= CMD4shr; else newPC <= data_in; newCMD <= CMD4shr; end if; newBOT <= BOT; newTOP <= TOP; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newRStack <= RStack; newDStack <= DStack; -- DUP operations when 5 => enaX <= '0'; newPC <= PC; newBOT <= alu1_resB; newTOP <= alu1_resT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= BOT; newDStack <= DStackPUSH; -- BOT; -- DStack-PUSH newRStack <= RStack; newCMD <= CMD8shr; -- SWAP opeations when 6 => -- SWAP, ROT, -ROT, INC, DEC, NEG, NOT... enaX <= '0'; newPC <= PC; newBOT <= alu2_resB; newTOP <= alu2_resT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStackSWAP; newRStack <= RStack; newCMD <= CMD8shr; -- DROP operations when 7 => enaX <= '0'; newPC <= PC; newBOT <= alu3_resB; newTOP <= alu3_resT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- DStack-POP newRStack <= RStack; newCMD <= CMD8shr; -- @ when 8 => enaX <= '1'; if (xSWAP = '0') then newPC <= TOP; newTOP <= BOT; newBOT <= DStackRD; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= PC; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- SDtack-POP newRStack <= RStackPUSH; -- PC; -- RStack-PUSH newCMD <= CMD; -- команда не меняется else newPC <= RStackRD; newBOT <= TOP; newTOP <= data_in; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= BOT; newDStack <= DStackPUSH; -- DStack-POP newRStack <= RStackPOP; -- RStack-POP newCMD <= CMD4shr; -- следующая команда end if; -- ! when 9 => enaX <= '1'; if (xSWAP = '0') then newPC <= TOP; newTOP <= BOT; newBOT <= DStackRD; -- SDtack-POP rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= PC; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- SDtack-POP newRStack <= RStackPUSH; -- PC; -- RStack-PUSH newCMD <= CMD; -- команда не меняется else newPC <= RStackRD; newBOT <= DStackRD; newTOP <= BOT; rrd <= '1'; rcs <= '0'; rwr <= '0'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- DStack-POP newRStack <= RStackPOP; -- RStack-POP newCMD <= CMD4shr; -- следующая команда end if; -- >R when 10 => enaX <= '0'; newPC <= PC; newBOT <= DStackRD; newTOP <= BOT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= TOP; DSTackWR <= DStackRD; newDStack <= DStackPOP; newRStack <= RStackPUSH; newCMD <= CMD4shr; -- R> when 11 => enaX <= '0'; newPC <= PC; newBOT <= TOP; newTOP <= RStackRD; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= RStackRD; newDStack <= DStackPUSH; -- DStack-PUSH newRStack <= RStackPOP; -- RSTack-POP newCMD <= CMD4shr; -- MOVE when 12 => enaX <= '1'; if (xSWAP = '0') then newPC <= RStackRD; newBOT <= TOP; newTOP <= data_in; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= PC+1; DSTackWR <= BOT; newDStack <= DStackPUSH; newRStack <= RStackSWAP; newCMD <= CMD; else newPC <=RStackRD; newTOP <= BOT-1; newBOT <= DStackRD; rrd <= '1'; rcs <= '0'; rwr <= '0'; RSTackWR <= PC+1; DSTackWR <= DStackRD; newDStack <= DStackPOP; newRStack <= RStackSWAP; if (conv_integer(BOT) = 1) then newCMD <= CMD4shr; else newCMD <= CMD; end if; end if; -- NEXT when 13 => enaX <= '1'; if (xSWAP = '0') then newPC <= RStackRD; newBOT <= BOT; newTOP <= TOP; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStack; newRStack <= RStackPOP; newCMD <= CMD; -- здесь команда не меняется else newPC <= data_in; newBOT <= BOT; newTOP <= TOP; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= PC+1; DSTackWR <= DStackRD; newDStack <= DStackPUSH; newRStack <= RStackPUSH; newCMD <= CMD4shr; end if; when others =>
enaX <= '0'; newPC <= PC; newBOT <= BOT; newTOP <= TOP; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStack; newRStack <= RStack; newCMD <= CMD4shr; end case; end if; end process; -- все регистры process (clk,all_ena) begin if (clk'event and clk='1' and all_ena='1') then CMD <= newCMD; PC <= newPC; TOP <= newTOP; BOT <= newBOT; RESET <= rst; RStack <= newRStack; DStack <= newDStack; xSWAP <= (not xSWAP) and enaX; addr_fix <= newPC; end if; end process; -- умножение производится сразу, как в TOP и BOT появились новые значения -- независимо от all_ena process (clk) begin if (clk'event and clk='1') then pre_mul <= TOP * BOT; end if; end process;
-- назначения выходов -- addr <= PC; addr <= newPC; data_out <= TOP; rd_ram <= rrd; wr_ram <= rwr; cs_ram <= rcs; command <= CMD (3 downto 0);
END ARCHITECTURE;
В симуляторе эта штука уже работает.
Quartus II обещает рабочую частоту 120MHz на EP2C20F484C7 (CYCLONE-II)
Так же, надо заметить, что и объем требуемый от ПЛИС для этого варианта - 571LE (против 700 с гаком, что было на AHDL)
Интересно, что скажет ISE на счет этого кода? Прожует или будет плеваться?
Но теперь на VHDL...
[code]LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all;
-- Forth-CPU ver.8
ENTITY fcpu IS
GENERIC ( widtx : integer :=16; Ddepth : integer :=5; Rdepth : integer :=5);
Port( rst : in std_logic; clk : in std_logic; all_ena : in std_logic; addr : out std_logic_vector (widtx-1 downto 0); data_in : in std_logic_vector (widtx-1 downto 0); data_out : out std_logic_vector (widtx-1 downto 0); rd_ram : out std_logic; wr_ram : out std_logic; cs_ram : out std_logic; command : out std_logic_vector (3 downto 0); addr_fix : out std_logic_vector (widtx-1 downto 0) );
END fcpu;
ARCHITECTURE RTL OF fcpu IS
TYPE TstackD IS array (Ddepth-1 downto 0 ) of std_logic_vector (widtx-1 downto 0); TYPE TstackR IS array (Rdepth-1 downto 0 ) of std_logic_vector (widtx-1 downto 0); -- TYPE comands IS (NOP,LIT,CALL,RET,BRANCH,DUP,SWAP,DROP,RAZIM,PRISV,toR,fromR,MOVE,NEXXT);
signal RESET : std_logic; signal PC : std_logic_vector (widtx-1 downto 0); signal newPC : std_logic_vector (widtx-1 downto 0); signal TOP : std_logic_vector (widtx-1 downto 0); signal newTOP : std_logic_vector (widtx-1 downto 0); signal BOT : std_logic_vector (widtx-1 downto 0); signal newBOT : std_logic_vector (widtx-1 downto 0); signal CMD : std_logic_vector (widtx-1 downto 0); signal newCMD : std_logic_vector (widtx-1 downto 0); signal rrd : std_logic; signal rwr : std_logic; signal rcs : std_logic; signal CMD4shr : std_logic_vector (widtx-1 downto 0); signal CMD8shr : std_logic_vector (widtx-1 downto 0); signal RStack : TstackR; -- array (depth-1 downto 0) of std_logic_vector (widtx-1 downto 0); signal DStack : TstackD; -- array (depth-1 downto 0) of std_logic_vector (widtx-1 downto 0); signal newRStack : TstackR; -- std_logic_vector (widtx-1 downto 0); signal newDStack : TstackD; -- std_logic_vector (widtx-1 downto 0); signal alu1_resT : std_logic_vector (widtx-1 downto 0); signal alu1_resB : std_logic_vector (widtx-1 downto 0); signal alu2_resT : std_logic_vector (widtx-1 downto 0); signal alu2_resB : std_logic_vector (widtx-1 downto 0); signal alu3_resT : std_logic_vector (widtx-1 downto 0); signal alu3_resB : std_logic_vector (widtx-1 downto 0); signal mul_res : std_logic_vector (widtx+widtx-1 downto 0); signal pre_mul : std_logic_vector (widtx+widtx-1 downto 0); signal enaX : std_logic; signal xSWAP : std_logic; signal DStackRD : std_logic_vector (widtx-1 downto 0); signal DStackWR : std_logic_vector (widtx-1 downto 0); signal RStackRD : std_logic_vector (widtx-1 downto 0); signal RStackWR : std_logic_vector (widtx-1 downto 0); signal DStackPUSH : TstackD; signal DStackPOP : TstackD; signal DStackSWAP : TstackD; signal RStackPUSH : TstackR; signal RStackPOP : TstackR; signal RStackSWAP : TstackR; signal zero : std_logic_vector (widtx-1 downto 0);
BEGIN zero <= (others => '0'); -- вспомогательные сигналы: -- регистр команд, сдвинутый на 4 бита (для большинства команд) CMD4shr(widtx-5 downto 0) <= (CMD(widtx-1 downto 4)); CMD4shr(widtx-1 downto widtx-4)<=zero(widtx-1 downto widtx-4); -- регистр команд, сдвинутый на 8 бит для дкоманд-префиксов CMD8shr(widtx-9 downto 0) <= (CMD(widtx-1 downto 8)); CMD8shr(widtx-1 downto widtx-8)<=zero(widtx-1 downto widtx-8); -- стек данных DStackRD <= DStack(0); DStackPUSH(0) <= DStackWR; DStackPUSH(Ddepth-1 downto 1) <= DStack(Ddepth-2 downto 0); DStackPOP(Ddepth-2 downto 0) <= DStack(Ddepth-1 downto 1); DStackPOP(Ddepth-1) <= zero; DStackSWAP(Ddepth-1 downto 1) <= DStack(Ddepth-1 downto 1);DStackSWAP(0) <= DStackWR; -- стек возвратов RStackRD <= RStack(0); RStackPUSH(0) <= RStackWR; RStackPUSH(Rdepth-1 downto 1) <= RStack(Rdepth-2 downto 0); RStackPOP(Rdepth-2 downto 0) <= RStack(Rdepth-1 downto 1); RStackPOP(Rdepth-1) <= zero; RStackSWAP(Rdepth-1 downto 1) <= RStack(Rdepth-1 downto 1); RStackSWAP(0) <= RStackWR; -- результат умножения -- mul_res <= TOP * BOT; -- mul_res <= (others => '0'); mul_res <= pre_mul; -- ALU для команд типа DUP#, SWAP#, DROP# process (CMD) begin case conv_integer(CMD(7 downto 4)) is when 0 => -- DUP alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= TOP; -- caaeooea aey DUP -- SWAP alu2_resB <= TOP; -- caaeooea aey SWAP alu2_resT <= BOT; -- caaeooea aey SWAP -- DROP alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT; -- caaeooea aey DROP when 1 => -- OVER alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= BOT; -- caaeooea aey DUP -- INC alu2_resB <= BOT; -- caaeooea aey SWAP alu2_resT <= TOP+1; -- caaeooea aey SWAP -- ADD alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT+TOP; -- caaeooea aey DROP when 2 => -- TRUE alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= zero; -- caaeooea aey DUP -- DEC alu2_resB <= BOT; -- caaeooea aey SWAP alu2_resT <= TOP-1; -- caaeooea aey SWAP -- SUB alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT-TOP; -- caaeooea aey DROP when 3 => -- FALSE alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= (others => '1'); -- caaeooea aey DUP -- MUL alu2_resB <= mul_res(widtx+widtx-1 downto widtx); alu2_resT <= mul_res(widtx-1 downto 0); --alu2_resB <= BOT; -- caaeooea aey SWAP --alu2_resT <= TOP-1; -- caaeooea aey SWAP -- AND alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT and TOP; -- caaeooea aey DROP when 4 => -- ONE alu1_resB <= TOP; -- caaeooea aey DUP alu1_resT <= (0 => '1',others => '0'); -- caaeooea aey DUP -- MUL alu2_resB <= mul_res(widtx+widtx-1 downto widtx); alu2_resT <= mul_res(widtx-1 downto 0); --alu2_resB <= BOT; -- caaeooea aey SWAP --alu2_resT <= TOP-1; -- caaeooea aey SWAP -- OR alu3_resB <= DStackRD; -- caaeooea aey DROP alu3_resT <= BOT or TOP; -- caaeooea aey DROP when others => alu1_resB <= TOP; -- заглушка для DUP alu1_resT <= TOP; -- заглушка для DUP alu2_resB <= TOP; -- заглушка для SWAP alu2_resT <= BOT; -- заглушка для SWAP alu3_resB <= DStackRD; -- заглушка для DROP alu3_resT <= BOT; -- заглушка для DROP end case; end process;
-- вся логика процессора process (RESET,CMD) begin -- установки при сбросе if RESET = '0' then
newPC <= zero; newBOT <= BOT; newTOP <= TOP; DStackWR <= DStackRD; RStackWR <= RStackRD; newRStack <= RStack; -- RStack-NOP newDStack <= DStack; -- DStack-NOP enaX <= '0'; rrd <= '1'; rcs <= '1'; rwr <= '1'; newCMD <= zero; else -- система команд здесь! case conv_integer(CMD(3 downto 0)) is -- NOP when 0 => newPC <= PC+1; enaX <= '0'; newCMD <= data_in; newBOT <= BOT; newTOP <= TOP; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newRStack <= RStack; newDStack <= DStack; rrd <= '0'; rcs <= '0'; rwr <= '1'; enaX <= '0'; -- LIT when 1 => enaX <= '0'; newBOT <= TOP; newTOP <= data_in; newPC <= PC+1; rrd <= '0'; rcs <= '0'; rwr <= '1'; newDStack <= DStackPUSH; DStackWR <= BOT; newRStack <= RStack; RStackWR <= RStackRD; newCMD <= CMD4shr; -- CALL when 2 => enaX <= '0'; newBOT <= BOT; newTOP <= TOP; newPC <= data_in; rrd <= '0'; rcs <= '0'; rwr <= '1'; DStackWR <= DStackRD; newRStack <= RStackPUSH; RStackWR <= PC+1; newDStack <= DStack; newCMD <= zero; -- RET when 3 => enaX <= '0'; newBOT <= BOT; newTOP <= TOP; newPC <= RStackRD; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStack; newRStack <= RStackPOP; -- RStack-POP newCMD <= CMD4shr; -- IF when 4 => enaX <= '0'; if (conv_integer(TOP) = 0) then newPC <= PC+1; newCMD <= CMD4shr; else newPC <= data_in; newCMD <= CMD4shr; end if; newBOT <= BOT; newTOP <= TOP; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newRStack <= RStack; newDStack <= DStack; -- DUP operations when 5 => enaX <= '0'; newPC <= PC; newBOT <= alu1_resB; newTOP <= alu1_resT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= BOT; newDStack <= DStackPUSH; -- BOT; -- DStack-PUSH newRStack <= RStack; newCMD <= CMD8shr; -- SWAP opeations when 6 => -- SWAP, ROT, -ROT, INC, DEC, NEG, NOT... enaX <= '0'; newPC <= PC; newBOT <= alu2_resB; newTOP <= alu2_resT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStackSWAP; newRStack <= RStack; newCMD <= CMD8shr; -- DROP operations when 7 => enaX <= '0'; newPC <= PC; newBOT <= alu3_resB; newTOP <= alu3_resT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- DStack-POP newRStack <= RStack; newCMD <= CMD8shr; -- @ when 8 => enaX <= '1'; if (xSWAP = '0') then newPC <= TOP; newTOP <= BOT; newBOT <= DStackRD; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= PC; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- SDtack-POP newRStack <= RStackPUSH; -- PC; -- RStack-PUSH newCMD <= CMD; -- команда не меняется else newPC <= RStackRD; newBOT <= TOP; newTOP <= data_in; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= BOT; newDStack <= DStackPUSH; -- DStack-POP newRStack <= RStackPOP; -- RStack-POP newCMD <= CMD4shr; -- следующая команда end if; -- ! when 9 => enaX <= '1'; if (xSWAP = '0') then newPC <= TOP; newTOP <= BOT; newBOT <= DStackRD; -- SDtack-POP rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= PC; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- SDtack-POP newRStack <= RStackPUSH; -- PC; -- RStack-PUSH newCMD <= CMD; -- команда не меняется else newPC <= RStackRD; newBOT <= DStackRD; newTOP <= BOT; rrd <= '1'; rcs <= '0'; rwr <= '0'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStackPOP; -- DStack-POP newRStack <= RStackPOP; -- RStack-POP newCMD <= CMD4shr; -- следующая команда end if; -- >R when 10 => enaX <= '0'; newPC <= PC; newBOT <= DStackRD; newTOP <= BOT; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= TOP; DSTackWR <= DStackRD; newDStack <= DStackPOP; newRStack <= RStackPUSH; newCMD <= CMD4shr; -- R> when 11 => enaX <= '0'; newPC <= PC; newBOT <= TOP; newTOP <= RStackRD; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= RStackRD; newDStack <= DStackPUSH; -- DStack-PUSH newRStack <= RStackPOP; -- RSTack-POP newCMD <= CMD4shr; -- MOVE when 12 => enaX <= '1'; if (xSWAP = '0') then newPC <= RStackRD; newBOT <= TOP; newTOP <= data_in; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= PC+1; DSTackWR <= BOT; newDStack <= DStackPUSH; newRStack <= RStackSWAP; newCMD <= CMD; else newPC <=RStackRD; newTOP <= BOT-1; newBOT <= DStackRD; rrd <= '1'; rcs <= '0'; rwr <= '0'; RSTackWR <= PC+1; DSTackWR <= DStackRD; newDStack <= DStackPOP; newRStack <= RStackSWAP; if (conv_integer(BOT) = 1) then newCMD <= CMD4shr; else newCMD <= CMD; end if; end if; -- NEXT when 13 => enaX <= '1'; if (xSWAP = '0') then newPC <= RStackRD; newBOT <= BOT; newTOP <= TOP; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStack; newRStack <= RStackPOP; newCMD <= CMD; -- здесь команда не меняется else newPC <= data_in; newBOT <= BOT; newTOP <= TOP; rrd <= '0'; rcs <= '0'; rwr <= '1'; RSTackWR <= PC+1; DSTackWR <= DStackRD; newDStack <= DStackPUSH; newRStack <= RStackPUSH; newCMD <= CMD4shr; end if; when others =>
enaX <= '0'; newPC <= PC; newBOT <= BOT; newTOP <= TOP; rrd <= '1'; rcs <= '1'; rwr <= '1'; RSTackWR <= RStackRD; DSTackWR <= DStackRD; newDStack <= DStack; newRStack <= RStack; newCMD <= CMD4shr; end case; end if; end process; -- все регистры process (clk,all_ena) begin if (clk'event and clk='1' and all_ena='1') then CMD <= newCMD; PC <= newPC; TOP <= newTOP; BOT <= newBOT; RESET <= rst; RStack <= newRStack; DStack <= newDStack; xSWAP <= (not xSWAP) and enaX; addr_fix <= newPC; end if; end process; -- умножение производится сразу, как в TOP и BOT появились новые значения -- независимо от all_ena process (clk) begin if (clk'event and clk='1') then pre_mul <= TOP * BOT; end if; end process;
-- назначения выходов -- addr <= PC; addr <= newPC; data_out <= TOP; rd_ram <= rrd; wr_ram <= rwr; cs_ram <= rcs; command <= CMD (3 downto 0);
END ARCHITECTURE; [/code]
В симуляторе эта штука уже работает.
Quartus II обещает рабочую частоту 120MHz на EP2C20F484C7 (CYCLONE-II)
Так же, надо заметить, что и объем требуемый от ПЛИС для этого варианта - 571LE (против 700 с гаком, что было на AHDL)
Интересно, что скажет ISE ;) на счет этого кода? Прожует или будет плеваться?
|
|
|
|
Добавлено: Пн сен 28, 2009 22:13 |
|
|
|
|