Subversion Repositories pentevo

Rev

Rev 737 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
713 lvd 1
// ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014,2015,2016
389 lvd 2
//
3
// NMI generation
4
 
668 lvd 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
 
389 lvd 24
`include "../include/tune.v"
25
 
26
module znmi
27
(
518 lvd 28
        input  wire        rst_n,
29
        input  wire        fclk,
389 lvd 30
 
518 lvd 31
        input  wire        zpos,
32
        input  wire        zneg,
389 lvd 33
 
518 lvd 34
        input  wire        int_start, // when INT starts
576 lvd 35
        input  wire [ 1:0] set_nmi,   // NMI requests from slavespi and #BF port
36
        input  wire        imm_nmi,   // immediate NMI from breakpoint
401 lvd 37
 
518 lvd 38
        input  wire        clr_nmi, // clear nmi: from zports, pulsed at out to #xxBE
389 lvd 39
 
401 lvd 40
 
518 lvd 41
        input  wire        rfsh_n,
42
        input  wire        m1_n,
43
        input  wire        mreq_n,
389 lvd 44
 
518 lvd 45
        input  wire        csrom,
389 lvd 46
 
518 lvd 47
        input  wire [15:0] a,
515 lvd 48
 
389 lvd 49
 
699 lvd 50
        output wire drive_00, // drive nop to Z80 databus
51
 
52
 
737 lvd 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
389 lvd 56
);
57
 
476 lvd 58
        reg  [1:0] set_nmi_r;
59
        wire       set_nmi_now;
389 lvd 60
 
576 lvd 61
        reg        imm_nmi_r;
62
        wire       imm_nmi_now;
63
 
64
 
404 lvd 65
        reg pending_nmi;
66
 
543 lvd 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
404 lvd 69
 
389 lvd 70
 
543 lvd 71
        reg [2:0] nmi_count;
72
 
404 lvd 73
        reg [1:0] clr_count;
389 lvd 74
 
404 lvd 75
        reg pending_clr;
76
 
77
 
515 lvd 78
        reg last_m1_rom;
79
 
543 lvd 80
        reg last_m1_0066;
515 lvd 81
 
82
 
576 lvd 83
        wire nmi_start;
515 lvd 84
 
543 lvd 85
 
576 lvd 86
 
515 lvd 87
        //remember whether last M1 opcode read was from ROM or RAM
88
        reg m1_n_reg, mreq_n_reg;
543 lvd 89
        reg [1:0] rfsh_n_reg;
515 lvd 90
 
91
        always @(posedge fclk) if( zpos )
543 lvd 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 )
515 lvd 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
 
401 lvd 107
        always @(posedge fclk)
515 lvd 108
                was_m1_reg <= was_m1;
109
 
110
 
111
        always @(posedge fclk)
112
        if( was_m1 && (!was_m1_reg) )
518 lvd 113
                last_m1_rom <= csrom && (a[15:14]==2'b00);
515 lvd 114
 
543 lvd 115
        always @(posedge fclk)
116
        if( was_m1 && (!was_m1_reg) )
117
                last_m1_0066 <= ( a[15:0]==16'h0066 );
515 lvd 118
 
119
 
120
 
121
 
122
 
123
        always @(posedge fclk)
404 lvd 124
                set_nmi_r <= set_nmi;
125
        //
576 lvd 126
        assign set_nmi_now = | (set_nmi_r & (~set_nmi) );
389 lvd 127
 
576 lvd 128
        always @(posedge fclk)
129
                imm_nmi_r <= imm_nmi;
130
        //
131
        assign imm_nmi_now = | ( (~imm_nmi_r) & imm_nmi );
389 lvd 132
 
576 lvd 133
 
134
 
401 lvd 135
        always @(posedge fclk, negedge rst_n)
389 lvd 136
        if( !rst_n )
404 lvd 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
 
576 lvd 147
        // actual nmi start
148
        assign nmi_start = (pending_nmi && int_start) || imm_nmi_now;
404 lvd 149
 
150
 
576 lvd 151
 
404 lvd 152
        always @(posedge fclk)
153
        if( clr_nmi )
154
                clr_count <= 2'd3;
543 lvd 155
        else if( rfsh_n_reg[1] && (!rfsh_n_reg[0]) && clr_count[1] )
404 lvd 156
                clr_count <= clr_count - 2'd1;
157
 
158
        always @(posedge fclk)
159
        if( clr_nmi )
160
                pending_clr <= 1'b1;
543 lvd 161
        else if( !clr_count[1] )
404 lvd 162
                pending_clr <= 1'b0;
163
 
164
 
543 lvd 165
        always @(posedge fclk, negedge rst_n)
166
        if( !rst_n )
167
                in_nmi_2 <= 1'b0;
168
        else // posedge fclk
169
        begin
668 lvd 170
                if( nmi_start && (!in_nmi) /*&& last_m1_rom*/ ) // fix for NMI page after execution of 0066 opcode everywhere
543 lvd 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
404 lvd 175
 
543 lvd 176
 
738 lvd 177
        assign drive_00 = in_nmi_2 && (!m1_n) && (!mreq_n) && (a[15:0]==16'h0066); // && last_m1_0066;
699 lvd 178
 
737 lvd 179
        assign nmi_buf_clr = last_m1_0066 && in_nmi_2;
699 lvd 180
 
404 lvd 181
        always @(posedge fclk, negedge rst_n)
182
        if( !rst_n )
389 lvd 183
                in_nmi <= 1'b0;
404 lvd 184
        else // posedge clk
389 lvd 185
        begin
543 lvd 186
                if( pending_clr && (!clr_count[1]) )
389 lvd 187
                        in_nmi <= 1'b0;
668 lvd 188
                else if( /*(nmi_start && (!in_nmi) && (!last_m1_rom))                      ||*/
543 lvd 189
                         (rfsh_n_reg[1] && (!rfsh_n_reg[0]) && last_m1_0066 && in_nmi_2) )
389 lvd 190
                        in_nmi <= 1'b1;
191
        end
192
 
193
 
401 lvd 194
        always @(posedge fclk, negedge rst_n)
389 lvd 195
        if( !rst_n )
543 lvd 196
                nmi_count <= 3'b000;
576 lvd 197
        else if( nmi_start && (!in_nmi) )
543 lvd 198
                nmi_count <= 3'b111;
199
        else if( nmi_count[2] && zpos )
200
                nmi_count <= nmi_count - 3'd1;
389 lvd 201
 
202
 
543 lvd 203
        assign gen_nmi = nmi_count[2];
389 lvd 204
 
205
 
206
endmodule
207