Для начала следует сказать, что флаг C я планировал реализовать как в 6502 - при вычитании будет использоваться инвертированный бит переноса, поэтому:
STC (установить флаг C) = NAN 0 (после этого A станет равным 255) либо XOR 0 (после этого значение регистра A не изменится)
CLC (сбросить флаг C) = RLC 0 (после этого A станет 0 или 1 в зависимости от старого значения флага C), а вот если веруть обратно команду ADI 0, то оно делало бы тоже самое БЕЗ изменения содержимого регистра A
CMC (инвертировать флаг C) = попробовал ADC 0 и SBC 0 - НЕ получается по простому...
P.S. Разве что F=~F, но оно ВСЕ флаги проинвертирует (включая 3 бита, используемые при передаче управления)
Я тут за главного - если что шлите мыло на me собака shaos точка net
В своём АЛУ я и решил использовать "инверсный" подход как в 6502, чтобы не надо было ничего железячно инвертировать как в 8080:
8080: A=A-N-c=A+(~N)+1-c=A+(~N)+!c (есть инверсия в железе для флага C, но с точки зрения программиста выглядит прямо A-N-c)
6502: A=A-N-!c=A+(~N)+1-!c=A+(~N)+c (нет инверсии в железе для флага C, но с точки зрения программиста выглядит инверсно A-N-!c)
P.S. а CMC - это команда для программиста, которая вроде как и не нужна ему по большому счёту...
Я тут за главного - если что шлите мыло на me собака shaos точка net
Shaos wrote:
P.P.S. В-принципе, можно уже нарисовать и заказать платки "слайсов", которые по приходу можно собрать и воткнуть в бредборду, на которой собрать это 4-битное АЛУ и погонять на разных скоростях, наблюдая за результатом по осциллографу, чтобы оценить пиковое быстродействие...
По-быстрому нарисовал в бесплатной версии Eagle v5 платку ALU-slice (см. eagle-nedonand.zip):
Развёл автороутером (всё кроме цепей питания, которые нарисовал вручную):
И заказал на oshpark.com несколько штучек :)
P.S. Распиновка:
1) GND
2) O0
3) O1
4) O2
5) A
6) B
7) C
8) H
9) L
10) COUT
11) DOUT
12) VCC
Я тут за главного - если что шлите мыло на me собака shaos точка net
Shaos wrote:тут мне удалось вывести C'=1 в случае логических операций NAN и XOR
Хозяин, конечно, барин... но "в случае логических операций", мне что-то помнится, флаг переноса в 0 сбрасывают... нет?
C'=1 проще
Без этих гейтов на выходе C' выдавал переполнение как при сложении, даже если операция была логическая, то есть оно было то 0, то 1 в зависимости от аргументов
А вообще мне надо бы ещё и "overflow" флаг V тут сделать (вумные люди пишут что это просто XOR переполнения из 6 бита и переполнения из 7 бита) - и флаг V тоже вроде как должен обнуляться при логических операциях...
P.S. С другой стороны на V при логических операциях можно наплювать (пусть будет мусор), а C'=1 может оказаться полезной фичей, позволяющей достаточно просто установить флаг C в 1...
А между тем я вчера прикрутил флаг знакового переполнения V' (именно так как описано в цитате чуть выше):
Флаг V имеет смысл только если аргументы для сложения или вычитания предполагались аргументами со знаком - во всех остальных случаях значение этого флага необходимо считать мусором и игнорировать...
Я тут за главного - если что шлите мыло на me собака shaos точка net
А теперь порассуждаем про скорость выполнения тех или иных команд. Ввиду того, что от идеи делать это как RISC я уже отказался, то будем делать из этого CISC на подобие 6502 или 8080 (ну или скорее z80 т.к. у нас 4-битный АЛУ) - соответственно разные типы команд будут требовать разного количества тактов - например копирование регистров с инверсией и без будет самой быстрой операцией, а сложение-вычитание самой долгой, т.к. бит переноса у нас последовательно распостраняется (это плюс к тому, что надо делать арифметику в 2 захода из-за 4-битности АЛУ)...
P.S. Возможно ради скорости надо будет сделать 2-уровневый конвейер (как в PIC) - чтобы параллельно читать команду из медленного ПЗУ (200нс) и делать один шаг вычислений в 4-битном АЛУ (который тоже 200нс в худшем случае) для предыдущей команды. Хотя для простоты можно начать с последовательного варианта...
Я тут за главного - если что шлите мыло на me собака shaos точка net
Итак, имеем:
RST: сохранить G и F, передать управление по новому адресу (подменить команду в конвейере на NOP)
RET: восстановить G и F, передав управление по следующему адресу (подменить команду в конвейере на NOP)
A=N: записать в регистр A код операции (однако для N=0 это должно означать NOP)
R1=R2: копирование из регистра в регистр (если R1 и R2 одно и тоже число, то с инверсией, плюс особый случай если R1 это G)
RRC: сдвинуть вправо старший ниббл, сдвинуть вправо младший ниббл (именно так - сначала старший, потом младший)
RLC: сдвинуть влево младший ниббл, сдвинуть влево старший ниббл
NAN: логическая операция NAND со старшим нибблом, затем с младшим нибблом (порядок неважен, но так наверное проще)
XOR: логическая операция XOR с младшим нибблом, затем со старшим нибблом
ADC: сложение A с регистром и C - младший ниббл, затем старший ниббл
SBC: сложение A с инвертированным регистром и C - младший ниббл, затем старший ниббл
A=A+N и A=A-N: детектируется как одно и тоже - сложение A с числом без учёта C:
- сначала складываем млаший ниббл из A и млаший ниббл кода операции, предварительно установив C в 0
- далее складываем старший ниббл из A и 0000 или 1111 в зависимости от бита 3 кода операции (с учётом C от предыдущего шага)
P.S. Особый случай если R1 это G - программный указатель должен получать новое значение после записи в регистр G (соответственно в случае конвейера также надо подменить команду в конвейере на NOP)...
P.P.S. Возможно надо воспользоваться тем фактом, что результат логической операции стабилизируется на выходе АЛУ более чем в 2 раза быстрее, чем результат арифметической. А может и ненадо...
Я тут за главного - если что шлите мыло на me собака shaos точка net
Shaos wrote:A=A+1 и A=A-1 (это ADI и SBI с 3-битным числом которые не используют входной флаг C)
А поподробней насчет "с 3-битным числомкоторые не используют входной флаг C" - а то как-то
не совсем понятно в рамках твоей системы команд АЛУ:
ADC: сложение A с регистром и C - младший ниббл, затем старший ниббл
SBC: сложение A с инвертированным регистром и C - младший ниббл, затем старший ниббл