Subversion Repositories pentevo

Rev

Rev 518 | Rev 668 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // Pentevo project (c) NedoPC 2011
  2. //
  3. // NMI generation
  4.  
  5. `include "../include/tune.v"
  6.  
  7. module znmi
  8. (
  9.         input  wire        rst_n,
  10.         input  wire        fclk,
  11.  
  12.         input  wire        zpos,
  13.         input  wire        zneg,
  14.  
  15.         input  wire        int_start, // when INT starts
  16.         input  wire [ 1:0] set_nmi,   // NMI request from slavespi
  17.  
  18.         input  wire        clr_nmi, // clear nmi: from zports, pulsed at out to #xxBE
  19.  
  20.  
  21.         input  wire        rfsh_n,
  22.         input  wire        m1_n,
  23.         input  wire        mreq_n,
  24.  
  25.         input  wire        csrom,
  26.  
  27.         input  wire [15:0] a,
  28.  
  29.  
  30.         output reg         in_nmi, // when 1, there must be last (#FF) ram page in 0000-3FFF
  31.  
  32.         output wire        gen_nmi // NMI generator: when 1, NMI_N=0, otherwise NMI_N=Z
  33. );
  34.  
  35.         reg  [1:0] set_nmi_r;
  36.         wire       set_nmi_now;
  37.  
  38.         reg pending_nmi;
  39.  
  40.         reg in_nmi_2; // active (=1) when NMIed to ROM, after 0066 M1 becomes 0,
  41.                       // but in_nmi becomes 1 -- ROM switches to #FF RAM
  42.  
  43.  
  44.         reg [2:0] nmi_count;
  45.  
  46.         reg [1:0] clr_count;
  47.  
  48.         reg pending_clr;
  49.  
  50.  
  51.         reg last_m1_rom;
  52.  
  53.         reg last_m1_0066;
  54.  
  55.  
  56.  
  57.  
  58.         //remember whether last M1 opcode read was from ROM or RAM
  59.         reg m1_n_reg, mreq_n_reg;
  60.         reg [1:0] rfsh_n_reg;
  61.  
  62.         always @(posedge fclk) if( zpos )
  63.                 rfsh_n_reg[0] <= rfsh_n;
  64.         always @(posedge fclk)
  65.                 rfsh_n_reg[1] <= rfsh_n_reg[0];
  66.  
  67.  
  68.         always @(posedge fclk) if( zpos )
  69.                 m1_n_reg <= m1_n;
  70.  
  71.         always @(posedge fclk) if( zneg )
  72.                 mreq_n_reg <= mreq_n;
  73.  
  74.         wire was_m1 = ~(m1_n_reg | mreq_n_reg);
  75.  
  76.         reg was_m1_reg;
  77.  
  78.         always @(posedge fclk)
  79.                 was_m1_reg <= was_m1;
  80.  
  81.  
  82.         always @(posedge fclk)
  83.         if( was_m1 && (!was_m1_reg) )
  84.                 last_m1_rom <= csrom && (a[15:14]==2'b00);
  85.  
  86.         always @(posedge fclk)
  87.         if( was_m1 && (!was_m1_reg) )
  88.                 last_m1_0066 <= ( a[15:0]==16'h0066 );
  89.  
  90.  
  91.  
  92.  
  93.  
  94.         always @(posedge fclk)
  95.                 set_nmi_r <= set_nmi;
  96.         //
  97.         assign set_nmi_now = (set_nmi_r[0] && (!set_nmi[0])) ||
  98.                              (set_nmi_r[1] && (!set_nmi[1])) ;
  99.  
  100.  
  101.         always @(posedge fclk, negedge rst_n)
  102.         if( !rst_n )
  103.                 pending_nmi <= 1'b0;
  104.         else // posedge clk
  105.         begin
  106.                 if( int_start )
  107.                         pending_nmi <= 1'b0;
  108.                 else if( set_nmi_now )
  109.                         pending_nmi <= 1'b1;
  110.         end
  111.  
  112.  
  113.  
  114.  
  115.         always @(posedge fclk)
  116.         if( clr_nmi )
  117.                 clr_count <= 2'd3;
  118.         else if( rfsh_n_reg[1] && (!rfsh_n_reg[0]) && clr_count[1] )
  119.                 clr_count <= clr_count - 2'd1;
  120.  
  121.         always @(posedge fclk)
  122.         if( clr_nmi )
  123.                 pending_clr <= 1'b1;
  124.         else if( !clr_count[1] )
  125.                 pending_clr <= 1'b0;
  126.  
  127.  
  128.         always @(posedge fclk, negedge rst_n)
  129.         if( !rst_n )
  130.                 in_nmi_2 <= 1'b0;
  131.         else // posedge fclk
  132.         begin
  133.                 if( pending_nmi && int_start && (!in_nmi) && last_m1_rom )
  134.                         in_nmi_2 <= 1'b1;
  135.                 else if( rfsh_n_reg[1] && (!rfsh_n_reg[0]) && last_m1_0066 )
  136.                         in_nmi_2 <= 1'b0;
  137.         end
  138.  
  139.  
  140.         always @(posedge fclk, negedge rst_n)
  141.         if( !rst_n )
  142.                 in_nmi <= 1'b0;
  143.         else // posedge clk
  144.         begin
  145.                 if( pending_clr && (!clr_count[1]) )
  146.                         in_nmi <= 1'b0;
  147.                 else if( (pending_nmi && int_start && (!in_nmi) && (!last_m1_rom))       ||
  148.                          (rfsh_n_reg[1] && (!rfsh_n_reg[0]) && last_m1_0066 && in_nmi_2) )
  149.                         in_nmi <= 1'b1;
  150.         end
  151.  
  152.  
  153.         always @(posedge fclk, negedge rst_n)
  154.         if( !rst_n )
  155.                 nmi_count <= 3'b000;
  156.         else if( pending_nmi && int_start && (!in_nmi) )
  157.                 nmi_count <= 3'b111;
  158.         else if( nmi_count[2] && zpos )
  159.                 nmi_count <= nmi_count - 3'd1;
  160.  
  161.  
  162.         assign gen_nmi = nmi_count[2];
  163.  
  164.  
  165. endmodule
  166.  
  167.