nedoPC.org

Community of electronics hobbyists established in 2002

...
Atom Feed | View unanswered posts | View active topics It is currently 16 Dec 2017 14:37



Reply to topic  [ 128 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9  Next
Z80 Finite State Machine 
Author Message
Banned
User avatar

Joined: 20 Mar 2005 14:41
Posts: 2152
Location: От туда
Reply with quote
Post 
pfgx wrote:
Выходные буферы #MREQ, #IORQ, #RD, #WR управляются через RS-триггеры, так что иголок быть не должно, но имеется интересная особенность: при переводе в Z-состояние у выходных буферов отключается только верхний транзистор, то есть RS-триггер при этом должен находиться в состоянии 1. Находится ли он в нём?

Т.е., при активации BUSR процессор должен встать в пассивной позиции иначе мы получаем ОК на шинах управления? И, соответственно, захват шины обрабатывается в строго определенный момент времени (предполагаю непосредственно перед М1)?


08 Nov 2013 07:46
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
HardWareMan wrote:
Т.е., при активации BUSR процессор должен встать в пассивной позиции иначе мы получаем ОК на шинах управления?
Да, именно так. Надо будет в Verilog учесть этот ОК, спасибо за замечание.
HardWareMan wrote:
И, соответственно, захват шины обрабатывается в строго определенный момент времени (предполагаю непосредственно перед М1)?
Выходной драйвер #BUSACK и отключение верхнего транзистора управляются одним и тем же сигналом, то есть если #BUSACK=0 - транзистор отключен. Сигнал активируется в какой-то сложный момент времени, но на эти же триггеры кроме #RESET, #BUSRQ и #CLK заведён сигнал 609 - завершение M-циклов текущей операции и переход к новой (M1).


10 Nov 2013 12:27
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Понял, что Z80 слишком сложен для "посмотреть как устроен процессор", да и в целом уже стало понятно как это делается, но постараюсь завершить начатое.

Пробую писать на Verilog. Из черновика (код нерабочий, в нём точно есть ошибки :) ):
Code:
module mod_state (
   input wire [200:131] w,
   input wire w127,
   input wire clk,
   input wire w_reset,
   output reg [6:1] Tstate,
   output reg [5:1] Mstate
);

   wire w249;

   wire w609; // w609=1 - начать новый M-цикл
   wire w609a, w609b, w609c;
   assign w609a = Tstate[3] & Mstate[2]; // по 3 такта только M2
   assign w609b = Tstate[4] & Mstate[1] & w[155]; // по 4 такта только M1 и только для w155
   assign w609c = Tstate[5] & Mstate[5] & w249; // по 5 тактов только M5 для w249
   assign w609 = w609a | w609b | w609c | Tstate[6] | w_reset; // M-цикл всегда заканчивается при T=6 или при reset=1

   always @(negedge clk)
   begin
      if (w609) Tstate='b000001;
      else Tstate[6:1]={Tstate[5:1],1'b0}; // сдвиг на 1 разряд
   end


   wire w627; // w627=1 - перейти на M1 // приоритет у перехода на M1
   wire w626; // w626=1 - перейти на M4

   // перейти на M1 (то есть начать новую команду)
   wire w627a,w627b,w627c;
   assign w627a = Mstate[1] & w[171] & w[172] & w[173] & w[177]; // при M1 только для этих команд
   assign w627b = Mstate[2] & (~w[172]) & w[173] & w[199] & (0|w[177]); // при M2 только для этих
   assign w627c = Mstate[3] & (w127 | (w[158] & (w[175] | (~w[156]))) ); // при M3 для этих
   assign w627 = w627a | w627b | w627c | Mstate[5] | w_reset ; // переход на M1 также всегда при M5 и при reset
   // команд, завершающихся на M4, не бывает
   // M3 это (для определённых команд) чтение байта смещения и расчёт адреса (5 тактов) для IX/IY+offset и относительных переходов

   // перейти на М4
   // т.е. пропуск M3 (чтения байта смещения и вычисления адреса) и иногда M2 (если w[172]=1)
   wire w626a,w626b;
   assign w626a = (Mstate[1] & w[172]) | Mstate[2]; // такие пропуски бывают на M1 для w172 и на M2
   assign w626b = w[173]&(~w[177]) | ((0)&w[177]); // дополнительное условие такого пропуска
   assign w626 = w626a & w626b;


   always @(negedge clk)
   begin
      if (w627) Mstate='b00001; // перейти на M1
      else
      if (w626) Mstate='b01000; // перейти на M4
      else
         Mstate[5:1]={Mstate[4:1],1'b0}; // сдвиг на 1 разряд
   end

endmodule


09 Dec 2013 17:22
Profile
Supreme God
User avatar

Joined: 21 Oct 2009 09:08
Posts: 7777
Location: Россия
Reply with quote
Post 
pfgx wrote:
Понял, что Z80 слишком сложен для "посмотреть как устроен процессор", да и в целом уже стало понятно как это делается, но постараюсь завершить начатое.

Да ты огромнейшую работу проделал! Я даже не думал, что это лишь для того,
чтобы "посмотреть как устроен процессор"! :o

Ты материалы всё же где-нибуть выложи свои - чтобы пройденной тобой дорогой
никому не пришлось бы пройти сначала...

_________________
iLavr


10 Dec 2013 09:50
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Да, я не понимал как сделать вот такую большую схему, в которой одновременно работает несколько блоков, и как их между собой согласовать. Решил посмотреть как оно в реальном процессоре, заодно разобраться с недокументированными командами. Теперь пытаюсь переложить это на Verilog.

Материалы выложу обязательно. А идущих этой дорогой много, я смотрю народ основательно взялся за NES, PlayStation и прочее, что можно рассмотреть в микроскоп :)


11 Dec 2013 04:04
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Поработал, отдохнул, продолжаю :)

