Subversion Repositories pentevo

Rev

Rev 197 | Rev 425 | 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. // 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 3FF7,7FF7,BFF7,FFF7 as well as 37F7, 77F7, B7F7, F7F7
  8.  
  9. `include "../include/tune.v"
  10.  
  11. module atm_pager(
  12.  
  13.         input  wire rst_n,
  14.  
  15.         input  wire fclk,
  16.         input  wire zpos,
  17.         input  wire zneg,
  18.  
  19.  
  20.         input  wire [15:0] za, // Z80 address bus
  21.  
  22.         input  wire [ 7:0] zd, // Z80 data bus - for latching port data
  23.  
  24.         input  wire        mreq_n,rd_n,m1_n, // to track DOS turn on/turn off
  25.  
  26.  
  27.         input  wire        pager_off, // PEN as in ATM2: turns off memory paging, service ROM is everywhere
  28.  
  29.  
  30.         input  wire        pent1m_ROM,    // for memory maps switching: d4 of 7ffd
  31.         input  wire [ 5:0] pent1m_page,   // 1 megabyte from pentagon1024 addressing, from 7FFD port
  32.         input  wire        pent1m_ram0_0, // RAM0 to the window 0 from pentagon1024 mode
  33.         input  wire        pent1m_1m_on,  // 1 meg addressing of pent1m mode on
  34.  
  35.  
  36.         input  wire        atmF7_wr, // write strobe for the xxF7 ATM port
  37.  
  38.  
  39.         input  wire        dos, // indicates state of computer: also determines ROM mapping
  40.  
  41.  
  42.         output wire        dos_turn_on,  // turns on or off DOS signal
  43.         output wire        dos_turn_off, //
  44.  
  45.         output wire        zclk_stall, // stall Z80 clock during DOS turning on
  46.  
  47.         output reg  [ 7:0] page,
  48.         output reg         romnram
  49. );
  50.         parameter ADDR = 2'b00;
  51.  
  52.  
  53.         reg [ 7:0] pages [0:1]; // 2 pages for each map - switched by pent1m_ROM
  54.  
  55.         reg [ 1:0] ramnrom; // ram(=1) or rom(=0)
  56.         reg [ 1:0] dos_7ffd; // =1 7ffd bits (ram) or DOS enter mode (rom) for given page
  57.  
  58.         reg mreq_n_reg, rd_n_reg, m1_n_reg;
  59.  
  60.         wire dos_exec_stb, ram_exec_stb;
  61.  
  62.  
  63.         reg [2:0] stall_count;
  64.  
  65.  
  66.         // paging function, does not set pages, ramnrom, dos_7ffd
  67.         //
  68.         always @(posedge fclk)
  69.         begin
  70.                 if( pager_off )
  71.                 begin // atm no pager mode - each window has same ROM
  72.                         romnram <= 1'b1;
  73.                         page    <= 8'hFF;
  74.                 end
  75.                 else // pager on
  76.                 begin
  77.                         if( pent1m_ram0_0 && (ADDR==2'b00) ) // shortcut for pentagon ram0
  78.                         begin
  79.                                 romnram <= 1'b0;
  80.                                 page    <= 8'd0;
  81.                         end
  82.                         else
  83.                         begin
  84.                                 romnram <= ~ramnrom[ pent1m_ROM ];
  85.  
  86.                                 if( dos_7ffd[ pent1m_ROM ] ) // 7ffd memmap switching
  87.                                 begin
  88.                                         if( ramnrom[ pent1m_ROM ] )
  89.                                         begin // ram map
  90.                                                 if( pent1m_1m_on )
  91.                                                 begin // map whole Mb from 7ffd to atm pages
  92.                                                         page <= { pages[ pent1m_ROM ][7:6], pent1m_page[5:0] };
  93.                                                 end
  94.                                                 else //128k like in atm2
  95.                                                 begin
  96.                                                         page <= { pages[ pent1m_ROM ][7:3], pent1m_page[2:0] };
  97.                                                 end
  98.                                         end
  99.                                         else // rom map with dos
  100.                                         begin
  101.                                                 page <= { pages[ pent1m_ROM ][7:1], dos };
  102.                                         end
  103.                                 end
  104.                                 else // no 7ffd impact
  105.                                 begin
  106.                                         page <= pages[ pent1m_ROM ];
  107.                                 end
  108.                         end
  109.                 end
  110.         end
  111.  
  112.  
  113.  
  114.  
  115.         // port reading: sets pages, ramnrom, dos_7ffd
  116.         //
  117.         always @(posedge fclk, negedge rst_n)
  118.         if( !rst_n )
  119.         begin
  120.                 // default mode must be pent1m
  121.                 case( ADDR )
  122.  
  123.                 2'b00: begin // ROM pages
  124.                         ramnrom[0] = 1'b0;
  125.                         ramnrom[1] = 1'b0;
  126.  
  127.                         dos_7ffd[0] = 1'b1;
  128.                         dos_7ffd[1] = 1'b1;
  129.  
  130.                         pages[0] = 8'hFE; // basic128 page
  131.                         pages[1] = 8'hFC; // basic48 page
  132.                 end
  133.  
  134.                 2'b01: begin // 4000-7fff ram page 5
  135.                         ramnrom[0] = 1'b1;
  136.                         ramnrom[1] = 1'b1;
  137.  
  138.                         dos_7ffd[0] = 1'b0;
  139.                         dos_7ffd[1] = 1'b0;
  140.  
  141.                         pages[0] = 8'h05; // pent1m 5 page
  142.                         pages[1] = 8'h05; // pent1m 5 page
  143.                 end
  144.  
  145.                 2'b10: begin // 8000-bfff ram page 2
  146.                         ramnrom[0] = 1'b1;
  147.                         ramnrom[1] = 1'b1;
  148.  
  149.                         dos_7ffd[0] = 1'b0;
  150.                         dos_7ffd[1] = 1'b0;
  151.  
  152.                         pages[0] = 8'h02; // pent1m 2 page
  153.                         pages[1] = 8'h02; // pent1m 2 page
  154.                 end
  155.  
  156.                 2'b11: begin // c000-ffff
  157.                         ramnrom[0] = 1'b1;
  158.                         ramnrom[1] = 1'b1;
  159.  
  160.                         dos_7ffd[0] = 1'b1;
  161.                         dos_7ffd[1] = 1'b1;
  162.  
  163.                         pages[0] = 8'h00; // pent1m 0 page
  164.                         pages[1] = 8'h00; // pent1m 0 page
  165.                 end
  166.  
  167.                 endcase
  168.         end
  169.         else if( atmF7_wr )
  170.         begin
  171.                 if( za[15:14]==ADDR )
  172.                 begin
  173.                         if( za[11] ) // xff7 ports - 1 meg
  174.                         begin
  175.                                 pages   [ pent1m_ROM ] <= ~{ 2'b11, zd[5:0] };
  176.                                 ramnrom [ pent1m_ROM ] <= zd[6];
  177.                                 dos_7ffd[ pent1m_ROM ] <= zd[7];
  178.                         end
  179.                         else // x7f7 ports - 4 meg ram
  180.                         begin
  181.                                 pages   [ pent1m_ROM ] <= ~zd;
  182.                                 ramnrom [ pent1m_ROM ] <= 1'b1; // RAM on
  183.                                 // dos_7ffd - UNCHANGED!!! (possibility to use 7ffd 1m and 128k addressing in the whole 4m!)
  184.                         end
  185.                 end
  186.         end
  187.  
  188.  
  189.         // DOS turn on/turn off
  190.         //
  191.  
  192. `ifdef SIMULATE
  193.         initial
  194.         begin
  195.                 m1_n_reg   = 1'b1;
  196.                 mreq_n_reg = 1'b1;
  197.                 rd_n_reg   = 1'b1;
  198.  
  199.                 stall_count = 3'b000;
  200.         end
  201. `endif
  202.  
  203.         always @(posedge fclk) if( zpos )
  204.         begin
  205.                 m1_n_reg <= m1_n;
  206.         end
  207.  
  208.         always @(posedge fclk) if( zneg )
  209.         begin
  210.                 mreq_n_reg <= mreq_n;
  211.         end
  212.  
  213.  
  214.  
  215.         assign dos_exec_stb = zneg && (za[15:14]==ADDR) &&
  216.                               (!m1_n_reg) && (!mreq_n) && mreq_n_reg &&
  217.                               (za[13:8]==6'h3D) &&
  218.                               dos_7ffd[1'b1] && (!ramnrom[1'b1]) && pent1m_ROM;
  219.  
  220.         assign ram_exec_stb = zneg && (za[15:14]==ADDR) &&
  221.                               (!m1_n_reg) && (!mreq_n) && mreq_n_reg &&
  222.                               ramnrom[pent1m_ROM];
  223.  
  224.         assign dos_turn_on  = dos_exec_stb;
  225.         assign dos_turn_off = ram_exec_stb;
  226.  
  227.  
  228.         // stall Z80 for some time when dos turning on to allow ROM chip to supply new data
  229.         // this can be important at 7 or even 14 mhz. minimum stall time is
  230.         // 3 clocks @ 28 MHz
  231.         always @(posedge fclk)
  232.         begin
  233.                 // яхЁхъы■ўхэшх т ─╬╤ ячє яЁюшёїюфшЄ чр яюыЄръЄр z80 фю Єюую, ъръ
  234.                 // z80 ёўшЄрхЄ фрээ√х. Є.х. є ячє яюыЄръЄр фы  т√фрўш эют√ї фрээ√ї.
  235.                 // 3.5ьуЎ - 140 эрэ, 7ьуЎ - 70 эрэ, 14ьуЎ - 35 эрэ.
  236.                 // фы  ячєїш 120эё эр 14ьуЎ эрфю х∙х 3 яюыЄръЄр фюсртшЄ№, шыш фЁєушьш
  237.                 // ёыютрьш, фюсртшЄ№ ъ ы■сющ чрфхЁцъх эр ы■сющ ўрёЄюЄх ьшэшьєь 3 ЄръЄр
  238.                 // 28 ьуЎ.
  239.                 if( dos_turn_on )
  240.                 begin
  241.                         stall_count[2] <= 1'b1; // count: 000(stop) -> 101 -> 110 -> 111 -> 000(stop)
  242.                         stall_count[0] <= 1'b1;
  243.                 end
  244.                 else if( stall_count[2] )
  245.                 begin
  246.                         stall_count[2:0] <= stall_count[2:0] + 3'd1;
  247.                 end
  248.  
  249.         end
  250.  
  251.         assign zclk_stall = dos_turn_on | stall_count[2];
  252.  
  253.  
  254.  
  255. endmodule
  256.  
  257.