mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 14:51:25 +03:00

Code to check: 10 out 61431, 128 20 out 57335, 0 30 print in 49143; 40 print " "; 50 goto 30
747 lines
20 KiB
Verilog
747 lines
20 KiB
Verilog
|
|
// PentEvo project (c) NedoPC 2008-2010
|
|
|
|
`include "tune.v"
|
|
|
|
module zports
|
|
(
|
|
input wire zclk, // z80 clock
|
|
input wire clk,
|
|
|
|
input wire [ 7:0] din,
|
|
output reg [ 7:0] dout,
|
|
output wire dataout,
|
|
input wire [15:0] a,
|
|
|
|
input wire rst, // system reset
|
|
input wire opfetch,
|
|
|
|
input wire rd,
|
|
input wire wr,
|
|
input wire rdwr,
|
|
|
|
input wire iorq,
|
|
input wire iorq_s,
|
|
input wire iord,
|
|
input wire iord_s,
|
|
input wire iowr,
|
|
input wire iowr_s,
|
|
input wire iordwr,
|
|
input wire iordwr_s,
|
|
|
|
output wire porthit, // when internal port hit occurs, this is 1, else 0; used for iorq1_n iorq2_n on zxbus
|
|
output wire external_port, // asserts for AY and VG93 accesses
|
|
|
|
output wire zborder_wr,
|
|
output wire border_wr,
|
|
output wire zvpage_wr,
|
|
output wire vpage_wr,
|
|
output wire vconf_wr,
|
|
output wire gx_offsl_wr,
|
|
output wire gx_offsh_wr,
|
|
output wire gy_offsl_wr,
|
|
output wire gy_offsh_wr,
|
|
output wire t0x_offsl_wr,
|
|
output wire t0x_offsh_wr,
|
|
output wire t0y_offsl_wr,
|
|
output wire t0y_offsh_wr,
|
|
output wire t1x_offsl_wr,
|
|
output wire t1x_offsh_wr,
|
|
output wire t1y_offsl_wr,
|
|
output wire t1y_offsh_wr,
|
|
output wire tsconf_wr,
|
|
output wire palsel_wr,
|
|
output wire tmpage_wr,
|
|
output wire t0gpage_wr,
|
|
output wire t1gpage_wr,
|
|
output wire sgpage_wr,
|
|
output wire hint_beg_wr,
|
|
output wire vint_begl_wr,
|
|
output wire vint_begh_wr,
|
|
|
|
output wire [31:0] xt_page,
|
|
|
|
output reg [4:0] fmaddr,
|
|
input wire regs_we,
|
|
|
|
output reg [7:0] sysconf,
|
|
output reg [7:0] memconf,
|
|
output reg [3:0] cacheconf,
|
|
input wire cfg_floppy_swap,
|
|
output reg [7:0] fddvirt,
|
|
|
|
`ifdef FDR
|
|
output reg fdr_en,
|
|
output wire fdr_cnt_lat,
|
|
input wire [18:0] fdr_cnt,
|
|
|
|
output wire [9:0] dmaport_wr,
|
|
`else
|
|
output wire [8:0] dmaport_wr,
|
|
`endif
|
|
input wire dma_act,
|
|
output reg [1:0] dmawpdev,
|
|
|
|
|
|
output reg [7:0] intmask,
|
|
|
|
input wire dos,
|
|
input wire vdos,
|
|
output wire vdos_on,
|
|
output wire vdos_off,
|
|
|
|
output wire ay_bdir,
|
|
output wire ay_bc1,
|
|
output wire covox_wr,
|
|
output wire beeper_wr,
|
|
|
|
input wire tape_read,
|
|
|
|
`ifdef IDE_HDD
|
|
// IDE interface
|
|
input wire [15:0] ide_in,
|
|
output wire [15:0] ide_out,
|
|
output wire ide_cs0_n,
|
|
output wire ide_cs1_n,
|
|
output wire ide_req,
|
|
input wire ide_stb,
|
|
input wire ide_ready,
|
|
output reg ide_stall,
|
|
`endif
|
|
|
|
input wire [ 4:0] keys_in, // keys (port FE)
|
|
input wire [ 7:0] mus_in, // mouse (xxDF)
|
|
|
|
`ifdef KEMPSTON_8BIT
|
|
input wire [ 7:0] kj_in,
|
|
`else
|
|
input wire [ 4:0] kj_in,
|
|
`endif
|
|
|
|
input wire vg_intrq,
|
|
input wire vg_drq, // from vg93 module - drq + irq read
|
|
output wire vg_cs_n,
|
|
output wire vg_wrFF,
|
|
output wire [1:0] drive_sel, // disk drive selection
|
|
|
|
// SPI
|
|
output wire sdcs_n,
|
|
output wire sd2cs_n,
|
|
`ifdef IDE_VDAC2
|
|
output wire ftcs_n,
|
|
`ifdef ESP32_SPI
|
|
output wire espcs_n,
|
|
`endif
|
|
`endif
|
|
output reg spi_mode,
|
|
output wire sd_start,
|
|
output wire [ 7:0] sd_datain,
|
|
input wire [ 7:0] sd_dataout,
|
|
|
|
// WAIT-ports related
|
|
output reg [ 7:0] wait_addr,
|
|
output wire wait_start_gluclock, // begin wait from some ports
|
|
output wire wait_start_comport, //
|
|
output reg [ 7:0] wait_write,
|
|
input wire [ 7:0] wait_read
|
|
);
|
|
|
|
//#nnAF
|
|
localparam VCONF = 8'h00;
|
|
localparam VPAGE = 8'h01;
|
|
localparam GXOFFSL = 8'h02;
|
|
localparam GXOFFSH = 8'h03;
|
|
localparam GYOFFSL = 8'h04;
|
|
localparam GYOFFSH = 8'h05;
|
|
localparam TSCONF = 8'h06;
|
|
localparam PALSEL = 8'h07;
|
|
localparam XBORDER = 8'h0F;
|
|
|
|
localparam T0XOFFSL = 8'h40;
|
|
localparam T0XOFFSH = 8'h41;
|
|
localparam T0YOFFSL = 8'h42;
|
|
localparam T0YOFFSH = 8'h43;
|
|
localparam T1XOFFSL = 8'h44;
|
|
localparam T1XOFFSH = 8'h45;
|
|
localparam T1YOFFSL = 8'h46;
|
|
localparam T1YOFFSH = 8'h47;
|
|
|
|
localparam RAMPAGE = 8'h10; // this covers #10-#13
|
|
localparam FMADDR = 8'h15;
|
|
localparam TMPAGE = 8'h16;
|
|
localparam T0GPAGE = 8'h17;
|
|
localparam T1GPAGE = 8'h18;
|
|
localparam SGPAGE = 8'h19;
|
|
localparam DMASADDRL = 8'h1A;
|
|
localparam DMASADDRH = 8'h1B;
|
|
localparam DMASADDRX = 8'h1C;
|
|
localparam DMADADDRL = 8'h1D;
|
|
localparam DMADADDRH = 8'h1E;
|
|
localparam DMADADDRX = 8'h1F;
|
|
|
|
localparam SYSCONF = 8'h20;
|
|
localparam MEMCONF = 8'h21;
|
|
localparam HSINT = 8'h22;
|
|
localparam VSINTL = 8'h23;
|
|
localparam VSINTH = 8'h24;
|
|
localparam DMAWPD = 8'h25;
|
|
localparam DMALEN = 8'h26;
|
|
localparam DMACTRL = 8'h27;
|
|
localparam DMANUM = 8'h28;
|
|
localparam FDDVIRT = 8'h29;
|
|
localparam INTMASK = 8'h2A;
|
|
localparam CACHECONF = 8'h2B;
|
|
localparam DMAWPA = 8'h2D;
|
|
|
|
localparam XSTAT = 8'h00;
|
|
localparam DMASTAT = 8'h27;
|
|
|
|
`ifdef FDR
|
|
localparam DMANUMH = 8'h2C;
|
|
localparam FRCTRL = 8'h30;
|
|
localparam FRCNT0 = 8'h30;
|
|
localparam FRCNT1 = 8'h31;
|
|
localparam FRCNT2 = 8'h32;
|
|
`endif
|
|
|
|
`ifdef FDR
|
|
localparam FDR_VER = 1'b1;
|
|
`else
|
|
localparam FDR_VER = 1'b0;
|
|
`endif
|
|
|
|
`ifdef IDE_VDAC
|
|
localparam VDAC_VER = 3'h3;
|
|
`elsif IDE_VDAC2
|
|
localparam VDAC_VER = 3'h7;
|
|
`else
|
|
localparam VDAC_VER = 3'h0;
|
|
`endif
|
|
|
|
localparam PORTFE = 8'hFE;
|
|
localparam PORTFD = 8'hFD;
|
|
localparam PORTXT = 8'hAF;
|
|
localparam PORTF7 = 8'hF7;
|
|
localparam COVOX = 8'hFB;
|
|
|
|
`ifdef IDE_HDD
|
|
localparam NIDE10 = 8'h10;
|
|
localparam NIDE11 = 8'h11;
|
|
localparam NIDE30 = 8'h30;
|
|
localparam NIDE50 = 8'h50;
|
|
localparam NIDE70 = 8'h70;
|
|
localparam NIDE90 = 8'h90;
|
|
localparam NIDEB0 = 8'hB0;
|
|
localparam NIDED0 = 8'hD0;
|
|
localparam NIDEF0 = 8'hF0;
|
|
localparam NIDE08 = 8'h08;
|
|
localparam NIDE28 = 8'h28;
|
|
localparam NIDE48 = 8'h48;
|
|
localparam NIDE68 = 8'h68;
|
|
localparam NIDE88 = 8'h88;
|
|
localparam NIDEA8 = 8'hA8;
|
|
localparam NIDEC8 = 8'hC8;
|
|
localparam NIDEE8 = 8'hE8;
|
|
`endif
|
|
|
|
localparam VGCOM = 8'h1F;
|
|
localparam VGTRK = 8'h3F;
|
|
localparam VGSEC = 8'h5F;
|
|
localparam VGDAT = 8'h7F;
|
|
localparam VGSYS = 8'hFF;
|
|
|
|
localparam KJOY = 8'h1F;
|
|
localparam KMOUSE = 8'hDF;
|
|
|
|
localparam SDCFG = 8'h77;
|
|
localparam SDDAT = 8'h57;
|
|
|
|
localparam COMPORT = 8'hEF; // F8EF..FFEF - rs232 ports
|
|
|
|
reg [3:0] spi_cs_n;
|
|
reg pwr_up_reg;
|
|
reg [7:0] rampage[0:3];
|
|
wire gluclock_on;
|
|
wire p7ffd_wr;
|
|
|
|
assign sdcs_n = spi_cs_n[0];
|
|
assign sd2cs_n = spi_cs_n[2];
|
|
`ifdef IDE_VDAC2
|
|
assign ftcs_n = spi_cs_n[1];
|
|
`ifdef ESP32_SPI
|
|
assign espcs_n = spi_cs_n[3];
|
|
`endif
|
|
`endif
|
|
|
|
wire open_vg;
|
|
wire [7:0] loa = a[7:0];
|
|
wire [7:0] hoa = regs_we ? a[7:0] : a[15:8];
|
|
|
|
wire vg_port = (loa==VGCOM) || (loa==VGTRK) || (loa==VGSEC) || (loa==VGDAT);
|
|
wire vgsys_port = (loa==VGSYS);
|
|
|
|
assign porthit = ((loa==PORTFE) || (loa==PORTXT) || (loa==PORTFD) || (loa==COVOX)) || ((loa==PORTF7) && !dos)
|
|
`ifdef IDE_HDD
|
|
|| ide_all
|
|
`endif
|
|
|| ((vg_port || vgsys_port) && (dos || open_vg)) || ((loa==KJOY) && !dos && !open_vg) || (loa==KMOUSE) || ((loa==SDCFG) || (loa==SDDAT)) || (loa==COMPORT);
|
|
|
|
`ifdef IDE_HDD
|
|
wire ide_all = ide_even || ide_port11;
|
|
wire ide_even = (loa[2:0] == 3'b000) && (loa[3] != loa[4]); // even ports
|
|
wire ide_port11 = (loa==NIDE11); // 11
|
|
wire ide_port10 = (loa==NIDE10); // 10
|
|
wire ide_portc8 = (loa==NIDEC8); // C8
|
|
`endif
|
|
|
|
assign external_port = ((loa==PORTFD) && a[15]) // AY
|
|
|| (((loa==VGCOM) || (loa==VGTRK) || (loa==VGSEC) || (loa==VGDAT)) && (dos || open_vg));
|
|
|
|
assign dataout = porthit && iord && (~external_port);
|
|
|
|
// zclk-synchronous strobes
|
|
reg iowr_reg;
|
|
reg iord_reg;
|
|
reg port_wr;
|
|
reg port_rd;
|
|
|
|
always @(posedge zclk)
|
|
begin
|
|
iowr_reg <= iowr;
|
|
iord_reg <= iord;
|
|
|
|
if (!iowr_reg && iowr)
|
|
port_wr <= 1'b1;
|
|
else
|
|
port_wr <= 1'b0;
|
|
|
|
if (!iord_reg && iord)
|
|
port_rd <= 1'b1;
|
|
else
|
|
port_rd <= 1'b0;
|
|
end
|
|
|
|
// reading ports
|
|
always @*
|
|
begin
|
|
case (loa)
|
|
PORTFE:
|
|
dout = {1'b1, tape_read, 1'b1, keys_in};
|
|
|
|
`ifdef IDE_HDD
|
|
NIDE10,NIDE30,NIDE50,NIDE70,NIDE90,NIDEB0,NIDED0,NIDEF0,NIDE08,NIDE28,NIDE48,NIDE68,NIDE88,NIDEA8,NIDEC8,NIDEE8:
|
|
dout = iderdeven;
|
|
NIDE11:
|
|
dout = iderdodd;
|
|
`endif
|
|
|
|
PORTXT:
|
|
begin
|
|
case (hoa)
|
|
XSTAT:
|
|
dout = {1'b0, pwr_up_reg, FDR_VER, 2'b0, VDAC_VER};
|
|
|
|
DMASTAT:
|
|
dout = {dma_act, 7'b0};
|
|
|
|
RAMPAGE + 8'd2, RAMPAGE + 8'd3:
|
|
dout = rampage[hoa[1:0]];
|
|
|
|
`ifdef FDR
|
|
FRCNT0:
|
|
dout = fdr_cnt[7:0];
|
|
|
|
FRCNT1:
|
|
dout = fdr_cnt[15:8];
|
|
|
|
FRCNT2:
|
|
dout = {5'b0, fdr_cnt[18:16]};
|
|
`endif
|
|
default:
|
|
dout = 8'hFF;
|
|
|
|
endcase
|
|
end
|
|
|
|
VGSYS:
|
|
dout = {vg_intrq, vg_drq, 6'b111111};
|
|
|
|
KJOY:
|
|
`ifdef KEMPSTON_8BIT
|
|
dout = kj_in;
|
|
`else
|
|
dout = {3'b000, kj_in};
|
|
`endif
|
|
|
|
KMOUSE:
|
|
dout = mus_in;
|
|
|
|
SDCFG:
|
|
dout = 8'h00; // always SD inserted, SD is in R/W mode
|
|
SDDAT:
|
|
dout = sd_dataout;
|
|
|
|
PORTF7:
|
|
begin
|
|
if (!a[14] && (a[8] ^ dos) && gluclock_on) // $BFF7 - data i/o
|
|
dout = wait_read;
|
|
// dout = 8'h55;
|
|
else // any other $xxF7 port
|
|
dout = 8'hFF;
|
|
end
|
|
|
|
COMPORT:
|
|
begin
|
|
dout = wait_read; // $F8EF..$FFEF
|
|
end
|
|
|
|
default:
|
|
dout = 8'hFF;
|
|
endcase
|
|
end
|
|
|
|
// power-up
|
|
// This bit is loaded as 1 while FPGA is configured and automatically reset to 0 after STATUS port reading
|
|
reg pwr_up = 1'b1;
|
|
always @(posedge clk)
|
|
if (iord_s & (loa == PORTXT) & (hoa == XSTAT))
|
|
begin
|
|
pwr_up_reg <= pwr_up;
|
|
pwr_up <= 1'b0;
|
|
end
|
|
|
|
wire portfe_wr = (loa==PORTFE) && iowr_s;
|
|
assign beeper_wr = portfe_wr;
|
|
assign covox_wr = (loa==COVOX) && iowr_s;
|
|
wire portxt_wr = ((loa==PORTXT) && iowr_s) || regs_we;
|
|
wire portxt_rd = (loa==PORTXT) && iord_s;
|
|
|
|
assign xt_page = {rampage[3], rampage[2], rampage[1], rampage[0]};
|
|
|
|
// writing ports
|
|
assign dmaport_wr[0] = portxt_wr && (hoa == DMASADDRL);
|
|
assign dmaport_wr[1] = portxt_wr && (hoa == DMASADDRH);
|
|
assign dmaport_wr[2] = portxt_wr && (hoa == DMASADDRX);
|
|
assign dmaport_wr[3] = portxt_wr && (hoa == DMADADDRL);
|
|
assign dmaport_wr[4] = portxt_wr && (hoa == DMADADDRH);
|
|
assign dmaport_wr[5] = portxt_wr && (hoa == DMADADDRX);
|
|
assign dmaport_wr[6] = portxt_wr && (hoa == DMALEN);
|
|
assign dmaport_wr[7] = portxt_wr && (hoa == DMACTRL);
|
|
assign dmaport_wr[8] = portxt_wr && (hoa == DMANUM);
|
|
`ifdef FDR
|
|
assign dmaport_wr[9] = portxt_wr && (hoa == DMANUMH);
|
|
`endif
|
|
|
|
assign zborder_wr = portfe_wr;
|
|
assign border_wr = (portxt_wr && (hoa == XBORDER));
|
|
assign zvpage_wr = p7ffd_wr;
|
|
assign vpage_wr = (portxt_wr && (hoa == VPAGE ));
|
|
assign vconf_wr = (portxt_wr && (hoa == VCONF ));
|
|
assign gx_offsl_wr = (portxt_wr && (hoa == GXOFFSL));
|
|
assign gx_offsh_wr = (portxt_wr && (hoa == GXOFFSH));
|
|
assign gy_offsl_wr = (portxt_wr && (hoa == GYOFFSL));
|
|
assign gy_offsh_wr = (portxt_wr && (hoa == GYOFFSH));
|
|
assign t0x_offsl_wr = (portxt_wr && (hoa == T0XOFFSL));
|
|
assign t0x_offsh_wr = (portxt_wr && (hoa == T0XOFFSH));
|
|
assign t0y_offsl_wr = (portxt_wr && (hoa == T0YOFFSL));
|
|
assign t0y_offsh_wr = (portxt_wr && (hoa == T0YOFFSH));
|
|
assign t1x_offsl_wr = (portxt_wr && (hoa == T1XOFFSL));
|
|
assign t1x_offsh_wr = (portxt_wr && (hoa == T1XOFFSH));
|
|
assign t1y_offsl_wr = (portxt_wr && (hoa == T1YOFFSL));
|
|
assign t1y_offsh_wr = (portxt_wr && (hoa == T1YOFFSH));
|
|
assign tsconf_wr = (portxt_wr && (hoa == TSCONF));
|
|
assign palsel_wr = (portxt_wr && (hoa == PALSEL));
|
|
assign tmpage_wr = (portxt_wr && (hoa == TMPAGE));
|
|
assign t0gpage_wr = (portxt_wr && (hoa == T0GPAGE));
|
|
assign t1gpage_wr = (portxt_wr && (hoa == T1GPAGE));
|
|
assign sgpage_wr = (portxt_wr && (hoa == SGPAGE));
|
|
assign hint_beg_wr = (portxt_wr && (hoa == HSINT ));
|
|
assign vint_begl_wr = (portxt_wr && (hoa == VSINTL));
|
|
assign vint_begh_wr = (portxt_wr && (hoa == VSINTH));
|
|
`ifdef FDR
|
|
assign fdr_cnt_lat = (portxt_rd && (hoa == FRCNT0));
|
|
`endif
|
|
|
|
reg m1_lock128;
|
|
|
|
wire lock128_2 = memconf[7:6] == 2'b10; // mode 2
|
|
wire lock128_3 = memconf[7:6] == 2'b11; // mode 3
|
|
wire lock128 = lock128_3 ? 1'b0 : (lock128_2 ? m1_lock128 : memconf[6]);
|
|
|
|
always @(posedge clk) if (opfetch)
|
|
m1_lock128 <= !(din[7] ^ din[6]);
|
|
|
|
always @(posedge clk or posedge rst)
|
|
if (rst)
|
|
begin
|
|
fmaddr[4] <= 1'b0;
|
|
intmask <= 8'b1;
|
|
fddvirt <= 8'b0;
|
|
sysconf <= 8'h00; // 3.5 MHz
|
|
memconf <= 8'h04; // no map
|
|
cacheconf <= 4'h0; // no cache
|
|
|
|
rampage[0] <= 8'h00;
|
|
rampage[1] <= 8'h05;
|
|
rampage[2] <= 8'h02;
|
|
rampage[3] <= 8'h00;
|
|
|
|
`ifdef FDR
|
|
fdr_en <= 1'b0;
|
|
`endif
|
|
end
|
|
else // if (rst)
|
|
begin
|
|
if (p7ffd_wr)
|
|
begin
|
|
memconf[0] <= din[4];
|
|
rampage[3] <= {2'b0, lock128_3 ? {din[5], din[7:6]} : ({1'b0, lock128 ? 2'b0 : din[7:6]}), din[2:0]};
|
|
end
|
|
|
|
else if (portxt_wr)
|
|
begin
|
|
if (hoa[7:2] == RAMPAGE[7:2])
|
|
rampage[hoa[1:0]] <= din;
|
|
|
|
if (hoa == FMADDR)
|
|
fmaddr <= din[4:0];
|
|
|
|
if (hoa == SYSCONF)
|
|
begin
|
|
sysconf <= din;
|
|
cacheconf <= {4{din[2]}};
|
|
end
|
|
|
|
if (hoa == DMAWPD)
|
|
dmawpdev <= din[1:0];
|
|
|
|
if (hoa == CACHECONF)
|
|
cacheconf <= din[3:0];
|
|
|
|
if (hoa == MEMCONF)
|
|
memconf <= din;
|
|
|
|
if (hoa == FDDVIRT)
|
|
fddvirt <= din;
|
|
|
|
`ifdef FDR
|
|
if (hoa == FRCTRL)
|
|
fdr_en <= din[0];
|
|
`endif
|
|
|
|
if (hoa == INTMASK)
|
|
intmask <= din;
|
|
end
|
|
end
|
|
|
|
// 7FFD port
|
|
reg lock48;
|
|
|
|
assign p7ffd_wr = !a[15] && (loa==PORTFD) && iowr_s && !lock48;
|
|
|
|
always @(posedge clk or posedge rst)
|
|
if (rst)
|
|
lock48 <= 1'b0;
|
|
else if (p7ffd_wr && !lock128_3)
|
|
lock48 <= din[5];
|
|
|
|
// AY control
|
|
wire ay_hit = (loa==PORTFD) & a[15];
|
|
assign ay_bc1 = ay_hit & a[14] & iordwr;
|
|
assign ay_bdir = ay_hit & iowr;
|
|
|
|
// VG93
|
|
reg [1:0] drive_sel_raw;
|
|
|
|
wire [3:0] fddvrt = fddvirt[3:0];
|
|
wire virt_vg = fddvrt[drive_sel_raw];
|
|
assign open_vg = fddvirt[7];
|
|
assign drive_sel = {drive_sel_raw[1], drive_sel_raw[0] ^ cfg_floppy_swap};
|
|
|
|
wire vg_wen = (dos || open_vg) && !vdos && !virt_vg;
|
|
assign vg_cs_n = !(iordwr && vg_port && vg_wen);
|
|
assign vg_wrFF = iowr_s && vgsys_port && vg_wen;
|
|
wire vg_wrDS = iowr_s && vgsys_port && (dos || open_vg);
|
|
|
|
assign vdos_on = iordwr_s && (vg_port || vgsys_port) && dos && !vdos && virt_vg;
|
|
assign vdos_off = iordwr_s && vg_port && vdos;
|
|
|
|
// write drive number
|
|
always @(posedge clk)
|
|
if (vg_wrDS)
|
|
drive_sel_raw <= din;
|
|
|
|
// SD card (Z-controller compatible)
|
|
wire sdcfg_wr;
|
|
wire sddat_wr;
|
|
wire sddat_rd;
|
|
|
|
assign sdcfg_wr = (loa==SDCFG) && iowr_s;
|
|
assign sddat_wr = (loa==SDDAT) && iowr_s;
|
|
assign sddat_rd = (loa==SDDAT) && iord_s;
|
|
|
|
// SDCFG write - sdcs_n control
|
|
always @(posedge clk or posedge rst)
|
|
if (rst)
|
|
begin
|
|
spi_cs_n <= 4'b1111;
|
|
spi_mode <= 1'b0;
|
|
end
|
|
else if (sdcfg_wr)
|
|
begin
|
|
spi_cs_n <= {~din[4:2], din[1]};
|
|
// spi_mode <= din[7];
|
|
end
|
|
|
|
// start signal for SPI module with resyncing to fclk
|
|
assign sd_start = sddat_wr || sddat_rd;
|
|
|
|
// data for SPI module
|
|
assign sd_datain = wr ? din : 8'hFF;
|
|
|
|
// xxF7
|
|
wire portf7_wr = ((loa==PORTF7) && (a[8]==1'b1) && port_wr && (!dos || vdos));
|
|
wire portf7_rd = ((loa==PORTF7) && (a[8]==1'b1) && port_rd && (!dos || vdos));
|
|
|
|
// EFF7 port
|
|
reg [7:0] peff7;
|
|
always @(posedge clk or posedge rst)
|
|
if (rst)
|
|
peff7 <= 8'h00;
|
|
else if (!a[12] && portf7_wr && !dos) // #EEF7 in dos is not accessible
|
|
peff7 <= din;
|
|
|
|
// gluclock ports
|
|
assign gluclock_on = peff7[7] || dos; // in dos mode EEF7 is not accessible, gluclock access is ON in dos mode.
|
|
|
|
// comports
|
|
wire comport_wr = ((loa == COMPORT) && port_wr);
|
|
wire comport_rd = ((loa == COMPORT) && port_rd);
|
|
|
|
// write to wait registers
|
|
always @(posedge zclk)
|
|
begin
|
|
// gluclocks
|
|
if (gluclock_on && portf7_wr)
|
|
begin
|
|
if (!a[14]) // $BFF7 - data reg
|
|
wait_write <= din;
|
|
|
|
if (!a[13]) // $DFF7 - addr reg
|
|
wait_addr <= din;
|
|
end
|
|
|
|
// com ports
|
|
if (comport_wr) // $xxEF
|
|
wait_write <= din;
|
|
|
|
if (comport_wr || comport_rd)
|
|
wait_addr <= a[15:8];
|
|
|
|
if (portxt_wr && (hoa == DMAWPA))
|
|
wait_addr <= din;
|
|
end
|
|
|
|
// wait from wait registers
|
|
assign wait_start_gluclock = (gluclock_on && !a[14] && (portf7_rd || portf7_wr)); // $BFF7 - gluclock r/w
|
|
assign wait_start_comport = (comport_rd || comport_wr);
|
|
|
|
`ifdef IDE_HDD
|
|
// IDE ports
|
|
// do NOT generate IDE write, if neither of ide_wrhi|lo latches set and writing to NIDE10
|
|
wire ide_cs0 = ide_even && !ide_portc8;
|
|
wire ide_cs1 = ide_portc8;
|
|
wire ide_rd = rd && !(ide_rd_latch && ide_port10);
|
|
wire ide_wr = wr && !(!ide_wrlo_latch && !ide_wrhi_latch && ide_port10);
|
|
assign ide_req = iorq_s && ide_even && (ide_rd || ide_wr);
|
|
assign ide_cs0_n = !ide_cs0;
|
|
assign ide_cs1_n = !ide_cs1;
|
|
|
|
always @(posedge clk)
|
|
if (ide_req)
|
|
ide_stall <= 1'b1;
|
|
else if (ide_ready)
|
|
ide_stall <= 1'b0;
|
|
|
|
// control read & write triggers, which allow nemo-divide mod to work.
|
|
// read trigger:
|
|
reg ide_rd_trig; // nemo-divide read trigger
|
|
always @(posedge zclk)
|
|
begin
|
|
if (ide_port10 && port_rd && !ide_rd_trig)
|
|
ide_rd_trig <= 1'b1;
|
|
else if (ide_all && (port_rd || port_wr))
|
|
ide_rd_trig <= 1'b0;
|
|
end
|
|
|
|
// two triggers for write sequence
|
|
reg ide_wrlo_trig, ide_wrhi_trig; // nemo-divide write triggers
|
|
always @(posedge zclk)
|
|
if (ide_all && (port_rd || port_wr))
|
|
begin
|
|
if (ide_port11 && port_wr)
|
|
ide_wrhi_trig <= 1'b1;
|
|
else
|
|
ide_wrhi_trig <= 1'b0;
|
|
|
|
if (ide_port10 && port_wr && !ide_wrhi_trig && !ide_wrlo_trig)
|
|
ide_wrlo_trig <= 1'b1;
|
|
else
|
|
ide_wrlo_trig <= 1'b0;
|
|
end
|
|
|
|
// normal read: #10(low), #11(high)
|
|
// divide read: #10(low), #10(high)
|
|
//
|
|
// normal write: #11(high), #10(low)
|
|
// divide write: #10(low), #10(high)
|
|
|
|
reg [15:0] idewrreg; // write register, either low or high part is pre-written here,
|
|
// while other part is out directly from Z80 bus
|
|
always @(posedge zclk)
|
|
begin
|
|
if (port_wr && ide_port11)
|
|
idewrreg[15:8] <= din;
|
|
|
|
if (port_wr && ide_port10 && !ide_wrlo_trig)
|
|
idewrreg[ 7:0] <= din;
|
|
end
|
|
|
|
// generate read cycles for IDE as usual, except for reading #10
|
|
// instead of #11 for high byte (nemo-divide). I use additional latch
|
|
// since 'ide_rd_trig' clears during second Z80 IO read cycle to #10
|
|
reg ide_rd_latch; // to save state of trigger during read cycle
|
|
always @*
|
|
if (!rd)
|
|
ide_rd_latch <= ide_rd_trig;
|
|
|
|
reg ide_wrlo_latch, ide_wrhi_latch; // save state during write cycles
|
|
always @*
|
|
if (!wr)
|
|
begin
|
|
ide_wrlo_latch <= ide_wrlo_trig; // same for write triggers
|
|
ide_wrhi_latch <= ide_wrhi_trig;
|
|
end
|
|
|
|
// data read by Z80 from IDE
|
|
wire idein_lo_rd = port_rd && ide_port10 && (!ide_rd_trig); // while high part is remembered here
|
|
wire [7:0] iderdodd = iderdreg[15:8]; // read data from "odd" port (#11)
|
|
wire [7:0] iderdeven = (ide_rd_latch && ide_port10) ? iderdreg[15:8] : iderdreg[7:0]; // to control read data from "even" ide ports (all except #11)
|
|
// wire [7:0] iderdeven = (ide_rd_latch && ide_port10) ? idehiin[7:0] : ide_in[7:0]; // to control read data from "even" ide ports (all except #11)
|
|
|
|
reg [15:0] iderdreg;
|
|
// reg [7:0] idehiin; // IDE high part read register: low part is read directly to Z80 bus,
|
|
always @(posedge clk)
|
|
if (ide_stb)
|
|
iderdreg <= ide_in;
|
|
// if (idein_lo_rd)
|
|
// idehiin <= ide_in[15:8];
|
|
|
|
// data written to IDE from Z80
|
|
wire [7:0] ideout1 = ide_wrhi_latch ? idewrreg[15:8] : din[ 7:0];
|
|
wire [7:0] ideout0 = ide_wrlo_latch ? idewrreg[ 7:0] : din[ 7:0];
|
|
assign ide_out = {ideout1, ideout0};
|
|
`endif
|
|
|
|
endmodule
|