URL
https://opencores.org/ocsvn/s80186/s80186/trunk
Subversion Repositories s80186
[/] [s80186/] [trunk/] [fpga/] [pic/] [PIC.sv] - Rev 2
Compare with Previous | Blame | View Log
// Copyright Jamie Iles, 2017//// This file is part of s80x86.//// s80x86 is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// s80x86 is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with s80x86. If not, see <http://www.gnu.org/licenses/>.// PIC-"lite"//// Only supports a single PIC, edge triggered interrupts and non-specific or// specific EOI. No rotating priorities etc.module PIC(input logic clk,input logic reset,input logic cs,input logic [15:0] data_m_data_in,output logic [15:0] data_m_data_out,input logic [1:0] data_m_bytesel,input logic data_m_wr_en,input logic data_m_access,output logic data_m_ack,input logic [7:0] intr_in,output logic [7:0] irq,output logic intr,input logic inta);enum bit [2:0] {INIT_STATE_ICW1,INIT_STATE_ICW2,INIT_STATE_ICW3,INIT_STATE_ICW4,INIT_STATE_IDLE} init_state, next_init_state;enum bit [1:0] {REG_LATCH_NONE,REG_LATCH_IRR,REG_LATCH_ISR} reg_latch;reg [7:3] vector_address;reg [7:0] mask, isr, irr;reg [2:0] delivered;reg [7:0] intr_last;wire [7:0] intr_edges = (intr_in ^ intr_last) & intr_in;wire [7:0] command_read_val = reg_latch == REG_LATCH_IRR ? irr :reg_latch == REG_LATCH_ISR ? isr : 8'b0;wire access_command = cs & data_m_access & data_m_bytesel[0];wire access_data = cs & data_m_access & data_m_bytesel[1];always_ff @(posedge clk)intr_last <= intr_in;always_comb begincase (init_state)INIT_STATE_ICW1: next_init_state =access_command & data_m_wr_en & data_m_data_in[4] ?INIT_STATE_ICW2 : INIT_STATE_ICW1;INIT_STATE_ICW2: next_init_state = access_data & data_m_wr_en ?INIT_STATE_ICW4 : INIT_STATE_ICW2;INIT_STATE_ICW4: next_init_state = access_data & data_m_wr_en ?INIT_STATE_IDLE : INIT_STATE_ICW4;default: next_init_state = init_state;endcaseif (reset)next_init_state = INIT_STATE_ICW1;endalways_ff @(posedge clk)init_state <= next_init_state;always_ff @(posedge clk)if (cs && data_m_access && !data_m_wr_en)data_m_data_out <= {mask, command_read_val};elsedata_m_data_out <= 16'b0;always_ff @(posedge clk)data_m_ack <= cs & data_m_access;always_ff @(posedge reset or posedge clk)if (reset)mask <= 8'b0;else if (init_state == INIT_STATE_IDLE && access_data && data_m_wr_en)mask <= data_m_data_in[15:8];always_ff @(posedge reset or posedge clk)if (reset)vector_address <= 5'b0;else if (access_data && data_m_wr_en && init_state == INIT_STATE_ICW2)vector_address <= data_m_data_in[15:11];always_ff @(posedge reset or posedge clk)if (reset)reg_latch <= REG_LATCH_NONE;else if (init_state == INIT_STATE_IDLE && access_command && data_m_wr_en &&data_m_data_in[3])reg_latch <= data_m_data_in[1:0] == 2'b10 ? REG_LATCH_IRR :data_m_data_in[1:0] == 2'b11 ? REG_LATCH_ISR :REG_LATCH_NONE;always_ff @(posedge reset or posedge clk)if (reset)irr <= 8'b0;else beginif (inta)irr[delivered] <= 1'b0;elseirr <= irr | (~mask & intr_edges);endalways_ff @(posedge reset or posedge clk)if (reset)isr <= 8'b0;else beginif (access_command && data_m_wr_en &&data_m_data_in[4:3] == 2'b00) beginif (data_m_data_in[7:5] == 3'b001) beginfor (int i = 0; i < 8; i += 1) beginif (isr[i]) beginisr[i] <= 1'b0;break;endendend else if (data_m_data_in[7:5] == 3'b011) beginisr[data_m_data_in[2:0]] <= 1'b0;endendif (inta)isr[delivered] <= 1'b1;endalways_comb beginintr = 1'b0;irq = 8'b0;for (logic [3:0] i = 4'b0; i < 4'd8; i += 1'b1) beginif (inta || isr[i[2:0]])break;if (irr[i[2:0]]) beginintr = 1'b1;irq = {vector_address, i[2:0]};break;endendendalways_ff @(posedge clk)delivered <= irq[2:0];endmodule