Вот есть эти счётчики (которые на самом деле сдвиговые регистры) тактов и циклов. Строб записи инструкции в буфер сделан просто: M1&T3. То есть в момент наступления 3-го такта цикла M1 инструкция с шины защёлкивается в буфер. Допустим, последний цикл предыдущей инструкции был длиной 3 такта, тогда при очередном перепаде тактового сигнала сбросится T3, установится T1, сбросится Mn и установится M1, но произойдёт это практически одновременно, неизвестно в каком порядке, и возможна ситуация, когда T3 ещё не сбросился, а M1 уже установлен, что вызовет "иголку" в стробе записи. Весь вечер пересматривал схему, но то ли я чего-то не замечаю, то ли эта иголка не влияет на работу, то ли случайно (или не совсем случайно) на кристалле получилось так, что T3 сбрасывается раньше. В любом случае в Verilog это надо учесть. Например, сделать так:
Code:
   reg cmdclock,cmdclock2;
   always @(posedge clock) cmdclock2 = (Mstate[1]) & (Tstate[2]);
   always @(negedge clock) cmdclock = cmdclock2;


15 Mar 2014 14:40
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Счётчики для беспрефиксных опкодов уже почти работают, основные проблемы с опкодами С0h...FFh, так как там есть исключения и много условных команд, длительность которых может изменяться.

Попробую перевести следующую часть схемы:
Code:
   // декодер для управления блоком регистров
   wire [399:301] w3;
   assign w3[331] = ~((w[51] & w211 & (w205 | w204)) | (w2[240] & ((w204 & w209) | (w205 & w210))));
   assign w3[342] = ~(w211 | (w209 & w206));
   assign w3[346] = ~(w3[331] & w3[332]);
   assign w3[347] = ~(w3[337] & w3[338]);
   assign w3[348] = ~(w3[339] & w3[340]);
   ...


17 Mar 2014 01:26
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Вся дальнейшая логика сильно привязана к выходам счётчика тактов-циклов, но в этой "шине" счётчиков кроме 10 уже известных проводов есть ещё провод под условным номером 201 и расположенный как бы отдельно от них провод под номером 212. После этой логики ещё один "слой", который и формирует сигналы выборки-чтения-записи регистров.

