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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [fpga/] [pic/] [PIC.sv] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see .
17
 
18
// PIC-"lite"
19
//
20
// Only supports a single PIC, edge triggered interrupts and non-specific or
21
// specific EOI.  No rotating priorities etc.
22
module PIC(input logic clk,
23
           input logic reset,
24
           input logic cs,
25
           input logic [15:0] data_m_data_in,
26
           output logic [15:0] data_m_data_out,
27
           input logic [1:0] data_m_bytesel,
28
           input logic data_m_wr_en,
29
           input logic data_m_access,
30
           output logic data_m_ack,
31
           input logic [7:0] intr_in,
32
           output logic [7:0] irq,
33
           output logic intr,
34
           input logic inta);
35
 
36
enum bit [2:0] {
37
    INIT_STATE_ICW1,
38
    INIT_STATE_ICW2,
39
    INIT_STATE_ICW3,
40
    INIT_STATE_ICW4,
41
    INIT_STATE_IDLE
42
} init_state, next_init_state;
43
 
44
enum bit [1:0] {
45
    REG_LATCH_NONE,
46
    REG_LATCH_IRR,
47
    REG_LATCH_ISR
48
} reg_latch;
49
 
50
reg [7:3] vector_address;
51
reg [7:0] mask, isr, irr;
52
reg [2:0] delivered;
53
 
54
reg [7:0] intr_last;
55
wire [7:0] intr_edges = (intr_in ^ intr_last) & intr_in;
56
 
57
wire [7:0] command_read_val = reg_latch == REG_LATCH_IRR ? irr :
58
                              reg_latch == REG_LATCH_ISR ? isr : 8'b0;
59
 
60
wire access_command = cs & data_m_access & data_m_bytesel[0];
61
wire access_data = cs & data_m_access & data_m_bytesel[1];
62
 
63
always_ff @(posedge clk)
64
    intr_last <= intr_in;
65
 
66
always_comb begin
67
    case (init_state)
68
    INIT_STATE_ICW1: next_init_state =
69
        access_command & data_m_wr_en & data_m_data_in[4] ?
70
            INIT_STATE_ICW2 : INIT_STATE_ICW1;
71
    INIT_STATE_ICW2: next_init_state = access_data & data_m_wr_en ?
72
        INIT_STATE_ICW4 : INIT_STATE_ICW2;
73
    INIT_STATE_ICW4: next_init_state = access_data & data_m_wr_en ?
74
        INIT_STATE_IDLE : INIT_STATE_ICW4;
75
    default: next_init_state = init_state;
76
    endcase
77
 
78
    if (reset)
79
        next_init_state = INIT_STATE_ICW1;
80
end
81
 
82
always_ff @(posedge clk)
83
    init_state <= next_init_state;
84
 
85
always_ff @(posedge clk)
86
    if (cs && data_m_access && !data_m_wr_en)
87
        data_m_data_out <= {mask, command_read_val};
88
    else
89
        data_m_data_out <= 16'b0;
90
 
91
always_ff @(posedge clk)
92
    data_m_ack <= cs & data_m_access;
93
 
94
always_ff @(posedge reset or posedge clk)
95
    if (reset)
96
        mask <= 8'b0;
97
    else if (init_state == INIT_STATE_IDLE && access_data && data_m_wr_en)
98
        mask <= data_m_data_in[15:8];
99
 
100
always_ff @(posedge reset or posedge clk)
101
    if (reset)
102
        vector_address <= 5'b0;
103
    else if (access_data && data_m_wr_en && init_state == INIT_STATE_ICW2)
104
        vector_address <= data_m_data_in[15:11];
105
 
106
always_ff @(posedge reset or posedge clk)
107
    if (reset)
108
        reg_latch <= REG_LATCH_NONE;
109
    else if (init_state == INIT_STATE_IDLE && access_command && data_m_wr_en &&
110
             data_m_data_in[3])
111
        reg_latch <= data_m_data_in[1:0] == 2'b10 ? REG_LATCH_IRR :
112
                     data_m_data_in[1:0] == 2'b11 ? REG_LATCH_ISR :
113
                     REG_LATCH_NONE;
114
 
115
always_ff @(posedge reset or posedge clk)
116
    if (reset)
117
        irr <= 8'b0;
118
    else begin
119
        if (inta)
120
            irr[delivered] <= 1'b0;
121
        else
122
            irr <= irr | (~mask & intr_edges);
123
    end
124
 
125
always_ff @(posedge reset or posedge clk)
126
    if (reset)
127
        isr <= 8'b0;
128
    else begin
129
        if (access_command && data_m_wr_en &&
130
            data_m_data_in[4:3] == 2'b00) begin
131
            if (data_m_data_in[7:5] == 3'b001) begin
132
                for (int i = 0; i < 8; i += 1) begin
133
                    if (isr[i]) begin
134
                        isr[i] <= 1'b0;
135
                        break;
136
                    end
137
                end
138
            end else if (data_m_data_in[7:5] == 3'b011) begin
139
                isr[data_m_data_in[2:0]] <= 1'b0;
140
            end
141
        end
142
        if (inta)
143
            isr[delivered] <= 1'b1;
144
    end
145
 
146
always_comb begin
147
    intr = 1'b0;
148
    irq = 8'b0;
149
 
150
    for (logic [3:0] i = 4'b0; i < 4'd8; i += 1'b1) begin
151
        if (inta || isr[i[2:0]])
152
            break;
153
        if (irr[i[2:0]]) begin
154
            intr = 1'b1;
155
            irq = {vector_address, i[2:0]};
156
            break;
157
        end
158
    end
159
end
160
 
161
always_ff @(posedge clk)
162
    delivered <= irq[2:0];
163
 
164
endmodule

powered by: WebSVN 2.1.0

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