forked from cores/microwatt
Remove Potato UART
Signed-off-by: Anton Blanchard <anton@linux.ibm.com>remove-potato-uart
parent
1896e5f803
commit
1d29cdcfb4
@ -1,91 +0,0 @@
|
|||||||
-- The Potato Processor - A simple processor for FPGAs
|
|
||||||
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
|
|
||||||
--! @brief A generic FIFO module.
|
|
||||||
--! Adopted from the FIFO module in <https://github.com/skordal/smallthings>.
|
|
||||||
entity pp_fifo is
|
|
||||||
generic(
|
|
||||||
DEPTH : natural := 64;
|
|
||||||
WIDTH : natural := 32
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
-- Control lines:
|
|
||||||
clk : in std_logic;
|
|
||||||
reset : in std_logic;
|
|
||||||
|
|
||||||
-- Status lines:
|
|
||||||
full : out std_logic;
|
|
||||||
empty : out std_logic;
|
|
||||||
|
|
||||||
-- Data in:
|
|
||||||
data_in : in std_logic_vector(WIDTH - 1 downto 0);
|
|
||||||
data_out : out std_logic_vector(WIDTH - 1 downto 0);
|
|
||||||
push, pop : in std_logic
|
|
||||||
);
|
|
||||||
end entity pp_fifo;
|
|
||||||
|
|
||||||
architecture behaviour of pp_fifo is
|
|
||||||
|
|
||||||
type memory_array is array(0 to DEPTH - 1) of std_logic_vector(WIDTH - 1 downto 0);
|
|
||||||
signal memory : memory_array := (others => (others => '0'));
|
|
||||||
|
|
||||||
subtype index_type is integer range 0 to DEPTH - 1;
|
|
||||||
signal top, bottom : index_type;
|
|
||||||
|
|
||||||
type fifo_op is (FIFO_POP, FIFO_PUSH);
|
|
||||||
signal prev_op : fifo_op := FIFO_POP;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
empty <= '1' when top = bottom and prev_op = FIFO_POP else '0';
|
|
||||||
full <= '1' when top = bottom and prev_op = FIFO_PUSH else '0';
|
|
||||||
|
|
||||||
read: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
bottom <= 0;
|
|
||||||
else
|
|
||||||
if pop = '1' then
|
|
||||||
data_out <= memory(bottom);
|
|
||||||
bottom <= (bottom + 1) mod DEPTH;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process read;
|
|
||||||
|
|
||||||
write: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
top <= 0;
|
|
||||||
else
|
|
||||||
if push = '1' then
|
|
||||||
memory(top) <= data_in;
|
|
||||||
top <= (top + 1) mod DEPTH;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process write;
|
|
||||||
|
|
||||||
set_prev_op: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
prev_op <= FIFO_POP;
|
|
||||||
else
|
|
||||||
if push = '1' and pop = '1' then
|
|
||||||
-- Keep the same value for prev_op
|
|
||||||
elsif push = '1' then
|
|
||||||
prev_op <= FIFO_PUSH;
|
|
||||||
elsif pop = '1' then
|
|
||||||
prev_op <= FIFO_POP;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process set_prev_op;
|
|
||||||
|
|
||||||
end architecture behaviour;
|
|
@ -1,395 +0,0 @@
|
|||||||
-- The Potato Processor - A simple processor for FPGAs
|
|
||||||
-- (c) Kristian Klomsten Skordal 2014 - 2016 <kristian.skordal@wafflemail.net>
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.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 (read/write) |
|
|
||||||
--! | 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
|
|
||||||
--!
|
|
||||||
--! The sample clock divisor should be set according to the formula:
|
|
||||||
--! sample_clk = (f_clk / (baudrate * 16)) - 1
|
|
||||||
--!
|
|
||||||
--! If the sample clock divisor register is set to 0, the sample clock
|
|
||||||
--! is stopped.
|
|
||||||
--!
|
|
||||||
--! 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 --! Depth of the input and output FIFOs.
|
|
||||||
);
|
|
||||||
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
|
|
||||||
|
|
||||||
subtype bitnumber is natural range 0 to 7; --! Type representing the index of a bit.
|
|
||||||
|
|
||||||
-- UART sample clock signals:
|
|
||||||
signal sample_clk : std_logic;
|
|
||||||
signal sample_clk_divisor : std_logic_vector(7 downto 0);
|
|
||||||
signal sample_clk_counter : std_logic_vector(sample_clk_divisor'range);
|
|
||||||
|
|
||||||
-- UART receive process signals:
|
|
||||||
type rx_state_type is (IDLE, RECEIVE, STARTBIT, STOPBIT);
|
|
||||||
signal rx_state : rx_state_type;
|
|
||||||
signal rx_byte : std_logic_vector(7 downto 0);
|
|
||||||
signal rx_current_bit : bitnumber;
|
|
||||||
|
|
||||||
subtype rx_sample_counter_type is natural range 0 to 15;
|
|
||||||
signal rx_sample_counter : rx_sample_counter_type;
|
|
||||||
signal rx_sample_value : rx_sample_counter_type;
|
|
||||||
|
|
||||||
subtype rx_sample_delay_type is natural range 0 to 7;
|
|
||||||
signal rx_sample_delay : rx_sample_delay_type;
|
|
||||||
|
|
||||||
-- UART transmit process signals:
|
|
||||||
type tx_state_type is (IDLE, TRANSMIT, STOPBIT);
|
|
||||||
signal tx_state : tx_state_type;
|
|
||||||
signal tx_byte : std_logic_vector(7 downto 0);
|
|
||||||
signal tx_current_bit : bitnumber;
|
|
||||||
|
|
||||||
-- UART transmit clock:
|
|
||||||
subtype uart_tx_counter_type is natural range 0 to 15;
|
|
||||||
signal uart_tx_counter : uart_tx_counter_type := 0;
|
|
||||||
signal uart_tx_clk : std_logic;
|
|
||||||
|
|
||||||
-- Buffer signals:
|
|
||||||
signal send_buffer_full, send_buffer_empty : std_logic;
|
|
||||||
signal recv_buffer_full, recv_buffer_empty : std_logic;
|
|
||||||
signal send_buffer_input, send_buffer_output : std_logic_vector(7 downto 0);
|
|
||||||
signal recv_buffer_input, recv_buffer_output : std_logic_vector(7 downto 0);
|
|
||||||
signal send_buffer_push, send_buffer_pop : std_logic := '0';
|
|
||||||
signal recv_buffer_push, recv_buffer_pop : std_logic := '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 rxd2 : std_logic := '1';
|
|
||||||
signal rxd3 : std_logic := '1';
|
|
||||||
signal txd2 : std_ulogic := '1';
|
|
||||||
begin
|
|
||||||
|
|
||||||
irq <= (irq_recv_enable and (not recv_buffer_empty))
|
|
||||||
or (irq_tx_ready_enable and send_buffer_empty);
|
|
||||||
|
|
||||||
---------- UART receive ----------
|
|
||||||
|
|
||||||
recv_buffer_input <= rx_byte;
|
|
||||||
|
|
||||||
-- Add a few FFs on the RX input to avoid metastability issues
|
|
||||||
process (clk) is
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
rxd3 <= rxd2;
|
|
||||||
rxd2 <= rxd;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
txd <= txd2;
|
|
||||||
|
|
||||||
uart_receive: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
rx_state <= IDLE;
|
|
||||||
recv_buffer_push <= '0';
|
|
||||||
else
|
|
||||||
case rx_state is
|
|
||||||
when IDLE =>
|
|
||||||
if recv_buffer_push = '1' then
|
|
||||||
recv_buffer_push <= '0';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if sample_clk = '1' and rxd3 = '0' then
|
|
||||||
rx_sample_value <= rx_sample_counter;
|
|
||||||
rx_sample_delay <= 0;
|
|
||||||
rx_current_bit <= 0;
|
|
||||||
rx_state <= STARTBIT;
|
|
||||||
end if;
|
|
||||||
when STARTBIT =>
|
|
||||||
if sample_clk = '1' then
|
|
||||||
if rx_sample_delay = 7 then
|
|
||||||
rx_state <= RECEIVE;
|
|
||||||
rx_sample_value <= rx_sample_counter;
|
|
||||||
rx_sample_delay <= 0;
|
|
||||||
else
|
|
||||||
rx_sample_delay <= rx_sample_delay + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
when RECEIVE =>
|
|
||||||
if sample_clk = '1' and rx_sample_counter = rx_sample_value then
|
|
||||||
if rx_current_bit /= 7 then
|
|
||||||
rx_byte(rx_current_bit) <= rxd3;
|
|
||||||
rx_current_bit <= rx_current_bit + 1;
|
|
||||||
else
|
|
||||||
rx_byte(rx_current_bit) <= rxd3;
|
|
||||||
rx_state <= STOPBIT;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
when STOPBIT =>
|
|
||||||
if sample_clk = '1' and rx_sample_counter = rx_sample_value then
|
|
||||||
rx_state <= IDLE;
|
|
||||||
|
|
||||||
if recv_buffer_full = '0' then
|
|
||||||
recv_buffer_push <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process uart_receive;
|
|
||||||
|
|
||||||
sample_counter: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
rx_sample_counter <= 0;
|
|
||||||
elsif sample_clk = '1' then
|
|
||||||
if rx_sample_counter = 15 then
|
|
||||||
rx_sample_counter <= 0;
|
|
||||||
else
|
|
||||||
rx_sample_counter <= rx_sample_counter + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process sample_counter;
|
|
||||||
|
|
||||||
---------- UART transmit ----------
|
|
||||||
|
|
||||||
tx_byte <= send_buffer_output;
|
|
||||||
|
|
||||||
uart_transmit: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
txd2 <= '1';
|
|
||||||
tx_state <= IDLE;
|
|
||||||
send_buffer_pop <= '0';
|
|
||||||
tx_current_bit <= 0;
|
|
||||||
else
|
|
||||||
case tx_state is
|
|
||||||
when IDLE =>
|
|
||||||
if send_buffer_empty = '0' and uart_tx_clk = '1' then
|
|
||||||
txd2 <= '0';
|
|
||||||
send_buffer_pop <= '1';
|
|
||||||
tx_current_bit <= 0;
|
|
||||||
tx_state <= TRANSMIT;
|
|
||||||
elsif uart_tx_clk = '1' then
|
|
||||||
txd2 <= '1';
|
|
||||||
end if;
|
|
||||||
when TRANSMIT =>
|
|
||||||
if send_buffer_pop = '1' then
|
|
||||||
send_buffer_pop <= '0';
|
|
||||||
elsif uart_tx_clk = '1' and tx_current_bit = 7 then
|
|
||||||
txd2 <= tx_byte(tx_current_bit);
|
|
||||||
tx_state <= STOPBIT;
|
|
||||||
elsif uart_tx_clk = '1' then
|
|
||||||
txd2 <= tx_byte(tx_current_bit);
|
|
||||||
tx_current_bit <= tx_current_bit + 1;
|
|
||||||
end if;
|
|
||||||
when STOPBIT =>
|
|
||||||
if uart_tx_clk = '1' then
|
|
||||||
txd2 <= '1';
|
|
||||||
tx_state <= IDLE;
|
|
||||||
end if;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process uart_transmit;
|
|
||||||
|
|
||||||
uart_tx_clock_generator: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
uart_tx_counter <= 0;
|
|
||||||
uart_tx_clk <= '0';
|
|
||||||
else
|
|
||||||
if sample_clk = '1' then
|
|
||||||
if uart_tx_counter = 15 then
|
|
||||||
uart_tx_counter <= 0;
|
|
||||||
uart_tx_clk <= '1';
|
|
||||||
else
|
|
||||||
uart_tx_counter <= uart_tx_counter + 1;
|
|
||||||
uart_tx_clk <= '0';
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
uart_tx_clk <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process uart_tx_clock_generator;
|
|
||||||
|
|
||||||
---------- Sample clock generator ----------
|
|
||||||
|
|
||||||
sample_clock_generator: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
sample_clk_counter <= (others => '0');
|
|
||||||
sample_clk <= '0';
|
|
||||||
else
|
|
||||||
if sample_clk_divisor /= x"00" then
|
|
||||||
if sample_clk_counter = sample_clk_divisor then
|
|
||||||
sample_clk_counter <= (others => '0');
|
|
||||||
sample_clk <= '1';
|
|
||||||
else
|
|
||||||
sample_clk_counter <= std_logic_vector(unsigned(sample_clk_counter) + 1);
|
|
||||||
sample_clk <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process sample_clock_generator;
|
|
||||||
|
|
||||||
---------- Data Buffers ----------
|
|
||||||
|
|
||||||
send_buffer: entity work.pp_fifo
|
|
||||||
generic map(
|
|
||||||
DEPTH => FIFO_DEPTH,
|
|
||||||
WIDTH => 8
|
|
||||||
) port map(
|
|
||||||
clk => clk,
|
|
||||||
reset => reset,
|
|
||||||
full => send_buffer_full,
|
|
||||||
empty => send_buffer_empty,
|
|
||||||
data_in => send_buffer_input,
|
|
||||||
data_out => send_buffer_output,
|
|
||||||
push => send_buffer_push,
|
|
||||||
pop => send_buffer_pop
|
|
||||||
);
|
|
||||||
|
|
||||||
recv_buffer: entity work.pp_fifo
|
|
||||||
generic map(
|
|
||||||
DEPTH => FIFO_DEPTH,
|
|
||||||
WIDTH => 8
|
|
||||||
) port map(
|
|
||||||
clk => clk,
|
|
||||||
reset => reset,
|
|
||||||
full => recv_buffer_full,
|
|
||||||
empty => recv_buffer_empty,
|
|
||||||
data_in => recv_buffer_input,
|
|
||||||
data_out => recv_buffer_output,
|
|
||||||
push => recv_buffer_push,
|
|
||||||
pop => recv_buffer_pop
|
|
||||||
);
|
|
||||||
|
|
||||||
---------- Wishbone Interface ----------
|
|
||||||
|
|
||||||
wishbone: process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset = '1' then
|
|
||||||
wb_ack_out <= '0';
|
|
||||||
wb_state <= IDLE;
|
|
||||||
send_buffer_push <= '0';
|
|
||||||
recv_buffer_pop <= '0';
|
|
||||||
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 = x"000" then
|
|
||||||
send_buffer_input <= wb_dat_in;
|
|
||||||
send_buffer_push <= '1';
|
|
||||||
elsif wb_adr_in = x"018" then
|
|
||||||
sample_clk_divisor <= wb_dat_in;
|
|
||||||
elsif wb_adr_in = x"020" then
|
|
||||||
irq_recv_enable <= wb_dat_in(0);
|
|
||||||
irq_tx_ready_enable <= wb_dat_in(1);
|
|
||||||
end if;
|
|
||||||
|
|
||||||
-- Invalid writes are acked and ignored.
|
|
||||||
wb_ack_out <= '1';
|
|
||||||
wb_state <= WRITE_ACK;
|
|
||||||
else -- Read from register
|
|
||||||
if wb_adr_in = x"008" then
|
|
||||||
recv_buffer_pop <= '1';
|
|
||||||
elsif wb_adr_in = x"010" then
|
|
||||||
wb_dat_out <= x"0" & send_buffer_full & recv_buffer_full &
|
|
||||||
send_buffer_empty & recv_buffer_empty;
|
|
||||||
wb_ack_out <= '1';
|
|
||||||
elsif wb_adr_in = x"018" then
|
|
||||||
wb_dat_out <= sample_clk_divisor;
|
|
||||||
wb_ack_out <= '1';
|
|
||||||
elsif wb_adr_in = x"020" then
|
|
||||||
wb_dat_out <= (0 => irq_recv_enable,
|
|
||||||
1 => irq_tx_ready_enable,
|
|
||||||
others => '0');
|
|
||||||
wb_ack_out <= '1';
|
|
||||||
else
|
|
||||||
wb_dat_out <= (others => '0');
|
|
||||||
wb_ack_out <= '1';
|
|
||||||
end if;
|
|
||||||
wb_state <= READ_ACK;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
when WRITE_ACK =>
|
|
||||||
send_buffer_push <= '0';
|
|
||||||
|
|
||||||
if wb_stb_in = '0' then
|
|
||||||
wb_ack_out <= '0';
|
|
||||||
wb_state <= IDLE;
|
|
||||||
end if;
|
|
||||||
when READ_ACK =>
|
|
||||||
if recv_buffer_pop = '1' then
|
|
||||||
recv_buffer_pop <= '0';
|
|
||||||
else
|
|
||||||
wb_dat_out <= recv_buffer_output;
|
|
||||||
wb_ack_out <= '1';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if wb_stb_in = '0' then
|
|
||||||
wb_ack_out <= '0';
|
|
||||||
wb_state <= IDLE;
|
|
||||||
end if;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process wishbone;
|
|
||||||
|
|
||||||
end architecture behaviour;
|
|
@ -1,90 +0,0 @@
|
|||||||
-- The Potato Processor - A simple processor for FPGAs
|
|
||||||
-- (c) Kristian Klomsten Skordal 2014 <kristian.skordal@wafflemail.net>
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
|
|
||||||
package pp_utilities is
|
|
||||||
|
|
||||||
--! Converts a boolean to an std_logic.
|
|
||||||
function to_std_logic(input : in boolean) return std_logic;
|
|
||||||
|
|
||||||
-- Checks if a number is 2^n:
|
|
||||||
function is_pow2(input : in natural) return boolean;
|
|
||||||
|
|
||||||
--! Calculates log2 with integers.
|
|
||||||
function log2(input : in natural) return natural;
|
|
||||||
|
|
||||||
-- Gets the value of the sel signals to the wishbone interconnect for the specified
|
|
||||||
-- operand size and address.
|
|
||||||
function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
|
|
||||||
return std_logic_vector;
|
|
||||||
|
|
||||||
end package pp_utilities;
|
|
||||||
|
|
||||||
package body pp_utilities is
|
|
||||||
|
|
||||||
function to_std_logic(input : in boolean) return std_logic is
|
|
||||||
begin
|
|
||||||
if input then
|
|
||||||
return '1';
|
|
||||||
else
|
|
||||||
return '0';
|
|
||||||
end if;
|
|
||||||
end function to_std_logic;
|
|
||||||
|
|
||||||
function is_pow2(input : in natural) return boolean is
|
|
||||||
variable c : natural := 1;
|
|
||||||
begin
|
|
||||||
for i in 0 to 31 loop
|
|
||||||
if input = c then
|
|
||||||
return true;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
c := c * 2;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
end function is_pow2;
|
|
||||||
|
|
||||||
function log2(input : in natural) return natural is
|
|
||||||
variable retval : natural := 0;
|
|
||||||
variable temp : natural := input;
|
|
||||||
begin
|
|
||||||
while temp > 1 loop
|
|
||||||
retval := retval + 1;
|
|
||||||
temp := temp / 2;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
end function log2;
|
|
||||||
|
|
||||||
function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
|
|
||||||
return std_logic_vector is
|
|
||||||
begin
|
|
||||||
case size is
|
|
||||||
when b"01" =>
|
|
||||||
case address(1 downto 0) is
|
|
||||||
when b"00" =>
|
|
||||||
return b"0001";
|
|
||||||
when b"01" =>
|
|
||||||
return b"0010";
|
|
||||||
when b"10" =>
|
|
||||||
return b"0100";
|
|
||||||
when b"11" =>
|
|
||||||
return b"1000";
|
|
||||||
when others =>
|
|
||||||
return b"0001";
|
|
||||||
end case;
|
|
||||||
when b"10" =>
|
|
||||||
if address(1) = '0' then
|
|
||||||
return b"0011";
|
|
||||||
else
|
|
||||||
return b"1100";
|
|
||||||
end if;
|
|
||||||
when others =>
|
|
||||||
return b"1111";
|
|
||||||
end case;
|
|
||||||
end function wb_get_data_sel;
|
|
||||||
|
|
||||||
end package body pp_utilities;
|
|
Binary file not shown.
Binary file not shown.
@ -1,135 +0,0 @@
|
|||||||
-- 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;
|
|
Loading…
Reference in New Issue