Subversion Repositories pentevo

Rev

Rev 905 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014
  2. //
  3. // ATM-like memory pager (it pages specific 16kb region)
  4. //  with additions to support 4m addressable memory
  5. //  and pent1m mode.
  6. //
  7. // contain ports xFF7, x7F7, xBF7
  8.  
  9. /*
  10.     This file is part of ZX-Evo Base Configuration firmware.
  11.  
  12.     ZX-Evo Base Configuration firmware is free software:
  13.     you can redistribute it and/or modify it under the terms of
  14.     the GNU General Public License as published by
  15.     the Free Software Foundation, either version 3 of the License, or
  16.     (at your option) any later version.
  17.  
  18.     ZX-Evo Base Configuration firmware is distributed in the hope that
  19.     it will be useful, but WITHOUT ANY WARRANTY; without even
  20.     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  21.     See the GNU General Public License for more details.
  22.  
  23.     You should have received a copy of the GNU General Public License
  24.     along with ZX-Evo Base Configuration firmware.
  25.     If not, see <http://www.gnu.org/licenses/>.
  26. */
  27.  
  28. `include "../include/tune.v"
  29.  
  30. module atm_pager(
  31.  
  32.         input  wire rst_n,
  33.  
  34.         input  wire fclk,
  35.         input  wire zpos,
  36.         input  wire zneg,
  37.  
  38.  
  39.         input  wire [15:0] za, // Z80 address bus
  40.  
  41.         input  wire [ 7:0] zd, // Z80 data bus - for latching port data
  42.  
  43.         input  wire        mreq_n,rd_n,m1_n, // to track DOS turn on/turn off
  44.  
  45.  
  46.         input  wire        pager_off, // PEN as in ATM2: turns off memory paging, service ROM is everywhere
  47.  
  48.  
  49.         input  wire        pent1m_ROM,    // for memory maps switching: d4 of 7ffd
  50.         input  wire [ 5:0] pent1m_page,   // 1 megabyte from pentagon1024 addressing, from 7FFD port
  51.         input  wire        pent1m_ram0_0, // RAM0 to the window 0 from pentagon1024 mode
  52.         input  wire        pent1m_1m_on,  // 1 meg addressing of pent1m mode on
  53.  
  54.         input  wire        in_nmi, // when we are in nmi, in 0000-3FFF must be last (FFth)
  55.                                    // RAM page. analoguous to pent1m_ram0_0
  56.                                    // but has higher priority
  57.  
  58.         input  wire        in_trdemu, // like 'in_nmi', page 0xFE
  59.         input  wire        trdemu_wr_disable, // disable writes to page FE when trdemu is active
  60.  
  61.         input  wire        atmF7_wr, // write strobe for the xxF7 ATM port
  62.  
  63.  
  64.         input  wire        dos, // indicates state of computer: also determines ROM mapping
  65.  
  66.  
  67.         output wire        dos_turn_on,  // turns on or off DOS signal
  68.         output wire        dos_turn_off, //
  69.  
  70.         output wire        zclk_stall, // stall Z80 clock during DOS turning on
  71.  
  72.         output reg  [ 7:0] page,
  73.         output reg         romnram,
  74.         output reg         wrdisable,
  75.  
  76.         // output for xxBE port read
  77.         output wire     [ 7:0] rd_page0,
  78.         output wire     [ 7:0] rd_page1,
  79.         output wire [ 1:0] rd_dos7ffd,
  80.         output wire [ 1:0] rd_ramnrom,
  81.         output wire [ 1:0] rd_wrdisables
  82. );
  83.         parameter ADDR = 2'b00;
  84.  
  85.  
  86.         reg [ 7:0] pages [0:1]; // 2 pages for each map - switched by pent1m_ROM
  87.  
  88.         reg [ 1:0] ramnrom; // ram(=1) or rom(=0)
  89.         reg [ 1:0] dos_7ffd; // =1 7ffd bits (ram) or DOS enter mode (rom) for given page
  90.  
  91.         reg [ 1:0] wrdisables; // for each map
  92.  
  93.         reg mreq_n_reg, rd_n_reg, m1_n_reg;
  94.  
  95.         wire dos_exec_stb, ram_exec_stb;
  96.  
  97.  
  98.         reg [2:0] stall_count;
  99.  
  100.  
  101.  
  102.         // output data for port xxBE
  103.         assign rd_page0 = pages[0];
  104.         assign rd_page1 = pages[1];
  105.         //
  106.         assign rd_dos7ffd = dos_7ffd;
  107.         assign rd_ramnrom = ramnrom;
  108.         assign rd_wrdisables = wrdisables;
  109.  
  110.  
  111.  
  112.         // paging function, does not set pages, ramnrom, dos_7ffd
  113.         //
  114.         always @(posedge fclk)
  115.         begin
  116.                 if( pager_off )
  117.                 begin // atm no pager mode - each window has same ROM
  118.                         romnram   <= 1'b1;
  119.                         page      <= 8'hFF;
  120.                         wrdisable <= 1'b0;
  121.                 end
  122.                 else // pager on
  123.                 begin
  124.                         if( (ADDR==2'b00) && (pent1m_ram0_0 || in_nmi || in_trdemu) )
  125.                         begin
  126.                                 wrdisable <= trdemu_wr_disable;
  127.  
  128.                                 if( in_nmi || in_trdemu )
  129.                                 begin
  130.                                         romnram <= 1'b0;
  131.                                         page    <= { 7'h7F, in_nmi };
  132.                                 end
  133.                                 else // if( pent1m_ram0_0 )
  134.                                 begin
  135.                                         romnram <= 1'b0;
  136.                                         page    <= 8'd0;
  137.                                 end
  138.                         end
  139.                         else
  140.                         begin
  141.                                 wrdisable <= wrdisables[ pent1m_ROM ];
  142.  
  143.                                 romnram <= ~ramnrom[ pent1m_ROM ];
  144.  
  145.                                 if( dos_7ffd[ pent1m_ROM ] ) // 7ffd memmap switching
  146.                                 begin
  147.                                         if( ramnrom[ pent1m_ROM ] )
  148.                                         begin // ram map
  149.                                                 if( pent1m_1m_on )
  150.                                                 begin // map whole Mb from 7ffd to atm pages
  151.                                                         page <= { pages[ pent1m_ROM ][7:6], pent1m_page[5:0] };
  152.                                                 end
  153.                                                 else //128k like in atm2
  154.                                                 begin
  155.                                                         page <= { pages[ pent1m_ROM ][7:3], pent1m_page[2:0] };
  156.                                                 end
  157.                                         end
  158.                                         else // rom map with dos
  159.                                         begin
  160.                                                 page <= { pages[ pent1m_ROM ][7:1], dos };
  161.                                         end
  162.                                 end
  163.                                 else // no 7ffd impact
  164.                                 begin
  165.                                         page <= pages[ pent1m_ROM ];
  166.                                 end
  167.                         end
  168.                 end
  169.         end
  170.  
  171.  
  172.  
  173.  
  174.         // port reading: sets pages, ramnrom, dos_7ffd
  175.         //
  176.         always @(posedge fclk, negedge rst_n)
  177.         if( !rst_n )
  178.         begin
  179.                 wrdisables <= 2'b00;
  180.         end
  181.         else if( atmF7_wr )
  182.         begin
  183.                 if( za[15:14]==ADDR )
  184.                 case( {za[11],za[10]} )
  185.                         2'b10: begin // xxBF7 port -- ROM/RAM readonly bit
  186.                                 wrdisables[ pent1m_ROM ] <= zd[0];
  187.                         end
  188.  
  189.                         default: begin
  190.                                 // nothing
  191.                         end
  192.                 endcase
  193.         end
  194.         //     
  195.         always @(posedge fclk)
  196.         if( atmF7_wr )
  197.         begin
  198.                 if( za[15:14]==ADDR )
  199.                 case( {za[11],za[10]} )
  200.                         2'b11: begin // xFF7 port
  201.                                 pages   [ pent1m_ROM ] <= ~{ 2'b11, zd[5:0] };
  202.                                 ramnrom [ pent1m_ROM ] <= zd[6];
  203.                                 dos_7ffd[ pent1m_ROM ] <= zd[7];
  204.                         end
  205.  
  206.                         2'b01: begin // x7F7 port
  207.                                 pages   [ pent1m_ROM ] <= ~zd;
  208.                                 ramnrom [ pent1m_ROM ] <= 1'b1; // RAM on
  209.                                 // dos_7ffd - UNCHANGED!!! (possibility to use 7ffd 1m and 128k addressing in the whole 4m!)
  210.                         end
  211.  
  212.                         default: begin
  213.                                 // nothing
  214.                         end
  215.  
  216.                 endcase
  217.         end
  218.  
  219.  
  220.         // DOS turn on/turn off
  221.         //
  222.  
  223. `ifdef SIMULATE
  224.         initial
  225.         begin
  226.                 m1_n_reg   = 1'b1;
  227.                 mreq_n_reg = 1'b1;
  228.                 rd_n_reg   = 1'b1;
  229.  
  230.                 stall_count = 3'b000;
  231.         end
  232. `endif
  233.  
  234.         always @(posedge fclk) if( zpos )
  235.         begin
  236.                 m1_n_reg <= m1_n;
  237.         end
  238.  
  239.         always @(posedge fclk) if( zneg )
  240.         begin
  241.                 mreq_n_reg <= mreq_n;
  242.         end
  243.  
  244.  
  245.  
  246.         assign dos_exec_stb = zneg && (za[15:14]==ADDR) &&
  247.                               (!m1_n_reg) && (!mreq_n) && mreq_n_reg &&
  248.                               (za[13:8]==6'h3D) &&
  249.                               dos_7ffd[1'b1] && (!ramnrom[1'b1]) && pent1m_ROM;
  250.  
  251.         assign ram_exec_stb = zneg && (za[15:14]==ADDR) &&
  252.                               (!m1_n_reg) && (!mreq_n) && mreq_n_reg &&
  253.                               ramnrom[pent1m_ROM];
  254.  
  255.         assign dos_turn_on  = dos_exec_stb;
  256.         assign dos_turn_off = ram_exec_stb;
  257.  
  258.  
  259.         // stall Z80 for some time when dos turning on to allow ROM chip to supply new data
  260.         // this can be important at 7 or even 14 mhz. minimum stall time is
  261.         // 3 clocks @ 28 MHz
  262.         always @(posedge fclk)
  263.         begin
  264.                 // переключение в ДОС пзу происходит за полтакта z80 до того, как
  265.                 // z80 считает данные. т.е. у пзу полтакта для выдачи новых данных.
  266.                 // 3.5мгц - 140 нан, 7мгц - 70 нан, 14мгц - 35 нан.
  267.                 // для пзухи 120нс на 14мгц надо еще 3 полтакта добавить, или другими
  268.                 // словами, добавить к любой задержке на любой частоте минимум 3 такта
  269.                 // 28 мгц.
  270.                 if( dos_turn_on )
  271.                 begin
  272.                         stall_count[2] <= 1'b1; // count: 000(stop) -> 101 -> 110 -> 111 -> 000(stop)
  273.                         stall_count[0] <= 1'b1;
  274.                 end
  275.                 else if( stall_count[2] )
  276.                 begin
  277.                         stall_count[2:0] <= stall_count[2:0] + 3'd1;
  278.                 end
  279.  
  280.         end
  281.  
  282.         assign zclk_stall = dos_turn_on | stall_count[2];
  283.  
  284.  
  285.  
  286. endmodule
  287.  
  288.