Line 229... |
Line 229... |
end record;
|
end record;
|
signal rx_buffer : rx_buffer_t;
|
signal rx_buffer : rx_buffer_t;
|
|
|
-- interrupt generator --
|
-- interrupt generator --
|
type irq_t is record
|
type irq_t is record
|
pending : std_ulogic; -- pending interrupt request
|
|
set : std_ulogic;
|
set : std_ulogic;
|
clr : std_ulogic;
|
buf : std_ulogic_vector(1 downto 0);
|
end record;
|
end record;
|
signal rx_irq, tx_irq : irq_t;
|
signal rx_irq, tx_irq : irq_t;
|
|
|
begin
|
begin
|
|
|
Line 488... |
Line 487... |
|
|
end case;
|
end case;
|
|
|
-- overrun flag --
|
-- overrun flag --
|
if (rden = '1') and (addr = uart_id_rtx_addr_c) then -- clear when reading data register
|
if (rden = '1') and (addr = uart_id_rtx_addr_c) then -- clear when reading data register
|
rx_engine.overr <= '1';
|
|
elsif (rx_buffer.we = '1') and (rx_buffer.free = '0') then -- write to full FIFO
|
|
rx_engine.overr <= '0';
|
rx_engine.overr <= '0';
|
|
elsif (rx_buffer.we = '1') and (rx_buffer.free = '0') then -- write to full FIFO
|
|
rx_engine.overr <= '1';
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process uart_rx_engine;
|
end process uart_rx_engine;
|
|
|
Line 554... |
Line 553... |
end process flow_control_buffer;
|
end process flow_control_buffer;
|
|
|
|
|
-- Interrupt Generator --------------------------------------------------------------------
|
-- Interrupt Generator --------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
irq_type: process(ctrl, tx_buffer, rx_buffer)
|
irq_type: process(ctrl, tx_buffer, rx_buffer, tx_engine.done)
|
begin
|
begin
|
-- TX interrupt --
|
-- TX interrupt --
|
if (UART_TX_FIFO = 1) then
|
if (UART_TX_FIFO = 1) or (ctrl(ctrl_tx_irq_c) = '0') then
|
tx_irq.set <= tx_buffer.free; -- fire IRQ if FIFO is not full
|
tx_irq.set <= tx_buffer.free and tx_engine.done; -- fire IRQ if FIFO is not full
|
else
|
|
if (ctrl(ctrl_tx_irq_c) = '1') then
|
|
tx_irq.set <= not tx_buffer.half; -- fire IRQ if FIFO is less than half-full
|
|
else
|
else
|
tx_irq.set <= tx_buffer.free; -- fire IRQ if FIFO is not full
|
tx_irq.set <= (not tx_buffer.half) and tx_engine.done; -- fire IRQ if FIFO is less than half-full
|
end if;
|
|
end if;
|
end if;
|
|
|
-- RX interrupt --
|
-- RX interrupt --
|
if (UART_RX_FIFO = 1) then
|
if (UART_RX_FIFO = 1) or (ctrl(ctrl_rx_irq_c) = '0') then
|
rx_irq.set <= rx_buffer.avail; -- fire IRQ if FIFO is not empty
|
rx_irq.set <= rx_buffer.avail; -- fire IRQ if FIFO is not empty
|
else
|
else
|
if (ctrl(ctrl_rx_irq_c) = '1') then
|
|
rx_irq.set <= rx_buffer.half; -- fire IRQ if FIFO is at least half-full
|
rx_irq.set <= rx_buffer.half; -- fire IRQ if FIFO is at least half-full
|
else
|
|
rx_irq.set <= rx_buffer.avail; -- fire IRQ is FIFO is not empty
|
|
end if;
|
|
end if;
|
end if;
|
end process irq_type;
|
end process irq_type;
|
|
|
-- interrupt arbiter --
|
-- interrupt edge detector --
|
irq_generator: process(clk_i)
|
irq_detect: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if (ctrl(ctrl_en_c) = '0') then
|
if (ctrl(ctrl_en_c) = '0') then
|
rx_irq.pending <= '0';
|
tx_irq.buf <= "00";
|
tx_irq.pending <= '0';
|
rx_irq.buf <= "00";
|
else
|
else
|
-- TX --
|
tx_irq.buf <= tx_irq.buf(0) & tx_irq.set;
|
if (tx_irq.set = '1') and (tx_engine.done = '1') then -- evaluate IRQ condition when TX is done with current sending
|
rx_irq.buf <= rx_irq.buf(0) & rx_irq.set;
|
tx_irq.pending <= '1';
|
|
elsif (tx_irq.clr = '1') then
|
|
tx_irq.pending <= '0';
|
|
end if;
|
end if;
|
-- RX --
|
|
if (rx_irq.set = '1') and (rx_engine.done = '1') then -- evaluate IRQ condition when RX is done with current receiving
|
|
rx_irq.pending <= '1';
|
|
elsif (rx_irq.clr = '1') then
|
|
rx_irq.pending <= '0';
|
|
end if;
|
end if;
|
end if;
|
end process irq_detect;
|
end if;
|
|
end process irq_generator;
|
|
|
|
-- IRQ requests to CPU --
|
-- IRQ requests to CPU --
|
irq_txd_o <= tx_irq.pending;
|
irq_txd_o <= '1' when (tx_irq.buf = "01") else '0';
|
irq_rxd_o <= rx_irq.pending;
|
irq_rxd_o <= '1' when (rx_irq.buf = "01") else '0';
|
|
|
-- IRQ acknowledge --
|
|
tx_irq.clr <= '1' when (tx_buffer.we = '1') or ((wren = '1') and (addr = uart_id_ctrl_addr_c)) else '0'; -- write to data reg OR write to control reg
|
|
rx_irq.clr <= '1' when (rx_buffer.re = '1') or ((wren = '1') and (addr = uart_id_ctrl_addr_c)) else '0'; -- read from data reg OR write to control reg
|
|
|
|
|
|
-- SIMULATION Transmitter -----------------------------------------------------------------
|
-- SIMULATION Transmitter -----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- pragma translate_off
|
-- pragma translate_off
|