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 |