Subversion Repositories pentevo

Rev

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

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