101 lines
3.1 KiB
Systemverilog
101 lines
3.1 KiB
Systemverilog
// Copyright 2017 ETH Zurich and University of Bologna.
|
|
// Copyright and related rights are licensed under the Solderpad Hardware
|
|
// License, Version 0.51 (the “License”); you may not use this file except in
|
|
// compliance with the License. You may obtain a copy of the License at
|
|
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
|
// or agreed to in writing, software, hardware and materials distributed under
|
|
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
|
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations under the License.
|
|
|
|
module uart_interrupt
|
|
#(
|
|
parameter TX_FIFO_DEPTH = 32,
|
|
parameter RX_FIFO_DEPTH = 32
|
|
)
|
|
(
|
|
input logic clk_i,
|
|
input logic rstn_i,
|
|
|
|
// registers
|
|
input logic [7:0] IER_i, // interrupt enable register
|
|
input logic RDA_i, // receiver data available
|
|
input logic overrun_i, // character timeout indication
|
|
|
|
// control logic
|
|
input logic error_i,
|
|
input logic [$clog2(RX_FIFO_DEPTH):0] rx_elements_i,
|
|
input logic [$clog2(TX_FIFO_DEPTH):0] tx_elements_i,
|
|
input logic [1:0] trigger_level_i,
|
|
|
|
input logic [3:0] clr_int_i, // one hot
|
|
|
|
output logic interrupt_o,
|
|
output logic [3:0] IIR_o
|
|
);
|
|
|
|
logic [3:0] iir_n, iir_q;
|
|
logic trigger_level_reached;
|
|
|
|
always_comb
|
|
begin
|
|
trigger_level_reached = 1'b0;
|
|
case (trigger_level_i)
|
|
2'b00:
|
|
if ($unsigned(rx_elements_i) == 1)
|
|
trigger_level_reached = 1'b1;
|
|
2'b01:
|
|
if ($unsigned(rx_elements_i) == 4)
|
|
trigger_level_reached = 1'b1;
|
|
2'b10:
|
|
if ($unsigned(rx_elements_i) == 8)
|
|
trigger_level_reached = 1'b1;
|
|
2'b11:
|
|
if ($unsigned(rx_elements_i) == 14)
|
|
trigger_level_reached = 1'b1;
|
|
default : /* default */;
|
|
endcase
|
|
end
|
|
|
|
always_comb
|
|
begin
|
|
iir_n = iir_q;
|
|
if (clr_int_i == iir_q)
|
|
iir_n = 4'b0001;
|
|
|
|
if (iir_q == 4'b0100 && (!trigger_level_reached && !RDA_i))
|
|
iir_n = 4'b0001;
|
|
|
|
// Parity error
|
|
if (IER_i[2] & error_i)
|
|
iir_n = 4'b0110;
|
|
// Received data available or trigger level reached in FIFO mode
|
|
else if (IER_i[0] & (trigger_level_reached | RDA_i))
|
|
iir_n = 4'b0100;
|
|
// Overrun error
|
|
else if (IER_i[4] & overrun_i)
|
|
iir_n = 4'b1100;
|
|
// Transmitter holding register empty
|
|
else if (IER_i[1] & tx_elements_i == 0)
|
|
iir_n = 4'b0010;
|
|
end
|
|
|
|
|
|
always_ff @(posedge clk_i, negedge rstn_i)
|
|
begin
|
|
if (~rstn_i)
|
|
begin
|
|
iir_q <= 4'b0001;
|
|
end
|
|
else
|
|
begin
|
|
iir_q <= iir_n;
|
|
end
|
|
end
|
|
|
|
assign IIR_o = iir_q;
|
|
assign interrupt_o = ~iir_q[0];
|
|
|
|
endmodule
|
|
|