Forth http://fforum.winglion.ru/ |
|
VHDL: процессор за час http://fforum.winglion.ru/viewtopic.php?f=3&t=2706 |
Страница 1 из 10 |
Автор: | WingLion [ Пт фев 04, 2011 18:10 ] |
Заголовок сообщения: | VHDL: процессор за час |
Смешно звучит название темы, правда? А, вот, ничего смешного! Хищник когда-то мне продемонстрировал сей трюк. Теперь моя очередь демонстрировать, до чего сам додумался. Итак, предпосылки следующие. Во-первых. Делаем это дело на VHDL. Язык этот структурированый, типизированый и еще бес его знает какой умный. Поэтому буду пользоваться всеми его возможностями, которыe до меня дошли. В смысле, я дошел, как ими пользоваться. Во-вторых. В основу кладем ту идею, что я описал в наметке своей статьи про процессор в ПЛИС: http://winglion.ru/ahdl/processor.htm AHDL уходит прочь, и вместо него только VHDL. Начинаю с того, что прямо сейчас запускаю QUARTUS II. Вот, нажму кнопку 'отправить' и запускаю. |
Автор: | WingLion [ Пт фев 04, 2011 18:23 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
В квартусе, не мудрствуя особо, создаю новый проект с именем CPU_2011. И в созданном проекте сразу же создаю файл VHDL-исходника, в который копипастом вписываю группу Код: LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; Сохраняю в файл CPU2011.vhd и пишу дальше Код: LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; package CPUpack is end; А в начало первого файла добавляю четвертой строчкой: Код: USE WORK.CPUpack.all; Теперь небольшая задержка для объяснений. для портов процессора надо объявлять типы, кроме того, надо бы задать параметры, такие как ширина шин, глубина стеков, да и сами типы надо объявить. И, вот для этого в VHDL есть пакеты. А по сему, возвращаюсь в квартус и создаю еще один vhdl файл для пакета. Пишу в самом начале: Код: package CPUpack is
end; |
Автор: | WingLion [ Пт фев 04, 2011 18:29 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
В пакете объявляю константы ширины данных и глубины стеков и создаю первы подтип, который нужен для описания выводов процессора. получившийся код в файле пакета: Код: LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; USE WORK.CPUpack.all; package CPUpack is constant width : natural :=16; constant depth : natural :=8; subtype word is std_logic_vector (width-1 downto 0) end; теперь использую объявленный тип для описания выводов: Код: entity CPU2011 is
Ports( clk : in std_logic; reset : in std_logic; addr : out word; iData : in word; oData : out word; ); END CPU2011; |
Автор: | WingLion [ Пт фев 04, 2011 18:40 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Запускаю анализ, правлю ошибки... А пока оно крутится думаю, что еще надо обявлять в типах... Во первых - нужны стеки. Во множественном числе, поэтому для стека объявляю отдельный тип в виде record анализ закончился, в одном месте точки с запятой не хватает, в другом лишняя. после исправления ошибок нет, поэтому добавляю в пакет новые типы: Код: type stk is array (depth-3 downto 0) of word; type stack is record top : word; subtop : word; regs : stk; end record; stk - это просто набор регистров стека top и subtop - именованные регистры, и всего их depth штук снова делаю анализ и получаю, что все ok. |
Автор: | WingLion [ Пт фев 04, 2011 18:46 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Иду дальше. В главном файле объявляю архитектуру: В ней объявляю сигналы. Пока с неописанным типом, но он будет описан чуть позже, поэтому просто пишу заглушку: Код: architecture rtl of CPU2011 is signal new_CPU,CPU : CPU_regs; begin process (reset,clk) begin if reset = '0' then new_CPU <= (others =>'0'); elsif clk'event and clk='1' then CPU <= new_CPU; end if; end process; end; процесс описывает элементарное поведение - сброс и обновление состояния процессора по каждому тактовому сигналу. Анализ не запускаю, так как тип не объявлен и будет ошибка. |
Автор: | WingLion [ Пт фев 04, 2011 18:51 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Возвращаюсь к файлу с пакетом для объявления типа процессора. Он будет записью, как и стек, и в нем объявляются регистры, стеки, флаги, и выходы для адреса, данных и управления памятью. Получается следущий файл пакета: Код: LIBRARY IEEE;
USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; package CPUpack is constant width : natural :=16; constant depth : natural :=8; subtype word is std_logic_vector (width-1 downto 0); type stk is array (depth-3 downto 0) of word; type stack_d is record top : word; subtop : word; regs : stk; end record; tupe mem_t is (Mread,Mwrite,Mnop); type cpu_t is record cmd : word; pc : word; data_stack : stack_t; return_stack : stack_t; addr : word; oData : word; mem : mem_t; end record; end; |
Автор: | WingLion [ Пт фев 04, 2011 18:54 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Правлю тип в главном файле проекта, правлю tupe на type, и все снова ок. Код: LIBRARY IEEE;
USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; USE WORK.CPUpack.all; entity CPU2011 is Port( clk : in std_logic; reset : in std_logic; addr : out word; iData : in word; oData : out word ); END CPU2011; architecture rtl of CPU2011 is signal new_CPU,CPU : CPU_t; begin process (reset,clk) begin if reset = '0' then new_CPU <= (others =>'0'); elsif clk'event and clk='1' then CPU <= new_CPU; end if; end process; end; |
Автор: | WingLion [ Пт фев 04, 2011 19:00 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Теперь о том, как писать дальше. Можно было бы в главном файле выписать большой case в котором все определено, но я сделаю иначе. Обявляю функцию, которая все должна сделать, то есть вычислить новое состояние процессора по старому. И записываю ее объявление в пакет: Код: function logic_kernel(CPU : cpu_t, data : word) return cpu_t; end; function logic_kernel(CPU : cpu_t, data : word) return cpu_t is variable new_CPU; begin new_CPU :=CPU; return CPU; end; функция пока опеределена как заглушка простым повторением. A в начале описания архитектуры добавляю: Код: new_CPU := Logic_kernel(CPU);
|
Автор: | WingLion [ Пт фев 04, 2011 19:07 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Анализирую квартусом, исправляю ошибки. Забыто объявление package body, при использовании функции не хватает входного параметра... сигнал неправильно соединен командой := а надо <= неправильно обявлена переменная в функции... кажется, все. Анализ показывает отсутствие ошибок в синтаксисе. |
Автор: | WingLion [ Пт фев 04, 2011 19:13 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Так, смотрю, чего забыл... Не подключены выходы Addr и oData делаю подключение. Код: Addr <= Logic_kernel(CPU,iData).addr; oData <= Logic_kernel(CPU,iData).oData; Казалось бы, такая конструкция не должна работать, тем не менее, квартус ее компилирует как надо. Запускаю первую компиляцию, и тут же начинаю ловить ошибки. исправляю ветку сброса на: Код: if reset = '0' then new_CPU.pc <= (others =>'0'); new_CPU.cmd <= (others =>'0'); Компиляция проходит, 50 выводов у процессора и ноль логических ячеек. Еще бы, главная функция то еще не определена как надо! |
Автор: | WingLion [ Пт фев 04, 2011 19:22 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Возвращаюсь к пакету и редактирую логическое ядро: Код: function logic_kernel(CPU : cpu_t; data : word) return cpu_t is variable new_CPU : cpu_t; variable sh_cmd : word; begin new_CPU :=CPU; sh_cmd := CPU.cmd(width-5 downto 0)&nop; new_CPU.cmd :=sh_cmd; case CPU.cmd(width-1 downto width-4) is when nop => new_CPU.pc := CPU.pc+1; new_CPU.cmd := iData; when others => null; end case; Здесь уже определилось, что команда будет четырехбитная и полностью определено действие по команде nop. сам идентификатор nop - это константа, которая опеределена с другими именами команд чуть выше в пакете, строчками: Код: constant nop : std_logic_vector (3 downto 0) := "0000";
constant lit : std_logic_vector (3 downto 0) := "0001"; constant call : std_logic_vector (3 downto 0) := "0010"; constant ret : std_logic_vector (3 downto 0) := "0011"; |
Автор: | WingLion [ Пт фев 04, 2011 19:26 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Запускаю компиляцию, правлю ошибки новый код функции: Код: function logic_kernel(CPU : cpu_t; data : word) return cpu_t is
variable new_CPU : cpu_t; variable sh_cmd : word; begin new_CPU :=CPU; sh_cmd := CPU.cmd(width-5 downto 0)&nop; new_CPU.cmd :=sh_cmd; new_CPU.addr :=CPU.pc; case CPU.cmd(width-1 downto width-4) is when nop => new_CPU.pc := CPU.pc+1; new_CPU.cmd := Data; when others => null; end case; return CPU; end; |
Автор: | WingLion [ Пт фев 04, 2011 19:33 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Глупая ошибка return new_CPU; надо, а не return CPU; еще одна глупая ошибка - Код: if reset = '0' then CPU.pc <= (others =>'0'); CPU.cmd <= (others =>'0'); вместо того же самого с new_CPU Исправляю, компилирую... И вот, первый вариант компилируется на 33 логические ячейки и 32 тригера в них.. собственно, иного и ожидать сложно, когда есть лишь одна команда NOP. |
Автор: | WingLion [ Пт фев 04, 2011 19:41 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
Правлю, добавляю команды lit, call и ret Код: when lit => -- загружаем литерал new_CPU.top := iData; -- счетчик команды увеличивается на единицу new_CPU.pc := CPU.pc+1; -- старое значение вершины заталкиваем в стек данных new_CPU.data_stack := PUSH2STACK(CPU.data_stack,CPU.top); when call => -- загружаем новое значение для PC new_CPU.pc := iData; -- старое заталкиваем в стек возвратов new_CPU.return_stack := PUSH2STACK(CPU.return_stack,CPU.pc+1); when ret => -- возвращаем адрес new_CPU.pc := CPU.rst.top; -- и выталкиваем его из стека возвратов new_CPU.return_stack := POP4STACK(CPU.return_stack); функции для стеков еще не определены, но принцип должен быть ясен. Собственно, время вышло, в час я не уложился... |
Автор: | WingLion [ Пт фев 04, 2011 19:56 ] |
Заголовок сообщения: | Re: VHDL: процессор за час |
WingLion писал(а): Собственно, время вышло, в час я не уложился... Тем не менее, я продолжаю пусть, не час, а два или три, но... (топик можно и поправить ) Код: function PUSH2STACK(stack : stack_t; data: word) return stack_t is variable new_stack : stack_t; begin new_stack.top := data; new_stack.subtop := stack.top; new_stack.regs(depth-3) := stack.subtop; for i in depth-2 downto 0 loop new_stack.regs(i) := stack.regs(i+1); end loop; return new_stack; end; function POP4STACK(stack : stack_t) return stack_t is variable new_stack : stack_t; begin new_stack.top := stack.subtop; new_stack.subtop := stack.regs(depth-3); for i in depth-3 downto 1 loop new_stack.regs(i) := stack.regs(i-1); end loop; new_stack.regs(0) := zero; return new_stack; end; функции определены, компилирую, исправляю ошибки |
Страница 1 из 10 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |