Subversion Repositories pentevo

Rev

Rev 1319 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014
  2. //
  3. // most of pentevo ports are here
  4.  
  5. /*
  6.     This file is part of ZX-Evo Base Configuration firmware.
  7.  
  8.     ZX-Evo Base Configuration firmware is free software:
  9.     you can redistribute it and/or modify it under the terms of
  10.     the GNU General Public License as published by
  11.     the Free Software Foundation, either version 3 of the License, or
  12.     (at your option) any later version.
  13.  
  14.     ZX-Evo Base Configuration firmware is distributed in the hope that
  15.     it will be useful, but WITHOUT ANY WARRANTY; without even
  16.     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17.     See the GNU General Public License for more details.
  18.  
  19.     You should have received a copy of the GNU General Public License
  20.     along with ZX-Evo Base Configuration firmware.
  21.     If not, see <http://www.gnu.org/licenses/>.
  22. */
  23.  
  24. `include "../include/tune.v"
  25.  
  26. module zports(
  27.  
  28.         input  wire        zclk,   // z80 clock
  29.         input  wire        fclk,  // global FPGA clock
  30.         input  wire        rst_n, // system reset
  31.  
  32.         input  wire        zpos,
  33.         input  wire        zneg,
  34.  
  35.  
  36.         input  wire [ 7:0] din,
  37.         output reg  [ 7:0] dout,
  38.         output wire        dataout,
  39.         input  wire [15:0] a,
  40.  
  41.         input  wire        iorq_n,
  42.         input  wire        mreq_n,
  43.         input  wire        m1_n,
  44.         input  wire        rd_n,
  45.         input  wire        wr_n,
  46.  
  47.         output reg         porthit, // when internal port hit occurs, this is 1, else 0; used for iorq1_n iorq2_n on zxbus
  48.         output reg         external_port, // asserts for AY and VG93 accesses
  49.  
  50.         output wire [15:0] ideout,
  51.         input  wire [15:0] idein,
  52.         output wire        idedataout, // IDE must IN data from IDE device when idedataout=0, else it OUTs
  53.         output wire [ 2:0] ide_a,
  54.         output wire        ide_cs0_n,
  55.         output wire        ide_cs1_n,
  56.         output wire        ide_rd_n,
  57.         output wire        ide_wr_n,
  58.  
  59.  
  60.         input  wire [ 4:0] keys_in, // keys (port FE)
  61.         input  wire [ 7:0] mus_in,  // mouse (xxDF)
  62.         input  wire [ 7:0] kj_in,
  63.  
  64.         output reg  [ 3:0] border,
  65.  
  66.  
  67.         input  wire        dos,
  68.  
  69.  
  70.         output wire        ay_bdir,
  71.         output wire        ay_bc1,
  72.  
  73.         output wire [ 7:0] p7ffd,
  74.         output wire [ 7:0] peff7,
  75.  
  76.         input  wire        tape_read,
  77.  
  78.         output wire        vg_cs_n,
  79.         input  wire        vg_intrq,
  80.         input  wire        vg_drq, // from vg93 module - drq + irq read
  81.         output wire        vg_wrFF_fclk, // write strobe of #FF port
  82.         output reg         vg_rdwr_fclk, // pulses when ANY port of TR-DOS controller was read or written
  83.         input  wire [ 1:0] vg_a,
  84.         input  wire        vg_res_n,
  85.         input  wire        vg_hrdy,
  86.         input  wire        vg_side,
  87.  
  88.         // FDD mask
  89.         output reg  [ 3:0] fdd_mask,
  90.  
  91.  
  92.         output wire        sd_cs_n_val,
  93.         output wire        sd_cs_n_stb,
  94.         output wire        sd_start,
  95.         output wire [ 7:0] sd_datain,
  96.         input  wire [ 7:0] sd_dataout,
  97.  
  98.         // WAIT-ports related
  99.         //
  100.         output reg  [ 7:0] gluclock_addr,
  101.         //
  102.         output reg  [ 2:0] comport_addr,
  103.         //
  104.         output wire        wait_start_gluclock, // begin wait from some ports
  105.         output wire        wait_start_comport,  //
  106.         //
  107.         output reg         wait_rnw,   // whether it was read(=1) or write(=0)
  108.         output reg  [ 7:0] wait_write,
  109.         input  wire [ 7:0] wait_read,
  110.  
  111.  
  112.         output wire        atmF7_wr_fclk, // used in atm_pager.v
  113.  
  114.  
  115.         output reg  [ 2:0] atm_scr_mode, // RG0..RG2 in docs
  116.         output reg         atm_turbo,    // turbo mode ON
  117.         output reg         atm_pen,      // pager_off in atm_pager.v, NOT inverted!!!
  118.         output reg         atm_cpm_n,    // permanent dos on
  119.         output reg         atm_pen2,     // PEN2 - fucking palette mode, NOT inverted!!!
  120.  
  121.         output wire        romrw_en, // from port BF
  122.  
  123.  
  124.         output wire        pent1m_ram0_0, // d3.eff7
  125.         output wire        pent1m_1m_on,  // d2.eff7
  126.         output wire [ 5:0] pent1m_page,   // full 1 meg page number
  127.         output wire        pent1m_ROM,     // d4.7ffd
  128.  
  129.  
  130.         output wire        atm_palwr,   // palette write strobe
  131.         output wire [ 5:0] atm_paldata, // palette write data
  132.         output wire [ 5:0] atm_paldatalow, // palette write data low bits (ATM3)
  133.         output reg         pal444_ena, // ATM3 palette on
  134.  
  135.         output wire        covox_wr,
  136.         output wire        beeper_wr,
  137.  
  138.         output wire        clr_nmi,
  139.  
  140.         output wire        fnt_wr,              // write to font_ram enabled
  141.  
  142.         // inputs from atm_pagers, to read back its config
  143.         input  wire [63:0] pages,
  144.         input  wire [ 7:0] ramnroms,
  145.         input  wire [ 7:0] dos7ffds,
  146.         input  wire [ 7:0] wrdisables,
  147.  
  148.         input  wire [ 5:0] palcolor,
  149.         input  wire [ 7:0] fontrom_readback,
  150.  
  151.         // ulaplus
  152.         output reg         up_ena,
  153.         output reg  [ 5:0] up_paladdr,
  154.         output wire [ 7:0] up_paldata,
  155.         output wire        up_palwr,
  156.  
  157.  
  158.  
  159.         // NMI generation
  160.         output reg         set_nmi,
  161.  
  162.         // break enable & address
  163.         output reg         brk_ena,
  164.         output reg  [15:0] brk_addr,
  165.  
  166.         // irq control
  167.         output reg         irq_enh,
  168.         output reg         irq_ena_int_vec,
  169.         output reg         irq_ena_ext_vec,
  170.         output reg         irq_int_autoclr,
  171.         //
  172.         input  wire [ 6:0] irq_stat_rd,
  173.         //
  174.         output wire        irq_stat_setnrst,
  175.         output wire [ 6:0] irq_stat_wr_sel,
  176.         output wire        irq_stat_wr_stb,
  177.         //
  178.         input  wire [ 6:0] irq_ena_rd,
  179.         //
  180.         output wire        irq_ena_setnrst,
  181.         output wire [ 6:0] irq_ena_wr_sel,
  182.         output wire        irq_ena_wr_stb
  183. );
  184.  
  185.  
  186. `define IS_NIDE_REGS(x) ( (x[2:0]==3'b000) && (x[3]!=x[4]) )
  187. `define IS_NIDE_HIGH(x) ( x[7:0]==8'h11 )
  188. `define IS_PORT_NIDE(x) ( `IS_NIDE_REGS(x) || `IS_NIDE_HIGH(x) )
  189. `define NIDE_REGS 8'h10,8'h30,8'h50,8'h70,8'h90,8'hB0,8'hD0,8'hF0, \
  190.                   8'h08,8'h28,8'h48,8'h68,8'h88,8'hA8,8'hC8,8'hE8
  191.  
  192.         localparam PORTFE = 8'hFE;
  193.         localparam PORTF6 = 8'hF6;
  194.         localparam PORTF7 = 8'hF7;
  195.  
  196.         localparam NIDE10 = 8'h10;
  197.         localparam NIDE11 = 8'h11;
  198.         localparam NIDE30 = 8'h30;
  199.         localparam NIDE50 = 8'h50;
  200.         localparam NIDE70 = 8'h70;
  201.         localparam NIDE90 = 8'h90;
  202.         localparam NIDEB0 = 8'hB0;
  203.         localparam NIDED0 = 8'hD0;
  204.         localparam NIDEF0 = 8'hF0;
  205.         localparam NIDEC8 = 8'hC8;
  206.  
  207.         localparam PORTFD = 8'hFD;
  208.  
  209.         localparam VGCOM  = 8'h1F;
  210.         localparam VGTRK  = 8'h3F;
  211.         localparam VGSEC  = 8'h5F;
  212.         localparam VGDAT  = 8'h7F;
  213.         localparam VGSYS  = 8'hFF;
  214.  
  215.         localparam KJOY   = 8'h1F;
  216.         localparam KMOUSE = 8'hDF;
  217.  
  218.         localparam SDCFG  = 8'h77;
  219.         localparam SDDAT  = 8'h57;
  220.  
  221.         localparam ATMF7  = 8'hF7;
  222.         localparam ATM77  = 8'h77;
  223.  
  224.         localparam ZXEVBF = 8'hBF; // xxBF config port
  225.        
  226.         localparam ZXEVBE = 8'hBE; // xxBE nmi-end port
  227.         localparam ZXEVBD = 8'hBD; // xxBD config-read and write port
  228.  
  229.         localparam COMPORT = 8'hEF; // F8EF..FFEF - rs232 ports
  230.  
  231.         localparam COVOX   = 8'hFB;
  232.  
  233.         localparam ULAPLUS = 8'h3B;
  234.  
  235.  
  236.  
  237.         // xxBD high part addresses
  238.         localparam BD_PG0      = 5'h00;
  239.         localparam BD_PG1      = 5'h01;
  240.         localparam BD_PG2      = 5'h02;
  241.         localparam BD_PG3      = 5'h03;
  242.         localparam BD_PG4      = 5'h04;
  243.         localparam BD_PG5      = 5'h05;
  244.         localparam BD_PG6      = 5'h06;
  245.         localparam BD_PG7      = 5'h07;
  246.         //
  247.         localparam BD_RAMNROMS = 5'h08;
  248.         localparam BD_DOS7FFDS = 5'h09;
  249.         //
  250.         localparam BD_P7FFD    = 5'h0A;
  251.         localparam BD_PEFF7    = 5'h0B;
  252.         //
  253.         localparam BD_PXX77    = 5'h0C;
  254.         //
  255.         localparam BD_COLORRD  = 5'h0D;
  256.         localparam BD_FNTRD    = 5'h0E;
  257.         //
  258.         localparam BD_BORDERRD = 5'h0F;
  259.         //
  260.         localparam BD_LOBRK    = 5'h10;
  261.         localparam BD_HIBRK    = 5'h11;
  262.         //
  263.         localparam BD_WRDISRD  = 5'h12;
  264.         //
  265.         localparam BD_FDDMASK  = 5'h13;
  266.         //
  267.         // irq control
  268.         localparam BD_IRQCFG   = 5'h14;
  269.         localparam BD_IRQENA   = 5'h15;
  270.         localparam BD_IRQSTAT  = 5'h16;
  271.  
  272.  
  273.  
  274.         reg port_wr;
  275.         reg port_rd;
  276.  
  277.         reg iowr_reg;
  278.         reg iord_reg;
  279.  
  280.  
  281.         reg port_wr_fclk,
  282.             port_rd_fclk,
  283.             mem_wr_fclk;
  284.  
  285.         reg [1:0] iowr_reg_fclk,
  286.                   iord_reg_fclk;
  287.  
  288.         reg [1:0] memwr_reg_fclk;
  289.  
  290.  
  291.         wire [7:0] loa;
  292.  
  293.  
  294.  
  295.  
  296.         wire ideout_hi_wr;
  297.         wire idein_lo_rd;
  298.         reg [7:0] idehiin; // IDE high part read register: low part is read directly to Z80 bus,
  299.                            // while high part is remembered here
  300.         reg ide_ports; // ide ports selected
  301.  
  302.         reg ide_rd_trig; // nemo-divide read trigger
  303.         reg ide_rd_latch; // to save state of trigger during read cycle
  304.  
  305.         reg ide_wrlo_trig,  ide_wrhi_trig;  // nemo-divide write triggers
  306.         reg ide_wrlo_latch, ide_wrhi_latch; // save state during write cycles
  307.  
  308.  
  309.  
  310.         reg  [15:0] idewrreg; // write register, either low or high part is pre-written here,
  311.                               // while other part is out directly from Z80 bus
  312.  
  313.         wire [ 7:0] iderdeven; // to control read data from "even" ide ports (all except #11)
  314.         wire [ 7:0] iderdodd;  // read data from "odd" port (#11)
  315.  
  316.  
  317.  
  318.         reg pre_bc1,pre_bdir;
  319.  
  320.         wire gluclock_on;
  321.  
  322.  
  323.  
  324.         reg  shadow_en_reg; //bit0.xxBF
  325.         reg   romrw_en_reg; //bit1.xxBF
  326.         reg  fntw_en_reg;       //bit2.xxBF
  327.  
  328.         wire shadow;
  329.  
  330.  
  331.  
  332.         reg [7:0] portbdmux;
  333.  
  334.  
  335.  
  336.         wire vg_matched_n;
  337.  
  338.  
  339.         reg [7:0] up_lastwritten;
  340.  
  341.  
  342.         assign shadow = dos || shadow_en_reg;
  343.  
  344.  
  345.  
  346.         reg [7:0] sd_rd_buffer;
  347.  
  348.  
  349.         // irq related
  350.         wire [7:0] rd_irq_cfg;
  351.         wire [7:0] rd_irq_ena;
  352.         wire [7:0] rd_irq_stat;
  353.  
  354.  
  355.  
  356.         assign loa=a[7:0];
  357.  
  358.         always @*
  359.         begin
  360.                 if( (loa==PORTFE) || (loa==PORTF6) ||
  361.                     (loa==PORTFD) || (loa==8'hFC)  ||
  362.  
  363.                     `IS_PORT_NIDE(loa) ||
  364. //                  (loa==NIDE10) || (loa==NIDE11) || (loa==NIDE30) || (loa==NIDE50) || (loa==NIDE70) ||
  365. //                  (loa==NIDE90) || (loa==NIDEB0) || (loa==NIDED0) || (loa==NIDEF0) || (loa==NIDEC8) ||
  366.  
  367.                     (loa==KMOUSE) ||
  368.  
  369.                     ( (loa==VGCOM)&&shadow ) || ( (loa==VGTRK)&&shadow ) || ( (loa==VGSEC)&&shadow ) || ( (loa==VGDAT)&&shadow ) ||
  370.                     ( (loa==VGSYS)&&shadow ) || ( (loa==KJOY)&&(!shadow) ) ||
  371.  
  372.                     ( (loa==PORTF7)&&(!shadow) ) || ( (loa==SDCFG)&&(!shadow) ) || ( (loa==SDDAT) ) ||
  373.  
  374.                     ( (loa==ATMF7)&&shadow ) || ( (loa==ATM77)&&shadow ) ||
  375.  
  376.                     ( loa==ZXEVBF ) || ( loa==ZXEVBE) || ( loa==ZXEVBD) || ( loa==COMPORT ) ||
  377.  
  378.                     ( loa==ULAPLUS)
  379.                   )
  380.  
  381.  
  382.  
  383.                         porthit = 1'b1;
  384.                 else
  385.                         porthit = 1'b0;
  386.         end
  387.  
  388.         always @*
  389.         begin
  390.                 if( ((loa==PORTFD) && a[15]) || // 0xBFFD/0xFFFD ports
  391.                     (( (loa==VGCOM)&&shadow ) || ( (loa==VGTRK)&&shadow ) || ( (loa==VGSEC)&&shadow ) || ( (loa==VGDAT)&&shadow )) ) // vg93 ports
  392.                         external_port = 1'b1;
  393.                 else
  394.                         external_port = 1'b0;
  395.         end
  396.  
  397.         assign dataout = porthit & (~iorq_n) & (~rd_n) & (~external_port);
  398.  
  399.  
  400.  
  401.         // this is zclk-synchronous strobes
  402.         always @(posedge zclk)
  403.         begin
  404.                 iowr_reg <= ~(iorq_n | wr_n);
  405.                 iord_reg <= ~(iorq_n | rd_n);
  406.  
  407.                 if( (!iowr_reg) && (!iorq_n) && (!wr_n) )
  408.                         port_wr <= 1'b1;
  409.                 else
  410.                         port_wr <= 1'b0;
  411.  
  412.  
  413.                 if( (!iord_reg) && (!iorq_n) && (!rd_n) )
  414.                         port_rd <= 1'b1;
  415.                 else
  416.                         port_rd <= 1'b0;
  417.         end
  418.  
  419.  
  420.  
  421.  
  422.         // fclk-synchronous stobes
  423.         //
  424.         always @(posedge fclk) if( zpos )
  425.         begin
  426.                 iowr_reg_fclk[0] <= ~(iorq_n | wr_n);
  427.                 iord_reg_fclk[0] <= ~(iorq_n | rd_n);
  428.         end
  429.  
  430.         always @(posedge fclk)
  431.         begin
  432.                 iowr_reg_fclk[1] <= iowr_reg_fclk[0];
  433.                 iord_reg_fclk[1] <= iord_reg_fclk[0];
  434.         end
  435.  
  436.         always @(posedge fclk)
  437.         begin
  438.                 port_wr_fclk <= iowr_reg_fclk[0] && (!iowr_reg_fclk[1]);
  439.                 port_rd_fclk <= iord_reg_fclk[0] && (!iord_reg_fclk[1]);
  440.         end
  441.  
  442.         always @(posedge fclk)
  443.                 memwr_reg_fclk[1:0] <= { memwr_reg_fclk[0], ~(mreq_n | wr_n) };
  444.  
  445.         always @(posedge fclk)
  446.                 mem_wr_fclk <= memwr_reg_fclk[0] && (!memwr_reg_fclk[1]);
  447.  
  448.  
  449.  
  450.         // dout data
  451.         always @*
  452.         begin
  453.                 case( loa )
  454.                 PORTFE:
  455.                         dout = { 1'b1, tape_read, 1'b0, keys_in };
  456.                 PORTF6:
  457.                         dout = { 1'b1, tape_read, 1'b0, keys_in };
  458.  
  459.  
  460.                 `NIDE_REGS:
  461.                         dout = iderdeven;
  462.                 NIDE11:
  463.                         dout = iderdodd;
  464.  
  465.  
  466.                 //PORTFD:
  467.  
  468.                 VGSYS:
  469.                         dout = { vg_intrq, vg_drq, 1'b1, (~vg_side), vg_hrdy, vg_res_n, vg_a };
  470.  
  471.                 KJOY:
  472.                         dout = kj_in;
  473.                 KMOUSE:
  474.                         dout = mus_in;
  475.  
  476.                 SDCFG:
  477.                         dout = 8'h00; // always SD inserted, SD is in R/W mode
  478.                 SDDAT:
  479.                         dout = sd_rd_buffer;
  480.  
  481.  
  482.                 PORTF7: begin
  483.                         if( !a[14] && (a[8]^shadow) && gluclock_on ) // $BFF7 - data i/o
  484.                                 dout = wait_read;
  485.                         else // any other $xxF7 port
  486.                                 dout = 8'hFF;
  487.                 end
  488.  
  489.                 COMPORT: begin
  490.                         dout = wait_read; // $F8EF..$FFEF
  491.                 end
  492.  
  493.                 ZXEVBF: begin
  494.                         dout = { 2'b00, pal444_ena, brk_ena, set_nmi, fntw_en_reg, romrw_en_reg, shadow_en_reg };
  495.                 end
  496.  
  497.                 ZXEVBD: begin
  498.                         dout = portbdmux;
  499.                 end
  500.  
  501.                 ULAPLUS: begin
  502.                         dout = up_lastwritten;
  503.                 end
  504.  
  505.  
  506.                 default:
  507.                         dout = 8'hFF;
  508.                 endcase
  509.         end
  510.  
  511.  
  512.  
  513.         assign portfd_wr    = ( (loa==PORTFD || loa==8'hFC) && port_wr);
  514.  
  515.         // F7 ports (like EFF7) are accessible in shadow mode but at addresses like EEF7, DEF7, BEF7 so that
  516.         // there are no conflicts in shadow mode with ATM xFF7 and x7F7 ports
  517.         assign portf7_wr    = ( (loa==PORTF7) && (a[8]==1'b1) && port_wr && (!shadow) ) ||
  518.                               ( (loa==PORTF7) && (a[8]==1'b0) && port_wr &&   shadow  ) ;
  519.  
  520.         assign portf7_rd    = ( (loa==PORTF7) && (a[8]==1'b1) && port_rd && (!shadow) ) ||
  521.                               ( (loa==PORTF7) && (a[8]==1'b0) && port_rd &&   shadow  ) ;
  522.  
  523. //      assign vg_wrFF = ( ( (loa==VGSYS)&&shadow ) && port_wr);
  524. //      always @(posedge zclk) if( vg_wrFF )
  525. //              vgFF <= din[5:0];
  526.  
  527.         assign comport_wr   = ( (loa==COMPORT) && port_wr);
  528.         assign comport_rd   = ( (loa==COMPORT) && port_rd);
  529.  
  530.        
  531.         assign zxevbd_wr_fclk = ( (loa==ZXEVBD) && port_wr_fclk);
  532.  
  533.  
  534.  
  535.  
  536.  
  537.         // break address write
  538.         always @(posedge fclk)
  539.         if( zxevbd_wr_fclk && a[12:9]==(BD_LOBRK>>1) )
  540.         begin
  541.                 if( !a[8] )
  542.                         brk_addr[ 7:0] <= din;
  543.                 else // a[8]==1
  544.                         brk_addr[15:8] <= din;
  545.         end
  546.  
  547.         // fdd mask write
  548.         always @(posedge fclk, negedge rst_n)
  549.         if( !rst_n )
  550.                 fdd_mask <= 4'd0;
  551.         else if( zxevbd_wr_fclk && a[12:8]==BD_FDDMASK )
  552.                 fdd_mask <= din[3:0];
  553.  
  554.  
  555.  
  556.  
  557.         //border port FE
  558.         wire portwe_wr_fclk;
  559.  
  560.         assign portfe_wr_fclk = (((loa==PORTFE) || (loa==PORTF6) || (loa==8'hFC)) && port_wr_fclk);
  561.  
  562.         always @(posedge fclk)
  563.         if( portfe_wr_fclk )
  564.                 border <= { ~a[3], din[2:0] };
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.         // IDE ports
  572.  
  573.         // IDE physical ports (that go to IDE device)
  574.         always @(loa)
  575.         if( `IS_NIDE_REGS(loa) )
  576.                 ide_ports = 1'b1;
  577.         else
  578.                 ide_ports = 1'b0;
  579.  
  580.  
  581.         assign idein_lo_rd  = port_rd && (loa==NIDE10) && (!ide_rd_trig);
  582.  
  583.         // control read & write triggers, which allow nemo-divide mod to work.
  584.         //
  585.         // read trigger:
  586.         always @(posedge zclk)
  587.         begin
  588.                 if( (loa==NIDE10) && port_rd && !ide_rd_trig )
  589.                         ide_rd_trig <= 1'b1;
  590.                 else if( ( ide_ports || (loa==NIDE11) ) && ( port_rd || port_wr ) )
  591.                         ide_rd_trig <= 1'b0;
  592.         end
  593.         //
  594.         // two triggers for write sequence...
  595.         always @(posedge zclk)
  596.         if( ( ide_ports || (loa==NIDE11) ) && ( port_rd || port_wr ) )
  597.         begin
  598.                 if( (loa==NIDE11) && port_wr )
  599.                         ide_wrhi_trig <= 1'b1;
  600.                 else
  601.                         ide_wrhi_trig <= 1'b0;
  602.                 //
  603.                 if( (loa==NIDE10) && port_wr && !ide_wrhi_trig && !ide_wrlo_trig )
  604.                         ide_wrlo_trig <= 1'b1;
  605.                 else
  606.                         ide_wrlo_trig <= 1'b0;
  607.         end
  608.  
  609.         // normal read: #10(low), #11(high)
  610.         // divide read: #10(low), #10(high)
  611.         //
  612.         // normal write: #11(high), #10(low)
  613.         // divide write: #10(low),  #10(high)
  614.  
  615.  
  616.         always @(posedge zclk)
  617.         begin
  618.                 if( port_wr && (loa==NIDE11) )
  619.                         idewrreg[15:8] <= din;
  620.  
  621.                 if( port_wr && (loa==NIDE10) && !ide_wrlo_trig )
  622.                         idewrreg[ 7:0] <= din;
  623.         end
  624.  
  625.  
  626.  
  627.  
  628.         always @(posedge zclk)
  629.         if( idein_lo_rd )
  630.                         idehiin <= idein[15:8];
  631.  
  632.  
  633.         assign ide_a = a[7:5];
  634.  
  635.  
  636.         // This is unknown shit... Probably need more testing with old WD
  637.         // drives WITHOUT this commented fix.
  638.         //
  639.         // trying to fix old WD drives...
  640.         //assign ide_cs0_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa!=NIDEC8));
  641.         //assign ide_cs1_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa==NIDEC8));
  642.         // fix ends...
  643.  
  644.  
  645.         assign ide_cs0_n = (~ide_ports) | (~(loa!=NIDEC8));
  646.         assign ide_cs1_n = (~ide_ports) | (~(loa==NIDEC8));
  647.  
  648.  
  649.         // generate read cycles for IDE as usual, except for reading #10
  650.         // instead of #11 for high byte (nemo-divide). I use additional latch
  651.         // since 'ide_rd_trig' clears during second Z80 IO read cycle to #10
  652.         always @* if( rd_n ) ide_rd_latch <= ide_rd_trig;
  653.         //
  654.         assign ide_rd_n = iorq_n | rd_n | (~ide_ports) | (ide_rd_latch && (loa==NIDE10));
  655.  
  656.         always @* if( wr_n ) ide_wrlo_latch <= ide_wrlo_trig; // same for write triggers
  657.         always @* if( wr_n ) ide_wrhi_latch <= ide_wrhi_trig; //
  658.         //
  659.         assign ide_wr_n = iorq_n | wr_n | (~ide_ports) | ( (loa==NIDE10) && !ide_wrlo_latch && !ide_wrhi_latch );
  660.                                                   // do NOT generate IDE write, if neither of ide_wrhi|lo latches
  661.                                                   // set and writing to NIDE10
  662.  
  663.  
  664.  
  665. //      assign idedataout = ide_rd_n;
  666.         assign idedataout = ~ide_wr_n; // shit-fix in try to fix IDE errors
  667.         // warning: this fix kinda blind-picking, good way is to
  668.         // have idedataout lead wr or rd strobes. also good point to disable data ringing
  669.         // on ide data bus while not accessing IDE
  670.  
  671.  
  672.         // data read by Z80 from IDE
  673.         //
  674.         assign iderdodd[ 7:0] = idehiin[ 7:0];
  675.         //
  676.         assign iderdeven[ 7:0] = (ide_rd_latch && (loa==NIDE10)) ? idehiin[ 7:0] : idein[ 7:0];
  677.  
  678.         // data written to IDE from Z80
  679.         //
  680.         assign ideout[15:8] = ide_wrhi_latch ? idewrreg[15:8] : din[ 7:0];
  681.         assign ideout[ 7:0] = ide_wrlo_latch ? idewrreg[ 7:0] : din[ 7:0];
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.         // AY control
  690.         always @*
  691.         begin
  692.                 pre_bc1 = 1'b0;
  693.                 pre_bdir = 1'b0;
  694.  
  695.                 if( loa==PORTFD )
  696.                 begin
  697.                         if( a[15:14]==2'b11 )
  698.                         begin
  699.                                 pre_bc1=1'b1;
  700.                                 pre_bdir=1'b1;
  701.                         end
  702.                         else if( a[15:14]==2'b10 )
  703.                         begin
  704.                                 pre_bc1=1'b0;
  705.                                 pre_bdir=1'b1;
  706.                         end
  707.                 end
  708.         end
  709.  
  710.         assign ay_bc1  = pre_bc1  & (~iorq_n) & ((~rd_n)|(~wr_n));
  711.         assign ay_bdir = pre_bdir & (~iorq_n) & (~wr_n);
  712.  
  713.  
  714.  
  715.         // 7FFD port
  716.         reg [7:0] p7ffd_int,peff7_int;
  717.         reg p7ffd_rom_int;
  718.         wire block7ffd;
  719.         wire block1m;
  720.  
  721.         always @(posedge zclk, negedge rst_n)
  722.         begin
  723.                 if( !rst_n )
  724.                         p7ffd_int <= 7'h00;
  725.                 else if( (a[15]==1'b0) && portfd_wr && (!block7ffd) )
  726.                         p7ffd_int <= din; // 2..0 - page, 3 - screen, 4 - rom, 5 - block48k, 6..7 -
  727.         end
  728.  
  729.         always @(posedge zclk, negedge rst_n)
  730.         if( !rst_n )
  731.                         p7ffd_rom_int <= 1'b0;
  732.         else
  733.                 if( (a[15]==1'b0) && portfd_wr && (!block7ffd) )
  734.                         p7ffd_rom_int <= din[4];
  735.  
  736.  
  737.         assign block7ffd=p7ffd_int[5] & block1m;
  738.  
  739.  
  740.         // EFF7 port
  741.         always @(posedge zclk, negedge rst_n)
  742.         begin
  743.                 if( !rst_n )
  744.                         peff7_int <= 8'h00;
  745.                 else if( !a[12] && portf7_wr && (!shadow) ) // EEF7 in shadow mode is abandoned!
  746.                         peff7_int <= din; // 4 - turbooff, 0 - p16c on, 2 - block1meg
  747.         end
  748.         assign block1m = peff7_int[2];
  749.  
  750.         assign p7ffd = { (block1m ? 3'b0 : p7ffd_int[7:5]),p7ffd_rom_int,p7ffd_int[3:0]};
  751.  
  752.         assign peff7 = block1m ? { peff7_int[7], 1'b0, peff7_int[5], peff7_int[4], 3'b000, peff7_int[0] } : peff7_int;
  753.  
  754.  
  755.         assign pent1m_ROM       = p7ffd_int[4];
  756.         assign pent1m_page[5:0] = { p7ffd_int[7:5], p7ffd_int[2:0] };
  757.         assign pent1m_1m_on     = ~peff7_int[2];
  758.         assign pent1m_ram0_0    = peff7_int[3];
  759.  
  760.  
  761.  
  762.  
  763.         // gluclock ports (bit7:eff7 is above)
  764.  
  765.         assign gluclock_on = peff7_int[7] || shadow; // in shadow mode EEF7 is abandoned: instead, gluclock access
  766.                                                      // is ON forever in shadow mode.
  767.  
  768.         always @(posedge zclk)
  769.         begin
  770.                 if( gluclock_on && portf7_wr ) // gluclocks on
  771.                 begin
  772.                         if( !a[13] ) // $DFF7 - addr reg
  773.                                 gluclock_addr <= din;
  774.  
  775.                         // write to waiting register is not here - in separate section managing wait_write
  776.                 end
  777.         end
  778.  
  779.  
  780.         // comports
  781.  
  782.         always @(posedge zclk)
  783.         begin
  784.                 if( comport_wr || comport_rd )
  785.                         comport_addr <= a[10:8 ];
  786.         end
  787.  
  788.  
  789.  
  790.         // write to wait registers
  791.         always @(posedge zclk)
  792.         begin
  793.                 // gluclocks
  794.                 if( gluclock_on && portf7_wr && !a[14] ) // $BFF7 - data reg
  795.                         wait_write <= din;
  796.                 // com ports
  797.                 else if( comport_wr ) // $F8EF..$FFEF - comports
  798.                         wait_write <= din;
  799.         end
  800.  
  801.         // wait from wait registers
  802.         //
  803.         // ACHTUNG!!!! here portxx_wr are ON Z80 CLOCK! logic must change when moving to fclk strobes
  804.         //
  805.         assign wait_start_gluclock = ( gluclock_on && !a[14] && (portf7_rd || portf7_wr) ); // $BFF7 - gluclock r/w
  806.         //
  807.         assign wait_start_comport = ( comport_rd || comport_wr );
  808.         //
  809.         //
  810.         always @(posedge zclk) // wait rnw - only meanful during wait
  811.         begin
  812.                 if( port_wr )
  813.                         wait_rnw <= 1'b0;
  814.  
  815.                 if( port_rd )
  816.                         wait_rnw <= 1'b1;
  817.         end
  818.  
  819.  
  820.  
  821.  
  822.  
  823.         // VG93 control
  824.         assign vg_matched_n = fdd_mask[vg_a];
  825.  
  826.         assign vg_cs_n =  vg_matched_n | (~shadow) | iorq_n | (rd_n & wr_n) | ( ~((loa==VGCOM)|(loa==VGTRK)|(loa==VGSEC)|(loa==VGDAT)) );
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835. // SD card (z-controlâ••r compatible)
  836.  
  837.         wire sdcfg_wr,sddat_wr,sddat_rd;
  838.  
  839.         assign sdcfg_wr = ( (loa==SDCFG) && port_wr_fclk && (!shadow) )                  ||
  840.                           ( (loa==SDDAT) && port_wr_fclk &&   shadow  && (a[15]==1'b1) ) ;
  841.  
  842.         assign sddat_wr = ( (loa==SDDAT) && port_wr_fclk && (!shadow) )                  ||
  843.                           ( (loa==SDDAT) && port_wr_fclk &&   shadow  && (a[15]==1'b0) ) ;
  844.  
  845.         assign sddat_rd = ( (loa==SDDAT) && port_rd_fclk              );
  846.  
  847.         // SDCFG write - sdcs_n control
  848.         assign sd_cs_n_stb = sdcfg_wr;
  849.         assign sd_cs_n_val = din[1];
  850.  
  851.  
  852.         // start signal for SPI module with resyncing to fclk
  853.  
  854.         assign sd_start = sddat_wr || sddat_rd;
  855.  
  856.         // data for SPI module
  857.         assign sd_datain = sddat_rd ? 8'hFF : din;
  858.  
  859.  
  860.         // latch SD read data to fix bug with reading SD card in 48k and 128k contention modes
  861.         always @(posedge fclk)
  862.         if( sd_start )
  863.                 sd_rd_buffer <= sd_dataout;
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871. /////////////////////////////////////////////////////////////////////////////////////////////////
  872.  
  873.         ///////////////
  874.         // ATM ports //
  875.         ///////////////
  876.  
  877.         wire atm77_wr_fclk;
  878.         wire zxevbf_wr_fclk;
  879.  
  880.         assign atmF7_wr_fclk = ( (loa==ATMF7) && (a[8]==1'b1) && shadow && port_wr_fclk ); // xFF7 and x7F7 ports, NOT xEF7!
  881.         assign atm77_wr_fclk = ( (loa==ATM77) && shadow && port_wr_fclk );
  882.  
  883.         assign zxevbf_wr_fclk = ( (loa==ZXEVBF) && port_wr_fclk );
  884.  
  885.  
  886.         // port BF write
  887.         //
  888.         always @(posedge fclk, negedge rst_n)
  889.         if( !rst_n )
  890.         begin
  891.                 shadow_en_reg <= 1'b0;
  892.                 romrw_en_reg  <= 1'b0;
  893.                 fntw_en_reg   <= 1'b0;
  894.                 set_nmi       <= 1'b0;
  895.                 brk_ena       <= 1'b0;
  896.                 pal444_ena    <= 1'b0;
  897.         end
  898.         else if( zxevbf_wr_fclk )
  899.         begin
  900.                 shadow_en_reg <= din[0];
  901.                 romrw_en_reg  <= din[1];
  902.                 fntw_en_reg   <= din[2];
  903.                 set_nmi       <= din[3];
  904.                 brk_ena       <= din[4];
  905.                 pal444_ena    <= din[5];
  906.         end
  907.  
  908.         assign romrw_en = romrw_en_reg;
  909.  
  910.  
  911.  
  912.         // port xx77 write
  913.         always @(posedge fclk, negedge rst_n)
  914.         if( !rst_n )
  915.         begin
  916.                 atm_scr_mode = 3'b011;
  917.                 atm_turbo    = 1'b0;
  918.  
  919.                 atm_pen =   1'b1; // no manager,
  920.                 atm_cpm_n = 1'b0; // permanent dosen (shadow ports on)
  921.  
  922.  
  923.                 atm_pen2     = 1'b0;
  924.         end
  925.         else if( atm77_wr_fclk )
  926.         begin
  927.                 atm_scr_mode <= din[2:0];
  928.                 atm_turbo    <= din[3];
  929.                 atm_pen      <= ~a[8];
  930.                 atm_cpm_n    <=  a[9];
  931.                 atm_pen2     <= ~a[14];
  932.         end
  933.  
  934.  
  935.         // atm palette strobe and data
  936.         //wire vg_wrFF_fclk;
  937.  
  938.         assign vg_wrFF_fclk = ( ( (loa==VGSYS)&&shadow ) && port_wr_fclk);
  939.  
  940.  
  941.         assign atm_palwr = vg_wrFF_fclk & atm_pen2;
  942.  
  943.         assign atm_paldata = { ~din[4], ~din[7], ~din[1], ~din[6], ~din[0], ~din[5] }; //GgRrBb
  944.         assign atm_paldatalow = { ~a[4+8], ~a[7+8], ~a[1+8], ~a[6+8], ~a[0+8], ~a[5+8] }; //GgRrBb
  945.  
  946.  
  947.  
  948.         // TR-DOS any port access strobe -- for switching TR-DOS page to RAM page FE
  949.         always @(posedge fclk, negedge rst_n)
  950.         if( !rst_n )
  951.                 vg_rdwr_fclk <= 1'b0;
  952.         else
  953.                 vg_rdwr_fclk <= ((loa==VGCOM) ||
  954.                                  (loa==VGTRK) ||
  955.                                  (loa==VGSEC) ||
  956.                                  (loa==VGDAT) ||
  957.                                  (loa==VGSYS)  ) && shadow && (port_wr_fclk || port_rd_fclk);
  958.                                
  959.  
  960.  
  961.  
  962.  
  963.         // port BE write
  964.         assign clr_nmi = ( (loa==ZXEVBE) && port_wr_fclk );
  965.  
  966.  
  967.  
  968.  
  969.         // covox/beeper writes
  970.  
  971.         assign beeper_wr = (loa==PORTFE) && portfe_wr_fclk;
  972.         assign covox_wr  = (loa==COVOX) && port_wr_fclk;
  973.  
  974.  
  975.  
  976.         // font write enable
  977.         assign fnt_wr = fntw_en_reg && mem_wr_fclk;
  978.  
  979.  
  980.  
  981.         // port BE read
  982.  
  983.         always @*
  984.         case( a[12:8] )
  985.  
  986.         BD_PG0: portbdmux = pages[ 7:0 ];
  987.         BD_PG1: portbdmux = pages[15:8 ];
  988.         BD_PG2: portbdmux = pages[23:16];
  989.         BD_PG3: portbdmux = pages[31:24];
  990.         BD_PG4: portbdmux = pages[39:32];
  991.         BD_PG5: portbdmux = pages[47:40];
  992.         BD_PG6: portbdmux = pages[55:48];
  993.         BD_PG7: portbdmux = pages[63:56];
  994.  
  995.         BD_RAMNROMS: portbdmux = ramnroms;
  996.         BD_DOS7FFDS: portbdmux = dos7ffds;
  997.  
  998.         BD_P7FFD: portbdmux = p7ffd_int;
  999.         BD_PEFF7: portbdmux = peff7_int;
  1000.  
  1001.         BD_PXX77: portbdmux = { ~atm_pen2, atm_cpm_n, ~atm_pen, dos, atm_turbo, atm_scr_mode };
  1002.  
  1003.         BD_COLORRD: portbdmux = { ~palcolor[4], ~palcolor[2], ~palcolor[0], ~palcolor[5], 2'b11, ~palcolor[3], ~palcolor[1] };
  1004. //      assign atm_paldata = { ~din[4], ~din[7], ~din[1], ~din[6], ~din[0], ~din[5] };
  1005. //  {GgRrBb} -> {grbG11RB}
  1006. // was: 76543210 -> 471605
  1007. // now:             543210 -> 4205xx31
  1008.         BD_FNTRD:    portbdmux = fontrom_readback;
  1009.         BD_BORDERRD: portbdmux = { 4'bXXXX, border };
  1010.  
  1011.         BD_LOBRK: portbdmux = brk_addr[7:0];
  1012.         BD_HIBRK: portbdmux = brk_addr[15:8];
  1013.  
  1014.         BD_WRDISRD: portbdmux = wrdisables;
  1015.  
  1016.         BD_FDDMASK: portbdmux = { 4'bXXXX, fdd_mask };
  1017.  
  1018.         BD_IRQCFG:  portbdmux = rd_irq_cfg ;
  1019.         BD_IRQENA:  portbdmux = rd_irq_ena ;
  1020.         BD_IRQSTAT: portbdmux = rd_irq_stat;
  1021.  
  1022.         default: portbdmux = 8'bXXXXXXXX;
  1023.  
  1024.         endcase
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.         // ULAPLUS ports
  1034.         reg up_select; // 0 -- ena/dis, 1 -- palette write
  1035.         //
  1036.         wire up_wr = port_wr_fclk && (loa==ULAPLUS);
  1037.         //
  1038.         always @(posedge fclk)
  1039.         if( up_wr && !a[14] )
  1040.         begin
  1041.                 if( !din[7] &&  din[6] )
  1042.                 begin
  1043.                         up_select <= 1'b1;
  1044.                 end
  1045.  
  1046.                 if( !din[7] && !din[6] )
  1047.                 begin
  1048.                         up_select <= 1'b0;
  1049.                         up_paladdr[5:0] <= din[5:0];
  1050.                 end
  1051.         end
  1052.         //
  1053.         always @(posedge fclk) if( up_wr && a[14] )
  1054.                 up_lastwritten <= din;
  1055.         //
  1056.         assign up_palwr = up_wr && a[14] && !up_select;
  1057.         //
  1058.         always @(posedge fclk, negedge rst_n)
  1059.         if( !rst_n )
  1060.                 up_ena <= 1'b0;
  1061.         else if( up_wr && a[14] && up_select )
  1062.                 up_ena <= din[0];
  1063.         //
  1064.         assign up_paldata = {din[4:2],din[7:5],din[1:0]}; // G3R3B2 to R3G3B2
  1065.  
  1066.  
  1067.         // irq ports
  1068.         assign rd_irq_cfg  = {irq_emh, 4'd0, irq_ena_ext_vec, irq_ena_int_vec, irq_ena_autoclr};
  1069.         assign rd_irq_ena  = {1'b0, irq_ena_rd};
  1070.         assign rd_irq_stat = (1'b0, irq_stat_rd};
  1071.  
  1072.         always @(posedge fclk, negedge rst_n)
  1073.         if( !rst_n )
  1074.         begin
  1075.                 irq_enh         <= 1'b0;
  1076.                 irq_ena_int_vec <= 1'b0;
  1077.                 irq_ena_ext_vec <= 1'b0;
  1078.                 irq_int_autoclr <= 1'b0;
  1079.         end
  1080.         else if( zxevbd_wr_fclk && a[12:8]==BD_IRQCFG )
  1081.         begin
  1082.                 irq_enh         <= din[7];
  1083.                 irq_ena_int_vec <= din[2];
  1084.                 irq_ena_ext_vec <= din[1];
  1085.                 irq_int_autoclr <= din[0];
  1086.         end
  1087.  
  1088.         assign  irq_stat_wr_stb = zxevbd_wr_fclk && a[12:8]==BD_IRQSTAT;
  1089.         assign {irq_stat_setnrst,
  1090.                 irq_stat_wr_sel } = din;
  1091.  
  1092.         assign  irq_ena_wr_stb = zxevbd_wr_fclk && a[12:8]==BD_IRQENA;
  1093.         assign {irq_ena_setnrst,
  1094.                 irq_ena_wr_sel } = din;
  1095.  
  1096.  
  1097.  
  1098. endmodule
  1099.  
  1100.