OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [pic/] [pic.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
module pic(
28
    input               clk,
29
    input               rst_n,
30
 
31
    //master pic
32
    input               master_address,
33
    input               master_read,
34
    output reg  [7:0]   master_readdata,
35
    input               master_write,
36
    input       [7:0]   master_writedata,
37
 
38
    //slave pic
39
    input               slave_address,
40
    input               slave_read,
41
    output reg  [7:0]   slave_readdata,
42
    input               slave_write,
43
    input       [7:0]   slave_writedata,
44
 
45
    //interrupt input
46
    input       [15:0]  interrupt_input,
47
 
48
    //interrupt output
49
    output reg          interrupt_do,
50
    output reg  [7:0]   interrupt_vector,
51
    input               interrupt_done
52
);
53
 
54
//------------------------------------------------------------------------------
55
 
56
reg slave_read_last;
57
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) slave_read_last <= 1'b0; else if(slave_read_last) slave_read_last <= 1'b0; else slave_read_last <= slave_read; end
58
wire slave_read_valid = slave_read && slave_read_last == 1'b0;
59
 
60
reg master_read_last;
61
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) master_read_last <= 1'b0; else if(master_read_last) master_read_last <= 1'b0; else master_read_last <= master_read; end
62
wire master_read_valid = master_read && master_read_last == 1'b0;
63
 
64
//------------------------------------------------------------------------------
65
 
