Subversion Repositories pentevo

Rev

Rev 738 | 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,2015,2016
  2. //
  3. // NMI generation
  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 znmi
  27. (
  28.         input  wire        rst_n,
  29.         input  wire        fclk,
  30.  
  31.         input  wire        zpos,
  32.         input  wire        zneg,
  33.  
  34.         input  wire        int_start, // when INT starts
  35.         input  wire [ 1:0] set_nmi,   // NMI requests from slavespi and #BF port
  36.         input  wire        imm_nmi,   // immediate NMI from breakpoint
  37.  
  38.         input  wire        clr_nmi, // clear nmi: from zports, pulsed at out to #xxBE
  39.  
  40.  
  41.         input  wire        rfsh_n,
  42.         input  wire        m1_n,
  43.         input  wire        mreq_n,
  44.  
  45.         input  wire        csrom,
  46.  
  47.         input  wire [15:0] a,
  48.  
  49.  
  50.         output wire drive_00, // drive nop to Z80 databus
  51.  
  52.  
  53.         output reg         in_nmi,  // when 1, there must be last (#FF) ram page in 0000-3FFF
  54.         output wire        gen_nmi, // NMI generator: when 1, NMI_N=0, otherwise NMI_N=Z
  55.         output wire        nmi_buf_clr // clear ram read buffer in zmem during nmi entry
  56. );
  57.  
  58.         reg  [1:0] set_nmi_r;
  59.         wire       set_nmi_now;
  60.  
  61.         reg        imm_nmi_r;
  62.         wire       imm_nmi_now;
  63.  
  64.  
  65.         reg pending_nmi;
  66.  
  67.         reg in_nmi_2; // active (=1) when NMIed to ROM, after 0066 M1 becomes 0,
  68.                       // but in_nmi becomes 1 -- ROM switches to #FF RAM
  69.  
  70.  
  71.         reg [2:0] nmi_count;
  72.  
  73.         reg [1:0] clr_count;
  74.  
  75.         reg pending_clr;
  76.  
  77.  
  78.         reg last_m1_rom;
  79.  
  80.         reg last_m1_0066;
  81.  
  82.  
  83.         wire nmi_start;
  84.  
  85.  
  86.  
  87.         //remember whether last M1 opcode read was from ROM or RAM
  88.         reg m1_n_reg, mreq_n_reg;
  89.         reg [1:0] rfsh_n_reg;
  90.  
  91.         always @(posedge fclk) if( zpos )
  92.                 rfsh_n_reg[0] <= rfsh_n;
  93.         always @(posedge fclk)
  94.                 rfsh_n_reg[1] <= rfsh_n_reg[0];
  95.  
  96.  
  97.         always @(posedge fclk) if( zpos )
  98.                 m1_n_reg <= m1_n;
  99.  
  100.         always @(posedge fclk) if( zneg )
  101.                 mreq_n_reg <= mreq_n;
  102.  
  103.         wire was_m1 = ~(m1_n_reg | mreq_n_reg);
  104.  
  105.         reg was_m1_reg;
  106.  
  107.         always @(posedge fclk)
  108.                 was_m1_reg <= was_m1;
  109.  
  110.  
  111.         always @(posedge fclk)
  112.         if( was_m1 && (!was_m1_reg) )
  113.                 last_m1_rom <= csrom && (a[15:14]==2'b00);
  114.  
  115.         always @(posedge fclk)
  116.         if( was_m1 && (!was_m1_reg) )
  117.                 last_m1_0066 <= ( a[15:0]==16'h0066 );
  118.  
  119.  
  120.  
  121.  
  122.  
  123.         always @(posedge fclk)
  124.                 set_nmi_r <= set_nmi;
  125.         //
  126.         assign set_nmi_now = | (set_nmi_r & (~set_nmi) );
  127.  
  128.         always @(posedge fclk)
  129.                 imm_nmi_r <= imm_nmi;
  130.         //
  131.         assign imm_nmi_now = | ( (~imm_nmi_r) & imm_nmi );
  132.  
  133.  
  134.  
  135.         always @(posedge fclk, negedge rst_n)
  136.         if( !rst_n )
  137.                 pending_nmi <= 1'b0;
  138.         else // posedge clk
  139.         begin
  140.                 if( int_start )
  141.                         pending_nmi <= 1'b0;
  142.                 else if( set_nmi_now )
  143.                         pending_nmi <= 1'b1;
  144.         end
  145.  
  146.  
  147.         // actual nmi start
  148.         assign nmi_start = (pending_nmi && int_start) || imm_nmi_now;
  149.  
  150.  
  151.  
  152.         always @(posedge fclk)
  153.         if( clr_nmi )
  154.                 clr_count <= 2'd3;
  155.         else if( rfsh_n_reg[1] && (!rfsh_n_reg[0]) && clr_count[1] )
  156.                 clr_count <= clr_count - 2'd1;
  157.  
  158.         always @(posedge fclk)
  159.         if( clr_nmi )
  160.                 pending_clr <= 1'b1;
  161.         else if( !clr_count[1] )
  162.                 pending_clr <= 1'b0;
  163.  
  164.  
  165.         always @(posedge fclk, negedge rst_n)
  166.         if( !rst_n )
  167.                 in_nmi_2 <= 1'b0;
  168.         else // posedge fclk
  169.         begin
  170.                 if( nmi_start && (!in_nmi) /*&& last_m1_rom*/ ) // fix for NMI page after execution of 0066 opcode everywhere
  171.                         in_nmi_2 <= 1'b1;
  172.                 else if( rfsh_n_reg[1] && (!rfsh_n_reg[0]) && last_m1_0066 )
  173.                         in_nmi_2 <= 1'b0;
  174.         end
  175.  
  176.  
  177.         assign drive_00 = in_nmi_2 && (!m1_n) && (!mreq_n) && (a[15:0]==16'h0066); // && last_m1_0066;
  178.  
  179.         assign nmi_buf_clr = last_m1_0066 && in_nmi_2;
  180.  
  181.         always @(posedge fclk, negedge rst_n)
  182.         if( !rst_n )
  183.                 in_nmi <= 1'b0;
  184.         else // posedge clk
  185.         begin
  186.                 if( pending_clr && (!clr_count[1]) )
  187.                         in_nmi <= 1'b0;
  188.                 else if( /*(nmi_start && (!in_nmi) && (!last_m1_rom))                      ||*/
  189.                          (rfsh_n_reg[1] && (!rfsh_n_reg[0]) && last_m1_0066 && in_nmi_2) )
  190.                         in_nmi <= 1'b1;
  191.         end
  192.  
  193.  
  194.         always @(posedge fclk, negedge rst_n)
  195.         if( !rst_n )
  196.                 nmi_count <= 3'b000;
  197.         else if( nmi_start && (!in_nmi) )
  198.                 nmi_count <= 3'b111;
  199.         else if( nmi_count[2] && zpos )
  200.                 nmi_count <= nmi_count - 3'd1;
  201.  
  202.  
  203.         assign gen_nmi = nmi_count[2];
  204.  
  205.  
  206. endmodule
  207.  
  208.