Subversion Repositories pentevo

Rev

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

  1. `include "../include/tune.v"
  2.  
  3. // PentEvo project (c) NedoPC 2008-2009
  4. //
  5. // Z80 memory manager: routes ROM/RAM accesses, makes wait-states for 14MHz or stall condition, etc.
  6. //
  7. //
  8. // fclk    _/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\
  9. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  10. // zclk     /```\___/```\___/```\___/```````\_______/```````\_______/```````````````\_______________/```````````````\_______________/`
  11. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  12. // zpos     `\___/```\___/```\___/```\___________/```\___________/```\___________________________/```\___________________________/```\
  13. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  14. // zneg     _/```\___/```\___/```\_______/```\___________/```\___________________/```\___________________________/```\________________
  15.  
  16. module zmem(
  17.  
  18.         input  wire fclk,
  19.         input  wire rst_n,
  20.  
  21.         input  wire zpos, //
  22.         input  wire zneg, // strobes which show positive and negative edges of zclk
  23.  
  24.         input  wire cbeg,      // DRAM synchronization
  25.         input  wire post_cbeg, //
  26.         input  wire pre_cend,  //
  27.         input  wire cend,      //
  28.  
  29.  
  30.         input  wire [15:0] za,
  31.  
  32.         input  wire [ 7:0] zd_in, // won't emit anything to Z80 bus, data bus mux is another module
  33.         output wire [ 7:0] zd_out, // output to Z80 bus
  34.  
  35.         output wire zd_ena, // out bus to the Z80
  36.  
  37.         input  wire m1_n,
  38.         input  wire rfsh_n,
  39.         input  wire mreq_n,
  40.         input  wire iorq_n,
  41.         input  wire rd_n,
  42.         input  wire wr_n,
  43.  
  44.  
  45.         input  wire [ 1:0] int_turbo, // 2'b00 - 3.5,
  46.                                       // 2'b01 - 7.0,
  47.                                       // 2'b1x - 14.0
  48.  
  49.  
  50.  
  51.         input  wire        win0_romnram, // four windows, each 16k,
  52.         input  wire        win1_romnram, // ==1 - there is rom,
  53.         input  wire        win2_romnram, // ==0 - there is ram
  54.         input  wire        win3_romnram, //
  55.  
  56.         input  wire [ 7:0] win0_page, // which 16k page is in given window
  57.         input  wire [ 7:0] win1_page, //
  58.         input  wire [ 7:0] win2_page, //
  59.         input  wire [ 7:0] win3_page, //
  60.  
  61.  
  62.         input  wire        romrw_en,
  63.  
  64.  
  65.         output reg  [ 4:0] rompg, // output for ROM paging
  66.         output wire        romoe_n,
  67.         output wire        romwe_n,
  68.         output wire        csrom,
  69.  
  70.  
  71.         output wire        cpu_req,
  72.         output wire        cpu_rnw,
  73.         output wire [20:0] cpu_addr,
  74.         output wire [ 7:0] cpu_wrdata,
  75.         output wire        cpu_wrbsel,
  76.  
  77.         input  wire [15:0] cpu_rddata,
  78.  
  79.         input  wire        cpu_next,
  80.         input  wire        cpu_strobe,
  81.  
  82.  
  83.         output wire        cpu_stall // for zclock
  84.  
  85. );
  86.  
  87.  
  88.         wire [1:0] win;
  89.         reg [7:0] page;
  90.         reg romnram;
  91.  
  92.  
  93.  
  94.  
  95.         reg [15:0] rd_buf;
  96.  
  97.         reg [15:1] cached_addr;
  98.         reg        cached_addr_valid;
  99.  
  100.         wire cache_hit;
  101.  
  102.  
  103.         wire dram_beg;
  104.         wire opfetch, memrd, memwr;
  105.         wire stall14, stall7_35;
  106.  
  107.         wire stall14_ini;
  108.         wire stall14_cyc;
  109.         reg  stall14_cycrd;
  110.         reg  stall14_fin;
  111.  
  112.         reg r_mreq_n;
  113.  
  114.  
  115.         reg pending_cpu_req;
  116.  
  117.         reg cpu_rnw_r;
  118.  
  119.  
  120.  
  121.         // this is for 7/3.5mhz  
  122.         wire ramreq;
  123.         wire ramwr,ramrd;
  124.         wire cpureq_357;
  125.         reg ramrd_reg,ramwr_reg;
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.         // make paging
  133.         assign win[1:0] = za[15:14];
  134.  
  135.         always @*
  136.         case( win )
  137.                 2'b00: begin
  138.                         page    = win0_page;
  139.                         romnram = win0_romnram;
  140.                 end
  141.  
  142.                 2'b01: begin
  143.                         page    = win1_page;
  144.                         romnram = win1_romnram;
  145.                 end
  146.  
  147.                 2'b10: begin
  148.                         page    = win2_page;
  149.                         romnram = win2_romnram;
  150.                 end
  151.  
  152.                 2'b11: begin
  153.                         page    = win3_page;
  154.                         romnram = win3_romnram;
  155.                 end
  156.         endcase
  157.  
  158.  
  159.         // rom paging - only half a megabyte addressing.
  160.         always @*
  161.         begin
  162.                 rompg[4:0] = page[4:0];
  163.         end
  164.  
  165.  
  166.  
  167.  
  168.         assign romwe_n = wr_n | mreq_n | (~romrw_en);
  169.         assign romoe_n = rd_n | mreq_n;
  170.  
  171.         assign csrom = romnram; // positive polarity!
  172.  
  173.  
  174.  
  175.         // 7/3.5mhz support
  176.  
  177.         assign ramreq = (~mreq_n) && (~romnram) && rfsh_n;
  178.         assign ramrd = ramreq & (~rd_n);
  179.         assign ramwr = ramreq & (~wr_n);
  180.  
  181.         always @(posedge fclk)
  182.         if( cend && (!cpu_stall) )
  183.         begin
  184.                 ramrd_reg <= ramrd;
  185.                 ramwr_reg <= ramwr;
  186.         end
  187.  
  188.         assign cpureq_357 = ( ramrd & (~ramrd_reg) ) | ( ramwr & (~ramwr_reg) );
  189.        
  190.  
  191.  
  192.  
  193.         assign zd_ena = (~mreq_n) & (~rd_n) & (~romnram);
  194.  
  195.  
  196.  
  197.         assign cache_hit = ( (za[15:1] == cached_addr[15:1]) && cached_addr_valid );
  198.  
  199.  
  200.  
  201.         // strobe the beginnings of DRAM cycles
  202.  
  203.         always @(posedge fclk)
  204.         if( zneg )
  205.                 r_mreq_n <= mreq_n | (~rfsh_n);
  206.         //
  207.         assign dram_beg = ( (!cache_hit) || memwr ) && zneg && r_mreq_n && (!romnram) && (!mreq_n) && rfsh_n;
  208.  
  209.         // access type
  210.         assign opfetch = (~mreq_n) && (~m1_n);
  211.         assign memrd   = (~mreq_n) && (~rd_n);
  212.         assign memwr   = (~mreq_n) &&   rd_n && rfsh_n;
  213.  
  214.  
  215.         // wait tables:
  216.         //
  217.         // M1 opcode fetch, dram_beg coincides with:
  218.         // cend:      +3
  219.         // pre_cend:  +4
  220.         // post_cbeg: +5
  221.         // cbeg:      +6
  222.         //
  223.         // memory read, dram_beg coincides with:
  224.         // cend:      +2
  225.         // pre_cend:  +3
  226.         // post_cbeg: +4
  227.         // cbeg:      +5
  228.         //
  229.         // memory write: no wait
  230.         //
  231.         // special case: if dram_beg pulses 1 when cpu_next is 0,
  232.         // unconditional wait has to be performed until cpu_next is 1, and
  233.         // then wait as if dram_beg would coincide with cbeg
  234.  
  235.         assign stall14_ini = dram_beg && ( (!cpu_next) || opfetch || memrd ); // no wait at all in write cycles, if next dram cycle is available
  236.  
  237.  
  238.         // memrd, opfetch - wait till cend & cpu_next,
  239.         // memwr - wait till cpu_next
  240.         assign stall14_cyc = memwr ? (!cpu_next) : stall14_cycrd;
  241.         //
  242.         always @(posedge fclk, negedge rst_n)
  243.         if( !rst_n )
  244.                 stall14_cycrd <= 1'b0;
  245.         else // posedge fclk
  246.         begin
  247.                 if( cpu_next && cend )
  248.                         stall14_cycrd <= 1'b0;
  249.                 else if( dram_beg && ( (!cend) || (!cpu_next) ) && (opfetch || memrd) )
  250.                         stall14_cycrd <= 1'b1;
  251.         end
  252.         //
  253.         always @(posedge fclk, negedge rst_n)
  254.         if( !rst_n )
  255.                 stall14_fin <= 1'b0;
  256.         else // posedge fclk
  257.         begin
  258.                 if( stall14_fin && ( (opfetch&pre_cend) || (memrd&post_cbeg) ) )
  259.                         stall14_fin <= 1'b0;
  260.                 else if( cpu_next && cend && cpu_req && (opfetch || memrd) )
  261.                         stall14_fin <= 1'b1;
  262.         end
  263.  
  264.  
  265.         //
  266.         assign cpu_stall = int_turbo[1] ? (stall14_ini | stall14_cyc | stall14_fin) : (cpureq_357 && (!cpu_next));
  267.  
  268.         // cpu request
  269.         assign cpu_req = int_turbo[1] ? (pending_cpu_req | dram_beg) : cpureq_357;
  270.         //
  271.         assign cpu_rnw = int_turbo[1] ? (dram_beg ? (!memwr) : cpu_rnw_r) : ramrd;
  272.         //
  273.         //
  274.         always @(posedge fclk, negedge rst_n)
  275.         if( !rst_n )
  276.                 pending_cpu_req <= 1'b0;
  277.         else if( cpu_next && cend )
  278.                 pending_cpu_req <= 1'b0;
  279.         else if( dram_beg )
  280.                 pending_cpu_req <= 1'b1;
  281.         //
  282.         always @(posedge fclk)
  283.         if( dram_beg )
  284.                 cpu_rnw_r <= !memwr;
  285.  
  286.  
  287.  
  288.         // address, data in and data out
  289.         //
  290.         assign cpu_wrbsel = za[0];
  291.         assign cpu_addr[20:0] = { page[7:0], za[13:1] };
  292.         assign cpu_wrdata = zd_in;
  293.         //
  294.         always @* if( cpu_strobe ) // WARNING! ACHTUNG! LATCH!!!
  295.                 rd_buf <= cpu_rddata;
  296.         //
  297.         assign zd_out = cpu_wrbsel ? rd_buf[7:0] : rd_buf[15:8];
  298.  
  299.  
  300.  
  301.  
  302.  
  303.         wire io;
  304.         reg  io_r;
  305.         //
  306.         assign io = (~iorq_n);
  307.         //
  308.         always @(posedge fclk)
  309.         if( zpos )
  310.                 io_r <= io;
  311.         //
  312.         always @(posedge fclk, negedge rst_n)
  313.         if( !rst_n )
  314.         begin
  315.                 cached_addr_valid <= 1'b0;
  316.         end
  317.         else
  318.         begin
  319.                 if( (zneg && r_mreq_n && (!mreq_n) && rfsh_n && romnram) ||
  320.                     (zneg && r_mreq_n && memwr                         ) ||
  321.                     (io && (!io_r) && zpos                             ) )
  322.                         cached_addr_valid <= 1'b0;
  323.                 else if( cpu_strobe )
  324.                         cached_addr_valid <= 1'b1;
  325.         end
  326.         //
  327.         always @(posedge fclk)
  328.         if( !rst_n )
  329.         begin
  330.                 cached_addr <= 15'd0;
  331.         end
  332.         else if( cpu_strobe )
  333.         begin
  334.                 cached_addr[15:1] <= za[15:1];
  335.         end
  336.  
  337.  
  338.  
  339.  
  340. endmodule
  341.  
  342.