Ещё в процессоре есть провод 612, который часто используется, но пока совершенно непонятно откуда он идёт и зачем он нужен.
Code:
   // декодер для управления блоком регистров
   wire [399:301] w3;
   assign w3[301] = ~((w1[199] & w209 & w209) | (w211 & ((w202 & 0) | (w203 & (0 | 0))))); // TODO проверить 209-209
   assign w3[302] = ~((w[51] & w205 & (w209 | w211)) | (M1 & w208 & w2[237]));
   assign w3[303] = ~((w205 & w210) | (w211 & ((w203 & w2[252]) | (w204 & w[51]))));
   assign w3[304] = ~((M1 & w208 & w2[252]) | (w202 & w211 & ~w2[244]));
   assign w3[305] = ~(M1 & w211 & w[80]); // 80 - ex AF,AF'
   assign w3[306] = ~((M1 & w210 & w1[183]) | (w1[199] & w204 & w207) | (w203 & w209 & w2[236]));
   assign w3[307] = ~((w209 & (w202 | (w204 & w2[251]))) | (w205 & w211 & (w2[296] | w2[297])));
   assign w3[308] = ~((w210 & w204 & (w2[246] | w[51])) | (w209 & ((w205 & ~w[51] & w2[251]) | (w203 & w2[261]))));
   assign w3[309] = ~(w210 & M1 & w[130]);
   assign w3[310] = ~(M1 & w208 & w[87]); // какая-то ED
   assign w3[311] = ~((M1 & w208 & w2[260]) | (w203 & w211 & (~w1[174] | w[94]))); // 94 - какая-то ED
   assign w3[312] = ~((M1 & w210 & w1[183]) | (M1 & w208 & w[97]) | (w203 & w209 & w1[176] & w2[236]) | (w203 & w211 & w2[236])); // 97 - сдвиги rlc, rrc, rlnc, rrnc
   assign w3[313] = ~((w211 | w209) & (w203 | w202) & w[99]); // 99 - push/pop
   assign w3[314] = ~((w209 & ((w205 & w[103]) | (w204 & w1[196]))) | (w211 & w205 & w2[298]) | (w207 & w206 & w[101]) | (w208 & ((w206 & w2[298]) | (w204 & w1[196]))));
   assign w3[315] = ~(w[105] & ((w204 | w210) | (w205 & w209)));
   assign w3[316] = ~((w205 & w209 & (w[106] | w[101])) | (w204 & w210 & w[101]) | (M1 & w208 & (w2[255] | w1[198])) | (M1 & w207 & w[103])); // 106 - ld R,byte
   assign w3[317] = ~((w1[198] & w209 & (w202 | w203)) | (w208 & ((w1[198] & w203) | (w[109] & w204))) | (w2[299] & w205 & w210)); // 109 - какая-то ED
   assign w3[318] = ~(w2[259] & ((w205 & w210) | (w204 & w209)));
   assign w3[319] = ~((w3[318] & w2[257] & (w202 | w203)) | (w211 & (w202 | w203) & (w2[250] | w[115] | w1[198])));
   assign w3[320] = ~(((w207 | w208) & (w202 | (M1 & (w[117] | w[118])))) | (w209 & w[119] & (w205 | w204))); // 117 - inc/dec RR; 118 - ???; 119 - ld RR,word
   assign w3[321] = ~((w205 & w210 & w[51]) | ((w[51] | w2[243]) & (w204 | M1) & (w207 | w208)));
   // 322...330 ???
   assign w3[331] = ~((w[51] & w211 & (w205 | w204)) | (w2[240] & ((w204 & w209) | (w205 & w210))));
   assign w3[332] = ~((w203 & w208 & w1[196]) | (w211 & (w202 | w203) & (w[50] | w2[254])));
   assign w3[333] = w204 | w2[256];
   assign w3[334] = ~((w210 & (M1 | (w204 & w2[243]))) | (M1 & w208) | (w209 & (w202 | (w204 & w1[196]))));
   assign w3[335] = ~(w204 | M1 | (w205 & w2[262]));
   assign w3[336] = ~w3[335];
   assign w3[337] = ~((w210 & ((w202 & w1[176] & w2[243]) | (w1[196] & w204))) | (M1 & w207 & (w[51] | ~w1[176])) | (M1 & w209));
   assign w3[338] = ~((w208 & (w202 | ((w204 | w203) & (w1[196] | w2[243])))) | (w210 & ((w205 & w2[263]) | (w203 & w2[264]))));
   assign w3[339] = ~(w211 & ((w205 & (w[51] | 0)) | (w203 & w2[243] & 0) | (w204 & 0))); // TODO
   assign w3[340] = ~((w204 & w209 & 0) | (w1[196] & w203 & (w209 | w211)) | (M1 & w208 & w2[267])); // "0" завязан на 612 // TODO
   assign w3[341] = ~((T4 & w[121]) | (w[115] & M5 & T3)); // 121 - ld SP,HL; 115 - ex [SP],HL
   assign w3[342] = ~(w211 | (w209 & M1));
   assign w3[343] = (w204 & w2[268]) | (~w2[269] & (w202 | w203));
   assign w3[344] = ~((w202 & (w1[199] | ~w1[176])) | (~w1[176] & w203) | (w[51] & w205) | (w204 & (w[51] | w1[196])));
   assign w3[345] = ~(w3[343] | w3[344]);
   assign w3[346] = ~(w3[331] & w3[332]);
   assign w3[347] = ~(w3[337] & w3[338]);
   assign w3[348] = ~(w3[339] & w3[340]);
