You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.1 KiB
135 lines
4.1 KiB
-- Sim console UART, provides the same interface as potato UART by |
|
-- Kristian Klomsten Skordal. |
|
|
|
library ieee; |
|
use ieee.std_logic_1164.all; |
|
use ieee.numeric_std.all; |
|
|
|
library work; |
|
use work.wishbone_types.all; |
|
use work.sim_console.all; |
|
|
|
--! @brief Simple UART module. |
|
--! The following registers are defined: |
|
--! |--------------------|--------------------------------------------| |
|
--! | Address | Description | |
|
--! |--------------------|--------------------------------------------| |
|
--! | 0x00 | Transmit register (write-only) | |
|
--! | 0x08 | Receive register (read-only) | |
|
--! | 0x10 | Status register (read-only) | |
|
--! | 0x18 | Sample clock divisor register (dummy) | |
|
--! | 0x20 | Interrupt enable register (read/write) | |
|
--! |--------------------|--------------------------------------------| |
|
--! |
|
--! The status register contains the following bits: |
|
--! - Bit 0: receive buffer empty |
|
--! - Bit 1: transmit buffer empty |
|
--! - Bit 2: receive buffer full |
|
--! - Bit 3: transmit buffer full |
|
--! |
|
--! Interrupts are enabled by setting the corresponding bit in the interrupt |
|
--! enable register. The following bits are available: |
|
--! - Bit 0: data received (receive buffer not empty) |
|
--! - Bit 1: ready to send data (transmit buffer empty) |
|
entity pp_soc_uart is |
|
generic( |
|
FIFO_DEPTH : natural := 64 --Unused |
|
); |
|
port( |
|
clk : in std_logic; |
|
reset : in std_logic; |
|
|
|
-- UART ports: |
|
txd : out std_logic; |
|
rxd : in std_logic; |
|
|
|
-- Interrupt signal: |
|
irq : out std_logic; |
|
|
|
-- Wishbone ports: |
|
wb_adr_in : in std_logic_vector(11 downto 0); |
|
wb_dat_in : in std_logic_vector( 7 downto 0); |
|
wb_dat_out : out std_logic_vector( 7 downto 0); |
|
wb_we_in : in std_logic; |
|
wb_cyc_in : in std_logic; |
|
wb_stb_in : in std_logic; |
|
wb_ack_out : out std_logic |
|
); |
|
end entity pp_soc_uart; |
|
|
|
architecture behaviour of pp_soc_uart is |
|
|
|
signal sample_clk_divisor : std_logic_vector(7 downto 0); |
|
|
|
-- IRQ enable signals: |
|
signal irq_recv_enable, irq_tx_ready_enable : std_logic := '0'; |
|
|
|
-- Wishbone signals: |
|
type wb_state_type is (IDLE, WRITE_ACK, READ_ACK); |
|
signal wb_state : wb_state_type; |
|
signal wb_ack : std_logic; --! Wishbone acknowledge signal |
|
|
|
begin |
|
|
|
wb_ack_out <= wb_ack and wb_cyc_in and wb_stb_in; |
|
|
|
-- For the sim console, the transmit buffer is always empty, so always |
|
-- interrupt if enabled. No recieve interrupt. |
|
irq <= irq_tx_ready_enable; |
|
|
|
wishbone: process(clk) |
|
variable sim_tmp : std_logic_vector(63 downto 0); |
|
begin |
|
if rising_edge(clk) then |
|
if reset = '1' then |
|
wb_ack <= '0'; |
|
wb_state <= IDLE; |
|
sample_clk_divisor <= (others => '0'); |
|
irq_recv_enable <= '0'; |
|
irq_tx_ready_enable <= '0'; |
|
else |
|
case wb_state is |
|
when IDLE => |
|
if wb_cyc_in = '1' and wb_stb_in = '1' then |
|
if wb_we_in = '1' then -- Write to register |
|
if wb_adr_in(11 downto 0) = x"000" then |
|
sim_console_write(x"00000000000000" & wb_dat_in); |
|
elsif wb_adr_in(11 downto 0) = x"018" then |
|
sample_clk_divisor <= wb_dat_in; |
|
elsif wb_adr_in(11 downto 0) = x"020" then |
|
irq_recv_enable <= wb_dat_in(0); |
|
irq_tx_ready_enable <= wb_dat_in(1); |
|
end if; |
|
wb_ack <= '1'; |
|
wb_state <= WRITE_ACK; |
|
else -- Read from register |
|
if wb_adr_in(11 downto 0) = x"008" then |
|
sim_console_read(sim_tmp); |
|
wb_dat_out <= sim_tmp(7 downto 0); |
|
elsif wb_adr_in(11 downto 0) = x"010" then |
|
sim_console_poll(sim_tmp); |
|
wb_dat_out <= "00000" & sim_tmp(0) & '1' & not sim_tmp(0); |
|
elsif wb_adr_in(11 downto 0) = x"018" then |
|
wb_dat_out <= sample_clk_divisor; |
|
elsif wb_adr_in(11 downto 0) = x"020" then |
|
wb_dat_out <= (0 => irq_recv_enable, |
|
1 => irq_tx_ready_enable, |
|
others => '0'); |
|
else |
|
wb_dat_out <= (others => '0'); |
|
end if; |
|
wb_ack <= '1'; |
|
wb_state <= READ_ACK; |
|
end if; |
|
end if; |
|
when WRITE_ACK|READ_ACK => |
|
if wb_stb_in = '0' then |
|
wb_ack <= '0'; |
|
wb_state <= IDLE; |
|
end if; |
|
end case; |
|
end if; |
|
end if; |
|
end process wishbone; |
|
|
|
end architecture behaviour;
|
|
|