Blame | Last modification | View Log | Download | RSS feed
`include "../include/tune.v"module zports(input clk, // z80 clockinput fclk, // global FPGA clockinput rst_n, // system resetinput [7:0] din,output reg [7:0] dout,output dataout,input [15:0] a,input iorq_n,input mreq_n,input m1_n,input rd_n,input wr_n,output reg porthit, // when internal port hit occurs, this is 1, else 0; used for iorq1_n iorq2_n on zxbusoutput reg [15:0] ideout,input [15:0] idein,output idedataout, // IDE must IN data from IDE device when idedataout=0, else it OUTsoutput [2:0] ide_a,output ide_cs0_n,output ide_cs1_n,output ide_rd_n,output ide_wr_n,input [4:0] keys_in, // keys (port FE)input [7:0] mus_in, // mouse (xxDF)input [4:0] kj_in,output reg [2:0] border,output reg beep,output reg dos,output ay_bdir,output ay_bc1,output [7:0] p7ffd,output [7:0] p1ffd,output [7:0] peff7,input [1:0] rstrom,input wire tape_read,output reg [ 2:0] comport_addr,output vg_cs_n,input vg_intrq,vg_drq, // from vg93 module - drq + irq readoutput vg_wrFF, // write strobe of #FF portoutput reg sdcs_n,output sd_start,output [7:0] sd_datain,input [7:0] sd_dataout,output reg [ 7:0] gluclock_addr,output wire wait_start_gluclock, // begin wait from some portsoutput wire wait_start_comport, //output reg wait_rnw, // whether it was read(=1) or write(=0)output reg [ 7:0] wait_write,input wire [ 7:0] wait_read,input nmi_key, // input from keyboard, positive!!!output reg nmi_out, // output to CPU, positive!!!output reg turbo, // turbo switchinput turbo_key,input noturbo_key);reg rstsync1,rstsync2;localparam PORTFE = 8'hFE;localparam PORTF7 = 8'hF7;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 NIDEC8 = 8'hC8;localparam PORTFD = 8'hFD;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 SDCFG2 = 8'h08;localparam SDDAT2 = 8'h28;localparam COMPORT = 8'hEF; // F8EF..FFEF - rs232 portsreg external_port;reg port_wr;reg port_rd;reg iowr_reg;reg iord_reg;wire [7:0] loa;wire portfe_wr;wire ideout_hi_wr;wire idein_lo_rd;reg [7:0] idehiin;reg ide_ports; // ide ports selectedreg pre_bc1,pre_bdir;wire gluclock_on;assign loa=a[7:0];always @*beginif( (loa==PORTFE) || (loa==PORTFD) || (loa==PORTF7) || (loa==NIDE10) || (loa==NIDE11) || (loa==NIDE30) ||(loa==NIDE50) || (loa==NIDE70) || (loa==NIDE90) || (loa==NIDEB0) || (loa==NIDED0) || (loa==NIDEF0) ||(loa==NIDEC8) ||( (loa==VGCOM)&&dos ) || ( (loa==VGTRK)&&dos ) || ( (loa==VGSEC)&&dos ) || ( (loa==VGDAT)&&dos ) ||( (loa==VGSYS)&&dos ) || ( (loa==KJOY)&&(!dos) ) ||(loa==KMOUSE) || (loa==SDCFG) || (loa==SDDAT) || (loa==SDCFG2) || (loa==SDDAT2) || ( loa==COMPORT ))porthit = 1'b1;elseporthit = 1'b0;endalways @*beginif( ((loa==PORTFD) && (a[15:14]==2'b11)) || // 0xFFFD ports(( (loa==VGCOM)&&dos ) || ( (loa==VGTRK)&&dos ) || ( (loa==VGSEC)&&dos ) || ( (loa==VGDAT)&&dos )) ) // vg93 portsexternal_port = 1'b1;elseexternal_port = 1'b0;endassign dataout = porthit & (~iorq_n) & (~rd_n) & (~external_port);always @(posedge clk)beginiowr_reg <= ~(iorq_n | wr_n);iord_reg <= ~(iorq_n | rd_n);if( (!iowr_reg) && (!iorq_n) && (!wr_n) )port_wr <= 1'b1;elseport_wr <= 1'b0;if( (!iord_reg) && (!iorq_n) && (!rd_n) )port_rd <= 1'b1;elseport_rd <= 1'b0;end// dout dataalways @*begincase( loa )PORTFE:dout = { 1'b1, tape_read, 1'b1, keys_in };NIDE10,NIDE30,NIDE50,NIDE70,NIDE90,NIDEB0,NIDED0,NIDEF0,NIDEC8:dout = idein[7:0];NIDE11:dout = idehiin;//PORTFD:VGSYS:dout = { vg_intrq, vg_drq, 6'b111111 };KJOY:dout = {vg_intrq,vg_drq,1'b0, kj_in}; //3'b000KMOUSE:dout = mus_in;SDCFG,SDCFG2:dout = 8'h00; // always SD inserted, SD is on R/W mode // FIXME!FIXME!FIXME!FIXME!FIXME!SDDAT,SDDAT2:dout = sd_dataout;PORTF7: beginif( !a[14] && gluclock_on ) // $BFF7 - data i/odout = wait_read;else // any other $xxF7 portdout = 8'hFF;endCOMPORT: begindout = wait_read; // $F8EF..$FFEFenddefault:dout = 8'hFF;endcaseendassign portfe_wr = ( (loa==PORTFE) && port_wr);assign portfd_wr = ( (loa==PORTFD) && port_wr);assign portfd_rd = ( (loa==PORTFD) && port_rd);assign portf7_wr = ( (loa==PORTF7) && port_wr);assign portf7_rd = ( (loa==PORTF7) && port_rd);assign ideout_hi_wr = ( (loa==NIDE11) && port_wr);assign idein_lo_rd = ( (loa==NIDE10) && port_rd);assign vg_wrFF = ( ( (loa==VGSYS)&&dos ) && port_wr);assign comport_wr = ( (loa==COMPORT) && port_wr);assign comport_rd = ( (loa==COMPORT) && port_rd);//port FE beep/border bitalways @(posedge clk)beginif( portfe_wr )beginbeep <= din[4];border <= din[2:0];endend// IDE portsalways @*ideout[7:0] = din;always @(posedge clk)beginif( ideout_hi_wr )ideout[15:8] <= din;if( idein_lo_rd )idehiin <= idein[15:8];endalways @*case( loa )NIDE10,NIDE30,NIDE50,NIDE70,NIDE90,NIDEB0,NIDED0,NIDEF0,NIDEC8: ide_ports = 1'b1;default: ide_ports = 1'b0;endcaseassign ide_a = a[7:5];// trying to fix old WD drives...// assign ide_cs0_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa!=NIDEC8));// assign ide_cs1_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa==NIDEC8));assign ide_cs0_n = (~ide_ports) | (~(loa!=NIDEC8));assign ide_cs1_n = (~ide_ports) | (~(loa==NIDEC8));// fix ends...assign ide_rd_n = iorq_n | rd_n | (~ide_ports);assign ide_wr_n = iorq_n | wr_n | (~ide_ports);assign idedataout = ide_rd_n;// AY controlalways @*beginpre_bc1 = 1'b0;pre_bdir = 1'b0;if( loa==PORTFD )beginif( a[15:14]==2'b11 )beginpre_bc1=1'b1;pre_bdir=1'b1;endelse if( a[15:14]==2'b10 )beginpre_bc1=1'b0;pre_bdir=1'b1;endendendassign ay_bc1 = pre_bc1 & (~iorq_n) & ((~rd_n)|(~wr_n));assign ay_bdir = pre_bdir & (~iorq_n) & (~wr_n);reg [7:0] p7ffd_int,p1ffd_int,pdffd_int,peff7_int;reg p7ffd_rom_int;wire block7ffd;wire block1m;always @(posedge clk, negedge rst_n) // 7FFDbeginif( !rst_n )p7ffd_int <= 7'h00;else if( (a[15:12]==4'b0111) && portfd_wr && (!block7ffd) )p7ffd_int <= din; // 2..0 - page, 3 - screen, 4 - rom, 5 - block48k, 6..7 - ram extension (alternative)endalways @(posedge clk, negedge rst_n) // 1FFDbeginif( !rst_n )p1ffd_int <= 7'h00;else if( (a[15:12]==4'b0001) && portfd_wr)p1ffd_int <= din; // 0 - ram on 0000-3fff, 1 - shadow monitor, 4 - ram ppage 8..15, 5 - strobe CENTRONIX, 6..7 - ram extensionendalways@(posedge turbo_key, posedge portfd_rd) // turbo switchbeginif (turbo_key)turbo <= (~turbo);elsebeginif ((a[15:8]==8'b00011111) && portfd_rd)turbo <= 1'b0;if ((a[15:8]==8'b01111111) && portfd_rd)turbo <= 1'b1;endendassign block7ffd=p7ffd_int[5];// EFF7 portalways @(posedge clk, negedge rst_n) // EFF7beginif( !rst_n )peff7_int <= 8'h00;else if(!a[12] && portf7_wr )peff7_int <= din; // 0 - p16c onendassign p7ffd = { p7ffd_int};assign p1ffd = { p1ffd_int};assign peff7 = ( peff7_int);// gluclock ports (bit7:eff7 is above)assign gluclock_on = peff7_int[7];always @(posedge clk)beginif( gluclock_on && portf7_wr ) // gluclocks onbeginif( !a[13] ) // $DFF7 - addr reggluclock_addr <= din;// write to waiting register is not here - in separate section managing wait_writeendend// comportsalways @(posedge clk)beginif( comport_wr || comport_rd )comport_addr <= a[10:8 ];end// write to wait registersalways @(posedge clk)begin// gluclocksif( gluclock_on && portf7_wr && !a[14] ) // $BFF7 - data regwait_write <= din;// com portselse if( comport_wr ) // $F8EF..$FFEF - comportswait_write <= din;end// wait from wait registersassign wait_start_gluclock = ( gluclock_on && !a[14] && (portf7_rd || portf7_wr) ); // $BFF7 - gluclock r/wassign wait_start_comport = ( comport_rd || comport_wr );always @(posedge clk) // wait rnw - only meanful during waitbeginif( port_wr )wait_rnw <= 1'b0;if( port_rd )wait_rnw <= 1'b1;end// VG93 controlassign vg_cs_n = (~dos) | iorq_n | (rd_n & wr_n) | ( ~((loa==VGCOM)|(loa==VGTRK)|(loa==VGSEC)|(loa==VGDAT)) );always @(posedge clk) // DOSbeginif( rstsync2 )dos <= 1'b0; //~rstrom[1]else if( (!mreq_n) && (!m1_n) )beginif(( (a[15:8]==8'h3D) && p7ffd[4] ) | (nmi_out))dos <= 1'b1;else if( a[15:14]!=2'b00 )dos <= 1'b0;endendassign ramm1=(mreq_n | m1_n);always@(posedge ramm1) // NMIbeginif (!(mreq_n) && !(rd_n) && !(a[15:14]))nmi_out <= 1'b0;elsenmi_out <= nmi_key;end// reset rom selectionalways @(posedge clk)beginrstsync1<=~rst_n;rstsync2<=rstsync1;end// SD card (z-control?r compatible)wire sdcfg_wr,sddat_wr,sddat_rd;assign sdcfg_wr = ( ((loa==SDCFG) || (loa==SDCFG2)) && port_wr);assign sddat_wr = ( ((loa==SDDAT) || (loa==SDDAT2)) && port_wr);assign sddat_rd = ( ((loa==SDDAT) || (loa==SDDAT2)) && port_rd);// SDCFG write - sdcs_n controlalways @(posedge clk, negedge rst_n)beginif( !rst_n )sdcs_n <= 1'b1;else // posedge clkif( sdcfg_wr )sdcs_n <= din[1];end// start signal for SPI module with resyncing to fclkreg sd_start_toggle;reg [2:0] sd_stgl;// Z80 clockalways @(posedge clk)if( sddat_wr || sddat_rd )sd_start_toggle <= ~sd_start_toggle;// FPGA clockalways @(posedge fclk)sd_stgl[2:0] <= { sd_stgl[1:0], sd_start_toggle };assign sd_start = ( sd_stgl[1] != sd_stgl[2] );// data for SPI moduleassign sd_datain = wr_n ? 8'hFF : din;endmodule