66
reg [15:0] interrupt_last;
67
always @(posedge clk or negedge rst_n) begin
68
    if(rst_n == 1'b0)   interrupt_last <= 16'd0;
69
    else                interrupt_last <= interrupt_input;
70
end
71
 
72
//------------------------------------------------------------------------------
73
 
74
wire [7:0] sla_readdata_prepared =
75
    (sla_polled)?                                               { sla_current_irq, 4'd0, sla_irq_value } :
76
    (slave_address == 1'b0 && sla_read_reg_select == 1'b0)?     sla_irr :
77
    (slave_address == 1'b0 && sla_read_reg_select == 1'b1)?     sla_isr :
78
                                                                sla_imr;
79
 
80
always @(posedge clk or negedge rst_n) begin
81
    if(rst_n == 1'b0)   slave_readdata <= 8'd0;
82
    else                slave_readdata <= sla_readdata_prepared;
83
end
84
 
85
wire [7:0] mas_readdata_prepared =
86
    (mas_polled)?                                               { mas_current_irq, 4'd0, mas_irq_value } :
87
    (master_address == 1'b0 && mas_read_reg_select == 1'b0)?    mas_irr :
88
    (master_address == 1'b0 && mas_read_reg_select == 1'b1)?    mas_isr :
89
                                                                mas_imr;
90
 
91
always @(posedge clk or negedge rst_n) begin
92
    if(rst_n == 1'b0)   master_readdata <= 8'd0;
93
    else                master_readdata <= mas_readdata_prepared;
94
end
95
 
96
//------------------------------------------------------------------------------
97
 
98
wire sla_init_icw1 = slave_write && slave_address == 1'b0 && slave_writedata[4] == 1'b1;
99
wire sla_init_icw2 = slave_write && slave_address == 1'b1 && sla_in_init && sla_init_byte_expected == 3'd2;
100
wire sla_init_icw3 = slave_write && slave_address == 1'b1 && sla_in_init && sla_init_byte_expected == 3'd3;
101
wire sla_init_icw4 = slave_write && slave_address == 1'b1 && sla_in_init && sla_init_byte_expected == 3'd4;
102
 
103
wire sla_ocw1 = sla_in_init == 1'b0 && slave_write && slave_address == 1'b1;
104
wire sla_ocw2 = slave_write && slave_address == 1'b0 && slave_writedata[4:3] == 2'b00;
105
wire sla_ocw3 = slave_write && slave_address == 1'b0 && slave_writedata[4:3] == 2'b01;
106
 
107
reg sla_polled;
108
always @(posedge clk or negedge rst_n) begin
109
    if(rst_n == 1'b0)                       sla_polled <= 1'b0;
110
    else if(sla_polled && slave_read_valid) sla_polled <= 1'b0;
111
    else if(sla_ocw3)                       sla_polled <= slave_writedata[2];
112
end
113
 
114
reg sla_read_reg_select;
115
always @(posedge clk or negedge rst_n) begin
116
    if(rst_n == 1'b0)                                                       sla_read_reg_select <= 1'b0;
117
    else if(sla_init_icw1)                                                  sla_read_reg_select <= 1'b0;
118
    else if(sla_ocw3 && slave_writedata[2] == 1'b0 && slave_writedata[1])   sla_read_reg_select <= slave_writedata[0];
119
end
120
 
121
reg sla_special_mask;
122
always @(posedge clk or negedge rst_n) begin
123
    if(rst_n == 1'b0)                                                       sla_special_mask <= 1'd0;
124
    else if(sla_init_icw1)                                                  sla_special_mask <= 1'd0;
125
    else if(sla_ocw3 && slave_writedata[2] == 1'b0 && slave_writedata[6])   sla_special_mask <= slave_writedata[5];
126
end
127
 
128
reg sla_in_init;
129
always @(posedge clk or negedge rst_n) begin
130
    if(rst_n == 1'b0)                                   sla_in_init <= 1'b0;
131
    else if(sla_init_icw1)                              sla_in_init <= 1'b1;
132
    else if(sla_init_icw3 && ~(sla_init_requires_4))    sla_in_init <= 1'b0;
133
    else if(sla_init_icw4)                              sla_in_init <= 1'b0;
134
end
135
 
136
reg sla_init_requires_4;
137
always @(posedge clk or negedge rst_n) begin
138
    if(rst_n == 1'b0)       sla_init_requires_4 <= 1'b0;
139
    else if(sla_init_icw1)  sla_init_requires_4 <= slave_writedata[0];
140
end
141
 
142
reg sla_ltim;
143
always @(posedge clk or negedge rst_n) begin
144
    if(rst_n == 1'b0)       sla_ltim <= 1'b0;
145
    else if(sla_init_icw1)  sla_ltim <= slave_writedata[3];
146
end
147
 
148
reg [2:0] sla_init_byte_expected;
149
always @(posedge clk or negedge rst_n) begin
150
    if(rst_n == 1'b0)                               sla_init_byte_expected <= 3'd0;
151
    else if(sla_init_icw1)                          sla_init_byte_expected <= 3'd2;
152
    else if(sla_init_icw2)                          sla_init_byte_expected <= 3'd3;
153
    else if(sla_init_icw3 && sla_init_requires_4)   sla_init_byte_expected <= 3'd4;
154
end
155
 
156
reg [2:0] sla_lowest_priority;
157
always @(posedge clk or negedge rst_n) begin
158
    if(rst_n == 1'b0)                                                           sla_lowest_priority <= 3'd7;
159
    else if(sla_init_icw1)                                                      sla_lowest_priority <= 3'd7;
160
    else if(sla_ocw2 && slave_writedata == 8'hA0)                               sla_lowest_priority <= sla_lowest_priority + 3'd1;  //rotate on non-specific EOI
161
    else if(sla_ocw2 && { slave_writedata[7:3], 3'b000 } == 8'hC0)              sla_lowest_priority <= slave_writedata[2:0];        //set priority
162
    else if(sla_ocw2 && { slave_writedata[7:3], 3'b000 } == 8'hE0)              sla_lowest_priority <= slave_writedata[2:0];        //rotate on specific EOI
163
    else if(sla_acknowledge_not_spurious && sla_auto_eoi && sla_rotate_on_aeoi) sla_lowest_priority <= sla_lowest_priority + 3'd1;  //rotate on AEOI
164
end
165
 
166
reg [7:0] sla_imr;
167
always @(posedge clk or negedge rst_n) begin
168
    if(rst_n == 1'b0)           sla_imr <= 8'hFF;
169
    else if(sla_init_icw1)      sla_imr <= 8'h00;
170
    else if(sla_ocw1)           sla_imr <= slave_writedata;
171
end
172
 
173
wire [7:0] sla_edge_detect = {
174
    interrupt_input[15] == 1'b1 && interrupt_last[15] == 1'b0,
175
    interrupt_input[14] == 1'b1 && interrupt_last[14] == 1'b0,
176
    interrupt_input[13] == 1'b1 && interrupt_last[13] == 1'b0,
177
    interrupt_input[12] == 1'b1 && interrupt_last[12] == 1'b0,
178
    interrupt_input[11] == 1'b1 && interrupt_last[11] == 1'b0,
179
    interrupt_input[10] == 1'b1 && interrupt_last[10] == 1'b0,
180
    interrupt_input[9]  == 1'b1 && interrupt_last[9] == 1'b0,
181
    interrupt_input[8]  == 1'b1 && interrupt_last[8] == 1'b0
182
};
183
 
184
reg [7:0] sla_irr;
185
always @(posedge clk or negedge rst_n) begin
186
    if(rst_n == 1'b0)                       sla_irr <= 8'h00;
187
    else if(sla_init_icw1)                  sla_irr <= 8'h00;
188
    else if(sla_acknowledge_not_spurious)   sla_irr <= (sla_irr & interrupt_input[15:8] & ~(interrupt_vector_bits)) | ((~(sla_ltim))? sla_edge_detect : interrupt_input[15:8]);
189
    else                                    sla_irr <= (sla_irr & interrupt_input[15:8])                            | ((~(sla_ltim))? sla_edge_detect : interrupt_input[15:8]);
190
end
191
 
192
wire [7:0] sla_writedata_mask =
193
    (slave_writedata[2:0] == 3'd0)?     8'b00000001 :
194
    (slave_writedata[2:0] == 3'd1)?     8'b00000010 :
195
    (slave_writedata[2:0] == 3'd2)?     8'b00000100 :
196
    (slave_writedata[2:0] == 3'd3)?     8'b00001000 :
197
    (slave_writedata[2:0] == 3'd4)?     8'b00010000 :
198
    (slave_writedata[2:0] == 3'd5)?     8'b00100000 :
199
    (slave_writedata[2:0] == 3'd6)?     8'b01000000 :
200
                                        8'b10000000;
201
 
202
wire sla_isr_clear =
203
    (sla_polled && slave_read_valid) || //polling
204
    (sla_ocw2 && (slave_writedata == 8'h20 || slave_writedata == 8'hA0)); //non-specific EOI or rotate on non-specific EOF
205
 
206
reg [7:0] sla_isr;
207
always @(posedge clk or negedge rst_n) begin
208
    if(rst_n == 1'b0)                                               sla_isr <= 8'h00;
209
    else if(sla_init_icw1)                                          sla_isr <= 8'h00;
210
    else if(sla_ocw2 && { slave_writedata[7:3], 3'b000 } == 8'h60)  sla_isr <= sla_isr & ~(sla_writedata_mask);                     //clear on specific EOI
211
    else if(sla_ocw2 && { slave_writedata[7:3], 3'b000 } == 8'hE0)  sla_isr <= sla_isr & ~(sla_writedata_mask);                     //clear on rotate on specific EOI
212
    else if(sla_isr_clear)                                          sla_isr <= sla_isr & ~(sla_selected_shifted_isr_first_bits);    //clear on polling or non-specific EOI (with or without rotate)
213
    else if(sla_acknowledge_not_spurious && ~(sla_auto_eoi))        sla_isr <= sla_isr | interrupt_vector_bits;                     //set
214
end
215
 
216
reg [4:0] sla_interrupt_offset;
217
always @(posedge clk or negedge rst_n) begin
218
    if(rst_n == 1'b0)       sla_interrupt_offset <= 5'h0E;
219
    else if(sla_init_icw2)  sla_interrupt_offset <= slave_writedata[7:3];
220
end
221
 
222
reg sla_auto_eoi;
223
always @(posedge clk or negedge rst_n) begin
224
    if(rst_n == 1'b0)       sla_auto_eoi <= 1'b0;
225
    else if(sla_init_icw1)  sla_auto_eoi <= 1'b0;
226
    else if(sla_init_icw4)  sla_auto_eoi <= slave_writedata[1];
227
end
228
 
229
reg sla_rotate_on_aeoi;
230
always @(posedge clk or negedge rst_n) begin
231
    if(rst_n == 1'b0)                                   sla_rotate_on_aeoi <= 1'b0;
232
    else if(sla_init_icw1)                              sla_rotate_on_aeoi <= 1'b0;
233
    else if(sla_ocw2 && slave_writedata[6:0] == 7'd0)   sla_rotate_on_aeoi <= slave_writedata[7];
234
end
235
 
236
wire [7:0] sla_selected_prepare = sla_irr & ~(sla_imr) & ~(sla_isr);
237
 
238
wire [7:0] sla_selected_shifted =
239
    (sla_lowest_priority == 3'd7)?      sla_selected_prepare :
240
    (sla_lowest_priority == 3'd0)?      { sla_selected_prepare[0],   sla_selected_prepare[7:1] } :
241
    (sla_lowest_priority == 3'd1)?      { sla_selected_prepare[1:0], sla_selected_prepare[7:2] } :
242
    (sla_lowest_priority == 3'd2)?      { sla_selected_prepare[2:0], sla_selected_prepare[7:3] } :
243
    (sla_lowest_priority == 3'd3)?      { sla_selected_prepare[3:0], sla_selected_prepare[7:4] } :
244
    (sla_lowest_priority == 3'd4)?      { sla_selected_prepare[4:0], sla_selected_prepare[7:5] } :
245
    (sla_lowest_priority == 3'd5)?      { sla_selected_prepare[5:0], sla_selected_prepare[7:6] } :
246
                                        { sla_selected_prepare[6:0], sla_selected_prepare[7] };
247
 
248
wire [7:0] sla_selected_shifted_isr =
249
    (sla_lowest_priority == 3'd7)?      sla_isr :
250
    (sla_lowest_priority == 3'd0)?      { sla_isr[0],   sla_isr[7:1] } :
251
    (sla_lowest_priority == 3'd1)?      { sla_isr[1:0], sla_isr[7:2] } :
252
    (sla_lowest_priority == 3'd2)?      { sla_isr[2:0], sla_isr[7:3] } :
253
    (sla_lowest_priority == 3'd3)?      { sla_isr[3:0], sla_isr[7:4] } :
254
    (sla_lowest_priority == 3'd4)?      { sla_isr[4:0], sla_isr[7:5] } :
255
    (sla_lowest_priority == 3'd5)?      { sla_isr[5:0], sla_isr[7:6] } :
256
                                        { sla_isr[6:0], sla_isr[7] };
257
 
258
wire [2:0] sla_selected_shifted_isr_first =
259
    (sla_selected_shifted_isr[0])?  3'd0 :
260
    (sla_selected_shifted_isr[1])?  3'd1 :
261
    (sla_selected_shifted_isr[2])?  3'd2 :
262
    (sla_selected_shifted_isr[3])?  3'd3 :
263
    (sla_selected_shifted_isr[4])?  3'd4 :
264
    (sla_selected_shifted_isr[5])?  3'd5 :
265
    (sla_selected_shifted_isr[6])?  3'd6 :
266
                                    3'd7;
267
 
268
wire [2:0] sla_selected_shifted_isr_first_norm = sla_lowest_priority + sla_selected_shifted_isr_first + 3'd1;
269
 
270
wire [7:0] sla_selected_shifted_isr_first_bits =
271
    (sla_selected_shifted_isr_first_norm == 3'd0)?  8'b00000001 :
272
    (sla_selected_shifted_isr_first_norm == 3'd1)?  8'b00000010 :
273
    (sla_selected_shifted_isr_first_norm == 3'd2)?  8'b00000100 :
274
    (sla_selected_shifted_isr_first_norm == 3'd3)?  8'b00001000 :
275
    (sla_selected_shifted_isr_first_norm == 3'd4)?  8'b00010000 :
276
    (sla_selected_shifted_isr_first_norm == 3'd5)?  8'b00100000 :
277
    (sla_selected_shifted_isr_first_norm == 3'd6)?  8'b01000000 :
278
                                                    8'b10000000;
279
 
280
wire [2:0] sla_selected_index =
281
    (sla_selected_shifted[0])?      3'd0 :
282
    (sla_selected_shifted[1])?      3'd1 :
283
    (sla_selected_shifted[2])?      3'd2 :
284
    (sla_selected_shifted[3])?      3'd3 :
285
    (sla_selected_shifted[4])?      3'd4 :
286
    (sla_selected_shifted[5])?      3'd5 :
287
    (sla_selected_shifted[6])?      3'd6 :
288
                                    3'd7;
289
 
290
wire sla_irq = sla_selected_prepare != 8'd0 && (sla_special_mask || sla_selected_index < sla_selected_shifted_isr_first);
291
 
292
wire [2:0] sla_irq_value = (sla_irq)? sla_lowest_priority + sla_selected_index + 3'd1 : 3'd7;
293
 
294
reg sla_current_irq;
295
always @(posedge clk or negedge rst_n) begin
296
    if(rst_n == 1'b0)           sla_current_irq <= 1'b0;
297
    else if(sla_init_icw1)      sla_current_irq <= 1'b0;
298
    else if(sla_acknowledge)    sla_current_irq <= 1'b0;
299
    else if(sla_irq)            sla_current_irq <= 1'b1;
300
end
301
 
302
reg sla_current_irq_last;
303
always @(posedge clk or negedge rst_n) begin
304
    if(rst_n == 1'b0)   sla_current_irq_last <= 1'b0;
305
    else                sla_current_irq_last <= sla_current_irq;
306
end
307
 
308
wire sla_acknowledge_not_spurious = (sla_polled && slave_read_valid) || (mas_sla_active && interrupt_done && ~(sla_spurious));
309
wire sla_acknowledge              = (sla_polled && slave_read_valid) || (mas_sla_active && interrupt_done);
310
 
311
wire sla_spurious_start = sla_current_irq && ~(interrupt_done) && ~(sla_irq);
312
 
313
reg sla_spurious;
314
always @(posedge clk or negedge rst_n) begin
315
    if(rst_n == 1'b0)                       sla_spurious <= 1'd0;
316
    else if(sla_init_icw1)                  sla_spurious <= 1'b0;
317
    else if(sla_spurious_start)             sla_spurious <= 1'b1;
318
    else if(sla_acknowledge || sla_irq)     sla_spurious <= 1'b0;
319
end
320
 
321
//------------------------------------------------------------------------------
322
 
323
wire mas_init_icw1 = master_write && master_address == 1'b0 && master_writedata[4] == 1'b1;
324
wire mas_init_icw2 = master_write && master_address == 1'b1 && mas_in_init && mas_init_byte_expected == 3'd2;
325
wire mas_init_icw3 = master_write && master_address == 1'b1 && mas_in_init && mas_init_byte_expected == 3'd3;
326
wire mas_init_icw4 = master_write && master_address == 1'b1 && mas_in_init && mas_init_byte_expected == 3'd4;
327
 
328
wire mas_ocw1 = mas_in_init == 1'b0 && master_write && master_address == 1'b1;
329
wire mas_ocw2 = master_write && master_address == 1'b0 && master_writedata[4:3] == 2'b00;
330
wire mas_ocw3 = master_write && master_address == 1'b0 && master_writedata[4:3] == 2'b01;
331
 
332
reg mas_polled;
333
always @(posedge clk or negedge rst_n) begin
334
    if(rst_n == 1'b0)                           mas_polled <= 1'b0;
335
    else if(mas_polled && master_read_valid)    mas_polled <= 1'b0;
336
    else if(mas_ocw3)                           mas_polled <= master_writedata[2];
337
end
338
 
339
reg mas_read_reg_select;
340
always @(posedge clk or negedge rst_n) begin
341
    if(rst_n == 1'b0)                                                       mas_read_reg_select <= 1'b0;
342
    else if(mas_init_icw1)                                                  mas_read_reg_select <= 1'b0;
343
    else if(mas_ocw3 && master_writedata[2] == 1'b0 && master_writedata[1]) mas_read_reg_select <= master_writedata[0];
344
end
345
 
346
reg mas_special_mask;
347
always @(posedge clk or negedge rst_n) begin
348
    if(rst_n == 1'b0)                                                       mas_special_mask <= 1'd0;
349
    else if(mas_init_icw1)                                                  mas_special_mask <= 1'd0;
350
    else if(mas_ocw3 && master_writedata[2] == 1'b0 && master_writedata[6]) mas_special_mask <= master_writedata[5];
351
end
352
 
353
reg mas_in_init;
354
always @(posedge clk or negedge rst_n) begin
355
    if(rst_n == 1'b0)                                   mas_in_init <= 1'b0;
356
    else if(mas_init_icw1)                              mas_in_init <= 1'b1;
357
    else if(mas_init_icw3 && ~(mas_init_requires_4))    mas_in_init <= 1'b0;
358
    else if(mas_init_icw4)                              mas_in_init <= 1'b0;
359
end
360
 
361
reg mas_init_requires_4;
362
always @(posedge clk or negedge rst_n) begin
363
    if(rst_n == 1'b0)       mas_init_requires_4 <= 1'b0;
364
    else if(mas_init_icw1) mas_init_requires_4 <= master_writedata[0];
365
end
366
 
367
reg mas_ltim;
368
always @(posedge clk or negedge rst_n) begin
369
    if(rst_n == 1'b0)           mas_ltim <= 1'b0;
370
    else if(mas_init_icw1)      mas_ltim <= master_writedata[3];
371
end
372
 
373
reg [2:0] mas_init_byte_expected;
374
always @(posedge clk or negedge rst_n) begin
375
    if(rst_n == 1'b0)                               mas_init_byte_expected <= 3'd0;
376
    else if(mas_init_icw1)                          mas_init_byte_expected <= 3'd2;
377
    else if(mas_init_icw2)                          mas_init_byte_expected <= 3'd3;
378
    else if(mas_init_icw3 && mas_init_requires_4)   mas_init_byte_expected <= 3'd4;
379
end
380
 
381
reg [2:0] mas_lowest_priority;
382
always @(posedge clk or negedge rst_n) begin
383
    if(rst_n == 1'b0)                                                               mas_lowest_priority <= 3'd7;
384
    else if(mas_init_icw1)                                                          mas_lowest_priority <= 3'd7;
385
    else if(mas_ocw2 && master_writedata == 8'hA0)                                  mas_lowest_priority <= mas_lowest_priority + 3'd1;  //rotate on non-specific EOI
386
    else if(mas_ocw2 && { master_writedata[7:3], 3'b000 } == 8'hC0)                 mas_lowest_priority <= master_writedata[2:0];       //set priority
387
    else if(mas_ocw2 && { master_writedata[7:3], 3'b000 } == 8'hE0)                 mas_lowest_priority <= master_writedata[2:0];       //rotate on specific EOI
388
    else if(mas_acknowledge_not_spurious && mas_auto_eoi && mas_rotate_on_aeoi)     mas_lowest_priority <= mas_lowest_priority + 3'd1;  //rotate on AEOI
389
end
390
 
391
reg [7:0] mas_imr;
392
always @(posedge clk or negedge rst_n) begin
393
    if(rst_n == 1'b0)           mas_imr <= 8'hFF;
394
    else if(mas_init_icw1)      mas_imr <= 8'h00;
395
    else if(mas_ocw1)           mas_imr <= master_writedata;
396
end
397
 
398
wire [7:0] mas_interrupt_input = { interrupt_input[7:3], sla_current_irq, interrupt_input[1:0] };
399
 
400
wire [7:0] mas_edge_detect = {
401
    interrupt_input[7] == 1'b1    && interrupt_last[7] == 1'b0,
402
    interrupt_input[6] == 1'b1    && interrupt_last[6] == 1'b0,
403
    interrupt_input[5] == 1'b1    && interrupt_last[5] == 1'b0,
404
    interrupt_input[4] == 1'b1    && interrupt_last[4] == 1'b0,
405
    interrupt_input[3] == 1'b1    && interrupt_last[3] == 1'b0,
406
    sla_current_irq == 1'b1       && sla_current_irq_last == 1'b0,
407
    interrupt_input[1] == 1'b1    && interrupt_last[1] == 1'b0,
408
    interrupt_input[0] == 1'b1    && interrupt_last[0] == 1'b0
409
};
410
 
411
reg [7:0] mas_irr;
412
always @(posedge clk or negedge rst_n) begin
413
    if(rst_n == 1'b0)                       mas_irr <= 8'h00;
414
    else if(mas_init_icw1)                  mas_irr <= 8'h00;
415
    else if(mas_acknowledge_not_spurious)   mas_irr <= (mas_irr & mas_interrupt_input & ~(mas_interrupt_vector_bits)) | ((~(mas_ltim))? mas_edge_detect : mas_interrupt_input);
416
    else                                    mas_irr <= (mas_irr & mas_interrupt_input)                                | ((~(mas_ltim))? mas_edge_detect : mas_interrupt_input);
417
end
418
 
419
wire [7:0] mas_writedata_mask =
420
    (master_writedata[2:0] == 3'd0)?    8'b00000001 :
421
    (master_writedata[2:0] == 3'd1)?    8'b00000010 :
422
    (master_writedata[2:0] == 3'd2)?    8'b00000100 :
423
    (master_writedata[2:0] == 3'd3)?    8'b00001000 :
424
    (master_writedata[2:0] == 3'd4)?    8'b00010000 :
425
    (master_writedata[2:0] == 3'd5)?    8'b00100000 :
426
    (master_writedata[2:0] == 3'd6)?    8'b01000000 :
427
                                        8'b10000000;
428
 
429
wire mas_isr_clear =
430
    (mas_polled && master_read_valid) || //polling
431
    (mas_ocw2 && (master_writedata == 8'h20 || master_writedata == 8'hA0)); //non-specific EOI or rotate on non-specific EOF
432
 
433
reg [7:0] mas_isr;
434
always @(posedge clk or negedge rst_n) begin
435
    if(rst_n == 1'b0)                                                   mas_isr <= 8'h00;
436
    else if(mas_init_icw1)                                              mas_isr <= 8'h00;
437
    else if(mas_ocw2 && { master_writedata[7:3], 3'b000 } == 8'h60)     mas_isr <= mas_isr & ~(mas_writedata_mask);                     //clear on specific EOI
438
    else if(mas_ocw2 && { master_writedata[7:3], 3'b000 } == 8'hE0)     mas_isr <= mas_isr & ~(mas_writedata_mask);                     //clear on rotate on specific EOI
439
    else if(mas_isr_clear)                                              mas_isr <= mas_isr & ~(mas_selected_shifted_isr_first_bits);    //clear on polling or non-specific EOI (with or without rotate)
440
    else if(mas_acknowledge_not_spurious && ~(mas_auto_eoi))            mas_isr <= mas_isr | mas_interrupt_vector_bits;                 //set
441
end
442
 
443
reg [4:0] mas_interrupt_offset;
444
always @(posedge clk or negedge rst_n) begin
445
    if(rst_n == 1'b0)       mas_interrupt_offset <= 5'd1;
446
    else if(mas_init_icw2)  mas_interrupt_offset <= master_writedata[7:3];
447
end
448
 
449
reg mas_auto_eoi;
450
always @(posedge clk or negedge rst_n) begin
451
    if(rst_n == 1'b0)       mas_auto_eoi <= 1'b0;
452
    else if(mas_init_icw1)  mas_auto_eoi <= 1'b0;
453
    else if(mas_init_icw4)  mas_auto_eoi <= master_writedata[1];
454
end
455
 
456
reg mas_rotate_on_aeoi;
457
always @(posedge clk or negedge rst_n) begin
458
    if(rst_n == 1'b0)                                   mas_rotate_on_aeoi <= 1'b0;
459
    else if(mas_init_icw1)                              mas_rotate_on_aeoi <= 1'b0;
460
    else if(mas_ocw2 && master_writedata[6:0] == 7'd0)  mas_rotate_on_aeoi <= master_writedata[7];
461
end
462
 
463
wire [7:0] mas_selected_prepare = mas_irr & ~(mas_imr) & ~(mas_isr);
464
 
465
wire [7:0] mas_selected_shifted =
466
    (mas_lowest_priority == 3'd7)?      mas_selected_prepare :
467
    (mas_lowest_priority == 3'd0)?      { mas_selected_prepare[0],   mas_selected_prepare[7:1] } :
468
    (mas_lowest_priority == 3'd1)?      { mas_selected_prepare[1:0], mas_selected_prepare[7:2] } :
469
    (mas_lowest_priority == 3'd2)?      { mas_selected_prepare[2:0], mas_selected_prepare[7:3] } :
470
    (mas_lowest_priority == 3'd3)?      { mas_selected_prepare[3:0], mas_selected_prepare[7:4] } :
471
    (mas_lowest_priority == 3'd4)?      { mas_selected_prepare[4:0], mas_selected_prepare[7:5] } :
472
    (mas_lowest_priority == 3'd5)?      { mas_selected_prepare[5:0], mas_selected_prepare[7:6] } :
473
                                        { mas_selected_prepare[6:0], mas_selected_prepare[7] };
474
 
475
wire [7:0] mas_selected_shifted_isr =
476
    (mas_lowest_priority == 3'd7)?      mas_isr :
477
    (mas_lowest_priority == 3'd0)?      { mas_isr[0],   mas_isr[7:1] } :
478
    (mas_lowest_priority == 3'd1)?      { mas_isr[1:0], mas_isr[7:2] } :
479
    (mas_lowest_priority == 3'd2)?      { mas_isr[2:0], mas_isr[7:3] } :
480
    (mas_lowest_priority == 3'd3)?      { mas_isr[3:0], mas_isr[7:4] } :
481
    (mas_lowest_priority == 3'd4)?      { mas_isr[4:0], mas_isr[7:5] } :
482
    (mas_lowest_priority == 3'd5)?      { mas_isr[5:0], mas_isr[7:6] } :
483
                                        { mas_isr[6:0], mas_isr[7] };
484
 
485
wire [2:0] mas_selected_shifted_isr_first =
486
    (mas_selected_shifted_isr[0])?  3'd0 :
487
    (mas_selected_shifted_isr[1])?  3'd1 :
488
    (mas_selected_shifted_isr[2])?  3'd2 :
489
    (mas_selected_shifted_isr[3])?  3'd3 :
490
    (mas_selected_shifted_isr[4])?  3'd4 :
491
    (mas_selected_shifted_isr[5])?  3'd5 :
492
    (mas_selected_shifted_isr[6])?  3'd6 :
493
                                    3'd7;
494
 
495
wire [2:0] mas_selected_shifted_isr_first_norm = mas_lowest_priority + mas_selected_shifted_isr_first + 3'd1;
496
 
497
wire [7:0] mas_selected_shifted_isr_first_bits =
498
    (mas_selected_shifted_isr_first_norm == 3'd0)?  8'b00000001 :
499
    (mas_selected_shifted_isr_first_norm == 3'd1)?  8'b00000010 :
500
    (mas_selected_shifted_isr_first_norm == 3'd2)?  8'b00000100 :
501
    (mas_selected_shifted_isr_first_norm == 3'd3)?  8'b00001000 :
502
    (mas_selected_shifted_isr_first_norm == 3'd4)?  8'b00010000 :
503
    (mas_selected_shifted_isr_first_norm == 3'd5)?  8'b00100000 :
504
    (mas_selected_shifted_isr_first_norm == 3'd6)?  8'b01000000 :
505
                                                    8'b10000000;
506
 
507
wire [2:0] mas_selected_index =
508
    (mas_selected_shifted[0])?      3'd0 :
509
    (mas_selected_shifted[1])?      3'd1 :
510
    (mas_selected_shifted[2])?      3'd2 :
511
    (mas_selected_shifted[3])?      3'd3 :
512
    (mas_selected_shifted[4])?      3'd4 :
513
    (mas_selected_shifted[5])?      3'd5 :
514
    (mas_selected_shifted[6])?      3'd6 :
515
                                    3'd7;
516
 
517
wire mas_irq = mas_selected_prepare != 8'd0 && (mas_special_mask || mas_selected_index < mas_selected_shifted_isr_first);
518
 
519
wire [2:0] mas_irq_value = (mas_irq)? mas_lowest_priority + mas_selected_index + 3'd1 : 3'd7;
520
 
521
reg mas_current_irq;
522
always @(posedge clk or negedge rst_n) begin
523
    if(rst_n == 1'b0)           mas_current_irq <= 1'b0;
524
    else if(mas_init_icw1)      mas_current_irq <= 1'b0;
525
    else if(mas_acknowledge)    mas_current_irq <= 1'b0;
526
    else if(mas_irq)            mas_current_irq <= 1'b1;
527
end
528
 
529
wire mas_acknowledge_not_spurious = (mas_polled && master_read_valid) || (interrupt_done && ~(mas_spurious));
530
wire mas_acknowledge              = (mas_polled && master_read_valid) || interrupt_done;
531
 
532
wire mas_spurious_start = mas_current_irq && ~(interrupt_done) && ~(mas_irq);
533
 
534
reg mas_spurious;
535
always @(posedge clk or negedge rst_n) begin
536
    if(rst_n == 1'b0)                       mas_spurious <= 1'd0;
537
    else if(mas_init_icw1)                  mas_spurious <= 1'b0;
538
    else if(mas_spurious_start)             mas_spurious <= 1'b1;
539
    else if(mas_acknowledge || mas_irq)     mas_spurious <= 1'b0;
540
end
541
 
542
reg mas_sla_active;
543
always @(posedge clk or negedge rst_n) begin
544
    if(rst_n == 1'b0)                                               mas_sla_active <= 1'b0;
545
    else if(mas_init_icw1)                                          mas_sla_active <= 1'b0;
546
    else if(mas_acknowledge)                                        mas_sla_active <= 1'b0;
547
    else if((mas_irq || mas_current_irq) && mas_irq_value != 3'd2)  mas_sla_active <= 1'b0;
548
    else if((mas_irq || mas_current_irq) && mas_irq_value == 3'd2)  mas_sla_active <= 1'b1;
549
end
550
 
551
//------------------------------------------------------------------------------
552
 
553
wire [7:0] mas_interrupt_vector_bits = (mas_sla_active)? 8'b00000100 : interrupt_vector_bits;
554
 
555
always @(posedge clk or negedge rst_n) begin
556
    if(rst_n == 1'b0)           interrupt_do <= 1'b0;
557
    else if(mas_init_icw1)      interrupt_do <= 1'b0;
558
    else if(mas_acknowledge)    interrupt_do <= 1'b0;
559
    else if(mas_irq)            interrupt_do <= 1'b1;
560
end
561
 
562
always @(posedge clk or negedge rst_n) begin
563
    if(rst_n == 1'b0)                                               interrupt_vector <= 8'd0;
564
    else if(mas_init_icw1)                                          interrupt_vector <= 8'd0;
565
    else if((mas_irq || mas_current_irq) && mas_irq_value != 3'd2)  interrupt_vector <= { mas_interrupt_offset, mas_irq_value };
566
    else if((mas_irq || mas_current_irq) && mas_irq_value == 3'd2)  interrupt_vector <= { sla_interrupt_offset, sla_irq_value };
567
end
568
 
569
wire [7:0] interrupt_vector_bits =
570
    (interrupt_vector[2:0] == 3'd0)?    8'b00000001 :
571
    (interrupt_vector[2:0] == 3'd1)?    8'b00000010 :
572
    (interrupt_vector[2:0] == 3'd2)?    8'b00000100 :
573
    (interrupt_vector[2:0] == 3'd3)?    8'b00001000 :
574
    (interrupt_vector[2:0] == 3'd4)?    8'b00010000 :
575
    (interrupt_vector[2:0] == 3'd5)?    8'b00100000 :
576
    (interrupt_vector[2:0] == 3'd6)?    8'b01000000 :
577
                                        8'b10000000;
578
 
579
//------------------------------------------------------------------------------
580
 
581
// synthesis translate_off
582
wire _unused_ok = &{ 1'b0, interrupt_last[15:1], sla_selected_shifted[7],
583
                           sla_selected_shifted_isr[7], mas_interrupt_input[0],
584
                           mas_selected_shifted[7], mas_selected_shifted_isr[7], 1'b0 };
585
// synthesis translate_on
586
 
587
//------------------------------------------------------------------------------
588
 
589
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.