Могу предложить следующую структуру обработки данных.
Преимущество такого построения - уменьшается на один такт
конвейер процессора.
Вид для печати
Могу предложить следующую структуру обработки данных.
Преимущество такого построения - уменьшается на один такт
конвейер процессора.
Стандартный конвейер процессора имеет регистры после мультиплексоров регистрового файла,
т.е. на входах АЛУ. В состав АЛУ входит выходной мультиплексор, оканчивающийся своим
регистром. Тут мы видим 3 такта конвейера: декодирование команды, собственно операция АЛУ
и запись в регистровый файл.
У меня немного по другому. На стадии декодирования мы вычисляем операции АЛУ,
заканчивающиеся регистрами на каждую операцию, а затем на шаге записи в регистровый файл
мультиплексируем результаты каждой операции. На самом деле количество регистров можно
сократить, например, объединив несколько быстрых логических операций, суммирование и
вычитание имеют свои регистры.
Сигналы bypassRA и bypassRB нужны, если RD предыдущей команды совпал с RA или RB текущей,
т.е. когда результат предыдущей команды еще не попал в регистровый файл.
Типичный заголовок алу может быть следующим:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.my_arith.all;
entity alu32pe is
port (
opa : in std_logic_vector(31 downto 0);
opb : in std_logic_vector(31 downto 0);
opalu : in std_logic_vector(4 downto 0);
reset : in std_logic;
sclk : in std_logic;
cealu : in std_logic;
cb_in : in std_logic;
result: out std_logic_vector(31 downto 0);
cc : out std_logic_vector(3 downto 0)
);
end;
Что касается самих операций АЛУ, то их лучше оформить в отдельном файле библиотеки (package, у меня это my_arith.vhd),
и вызывать их в файле описания АЛУ.
Если надо, могу дать свой.
P.S.
Сигнал cealu - разрешение записи в регистры АЛУ (может быть использован для остановки
конвейера при извлечении операнда из синхронной памяти данных за 2 такта).
cb_in - (carry/borrow) вход переноса/заема от предыдущего вычисления.
Выходные флаги сс лучше хранить в одном из регистров регистрового файла (сделать его
специализированным, например, регистром флагов).
Если этот регистр делать отдельно - это увеличит аппаратуру.
Единый файл у Вас будет оооооочень большой.
У Вас же есть книжка Паттерсона, со стр.388.
Только там регистровый файл выполнен в виде ОЗУ.
И вычисление адреса памяти данных выполняется в АЛУ. У меня не так.
Вычисление адреса происходит на том же такте, что и операции АЛУ.
Это я не могу посчитать, но потребуются свои дешифраторы, отдельный код операции и что-нибудь еще.
Нет, это я просто вычленил схему вычисления данных из общей архитектуры своего процессора.
Честно говоря я не пойму, какова цель тогда тут что то спрашивать?, тебе говорят, ты же в ответ, извиняюсь за выражение "херню городишь".
Выбор вечно не по прямому простому пути, а через непонятные дали.
Это как на гитаре по книжке учиться играть, не беря в руки гитару.
АЛУ не самое сложное. ИМХО не с него надо начинать.Цитата:
А пока ещё и нечего брать, код даже для АЛУ ещё не написан, самой гитары нет.
Мой совет - не закладываться вообще на конкретный ПЛИС. Делать чтобы работало на чем угодно. Это вполне возможно. Я в качестве изучения переделывал Forth процессор J1 под себя (переписал с Verilog на VHDL, сделал его 32 битным, дописал байтовый доступ к памяти, инструкции ускорений циклов итд итп) все делал на чистом VHDL под эмулятором ghdl. Планирую делать из них 2D сеть на LX25 или LX75 (есть 2 платы от ztex)Цитата:
Не пойму, это к чему. Здесь и сейчас изучается и будет применяться микросхема ПЛИС фирмы Xilinx семейства Spartan-6.
Берем 1 и сдвигаем на 1 бит - это умножение на 2. Получается 2 бита. Сдвигаем еще на 1 бит - это умножение на 4. Получается 3 бита. Все логично. Если не понятно как делается умножение - делайте его в столбик как с десятичными числами - там получается сдвиг и суммирование с переносом.
В этом конечно что-то есть. Но например fetch и decode намного проще alu но их реализация уже создает иллюзию работы (; Да и потом к ним alu цеплять и проверять проще, чем один alu "в воздухе"Цитата:
Ну пока это единственное, что мне кажется стало более менее понятным, по крайней как будет выглядеть код, и как вообще этот блок работает, поэтому начинаю с него. Хотя как мне видится, не важно с чего начинать.
Мой 32 битный процессор занимает четверть от LX25, а уж я там себя не сдерживал (; Кстати он получился даже меньше чем "самый маленький 32 битный с поддержкой gcc toolchain" (ZPU)Цитата:
Но тут выбор уже сделан, так как смысл написать код, который влезет только в LX16
Мне было интересно смогу ли я. Смог. Заодно разобрался как он работает просто досконально.Цитата:
Интересно, и это оправдано?
Я оригинальную частоту не знаю. У меня на LX25 получилось 106Мгц. Меня соотношение размер/fmax устроил.Цитата:
снизилась частота дизайна.
Вся эпопея здесь - http://strijar.livejournal.com/tag/k32
Экономия RAM - можно иметь быстрый доступ (за один такт) к байтовым массивам. У меня в качестве теста реализована игра LifeЦитата:
И смысл тогда в байтовом доступе к памяти, если он уже может оперировать 4-мя?
---------- Post added at 15:06 ---------- Previous post was at 14:48 ----------
Посмотрел ваш код. У вас получился "подстрочный перевод". Я сделал по честному - логично связанные сигналы упаковывал в record (;
А циклические сдвиги делал через srl и sllКод:entity k32 is
port (
clk : in std_logic;
rst : in std_logic;
en : in std_logic;
ibus_in : in ibus_in_type;
ibus_out : out ibus_out_type;
data_in : in dbus_in_type;
data_out : out dbus_out_type;
io_in : in dbus_in_type;
io_out : out dbus_out_type;
exception : out exception_type
);
end k32;
Код:when x"8" =>
ds_top <= alu_a srl to_integer(unsigned(alu_b(4 downto 0)));
when x"9" =>
ds_top <= alu_a sll to_integer(unsigned(alu_b(4 downto 0)));