Subversion Repositories pentevo

Rev

Rev 471 | Rev 543 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // PentEvo project (c) NedoPC 2008-2010
  2. //
  3. // most of pentevo ports are here
  4.  
  5. `include "../include/tune.v"
  6.  
  7. module zports(
  8.  
  9.         input  wire        zclk,   // z80 clock
  10.         input  wire        fclk,  // global FPGA clock
  11.         input  wire        rst_n, // system reset
  12.  
  13.         input  wire        zpos,
  14.         input  wire        zneg,
  15.  
  16.  
  17.         input  wire [ 7:0] din,
  18.         output reg  [ 7:0] dout,
  19.         output wire        dataout,
  20.         input  wire [15:0] a,
  21.  
  22.         input  wire        iorq_n,
  23.         input  wire        mreq_n,
  24.         input  wire        m1_n,
  25.         input  wire        rd_n,
  26.         input  wire        wr_n,
  27.  
  28.         output reg         porthit, // when internal port hit occurs, this is 1, else 0; used for iorq1_n iorq2_n on zxbus
  29.         output reg         external_port, // asserts for AY and VG93 accesses
  30.  
  31.         output wire [15:0] ideout,
  32.         input  wire [15:0] idein,
  33.         output wire        idedataout, // IDE must IN data from IDE device when idedataout=0, else it OUTs
  34.         output wire [ 2:0] ide_a,
  35.         output wire        ide_cs0_n,
  36.         output wire        ide_cs1_n,
  37.         output wire        ide_rd_n,
  38.         output wire        ide_wr_n,
  39.  
  40.  
  41.         input  wire [ 4:0] keys_in, // keys (port FE)
  42.         input  wire [ 7:0] mus_in,  // mouse (xxDF)
  43.         input  wire [ 4:0] kj_in,
  44.  
  45.         output reg  [ 3:0] border,
  46.  
  47.  
  48.         input  wire        dos,
  49.  
  50.  
  51.         output wire        ay_bdir,
  52.         output wire        ay_bc1,
  53.  
  54.         output wire [ 7:0] p7ffd,
  55.         output wire [ 7:0] peff7,
  56.  
  57.         input  wire [ 1:0] rstrom,
  58.  
  59.         input  wire        tape_read,
  60.  
  61.         output wire        vg_cs_n,
  62.         input  wire        vg_intrq,
  63.         input  wire        vg_drq, // from vg93 module - drq + irq read
  64.         output wire        vg_wrFF,        // write strobe of #FF port
  65.  
  66.         output reg         sdcs_n,
  67.         output wire        sd_start,
  68.         output wire [ 7:0] sd_datain,
  69.         input  wire [ 7:0] sd_dataout,
  70.  
  71.         // WAIT-ports related
  72.         //
  73.         output reg  [ 7:0] gluclock_addr,
  74.         //
  75.         output reg  [ 2:0] comport_addr,
  76.         //
  77.         output wire        wait_start_gluclock, // begin wait from some ports
  78.         output wire        wait_start_comport,  //
  79.         //
  80.         output reg         wait_rnw,   // whether it was read(=1) or write(=0)
  81.         output reg  [ 7:0] wait_write,
  82.         input  wire [ 7:0] wait_read,
  83.  
  84.  
  85.         output wire        atmF7_wr_fclk, // used in atm_pager.v
  86.  
  87.  
  88.         output reg  [ 2:0] atm_scr_mode, // RG0..RG2 in docs
  89.         output reg         atm_turbo,    // turbo mode ON
  90.         output reg         atm_pen,      // pager_off in atm_pager.v, NOT inverted!!!
  91.         output reg         atm_cpm_n,    // permanent dos on
  92.         output reg         atm_pen2,     // PEN2 - fucking palette mode, NOT inverted!!!
  93.  
  94.         output wire        romrw_en, // from port BF
  95.  
  96.  
  97.         output wire        pent1m_ram0_0, // d3.eff7
  98.         output wire        pent1m_1m_on,  // d2.eff7
  99.         output wire [ 5:0] pent1m_page,   // full 1 meg page number
  100.         output wire        pent1m_ROM,     // d4.7ffd
  101.  
  102.  
  103.         output wire        atm_palwr,   // palette write strobe
  104.         output wire [ 5:0] atm_paldata, // palette write data
  105.  
  106.         output wire        covox_wr,
  107.         output wire        beeper_wr,
  108.  
  109.         output wire        clr_nmi,
  110.  
  111.         output wire        fnt_wr,              // write to font_ram enabled
  112.  
  113.         // inputs from atm_pagers, to read back its config
  114.         input  wire [63:0] pages,
  115.         input  wire [ 7:0] ramnroms,
  116.         input  wire [ 7:0] dos7ffds,
  117.  
  118.         input  wire [ 5:0] palcolor,
  119.  
  120.  
  121.         // NMI generation
  122.         output reg         set_nmi
  123. );
  124.  
  125.  
  126.         reg rstsync1,rstsync2;
  127.  
  128.  
  129.         localparam PORTFE = 8'hFE;
  130.         localparam PORTF6 = 8'hF6;
  131.         localparam PORTF7 = 8'hF7;
  132.  
  133.         localparam NIDE10 = 8'h10;
  134.         localparam NIDE11 = 8'h11;
  135.         localparam NIDE30 = 8'h30;
  136.         localparam NIDE50 = 8'h50;
  137.         localparam NIDE70 = 8'h70;
  138.         localparam NIDE90 = 8'h90;
  139.         localparam NIDEB0 = 8'hB0;
  140.         localparam NIDED0 = 8'hD0;
  141.         localparam NIDEF0 = 8'hF0;
  142.         localparam NIDEC8 = 8'hC8;
  143.  
  144.         localparam PORTFD = 8'hFD;
  145.  
  146.         localparam VGCOM  = 8'h1F;
  147.         localparam VGTRK  = 8'h3F;
  148.         localparam VGSEC  = 8'h5F;
  149.         localparam VGDAT  = 8'h7F;
  150.         localparam VGSYS  = 8'hFF;
  151.  
  152.         localparam SAVPORT1 = 8'h2F;
  153.         localparam SAVPORT2 = 8'h4F;
  154.         localparam SAVPORT3 = 8'h6F;
  155.         localparam SAVPORT4 = 8'h8F;
  156.  
  157.         localparam KJOY   = 8'h1F;
  158.         localparam KMOUSE = 8'hDF;
  159.  
  160.         localparam SDCFG  = 8'h77;
  161.         localparam SDDAT  = 8'h57;
  162.  
  163.         localparam ATMF7  = 8'hF7;
  164.         localparam ATM77  = 8'h77;
  165.  
  166.         localparam ZXEVBE = 8'hBE; // xxBE config-read and nmi-end port
  167.         localparam ZXEVBF = 8'hBF; // xxBF config port
  168.  
  169.         localparam COMPORT = 8'hEF; // F8EF..FFEF - rs232 ports
  170.  
  171.  
  172.         localparam COVOX   = 8'hFB;
  173.  
  174.  
  175.  
  176.  
  177.         reg port_wr;
  178.         reg port_rd;
  179.  
  180.         reg iowr_reg;
  181.         reg iord_reg;
  182.  
  183.  
  184.         reg port_wr_fclk,
  185.             port_rd_fclk,
  186.             mem_wr_fclk;
  187.  
  188.         reg [1:0] iowr_reg_fclk,
  189.                   iord_reg_fclk;
  190.  
  191.         reg [1:0] memwr_reg_fclk;
  192.  
  193.  
  194.         wire [7:0] loa;
  195.  
  196.         wire portfe_wr;
  197.  
  198.  
  199.  
  200.         wire ideout_hi_wr;
  201.         wire idein_lo_rd;
  202.         reg [7:0] idehiin; // IDE high part read register: low part is read directly to Z80 bus,
  203.                            // while high part is remembered here
  204.         reg ide_ports; // ide ports selected
  205.  
  206.         reg ide_rd_trig; // nemo-divide read trigger
  207.         reg ide_rd_latch; // to save state of trigger during read cycle
  208.  
  209.         reg ide_wrlo_trig,  ide_wrhi_trig;  // nemo-divide write triggers
  210.         reg ide_wrlo_latch, ide_wrhi_latch; // save state during write cycles
  211.  
  212.  
  213.  
  214.         reg  [15:0] idewrreg; // write register, either low or high part is pre-written here,
  215.                               // while other part is out directly from Z80 bus
  216.  
  217.         wire [ 7:0] iderdeven; // to control read data from "even" ide ports (all except #11)
  218.         wire [ 7:0] iderdodd;  // read data from "odd" port (#11)
  219.  
  220.  
  221.  
  222.         reg pre_bc1,pre_bdir;
  223.  
  224.         wire gluclock_on;
  225.  
  226.  
  227.  
  228.         reg  shadow_en_reg; //bit0.xxBF
  229.         reg   romrw_en_reg; //bit1.xxBF
  230.         reg  fntw_en_reg;       //bit2.xxBF
  231.  
  232.         wire shadow;
  233.  
  234.  
  235.  
  236.         reg [7:0] portbemux;
  237.  
  238.  
  239.  
  240.         reg [7:0] savport [3:0];
  241.  
  242.  
  243.  
  244.  
  245.  
  246.         assign shadow = dos || shadow_en_reg;
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.         assign loa=a[7:0];
  254.  
  255.         always @*
  256.         begin
  257.                 if( (loa==PORTFE) || (loa==PORTF6) ||
  258.                     (loa==PORTFD) ||
  259.  
  260.                     (loa==NIDE10) || (loa==NIDE11) || (loa==NIDE30) || (loa==NIDE50) || (loa==NIDE70) ||
  261.                     (loa==NIDE90) || (loa==NIDEB0) || (loa==NIDED0) || (loa==NIDEF0) || (loa==NIDEC8) ||
  262.  
  263.                     (loa==KMOUSE) ||
  264.  
  265.                     ( (loa==VGCOM)&&shadow ) || ( (loa==VGTRK)&&shadow ) || ( (loa==VGSEC)&&shadow ) || ( (loa==VGDAT)&&shadow ) ||
  266.                     ( (loa==VGSYS)&&shadow ) || ( (loa==KJOY)&&(!shadow) ) ||
  267.  
  268.                     ( (loa==SAVPORT1)&&shadow ) || ( (loa==SAVPORT2)&&shadow ) ||
  269.                     ( (loa==SAVPORT3)&&shadow ) || ( (loa==SAVPORT4)&&shadow ) ||
  270.  
  271.  
  272.                     ( (loa==PORTF7)&&(!shadow) ) || ( (loa==SDCFG)&&(!shadow) ) || ( (loa==SDDAT) ) ||
  273.  
  274.                     ( (loa==ATMF7)&&shadow ) || ( (loa==ATM77)&&shadow ) ||
  275.  
  276.                     ( loa==ZXEVBF ) || ( loa==ZXEVBE) || ( loa==COMPORT )
  277.                   )
  278.  
  279.  
  280.  
  281.                         porthit = 1'b1;
  282.                 else
  283.                         porthit = 1'b0;
  284.         end
  285.  
  286.         always @*
  287.         begin
  288.                 if( ((loa==PORTFD) && (a[15:14]==2'b11)) || // 0xFFFD ports
  289.                     (( (loa==VGCOM)&&shadow ) || ( (loa==VGTRK)&&shadow ) || ( (loa==VGSEC)&&shadow ) || ( (loa==VGDAT)&&shadow )) ) // vg93 ports
  290.                         external_port = 1'b1;
  291.                 else
  292.                         external_port = 1'b0;
  293.         end
  294.  
  295.         assign dataout = porthit & (~iorq_n) & (~rd_n) & (~external_port);
  296.  
  297.  
  298.  
  299.         // this is zclk-synchronous strobes
  300.         always @(posedge zclk)
  301.         begin
  302.                 iowr_reg <= ~(iorq_n | wr_n);
  303.                 iord_reg <= ~(iorq_n | rd_n);
  304.  
  305.                 if( (!iowr_reg) && (!iorq_n) && (!wr_n) )
  306.                         port_wr <= 1'b1;
  307.                 else
  308.                         port_wr <= 1'b0;
  309.  
  310.  
  311.                 if( (!iord_reg) && (!iorq_n) && (!rd_n) )
  312.                         port_rd <= 1'b1;
  313.                 else
  314.                         port_rd <= 1'b0;
  315.         end
  316.  
  317.  
  318.  
  319.  
  320.         // fclk-synchronous stobes
  321.         //
  322.         always @(posedge fclk) if( zpos )
  323.         begin
  324.                 iowr_reg_fclk[0] <= ~(iorq_n | wr_n);
  325.                 iord_reg_fclk[0] <= ~(iorq_n | rd_n);
  326.         end
  327.  
  328.         always @(posedge fclk)
  329.         begin
  330.                 iowr_reg_fclk[1] <= iowr_reg_fclk[0];
  331.                 iord_reg_fclk[1] <= iord_reg_fclk[0];
  332.         end
  333.  
  334.         always @(posedge fclk)
  335.         begin
  336.                 port_wr_fclk <= iowr_reg_fclk[0] && (!iowr_reg_fclk[1]);
  337.                 port_rd_fclk <= iord_reg_fclk[0] && (!iord_reg_fclk[1]);
  338.         end
  339.  
  340.         always @(posedge fclk)
  341.                 memwr_reg_fclk[1:0] <= { memwr_reg_fclk[0], ~(mreq_n | wr_n) };
  342.  
  343.         always @(posedge fclk)
  344.                 mem_wr_fclk <= memwr_reg_fclk[0] && (!memwr_reg_fclk[1]);
  345.  
  346.  
  347.  
  348.         // dout data
  349.         always @*
  350.         begin
  351.                 case( loa )
  352.                 PORTFE:
  353.                         dout = { 1'b1, tape_read, 1'b0, keys_in };
  354.                 PORTF6:
  355.                         dout = { 1'b1, tape_read, 1'b0, keys_in };
  356.  
  357.  
  358.                 NIDE10,NIDE30,NIDE50,NIDE70,NIDE90,NIDEB0,NIDED0,NIDEF0,NIDEC8:
  359.                         dout = iderdeven;
  360.                 NIDE11:
  361.                         dout = iderdodd;
  362.  
  363.  
  364.                 //PORTFD:
  365.  
  366.                 VGSYS:
  367.                         dout = { vg_intrq, vg_drq, 6'b111111 };
  368.  
  369.                 SAVPORT1, SAVPORT2, SAVPORT3, SAVPORT4:
  370.                         dout = savport[ loa[6:5] ];
  371.  
  372.  
  373.                 KJOY:
  374.                         dout = {3'b000, kj_in};
  375.                 KMOUSE:
  376.                         dout = mus_in;
  377.  
  378.                 SDCFG:
  379.                         dout = 8'h00; // always SD inserted, SD is in R/W mode
  380.                 SDDAT:
  381.                         dout = sd_dataout;
  382.  
  383.  
  384.                 PORTF7: begin
  385.                         if( !a[14] && (a[8]^shadow) && gluclock_on ) // $BFF7 - data i/o
  386.                                 dout = wait_read;
  387.                         else // any other $xxF7 port
  388.                                 dout = 8'hFF;
  389.                 end
  390.  
  391.                 COMPORT: begin
  392.                         dout = wait_read; // $F8EF..$FFEF
  393.                 end
  394.  
  395.                 ZXEVBF: begin
  396.                         dout = { 4'b0000, set_nmi, fntw_en_reg, romrw_en_reg, shadow_en_reg };
  397.                 end
  398.  
  399.                 ZXEVBE: begin
  400.                         dout = portbemux;
  401.                 end
  402.  
  403.  
  404.                 default:
  405.                         dout = 8'hFF;
  406.                 endcase
  407.         end
  408.  
  409.  
  410.  
  411.         assign portfe_wr    = (((loa==PORTFE) || (loa==PORTF6)) && port_wr);
  412.         assign portfd_wr    = ( (loa==PORTFD) && port_wr);
  413.  
  414.         // F7 ports (like EFF7) are accessible in shadow mode but at addresses like EEF7, DEF7, BEF7 so that
  415.         // there are no conflicts in shadow mode with ATM xFF7 and x7F7 ports
  416.         assign portf7_wr    = ( (loa==PORTF7) && (a[8]==1'b1) && port_wr && (!shadow) ) ||
  417.                               ( (loa==PORTF7) && (a[8]==1'b0) && port_wr &&   shadow  ) ;
  418.  
  419.         assign portf7_rd    = ( (loa==PORTF7) && (a[8]==1'b1) && port_rd && (!shadow) ) ||
  420.                               ( (loa==PORTF7) && (a[8]==1'b0) && port_rd &&   shadow  ) ;
  421.  
  422.         assign vg_wrFF = ( ( (loa==VGSYS)&&shadow ) && port_wr);
  423.  
  424.         assign comport_wr   = ( (loa==COMPORT) && port_wr);
  425.         assign comport_rd   = ( (loa==COMPORT) && port_rd);
  426.  
  427.  
  428.  
  429.         //border port FE
  430.         wire portwe_wr_fclk;
  431.  
  432.         assign portfe_wr_fclk = (((loa==PORTFE) || (loa==PORTF6)) && port_wr_fclk);
  433.  
  434.         always @(posedge fclk)
  435.         if( portfe_wr_fclk )
  436.                 border <= { ~a[3], din[2:0] };
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.         // IDE ports
  444.  
  445.         // IDE physical ports (that go to IDE device)
  446.         always @(loa)
  447.                 case( loa )
  448.                 NIDE10,NIDE30,NIDE50,NIDE70,NIDE90,NIDEB0,NIDED0,NIDEF0,NIDEC8: ide_ports = 1'b1;
  449.                 default: ide_ports = 1'b0;
  450.                 endcase
  451.  
  452.  
  453.         assign idein_lo_rd  = port_rd && (loa==NIDE10) && (!ide_rd_trig);
  454.  
  455.         // control read & write triggers, which allow nemo-divide mod to work.
  456.         //
  457.         // read trigger:
  458.         always @(posedge zclk)
  459.         begin
  460.                 if( (loa==NIDE10) && port_rd && !ide_rd_trig )
  461.                         ide_rd_trig <= 1'b1;
  462.                 else if( ( ide_ports || (loa==NIDE11) ) && ( port_rd || port_wr ) )
  463.                         ide_rd_trig <= 1'b0;
  464.         end
  465.         //
  466.         // two triggers for write sequence...
  467.         always @(posedge zclk)
  468.         if( ( ide_ports || (loa==NIDE11) ) && ( port_rd || port_wr ) )
  469.         begin
  470.                 if( (loa==NIDE11) && port_wr )
  471.                         ide_wrhi_trig <= 1'b1;
  472.                 else
  473.                         ide_wrhi_trig <= 1'b0;
  474.                 //
  475.                 if( (loa==NIDE10) && port_wr && !ide_wrhi_trig && !ide_wrlo_trig )
  476.                         ide_wrlo_trig <= 1'b1;
  477.                 else
  478.                         ide_wrlo_trig <= 1'b0;
  479.         end
  480.  
  481.         // normal read: #10(low), #11(high)
  482.         // divide read: #10(low), #10(high)
  483.         //
  484.         // normal write: #11(high), #10(low)
  485.         // divide write: #10(low),  #10(high)
  486.  
  487.  
  488.         always @(posedge zclk)
  489.         begin
  490.                 if( port_wr && (loa==NIDE11) )
  491.                         idewrreg[15:8] <= din;
  492.  
  493.                 if( port_wr && (loa==NIDE10) && !ide_wrlo_trig )
  494.                         idewrreg[ 7:0] <= din;
  495.         end
  496.  
  497.  
  498.  
  499.  
  500.         always @(posedge zclk)
  501.         if( idein_lo_rd )
  502.                         idehiin <= idein[15:8];
  503.  
  504.  
  505.         assign ide_a = a[7:5];
  506.  
  507.  
  508.         // This is unknown shit... Probably need more testing with old WD
  509.         // drives WITHOUT this commented fix.
  510.         //
  511.         // trying to fix old WD drives...
  512.         //assign ide_cs0_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa!=NIDEC8));
  513.         //assign ide_cs1_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa==NIDEC8));
  514.         // fix ends...
  515.  
  516.  
  517.         assign ide_cs0_n = (~ide_ports) | (~(loa!=NIDEC8));
  518.         assign ide_cs1_n = (~ide_ports) | (~(loa==NIDEC8));
  519.  
  520.  
  521.         // generate read cycles for IDE as usual, except for reading #10
  522.         // instead of #11 for high byte (nemo-divide). I use additional latch
  523.         // since 'ide_rd_trig' clears during second Z80 IO read cycle to #10
  524.         always @* if( rd_n ) ide_rd_latch <= ide_rd_trig;
  525.         //
  526.         assign ide_rd_n = iorq_n | rd_n | (~ide_ports) | (ide_rd_latch && (loa==NIDE10));
  527.  
  528.         always @* if( wr_n ) ide_wrlo_latch <= ide_wrlo_trig; // same for write triggers
  529.         always @* if( wr_n ) ide_wrhi_latch <= ide_wrhi_trig; //
  530.         //
  531.         assign ide_wr_n = iorq_n | wr_n | (~ide_ports) | ( (loa==NIDE10) && !ide_wrlo_latch && !ide_wrhi_latch );
  532.                                                   // do NOT generate IDE write, if neither of ide_wrhi|lo latches
  533.                                                   // set and writing to NIDE10
  534.  
  535.  
  536.  
  537.         assign idedataout = ide_rd_n;
  538.  
  539.  
  540.  
  541.         // data read by Z80 from IDE
  542.         //
  543.         assign iderdodd[ 7:0] = idehiin[ 7:0];
  544.         //
  545.         assign iderdeven[ 7:0] = (ide_rd_latch && (loa==NIDE10)) ? idehiin[ 7:0] : idein[ 7:0];
  546.  
  547.         // data written to IDE from Z80
  548.         //
  549.         assign ideout[15:8] = ide_wrhi_latch ? idewrreg[15:8] : din[ 7:0];
  550.         assign ideout[ 7:0] = ide_wrlo_latch ? idewrreg[ 7:0] : din[ 7:0];
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.         // AY control
  559.         always @*
  560.         begin
  561.                 pre_bc1 = 1'b0;
  562.                 pre_bdir = 1'b0;
  563.  
  564.                 if( loa==PORTFD )
  565.                 begin
  566.                         if( a[15:14]==2'b11 )
  567.                         begin
  568.                                 pre_bc1=1'b1;
  569.                                 pre_bdir=1'b1;
  570.                         end
  571.                         else if( a[15:14]==2'b10 )
  572.                         begin
  573.                                 pre_bc1=1'b0;
  574.                                 pre_bdir=1'b1;
  575.                         end
  576.                 end
  577.         end
  578.  
  579.         assign ay_bc1  = pre_bc1  & (~iorq_n) & ((~rd_n)|(~wr_n));
  580.         assign ay_bdir = pre_bdir & (~iorq_n) & (~wr_n);
  581.  
  582.  
  583.  
  584.         // 7FFD port
  585.         reg [7:0] p7ffd_int,peff7_int;
  586.         reg p7ffd_rom_int;
  587.         wire block7ffd;
  588.         wire block1m;
  589.  
  590.         always @(posedge zclk, negedge rst_n)
  591.         begin
  592.                 if( !rst_n )
  593.                         p7ffd_int <= 7'h00;
  594.                 else if( (a[15]==1'b0) && portfd_wr && (!block7ffd) )
  595.                         p7ffd_int <= din; // 2..0 - page, 3 - screen, 4 - rom, 5 - block48k, 6..7 -
  596.         end
  597.  
  598.         always @(posedge zclk)
  599.         begin
  600.                 if( rstsync2 )
  601.                         p7ffd_rom_int <= rstrom[0];
  602.                 else if( (a[15]==1'b0) && portfd_wr && (!block7ffd) )
  603.                         p7ffd_rom_int <= din[4];
  604.         end
  605.  
  606.         assign block7ffd=p7ffd_int[5] & block1m;
  607.  
  608.  
  609.         // EFF7 port
  610.         always @(posedge zclk, negedge rst_n)
  611.         begin
  612.                 if( !rst_n )
  613.                         peff7_int <= 8'h00;
  614.                 else if( !a[12] && portf7_wr && (!shadow) ) // EEF7 in shadow mode is abandoned!
  615.                         peff7_int <= din; // 4 - turbooff, 0 - p16c on, 2 - block1meg
  616.         end
  617.         assign block1m = peff7_int[2];
  618.  
  619.         assign p7ffd = { (block1m ? 3'b0 : p7ffd_int[7:5]),p7ffd_rom_int,p7ffd_int[3:0]};
  620.  
  621.         assign peff7 = block1m ? { peff7_int[7], 1'b0, peff7_int[5], peff7_int[4], 3'b000, peff7_int[0] } : peff7_int;
  622.  
  623.  
  624.         assign pent1m_ROM       = p7ffd_int[4];
  625.         assign pent1m_page[5:0] = { p7ffd_int[7:5], p7ffd_int[2:0] };
  626.         assign pent1m_1m_on     = ~peff7_int[2];
  627.         assign pent1m_ram0_0    = peff7_int[3];
  628.  
  629.  
  630.  
  631.  
  632.         // gluclock ports (bit7:eff7 is above)
  633.  
  634.         assign gluclock_on = peff7_int[7] || shadow; // in shadow mode EEF7 is abandoned: instead, gluclock access
  635.                                                      // is ON forever in shadow mode.
  636.  
  637.         always @(posedge zclk)
  638.         begin
  639.                 if( gluclock_on && portf7_wr ) // gluclocks on
  640.                 begin
  641.                         if( !a[13] ) // $DFF7 - addr reg
  642.                                 gluclock_addr <= din;
  643.  
  644.                         // write to waiting register is not here - in separate section managing wait_write
  645.                 end
  646.         end
  647.  
  648.  
  649.         // comports
  650.  
  651.         always @(posedge zclk)
  652.         begin
  653.                 if( comport_wr || comport_rd )
  654.                         comport_addr <= a[10:8 ];
  655.         end
  656.  
  657.  
  658.  
  659.         // write to wait registers
  660.         always @(posedge zclk)
  661.         begin
  662.                 // gluclocks
  663.                 if( gluclock_on && portf7_wr && !a[14] ) // $BFF7 - data reg
  664.                         wait_write <= din;
  665.                 // com ports
  666.                 else if( comport_wr ) // $F8EF..$FFEF - comports
  667.                         wait_write <= din;
  668.         end
  669.  
  670.         // wait from wait registers
  671.         //
  672.         // ACHTUNG!!!! here portxx_wr are ON Z80 CLOCK! logic must change when moving to fclk strobes
  673.         //
  674.         assign wait_start_gluclock = ( gluclock_on && !a[14] && (portf7_rd || portf7_wr) ); // $BFF7 - gluclock r/w
  675.         //
  676.         assign wait_start_comport = ( comport_rd || comport_wr );
  677.         //
  678.         //
  679.         always @(posedge zclk) // wait rnw - only meanful during wait
  680.         begin
  681.                 if( port_wr )
  682.                         wait_rnw <= 1'b0;
  683.  
  684.                 if( port_rd )
  685.                         wait_rnw <= 1'b1;
  686.         end
  687.  
  688.  
  689.  
  690.  
  691.  
  692.         // VG93 control
  693.         assign vg_cs_n =  (~shadow) | iorq_n | (rd_n & wr_n) | ( ~((loa==VGCOM)|(loa==VGTRK)|(loa==VGSEC)|(loa==VGDAT)) );
  694.  
  695.  
  696.  
  697.  
  698.  
  699. // reset rom selection
  700.  
  701.         always @(posedge zclk)
  702.         begin
  703.                 rstsync1<=~rst_n;
  704.                 rstsync2<=rstsync1;
  705.         end
  706.  
  707.  
  708.  
  709.  
  710. // SD card (z-controlâ••r compatible)
  711.  
  712.         wire sdcfg_wr,sddat_wr,sddat_rd;
  713.  
  714.         assign sdcfg_wr = ( (loa==SDCFG) && port_wr_fclk && (!shadow) )                  ||
  715.                           ( (loa==SDDAT) && port_wr_fclk &&   shadow  && (a[15]==1'b1) ) ;
  716.  
  717.         assign sddat_wr = ( (loa==SDDAT) && port_wr_fclk && (!shadow) )                  ||
  718.                           ( (loa==SDDAT) && port_wr_fclk &&   shadow  && (a[15]==1'b0) ) ;
  719.  
  720.         assign sddat_rd = ( (loa==SDDAT) && port_rd_fclk              );
  721.  
  722.         // SDCFG write - sdcs_n control
  723.         always @(posedge fclk, negedge rst_n)
  724.         begin
  725.                 if( !rst_n )
  726.                         sdcs_n <= 1'b1;
  727.                 else // posedge zclk
  728.                         if( sdcfg_wr )
  729.                                 sdcs_n <= din[1];
  730.         end
  731.  
  732.  
  733.         // start signal for SPI module with resyncing to fclk
  734.  
  735.         assign sd_start = sddat_wr || sddat_rd;
  736.  
  737.  
  738.         // data for SPI module
  739.         assign sd_datain = wr_n ? 8'hFF : din;
  740.  
  741.  
  742.  
  743.  
  744.  
  745.  
  746.  
  747. /////////////////////////////////////////////////////////////////////////////////////////////////
  748.  
  749.         ///////////////
  750.         // ATM ports //
  751.         ///////////////
  752.  
  753.         wire atm77_wr_fclk;
  754.         wire zxevbf_wr_fclk;
  755.  
  756.         assign atmF7_wr_fclk = ( (loa==ATMF7) && (a[8]==1'b1) && shadow && port_wr_fclk ); // xFF7 and x7F7 ports, NOT xEF7!
  757.         assign atm77_wr_fclk = ( (loa==ATM77) && shadow && port_wr_fclk );
  758.  
  759.         assign zxevbf_wr_fclk = ( (loa==ZXEVBF) && port_wr_fclk );
  760.  
  761.  
  762.         // port BF write
  763.         //
  764.         always @(posedge fclk, negedge rst_n)
  765.         if( !rst_n )
  766.         begin
  767.                 shadow_en_reg <= 1'b0;
  768.                 romrw_en_reg  <= 1'b0;
  769.                 fntw_en_reg   <= 1'b0;
  770.                 set_nmi       <= 1'b0;
  771.         end
  772.         else if( zxevbf_wr_fclk )
  773.         begin
  774.                 shadow_en_reg <= din[0];
  775.                 romrw_en_reg  <= din[1];
  776.                 fntw_en_reg   <= din[2];
  777.                 set_nmi       <= din[3];
  778.         end
  779.  
  780.         assign romrw_en = romrw_en_reg;
  781.  
  782.  
  783.  
  784.         // port xx77 write
  785.         always @(posedge fclk, negedge rst_n)
  786.         if( !rst_n )
  787.         begin
  788.                 atm_scr_mode = 3'b011;
  789.                 atm_turbo    = 1'b0;
  790.  
  791.                 atm_pen =   1'b1; // no manager,
  792.                 atm_cpm_n = 1'b0; // permanent dosen (shadow ports on)
  793.  
  794.  
  795.                 atm_pen2     = 1'b0;
  796.         end
  797.         else if( atm77_wr_fclk )
  798.         begin
  799.                 atm_scr_mode <= din[2:0];
  800.                 atm_turbo    <= din[3];
  801.                 atm_pen      <= ~a[8];
  802.                 atm_cpm_n    <=  a[9];
  803.                 atm_pen2     <= ~a[14];
  804.         end
  805.  
  806.  
  807.         // atm palette strobe and data
  808.         wire vg_wrFF_fclk;
  809.  
  810.         assign vg_wrFF_fclk = ( ( (loa==VGSYS)&&shadow ) && port_wr_fclk);
  811.  
  812.  
  813.         assign atm_palwr = vg_wrFF_fclk & atm_pen2;
  814.  
  815.         assign atm_paldata = { ~din[4], ~din[7], ~din[1], ~din[6], ~din[0], ~din[5] };
  816.  
  817.  
  818.  
  819.         // port BE write
  820.         assign clr_nmi = ( (loa==ZXEVBE) && port_wr_fclk );
  821.  
  822.  
  823.  
  824.  
  825.         // covox/beeper writes
  826.  
  827.         assign beeper_wr = (loa==PORTFE) && portfe_wr_fclk;
  828.         assign covox_wr  = (loa==COVOX) && port_wr_fclk;
  829.  
  830.  
  831.  
  832.         // font write enable
  833.         assign fnt_wr = fntw_en_reg && mem_wr_fclk;
  834.  
  835.  
  836.  
  837.         // port BE read
  838.  
  839.         always @*
  840.         case( a[11:8] )
  841.  
  842.         4'h0: portbemux = pages[ 7:0 ];
  843.         4'h1: portbemux = pages[15:8 ];
  844.         4'h2: portbemux = pages[23:16];
  845.         4'h3: portbemux = pages[31:24];
  846.         4'h4: portbemux = pages[39:32];
  847.         4'h5: portbemux = pages[47:40];
  848.         4'h6: portbemux = pages[55:48];
  849.         4'h7: portbemux = pages[63:56];
  850.  
  851.         4'h8: portbemux = ramnroms;
  852.         4'h9: portbemux = dos7ffds;
  853.  
  854.         4'hA: portbemux = p7ffd_int;
  855.         4'hB: portbemux = peff7_int;
  856.  
  857.         4'hC: portbemux = { ~atm_pen2, atm_cpm_n, ~atm_pen, 1'bX, atm_turbo, atm_scr_mode };
  858.  
  859.         4'hD: portbemux = { ~palcolor[4], ~palcolor[2], ~palcolor[0], ~palcolor[5], 2'b11, ~palcolor[3], ~palcolor[1] };
  860. //      assign atm_paldata = { ~din[4], ~din[7], ~din[1], ~din[6], ~din[0], ~din[5] };
  861. //  {GgRrBb} -> {grbG11RB}
  862. // was: 76543210 -> 471605
  863. // now:             543210 -> 4205xx31
  864.  
  865.         default: portbemux = 8'bXXXXXXXX;
  866.  
  867.         endcase
  868.  
  869.  
  870.  
  871.  
  872.  
  873.         // savelij ports write
  874.         //
  875.         always @(posedge fclk)
  876.         if( port_wr_fclk && shadow )
  877.         begin
  878.                 if( (loa==SAVPORT1) ||
  879.                     (loa==SAVPORT2) ||
  880.                     (loa==SAVPORT3) ||
  881.                     (loa==SAVPORT4) )
  882.                         savport[ loa[6:5] ] <= din;
  883.         end
  884.  
  885.  
  886.  
  887. endmodule
  888.  
  889.