Вот поэтому в #75 по всем сигнальным выводам резисторы - проверял работоспособность памяти с Али.
С мегом оперативки? :-)
А какой смысл в D0 #1FFD ?
Вид для печати
это не правильный матрас. правильный вот.
Короче тот матрас был фигня, это походу не работало что-то из ОЗУ/ПЗУ/Z80
Есть небольшие успехи, тест48 запустился, бордюр весело прыгает, на экране пока что хрень, но более менее статическая, т.е. регенерация DRAM идет нормально, но буферы пока что как-то коряво работают, буду дальше ковыряться...
Переписал большую часть на Verilog.. выбор RAM/ROM пока что не получается на нем сделать.
У меня уже начинает складываться впечатления, что я первый делаю клон на CPLD/FPGA на DRAM, куда не посмотри - все на SRAM делают...
--------- я первый делаю клон на CPLD/FPGA на DRAM
;)
Reverse U16 тоже на динамической памяти.
Но там отдельный модуль занимается памятью - регенерация, управлением банками, простым кэшированием.
Выбор ПЗУ может так:
assign nROMSEL = A15 | A14 | nRD;
Другие комбинации адресов и nMREQ для ОЗУ.
Только вот такая конструкция заработала для экрана, в схемном виде и в другом ни в какую не хотело работать
Код:reg [7:0] ATTR = 7;
reg [7:0] SHIFT_REG = 0;
// latch attributes
always @(posedge DC2)
ATTR <= MD;
// latch pixels, pixel shift
always @(negedge OSC)
if(DC2n & DC1 & DC0)
SHIFT_REG <= MD;
else
SHIFT_REG <= SHIFT_REG << 1;
// если написать SHIFT_REG = pixel_latch ? MD : SHIFT_REG << 1; - не работает!
... что и неудивительно, потому, что SHIFT_REG - регистр, а регистр должен тактироваться. :-)
Также нежелательно использовать для регистров блокирующее присвоение. ( "=" вместо "<=" )
З.Ы.
Нарезал шилд с процессором, пожалуй тоже что-нибудь сделаю. ;)
Одна беда - нечем зашить ПЗУшку... ну эт что-нибудь придумаю.
EvgenRU, а ты покажи пример схемного ввода и я покажу твои косяки.
Ну, я взял из стандартной схемы кворума
http://savepic.ru/13486557.png
Удалось даже немного упростить
Я тут почитал http://asdasd.rpg.fi/~svo/verilog/assignments/ и как-то уже не на 100% уверен в этом, т.к. синтезатор всё-равно сам всё сделает в этом случае.Код:// latch pixels, pixel shift
always @(negedge OSC)
if(DC2n & DC1 & DC0)
SHIFT_REG <= 202;//MD;
else
SHIFT_REG <= SHIFT_REG << 1;
PS: ПЗУ могу помочь зашить или подарить зашитое, при желании.
PS2: вот еще мультиплексор РАБОЧИЙ!
Скрытый текст
Код:module ZX_mux(
input wire [4:0] H, // horizontal counter
input wire [7:0] V, // vertical counter
input wire [19:14] RAM, // Muxed Extended RAM address
input wire [15:0] A, // Z80 adderss
input wire S0, // RAS
input wire DC1, // H1
input wire DC2, // H2
input wire SCR, // Second SCREEN (128k)
input wire CLK, // CLOCK signal 14MHZ
output reg [9:0] MA
);
always @(negedge CLK)
begin
//-----------------------
// S0 - RAS
// DC1 - 0=CPU/1=VIDEO
// DC2 - 0=PIXELS/1=ATTR
//-----------------------
if(DC1)
begin
// VIDEO CONTROLLER ADDRESSES
// screen area address + DRAM refresh
if(S0)
begin // SELECT B
// screen area row address
MA[0] <= 1;
MA[1] <= 1;
MA[2] <= 0;
if(DC2)
begin
// Attributes
MA[3] <= 0;
MA[4] <= 1;
MA[5] <= 1;
end
else
begin
// pixels
MA[3] <= V[2];
MA[4] <= V[6];
MA[5] <= V[7];
end
MA[6] <= 0;
MA[7] <= 0;//SCR;
MA[8] <= 0;
MA[9] <= 0;
end
else
begin // SELECT A
// screen area column address
MA[4:0] <= H[4:0];
MA[7:5] <= V[5:3];
if(DC2)
begin
// attributes
MA[8] <= V[6];
MA[9] <= V[7];
end
else
begin
//pixels
MA[8] <= V[0];
MA[9] <= V[1];
end
end
end
else
begin
// CPU ADDRESSES
// memory address
if(S0)
begin // SELECT B
// memory row address
MA[0] <= RAM[14];
MA[1] <= RAM[16];
MA[2] <= RAM[18];
MA[6:3] <= A[13:10];
MA[7] <= RAM[15];
MA[8] <= RAM[17];
MA[8] <= RAM[19];
end
else
begin // SELECT A
// memory column address
MA[9:0] <= A[9:0];
end
end
end
endmodule
[свернуть]
PS3: вот еще буферы
Скрытый текст
Код:module ZX_buf(
input RAMWEn,
input RAMCSn,
input DC0,
input DC1n,
inout [7:0] D,
inout [7:0] MD
);
reg [7:0] wr_buf;
wire wrbuf = DC0 & DC1n;
assign MD = RAMWEn ? 8'bZZZZZZZZ : D;
assign D = RAMCSn ? 8'bZZZZZZZZ : wr_buf;
always @ (posedge wrbuf)
wr_buf <= MD;
endmodule
[свернуть]
Зачем непонятная и сложная 299, когда есть православная 198 (ИР13)? Я понимаю, что синтезатор вырежет из нее тристэйт, но зачем усложнять то? И вообще, зачем использовать сложный элемент в кастрированном режиме, если синтезатор все равно его обкромсает, причем часто не так, как нужно вам? Если вам нужно только 2 режима: загрузка и сдвиг, то не проще ли синтезатору прямо об этом сказать?
http://savepic.ru/13447638.png
Откройте уже для себя просмотр RTL. Это единственный способ узнать, как именно поняли вас синтезатор и фиттер (а они работают вместе и результат часто отличается для разных типов ПЛИС).
Потому, что этот мультиплексор регистровый (с хранением результата) и управляется из одного always блока, что как раз и соответствует всем требованиям. Если бы вам нужен был мультплекор на комбинаторике, его синтаксис был бы несколько иначе. Вот пример:
Скрытый текст
Код:assign MAPC_A[17:10] = (~CTRL[7]) ? (
(PPU_A[12:11] == 2'h0) ? BCH0[7:0] :
(PPU_A[12:11] == 2'h1) ? BCH1[7:0] :
(PPU_A[12:10] == 3'h4) ? CHR2[7:0] :
(PPU_A[12:10] == 3'h5) ? CHR3[7:0] :
(PPU_A[12:10] == 3'h6) ? CHR4[7:0] : CHR5[7:0]
) : (
(PPU_A[12:10] == 3'h0) ? CHR2[7:0] :
(PPU_A[12:10] == 3'h1) ? CHR3[7:0] :
(PPU_A[12:10] == 3'h2) ? CHR4[7:0] :
(PPU_A[12:10] == 3'h3) ? CHR5[7:0] :
(PPU_A[12:11] == 2'h2) ? BCH0[7:0] : BCH1[7:0]
);
[свернуть]
Ну и для полноты картины генератор клока без лишних регистров, который использую сейчас
Скрытый текст
Код:module ZX_clock_gen(
input wire CLK, // 14 MHz clock input
input wire M1n,
input wire IORQn,
input wire RESn,
output reg PIXCLK = 0,
output wire PIXCLKn,
output wire DC0,
output wire DC0n,
output wire DC1,
output wire DC1n,
output wire DC2,
output wire DC2n,
output wire [4:0] H,
output wire [7:0] V,
output wire HSYN,
output wire VSYN,
output wire BORD,
output wire BLANCn,
output wire INTn,
output wire SYNn,
output wire CASn,
output reg RASn = 1,
output wire RAS
);
parameter HBorderStart = 256; // X resolution
parameter HBlancStart = 320;
parameter HBlancEnd = 384;
parameter HSynStart = 320;
parameter HSynEnd = 352;
parameter HLineEnd = 448;
parameter VBorderStart = 192; // Y Resolution
parameter VBlancStart = 248;
parameter VBlancEnd = 256;
parameter VSynStart = 248;
parameter VSynEnd = 256;
parameter VIntStart = 256;
parameter VIntEnd = 264;
parameter VLineEnd = 320;
reg [8:0] cntH = 0;
reg [8:0] cntV = 0;
reg CAS = 0;
always @(negedge CLK)
begin
PIXCLK <= ~PIXCLK;
CAS <= cntH[0];
end
always @(negedge PIXCLK)// or negedge RESn)
begin
cntH <= cntH + 1'b1;
RASn <= cntH[0];
if(cntH + 1'b1 == HLineEnd) // should be cntH + 1 as it is non blocking!
begin
cntH <= 9'b000000000;
cntV <= cntV + 1'b1;
if(cntV + 1'b1 == VLineEnd) // should be cntV + 1 as it is non blocking!
cntV <= 9'b000000000;
end
end
wire HBR = (cntH >= HBorderStart) ? 1'b1 : 1'b0;
wire VBR = (cntV >= VBorderStart) ? 1'b1 : 1'b0;
wire HBL = (cntH >= HBlancStart && cntH <= HBlancEnd ) ? 1'b1 : 1'b0;
wire VBL = (cntV >= VBlancStart && cntV <= VBlancEnd ) ? 1'b1 : 1'b0;
assign HSYN = (cntH >= HSynStart && cntH <= HSynEnd ) ? 1'b1 : 1'b0;
assign VSYN = (cntV >= VSynStart && cntV <= VSynEnd ) ? 1'b1 : 1'b0;
assign INTn = (cntV >= VIntStart && cntV <= VIntEnd ) ? 1'b0 : 1'b1;
assign PIXCLKn = PIXCLK;
assign DC0 = cntH[0];
assign DC0n = ~cntH[0];
assign DC1 = cntH[1];
assign DC1n = ~cntH[1];
assign DC2 = cntH[2];
assign DC2n = ~cntH[2];
assign H[4:0] = cntH[7:3];
assign V[7:0] = cntV[7:0];
assign BLANCn = ~(VBL | HBL);
assign SYNn = ~(HSYN ^ VSYN);
assign BORD = VBR | HBR;
assign CASn = ~CAS;
assign RAS = ~RASn;
endmodule
[свернуть]
Гляньте, может еще остались какие косяки...