//   assign w3[349] =
//   assign w3[350] =
   assign w3[351] = w1[185] ? ~w[56] : w[59]; // 56 - rst, 59 - ???
   assign w3[354] = ~(w3[311] & (w3[310] | w3[357]));
   assign w3[356] = ~(w3[309] & (w3[310] | ~w3[357]));
   assign w3[357] = w1[185] ? w[65] : ~w[63]; // 65 - 5-й бит регистра опкода; 63 - 4-й бит
//   assign w3[358] =
//   assign w3[359] =
   assign w3[360] = ~(w3[363] | ~w3[313] | (w3[309] & w3[311]));
   assign w3[361] = w1[185] ? w[66] : w[65]; // 65 - 5-й бит регистра опкода; 66 - 2-й бит
   assign w3[362] = ~(w3[316] & w3[317]);
   assign w3[363] = ~(w3[319] & w3[320]);
   assign w3[364] = ~(w3[362] | ((~w3[360] | w3[363]) & (~w3[357] | w3[361])));
   assign w3[365] = ~(w3[321] & w3[322]);
   assign w3[366] = ~(~w3[312] | ~w3[314] | ~w3[315] | w3[352] | w3[362] | ~w3[318] | w3[365]);


18 Mar 2014 14:31
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
pfgx wrote:
Строб записи инструкции в буфер сделан просто: M1&T3
Ой, а там за этим AND ещё RS-триггер есть :)


20 Mar 2014 10:48
Profile
Banned
User avatar

Joined: 04 Jan 2013 11:09
Posts: 398
Location: 95.24.178.158
Reply with quote
Post 
А из Ваших разработок не видно пока, как выполняется команда DAD RP?
Судя по тому, что АЛУ 4-битное, там должно быть 4 прохода через АЛУ, нет?


22 Mar 2014 09:48
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Пока не видно, но теоретически да, должно быть 4 прохода.
Выполняется она за 11 тактов, состоит из трёх M-циклов: M1 и M4 по 4 такта и M5 3 такта. На M4T3 и M5T3 есть строб записи в младший и старший байты.

Для желающих порассматривать черновики с кучей недоделок:
http://yadi.sk/d/Wg0bpuKAKzeu6
http://yadi.sk/d/I65stOaiKzehQ


22 Mar 2014 10:12
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Вопрос. После PUSH AF, POP BC куда попадёт A? В регистр B или C? Может кто-нибудь проверить на реальном Z80?


23 Mar 2014 11:52
Profile
Banned
User avatar

Joined: 04 Jan 2013 11:09
Posts: 398
Location: 95.24.178.158
Reply with quote
Post 
В реальном К580ВМ80А - вроде как в B, a в С - флаги.
По крайней мере, так видно под отладчиком.

А что, у Z80 есть отличие в исполнении этих команд?

Нет, всё верно - Особенности процессора Z80:
Quote:
1.11. Процессор Z-80 допускает проведение операций со стеком. На стек может помещаться только содержимое регистровых пар или индексных регистров. Для этих операций можно рассматривать регистры A и F как отдельную регистровую пару AF, состоящую из аккумулятора (старший байт) и набора флагов (младший байт) .

Коли аккумулятора А (старший байт), то он и попадет при РОР в В - тоже старший байт.


23 Mar 2014 13:47
Profile
Fanat

Joined: 10 Feb 2014 04:37
Posts: 79
Reply with quote
Post 
Я думаю, что не зря команду назвали PUSH AF а не PUSH FA. Но лучше конечно проверить.


24 Mar 2014 05:12
Profile
Senior

Joined: 20 Mar 2013 04:36
Posts: 137
Location: Ростов-на-Дону
Reply with quote
Post 
Оно вроде всё элементарно, но путаница небольшая есть, как и с RLC/RLNC, например.

Да, похоже что действительно AF, а не FA. Но тогда зачем происходит "refresh" регистра флагов на каждом M1T3? А может это у меня криво формируются сигналы чтения-записи регистров. Там же как: при рисовании одну стравленную перемычку где-то пропустил - всё поплыло, а кое-что даже инвертировалось.


27 Mar 2014 00:11
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 128 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9  Next

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.