Subversion Repositories pentevo

Rev

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