Придедут когда-то же.
Philips
Вид для печати
Серия HCT - это ТТЛ-совместимый по входу КМОП. То есть - входное напряжение высокого уровня у него начинается с 2.4 вольта, в отличие от обычного КМОП серии 74HC, где для гарантированного высокого логического уровня надо подавать 0.8*Vcc (то есть - 4 вольта при 5-вольтовом питании). Впрочем НСТ тоже не пойдет, тут надо LVC при питании 3.3 вольта - они переживают входное напряжение, превышающее напряжение питания.
Мы заменяем процессор, а не всю плату типа МС1201.01. Процессор же напрямую в МПИ не втыкается? Поэтому достаточно соответствовать его хиленьким выходным втекающим 3.2ма при "0" и -200мкА при "1". Ну и по входному току - не более 10мкА, по этому параметру никакие ТТЛ-серии тут не подойдут.
Впрочем, ничто не может помешать желающим впаять на плату 74А245MTC вместо 74HCT245, особенно если сделать схему портом Б наружу :)
А чтобы в корзинку ДВК сразу втыкать - это уже другое изделие, там и ног побольше чем у ВМ1 надо, и буфера надо, и отключаемые терминаторы (глупо только процессор такой платой имитировать, можно же все что угодно - контроллер дисковода, КЦГД, КМД, КЖД и прочее).
Сошлифовался КМ1801ВМ2:
КМ1801ВМ2, диффузия, полное разрешение (487 MB)
КМ1801ВМ2, диффузия, низкое разрешение (68 MB)
Переписал маловменяемый автосгенерированный ВП1-037 на "человеческом" верилоге:
По размеру усохло раза в три, и теперь можно хоть осмысленно в текст вникать.Код://
// Copyright (c) 2013 by 1801BM1@gmail.com
//______________________________________________________________________________
//
`timescale 1ns / 100ps
module va_037
(
input PIN_CLK, //
input PIN_R, //
input PIN_C, //
//
inout[15:0] PIN_nAD, // Address/Data inverted bus
input PIN_nSYNC, //
input PIN_nDIN, //
input PIN_nDOUT, //
input PIN_nWTBT, //
output PIN_nRPLY, //
//
output[6:0] PIN_A, //
output[1:0] PIN_nCAS, //
output PIN_nRAS, //
output PIN_nWE, //
//
output PIN_nE, //
output PIN_nBS, //
output PIN_WTI, //
output PIN_WTD, //
output PIN_nVSYNC //
);
//______________________________________________________________________________
//
reg nWTBT; // BYTE flag
reg [15:0] A; // Q-bus address latch
reg [7:0] RA; // 177664 register start address
reg M256; // 1/4 screen mode
//
wire RWR, ROE; // 177664 register strobes
//
wire RESET; // external reset
wire CLKIN; // external clock (pixel/2)
//
reg [2:0] PC; // pixel counter
reg [13:1] VA; // video address counter
reg [7:0] LC; // line counter
//
wire ALOAD, TV51; // base address load strobe
reg HGATE, VGATE; //
reg PC90; //
reg RASEL, AMUXSEL;//
wire CAS; //
reg CAS322; //
wire FREEZ; //
//
reg VTSYN; //
wire SYNC2, SYNC5; //
//
wire RPLY; //
reg TRPLY; //
//
//______________________________________________________________________________
//
assign PIN_nRPLY = ~(ROE | RWR | RPLY);
assign PIN_nAD[7:0] = ~ROE ? 8'hZZ : ~RA[7:0]; // read 177664 register back
assign PIN_nAD[8] = 1'bZ; //
assign PIN_nAD[9] = ~ROE ? 1'bZ : ~M256; //
assign PIN_nAD[14:10] = 5'hZZ; //
assign PIN_nAD[15] = (~PIN_nDIN & ~PIN_nSYNC & // start address vector 177716
(A[15:1] == (16'o177716 >> 1))) ? 1'b0 : 1'bZ;
assign PIN_nE = PIN_nSYNC | PIN_nDIN | (A[15:7] != (16'o177600 >> 7));
assign PIN_nBS = ~(A[15:2] == (16'o177660 >> 2));
always @(*) if (PIN_nDOUT) nWTBT <= PIN_nWTBT;
assign RWR = ~PIN_nSYNC & ~PIN_nDOUT & (A[15:1] == (16'o177664 >> 1));
assign ROE = ~PIN_nSYNC & ~PIN_nDIN & (A[15:1] == (16'o177664 >> 1));
assign RESET = PIN_R;
assign CLKIN = PIN_CLK;
always @(*) if (PIN_nSYNC) A[15:0] = ~PIN_nAD[15:0];
always @(*) if (RWR) RA[7:0] = ~PIN_nAD[7:0];
always @(*) if (RWR) M256 = ~PIN_nAD[9];
always @(*) if (RASEL) TRPLY = 1'b1; else if (PIN_nDIN & PIN_nDOUT) TRPLY = 1'b0;
assign RPLY = TRPLY & ~RASEL;
//______________________________________________________________________________
//
// Pixel counter (within word)
//
always @(negedge CLKIN) if (~PC[0]) PC90 <= PC[1];
always @(negedge CLKIN or posedge RESET)
begin
if (RESET)
PC[2:0] <= 3'b000;
else
PC[2:0] <= PC[2:0] + 3'b001;
end
//
// Word counter (within line)
//
always @(negedge CLKIN or posedge RESET)
begin
if (RESET)
VA[5:1] <= 5'b00000;
else
if (&PC[2:0])
begin
VA[4:1] <= VA[4:1] + 4'b0001;
if (&VA[4:1] & ~HGATE) VA[5] <= ~VA[5];
end
end
//
// Test clock assignment
//
assign TV51 = PIN_C ? 1'b0 : ~(&PC[2:0] & &VA[5:1]);
//
// RWR at active RESET is added for simulation and debug purposes
//
assign ALOAD = (FREEZ & ~LC[1]) | (RESET & RWR);
//
// Loadable part of video address counter
//
always @(negedge CLKIN)
begin
if (ALOAD)
VA[13:6] <= RA[7:0];
else
if (~TV51 & ~FREEZ)
VA[13:6] <= VA[13:6] + 8'b00000001;
end
always @(negedge CLKIN or posedge RESET)
begin
if (RESET)
begin
HGATE <= 1'b0;
VGATE <= 1'b1;
end
else
begin
if (&PC[2:0] & &VA[4:1] & (HGATE | VA[5]))
HGATE <= ~HGATE;
if (~TV51 & (LC[5:0] == 6'b000000) & (VGATE | (LC[7:6] == 2'b00)))
VGATE <= ~VGATE;
end
end
//
// Line counter
//
always @(negedge CLKIN or posedge RESET)
begin
if (RESET)
LC[7:0] <= 8'b11111111;
else
if (~TV51)
begin
LC[5:0] <= LC[5:0] - 6'b000001;
if ((LC[5:0] == 6'b000000) & ~VGATE) LC[6] <= ~LC[6];
if ( LC[6:0] == 7'b0000000) LC[7] <= ~LC[7];
end
end
assign FREEZ = VGATE & (LC[5:2] == 4'b1010);
//______________________________________________________________________________
//
// DRAM address mux and controls
//
assign PIN_A[6:0] = RASEL ? (AMUXSEL ? ~A[7:1] : ~A[14:8])
: (AMUXSEL ? ~VA[7:1] : {1'b0, ~VA[13:8]});
assign PIN_nCAS[0] = ~(CAS & (~A[0] | ~PC[2] | nWTBT));
assign PIN_nCAS[1] = ~(CAS & ( A[0] | ~PC[2] | nWTBT));
assign PIN_nRAS = PC90 | (PC[2] & ~RASEL);
assign PIN_WTI = ~VGATE & ~HGATE & (M256 | (LC[6] & LC[7])) & PC90 & ~PC[2] & PC[1];
assign PIN_WTD = RPLY & ~PIN_nDIN;
assign PIN_nWE = ~(RASEL & ~PIN_nDOUT);
//
// Converted to synchronous flip-flop without asynch reset, generates the same waveform
//
// always @(posedge CLKIN or posedge (PC[1] & AMUXSEL))
// begin
// if (PC[1] & AMUXSEL)
// RASEL <= 1'b0;
// else
// if (PC90 & ~PC[1] & PC[2])
// RASEL <= ~(PIN_nSYNC | A[15] | RPLY | (PIN_nDIN & PIN_nDOUT));
// end
//
always @(posedge CLKIN) AMUXSEL <= PC90;
always @(posedge CLKIN)
begin
if (PC90 & PC[1])
RASEL <= 1'b0;
else
if (PC90 & ~PC[1] & PC[2])
RASEL <= ~(PIN_nSYNC | A[15] | RPLY | (PIN_nDIN & PIN_nDOUT));
end
always @(negedge CLKIN) CAS322 <= RASEL;
assign CAS = (CAS322 & PC[1] & PC[2]) | (~VGATE & ~HGATE & PC[1] & ~PC[2]);
//______________________________________________________________________________
//
// Video synchronization
//
always @(negedge CLKIN or posedge RESET)
begin
if (RESET)
VTSYN <= 1'b0;
else
begin
if ((VA[3:1] == 3'b000) & (PC[1:0] == 2'b11))
VTSYN <= 1'b1;
if ((VA[4:1] == 4'b0100) & (PC[2:0] == 3'b111))
VTSYN <= 1'b0;
end
end
//
// Latch converted to clock synchronous flip-flop, generates the same waveform
//
// assign VTSET = (VA[3:1] == 3'b000) & PC[2];
// assign VTCLR = (VA[4:1] == 4'b0101);
//
// always @(*)
// begin
// if (VTCLR) VTSYN = 1'b0;
// if (VTSET) VTSYN = 1'b1;
// end
//
assign SYNC2 = ~(VGATE & (LC[5:2] == 4'b1010) & ~(LC[0] & LC[1]));
assign SYNC5 = VTSYN | (SYNC2 & ~HGATE);
assign PIN_nVSYNC = ~(SYNC2 ^ SYNC5);
//______________________________________________________________________________
//
endmodule
Update:
- исправил опечатку (спасибо anasana) в комментарии и переписал CAS в более внятном виде
- исправлен декодер адреса регистра 177664 (спасибо gid)
- исправлена ошибка с флагом nWTBT
Заметил копипасту в коде.
При формировании сигналов RWR и ROE проверка адреса должна бытьА в чём преимущество такого alwaysаКод:(A[15:1] == (16'o177664 >> 1))
перед таким:Код:always @(*) if (PIN_nSYNC) A[15:0] = ~PIN_nAD[15:0];
Можно ли вот как я сейчас, произвольно менять блокирующее присваивание на неблокирующее? Или есть какие-то хитрости, когда и где использовать определённые виды присваиваний?Код:always @(posedge PIN_nSYNC) A[15:0] <= ~PIN_nAD[15:0];
И почемузаписан так, а не так:Код:always @(negedge PIN_nDOUT) nWTBT <= PIN_nWTBT;
, как вроде бы подобные alwaysы ниже, это дело вкуса или есть какие-то тонкости в способах написания?Код:always @(*) if (~PIN_nDOUT) nWTBT <= PIN_nWTBT;
Да, спасибо, упустил я A1.
Тут не преимущество, тут есть разница - первый пример это латч (типа ИР22), а второй пример - флип-флоп (типа ИР23). Как и в обычных схемах они часто взаимоменяемы, если во втором примере заменить posedge на negedge, то тоже будет работать. Времянка на выходе будет немножно другая, но для данной модели это непринципально.
В данном тексте - обычно можно.
Блокирующие присваивания (=) они выполняются как бы немедленно по тексту. А неблокирующие (<=) - откладываются и как бы накапливаются, переменная в левой части не получает присвоенное значение немедленно, собственно накопленные присвоения выполняются все сразу в конце блока always.
Вот тут более-менее внятно описано.
Тут нет никакого сакрального смысла, меня просто квартус раздражал предупреждениями о латчах, я решил их немного подсократить. Но зато появились предупреждения о левых тактовых сигналах. Поскольку непосредственно этот исходник для синтеза в ПЛИС не предназначается, то предупреждения не имеют значения.
Кстати, получается что именно в этом месте я внес ошибку - nWTBT сохраняет свое значение после последнего среза PIN_nDOUT и может влиять на последующий циклы чтения (где среза PIN_nDOUT нет), запрещая один из CAS-ов. Так что правильно будет так:
Исходник в предыдущем посте подправил. Оно, конечно, моделировалось, но покрытие далеко не полное.Код:always @(*) if (PIN_nDOUT) nWTBT <= PIN_nWTBT;
В случае с флип-флоп разница между присваиваниями очевидна
http://storage9.static.itmages.ru/i/...c8a4c95522.pngКод:module demo
( input CLK,
input d_in,
output pin_A, pin_B, pin_C,
output pin_D, pin_E, pin_F
);
reg A,B,C;
reg D,E,F;
assign pin_A = A, pin_B = B, pin_C = C;
assign pin_D = D, pin_E = E, pin_F = F;
always @(negedge CLK )
begin
A <= d_in;
B <= A;
C <= B;
end
always @(negedge CLK )
begin
D = d_in;
E = D;
F = E;
end
endmodule
С латчами генерируется та-же схема, а вот разницы в работе не будет(с оговоркой про задержки)
http://storage9.static.itmages.ru/i/...d244da2f8b.pngКод:module demo2
( input CLK,
input d_in,
output pin_A, pin_B, pin_C,
output pin_D, pin_E, pin_F
);
reg A,B,C;
reg D,E,F;
assign pin_A = A, pin_B = B, pin_C = C;
assign pin_D = D, pin_E = E, pin_F = F;
always @(*)
begin
if (CLK)
begin A <= d_in;
B <= A;
C <= B;
end
end
always @(*)
begin
if (CLK)
begin D = d_in;
E = D;
F = E;
end
end
endmodule
Будем надеяться ВМ2 не "выбежит" за 20К транзисторов:
http://s017.radikal.ru/i429/1509/b5/82a88c603bbbt.jpg
Сейчас 10K, еще осталась примерно половина площади ядра.
Update: картинка кликабельна, можно дорожки рассмотреть (в гифке все)