mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-06 11:03:25 +00:00
Remove Potato UART
Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
This commit is contained in:
committed by
Anton Blanchard
parent
1896e5f803
commit
1d29cdcfb4
4
Makefile
4
Makefile
@@ -63,7 +63,7 @@ soc_files = wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \
|
||||
|
||||
uart_files = $(wildcard uart16550/*.v)
|
||||
|
||||
soc_sim_files = $(core_files) $(soc_files) sim_console.vhdl sim_pp_uart.vhdl sim_bram_helpers.vhdl \
|
||||
soc_sim_files = $(core_files) $(soc_files) sim_console.vhdl sim_bram_helpers.vhdl \
|
||||
sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl \
|
||||
sim_16550_uart.vhdl \
|
||||
foreign_random.vhdl glibc_random.vhdl glibc_random_helpers.vhdl
|
||||
@@ -190,7 +190,7 @@ clkgen=fpga/clk_gen_bypass.vhd
|
||||
endif
|
||||
|
||||
fpga_files = fpga/soc_reset.vhdl \
|
||||
fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd fpga/main_bram.vhdl \
|
||||
fpga/main_bram.vhdl \
|
||||
nonrandom.vhdl
|
||||
|
||||
synth_files = $(core_files) $(soc_files) $(fpga_files) $(clkgen) $(toplevel) $(dmi_dtm)
|
||||
|
||||
@@ -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;
|
||||
@@ -19,8 +19,7 @@ entity toplevel is
|
||||
SPI_FLASH_OFFSET : integer := 10485760;
|
||||
SPI_FLASH_DEF_CKDV : natural := 1;
|
||||
SPI_FLASH_DEF_QUAD : boolean := true;
|
||||
LOG_LENGTH : natural := 2048;
|
||||
UART_IS_16550 : boolean := true
|
||||
LOG_LENGTH : natural := 2048
|
||||
);
|
||||
port(
|
||||
clk200_p : in std_ulogic;
|
||||
@@ -133,8 +132,7 @@ begin
|
||||
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
|
||||
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
|
||||
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
|
||||
LOG_LENGTH => LOG_LENGTH,
|
||||
UART0_IS_16550 => UART_IS_16550
|
||||
LOG_LENGTH => LOG_LENGTH
|
||||
)
|
||||
port map (
|
||||
-- System signals
|
||||
|
||||
@@ -25,7 +25,6 @@ entity toplevel is
|
||||
SPI_FLASH_DEF_QUAD : boolean := true;
|
||||
LOG_LENGTH : natural := 512;
|
||||
USE_LITEETH : boolean := false;
|
||||
UART_IS_16550 : boolean := false;
|
||||
HAS_UART1 : boolean := true;
|
||||
USE_LITESDCARD : boolean := false;
|
||||
NGPIO : natural := 32
|
||||
@@ -204,7 +203,6 @@ begin
|
||||
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
|
||||
LOG_LENGTH => LOG_LENGTH,
|
||||
HAS_LITEETH => USE_LITEETH,
|
||||
UART0_IS_16550 => UART_IS_16550,
|
||||
HAS_UART1 => HAS_UART1,
|
||||
HAS_SD_CARD => USE_LITESDCARD,
|
||||
NGPIO => NGPIO
|
||||
|
||||
@@ -15,8 +15,7 @@ entity toplevel is
|
||||
HAS_BTC : boolean := false;
|
||||
ICACHE_NUM_LINES : natural := 64;
|
||||
LOG_LENGTH : natural := 512;
|
||||
DISABLE_FLATTEN_CORE : boolean := false;
|
||||
UART_IS_16550 : boolean := true
|
||||
DISABLE_FLATTEN_CORE : boolean := false
|
||||
);
|
||||
port(
|
||||
ext_clk : in std_ulogic;
|
||||
@@ -76,8 +75,7 @@ begin
|
||||
HAS_BTC => HAS_BTC,
|
||||
ICACHE_NUM_LINES => ICACHE_NUM_LINES,
|
||||
LOG_LENGTH => LOG_LENGTH,
|
||||
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE,
|
||||
UART0_IS_16550 => UART_IS_16550
|
||||
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
|
||||
)
|
||||
port map (
|
||||
system_clk => system_clk,
|
||||
|
||||
@@ -20,8 +20,7 @@ entity toplevel is
|
||||
SPI_FLASH_OFFSET : integer := 10485760;
|
||||
SPI_FLASH_DEF_CKDV : natural := 1;
|
||||
SPI_FLASH_DEF_QUAD : boolean := true;
|
||||
LOG_LENGTH : natural := 2048;
|
||||
UART_IS_16550 : boolean := true
|
||||
LOG_LENGTH : natural := 2048
|
||||
);
|
||||
port(
|
||||
clk200_p : in std_ulogic;
|
||||
@@ -136,8 +135,7 @@ begin
|
||||
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
|
||||
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
|
||||
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
|
||||
LOG_LENGTH => LOG_LENGTH,
|
||||
UART0_IS_16550 => UART_IS_16550
|
||||
LOG_LENGTH => LOG_LENGTH
|
||||
)
|
||||
port map (
|
||||
-- System signals
|
||||
|
||||
@@ -23,7 +23,6 @@ entity toplevel is
|
||||
SPI_FLASH_DEF_CKDV : natural := 1;
|
||||
SPI_FLASH_DEF_QUAD : boolean := true;
|
||||
LOG_LENGTH : natural := 2048;
|
||||
UART_IS_16550 : boolean := true;
|
||||
USE_LITEETH : boolean := false;
|
||||
USE_LITESDCARD : boolean := false
|
||||
);
|
||||
@@ -180,7 +179,6 @@ begin
|
||||
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
|
||||
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
|
||||
LOG_LENGTH => LOG_LENGTH,
|
||||
UART0_IS_16550 => UART_IS_16550,
|
||||
HAS_LITEETH => USE_LITEETH,
|
||||
HAS_SD_CARD => USE_LITESDCARD
|
||||
)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -515,48 +515,33 @@ e8010010ebc1fff0
|
||||
3c4000014e800020
|
||||
7c0802a638429800
|
||||
f8010010fbe1fff8
|
||||
480001edf821ffd1
|
||||
48000175f821ffd1
|
||||
6000000060000000
|
||||
4800015538628000
|
||||
480000dd38628000
|
||||
4800004960000000
|
||||
7c7f1b7860000000
|
||||
57ff063e5463063e
|
||||
60000000480000b9
|
||||
600000004800007d
|
||||
4082ffe02c1f000d
|
||||
480000a53860000a
|
||||
480000693860000a
|
||||
4bffffd060000000
|
||||
0100000000000000
|
||||
3c40000100000180
|
||||
6000000038429800
|
||||
6000000089228090
|
||||
2c09000039428088
|
||||
e92a000041820030
|
||||
7c0004ac39290014
|
||||
712900017d204eaa
|
||||
e86a00004182ffec
|
||||
39290014e9228088
|
||||
7d204eaa7c0004ac
|
||||
4182ffe871290001
|
||||
e862808860000000
|
||||
7c601eaa7c0004ac
|
||||
4e8000205463063e
|
||||
39290010e92a0000
|
||||
7d204eea7c0004ac
|
||||
4082ffec71290001
|
||||
38630008e86a0000
|
||||
7c601eea7c0004ac
|
||||
000000004bffffd0
|
||||
0000000000000000
|
||||
384298003c400001
|
||||
8922809060000000
|
||||
3942808860000000
|
||||
4182002c2c090000
|
||||
39290014e92a0000
|
||||
3c40000100000000
|
||||
6000000038429800
|
||||
39290014e9228088
|
||||
7d204eaa7c0004ac
|
||||
4182ffec71290020
|
||||
7c0004ace92a0000
|
||||
4e8000207c604faa
|
||||
39290010e92a0000
|
||||
7d204eea7c0004ac
|
||||
4082ffec71290008
|
||||
e94a00005469063e
|
||||
7d2057ea7c0004ac
|
||||
4182ffe871290020
|
||||
e922808860000000
|
||||
7c604faa7c0004ac
|
||||
000000004e800020
|
||||
0000000000000000
|
||||
384298003c400001
|
||||
@@ -565,10 +550,10 @@ fbe1fff87c0802a6
|
||||
f821ffd1f8010010
|
||||
2c3e00008fdf0001
|
||||
3821003040820010
|
||||
4bfffe4438600000
|
||||
4bfffebc38600000
|
||||
4082000c281e000a
|
||||
4bffff453860000d
|
||||
4bffff3d7fc3f378
|
||||
4bffff813860000d
|
||||
4bffff797fc3f378
|
||||
000000004bffffd0
|
||||
0000028001000000
|
||||
386000007c691b78
|
||||
@@ -577,29 +562,26 @@ f821ffd1f8010010
|
||||
000000004bfffff0
|
||||
0000000000000000
|
||||
384298003c400001
|
||||
614a00203d40c000
|
||||
7c0004ac794a0020
|
||||
3d20c0007d4056ea
|
||||
61290008794a0600
|
||||
612900203d20c000
|
||||
7c0004ac79290020
|
||||
712900207d204eea
|
||||
3d20c00041820018
|
||||
7929002061290040
|
||||
7d204eea7c0004ac
|
||||
3d00c0007929f804
|
||||
6108200079290fc3
|
||||
6000000079080020
|
||||
3d00001cf9028088
|
||||
7d4a439261082000
|
||||
6000000041820084
|
||||
9922809039200001
|
||||
6108200c3d00c000
|
||||
790800203920ff80
|
||||
7d2047aa7c0004ac
|
||||
7c0004ace9228088
|
||||
e92280887d404faa
|
||||
39290004794ac202
|
||||
7d404faa7c0004ac
|
||||
3d40c0007d204eea
|
||||
614a000879290600
|
||||
7c0004ac794a0020
|
||||
714a00207d4056ea
|
||||
3d40c00041820018
|
||||
794a0020614a0040
|
||||
7d4056ea7c0004ac
|
||||
600000003d40c000
|
||||
3d00c000614a2000
|
||||
6108200c794a0020
|
||||
f942808879080020
|
||||
614a20003d40001c
|
||||
3940ff807d295392
|
||||
7d4047aa7c0004ac
|
||||
7c0004ace9428088
|
||||
e94280887d2057aa
|
||||
394a00047929c202
|
||||
7d2057aa7c0004ac
|
||||
39400003e9228088
|
||||
7c0004ac3929000c
|
||||
e92280887d404faa
|
||||
@@ -607,53 +589,71 @@ e92280887d404faa
|
||||
e92280887d404faa
|
||||
3929000839400007
|
||||
7d404faa7c0004ac
|
||||
600000004e800020
|
||||
99228090394affff
|
||||
612920183d20c000
|
||||
7c0004ac79290020
|
||||
4e8000207d404fea
|
||||
000000004e800020
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
6000000038429800
|
||||
2c24000089228090
|
||||
600000002f890000
|
||||
419e0030e9228088
|
||||
3940000241820024
|
||||
384298003c400001
|
||||
392000002c240000
|
||||
3920000241820008
|
||||
418200082c230000
|
||||
39290004614a0001
|
||||
7d404faa7c0004ac
|
||||
394000004e800020
|
||||
418200084bffffe0
|
||||
3929002060630002
|
||||
7c604fea7c0004ac
|
||||
6000000061290001
|
||||
394a0004e9428088
|
||||
7d2057aa7c0004ac
|
||||
000000004e800020
|
||||
0000000000000000
|
||||
0000000000000010
|
||||
0141780400527a01
|
||||
0000001800010c1b
|
||||
fffffc4800000018
|
||||
fffffd2800000018
|
||||
300e460000000070
|
||||
000000019f7e4111
|
||||
0000000000000010
|
||||
0141780400527a01
|
||||
0000001000010c1b
|
||||
fffffc8800000018
|
||||
0000000000000084
|
||||
fffffd6800000018
|
||||
0000000000000048
|
||||
0000002c00000010
|
||||
00000080fffffcf8
|
||||
00000044fffffd9c
|
||||
0000002800000000
|
||||
fffffd6400000040
|
||||
fffffdcc00000040
|
||||
4109450000000060
|
||||
300e43029e019f00
|
||||
42000e0a447e4111
|
||||
0000000b4106dedf
|
||||
0000006c00000010
|
||||
00000028fffffd98
|
||||
00000028fffffe00
|
||||
0000001000000000
|
||||
fffffdac00000080
|
||||
000000000000012c
|
||||
fffffe1400000080
|
||||
00000000000000f0
|
||||
0000009400000010
|
||||
00000074fffffec4
|
||||
00000048fffffef0
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
0000000000000000
|
||||
|
||||
@@ -60,21 +60,6 @@
|
||||
#define SYS_REG_UART_IS_16550 (1ull << 32)
|
||||
|
||||
|
||||
/*
|
||||
* Register definitions for the potato UART
|
||||
*/
|
||||
#define POTATO_CONSOLE_TX 0x00
|
||||
#define POTATO_CONSOLE_RX 0x08
|
||||
#define POTATO_CONSOLE_STATUS 0x10
|
||||
#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01
|
||||
#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02
|
||||
#define POTATO_CONSOLE_STATUS_RX_FULL 0x04
|
||||
#define POTATO_CONSOLE_STATUS_TX_FULL 0x08
|
||||
#define POTATO_CONSOLE_CLOCK_DIV 0x18
|
||||
#define POTATO_CONSOLE_IRQ_EN 0x20
|
||||
#define POTATO_CONSOLE_IRQ_RX 0x01
|
||||
#define POTATO_CONSOLE_IRQ_TX 0x02
|
||||
|
||||
/*
|
||||
* Register definitionss for our standard (16550 style) UART
|
||||
*/
|
||||
|
||||
108
lib/console.c
108
lib/console.c
@@ -11,8 +11,6 @@
|
||||
* Core UART functions to implement for a port
|
||||
*/
|
||||
|
||||
bool uart_is_std;
|
||||
|
||||
static uint64_t uart_base;
|
||||
|
||||
static unsigned long uart_divisor(unsigned long uart_freq, unsigned long bauds)
|
||||
@@ -20,75 +18,6 @@ static unsigned long uart_divisor(unsigned long uart_freq, unsigned long bauds)
|
||||
return uart_freq / (bauds * 16);
|
||||
}
|
||||
|
||||
static uint64_t potato_uart_reg_read(int offset)
|
||||
{
|
||||
return readq(uart_base + offset);
|
||||
}
|
||||
|
||||
static void potato_uart_reg_write(int offset, uint64_t val)
|
||||
{
|
||||
writeq(val, uart_base + offset);
|
||||
}
|
||||
|
||||
static int potato_uart_rx_empty(void)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
|
||||
|
||||
if (val & POTATO_CONSOLE_STATUS_RX_EMPTY)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int potato_uart_tx_full(void)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
|
||||
|
||||
if (val & POTATO_CONSOLE_STATUS_TX_FULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char potato_uart_read(void)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = potato_uart_reg_read(POTATO_CONSOLE_RX);
|
||||
|
||||
return (char)(val & 0x000000ff);
|
||||
}
|
||||
|
||||
static void potato_uart_write(char c)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
val = c;
|
||||
|
||||
potato_uart_reg_write(POTATO_CONSOLE_TX, val);
|
||||
}
|
||||
|
||||
static void potato_uart_init(uint64_t uart_freq)
|
||||
{
|
||||
unsigned long div = uart_divisor(uart_freq, UART_BAUDS) - 1;
|
||||
potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, div);
|
||||
}
|
||||
|
||||
static void potato_uart_set_irq_en(bool rx_irq, bool tx_irq)
|
||||
{
|
||||
uint64_t en = 0;
|
||||
|
||||
if (rx_irq)
|
||||
en |= POTATO_CONSOLE_IRQ_RX;
|
||||
if (tx_irq)
|
||||
en |= POTATO_CONSOLE_IRQ_TX;
|
||||
potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, en);
|
||||
}
|
||||
|
||||
static bool std_uart_rx_empty(void)
|
||||
{
|
||||
return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_DR);
|
||||
@@ -137,28 +66,16 @@ static void std_uart_init(uint64_t uart_freq)
|
||||
|
||||
int getchar(void)
|
||||
{
|
||||
if (uart_is_std) {
|
||||
while (std_uart_rx_empty())
|
||||
/* Do nothing */ ;
|
||||
return std_uart_read();
|
||||
} else {
|
||||
while (potato_uart_rx_empty())
|
||||
/* Do nothing */ ;
|
||||
return potato_uart_read();
|
||||
}
|
||||
while (std_uart_rx_empty())
|
||||
/* Do nothing */ ;
|
||||
return std_uart_read();
|
||||
}
|
||||
|
||||
int putchar(int c)
|
||||
{
|
||||
if (uart_is_std) {
|
||||
while(std_uart_tx_full())
|
||||
/* Do Nothing */;
|
||||
std_uart_write(c);
|
||||
} else {
|
||||
while (potato_uart_tx_full())
|
||||
/* Do Nothing */;
|
||||
potato_uart_write(c);
|
||||
}
|
||||
while(std_uart_tx_full())
|
||||
/* Do Nothing */;
|
||||
std_uart_write(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -205,19 +122,10 @@ void console_init(void)
|
||||
uart_freq = proc_freq;
|
||||
|
||||
uart_base = UART_BASE;
|
||||
if (uart_info & SYS_REG_UART_IS_16550) {
|
||||
uart_is_std = true;
|
||||
std_uart_init(proc_freq);
|
||||
} else {
|
||||
uart_is_std = false;
|
||||
potato_uart_init(proc_freq);
|
||||
}
|
||||
std_uart_init(proc_freq);
|
||||
}
|
||||
|
||||
void console_set_irq_en(bool rx_irq, bool tx_irq)
|
||||
{
|
||||
if (uart_is_std)
|
||||
std_uart_set_irq_en(rx_irq, tx_irq);
|
||||
else
|
||||
potato_uart_set_irq_en(rx_irq, tx_irq);
|
||||
std_uart_set_irq_en(rx_irq, tx_irq);
|
||||
}
|
||||
|
||||
@@ -55,9 +55,6 @@ filesets:
|
||||
files:
|
||||
- fpga/main_bram.vhdl
|
||||
- fpga/soc_reset.vhdl
|
||||
- fpga/pp_fifo.vhd
|
||||
- fpga/pp_soc_uart.vhd
|
||||
- fpga/pp_utilities.vhd
|
||||
- fpga/firmware.hex : {copyto : firmware.hex, file_type : user}
|
||||
file_type : vhdlSource-2008
|
||||
|
||||
@@ -134,7 +131,6 @@ targets:
|
||||
- clk_frequency
|
||||
- disable_flatten_core
|
||||
- log_length=2048
|
||||
- uart_is_16550
|
||||
- has_fpu
|
||||
- has_btc
|
||||
tools:
|
||||
@@ -152,7 +148,6 @@ targets:
|
||||
- disable_flatten_core
|
||||
- spi_flash_offset=10485760
|
||||
- log_length=2048
|
||||
- uart_is_16550
|
||||
tools:
|
||||
vivado: {part : xc7a200tsbg484-2}
|
||||
toplevel : toplevel
|
||||
@@ -169,7 +164,6 @@ targets:
|
||||
- disable_flatten_core
|
||||
- spi_flash_offset=10485760
|
||||
- log_length=2048
|
||||
- uart_is_16550=false
|
||||
tools:
|
||||
vivado: {part : xc7k325tffg900-2}
|
||||
toplevel : toplevel
|
||||
@@ -185,7 +179,6 @@ targets:
|
||||
- no_bram
|
||||
- spi_flash_offset=10485760
|
||||
- log_length=2048
|
||||
- uart_is_16550
|
||||
generate: [litedram_acorn_cle_215]
|
||||
tools:
|
||||
vivado: {part : xc7a200tsbg484-2}
|
||||
@@ -202,7 +195,6 @@ targets:
|
||||
- no_bram
|
||||
- spi_flash_offset=10485760
|
||||
- log_length=2048
|
||||
- uart_is_16550=false
|
||||
generate: [litedram_genesys2]
|
||||
tools:
|
||||
vivado: {part : xc7k325tffg900-2}
|
||||
@@ -219,7 +211,6 @@ targets:
|
||||
- disable_flatten_core
|
||||
- spi_flash_offset=10485760
|
||||
- log_length=2048
|
||||
- uart_is_16550
|
||||
- has_fpu
|
||||
- has_btc
|
||||
tools:
|
||||
@@ -239,7 +230,6 @@ targets:
|
||||
- no_bram
|
||||
- spi_flash_offset=10485760
|
||||
- log_length=2048
|
||||
- uart_is_16550
|
||||
- has_fpu
|
||||
- has_btc
|
||||
generate: [litedram_nexys_video, liteeth_nexys_video, litesdcard_nexys_video]
|
||||
@@ -258,7 +248,6 @@ targets:
|
||||
- disable_flatten_core
|
||||
- spi_flash_offset=3145728
|
||||
- log_length=512
|
||||
- uart_is_16550
|
||||
- has_uart1
|
||||
- has_fpu=false
|
||||
- has_btc=false
|
||||
@@ -280,7 +269,6 @@ targets:
|
||||
- no_bram
|
||||
- spi_flash_offset=3145728
|
||||
- log_length=512
|
||||
- uart_is_16550
|
||||
- has_uart1
|
||||
- has_fpu=false
|
||||
- has_btc=false
|
||||
@@ -300,7 +288,6 @@ targets:
|
||||
- disable_flatten_core
|
||||
- spi_flash_offset=4194304
|
||||
- log_length=2048
|
||||
- uart_is_16550
|
||||
- has_uart1
|
||||
- has_fpu
|
||||
- has_btc
|
||||
@@ -322,7 +309,6 @@ targets:
|
||||
- no_bram
|
||||
- spi_flash_offset=4194304
|
||||
- log_length=2048
|
||||
- uart_is_16550
|
||||
- has_uart1
|
||||
- has_fpu
|
||||
- has_btc
|
||||
@@ -342,7 +328,6 @@ targets:
|
||||
- clk_frequency
|
||||
- disable_flatten_core
|
||||
- log_length=512
|
||||
- uart_is_16550
|
||||
- has_fpu=false
|
||||
- has_btc=false
|
||||
tools:
|
||||
@@ -453,12 +438,6 @@ parameters:
|
||||
paramtype : generic
|
||||
default : false
|
||||
|
||||
uart_is_16550:
|
||||
datatype : bool
|
||||
description : Use 16550-compatible UART from OpenCores
|
||||
paramtype : generic
|
||||
default : true
|
||||
|
||||
has_uart1:
|
||||
datatype : bool
|
||||
description : Enable second UART (always 16550-compatible)
|
||||
|
||||
135
sim_pp_uart.vhdl
135
sim_pp_uart.vhdl
@@ -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;
|
||||
91
soc.vhdl
91
soc.vhdl
@@ -71,7 +71,6 @@ entity soc is
|
||||
SPI_BOOT_CLOCKS : boolean := true;
|
||||
LOG_LENGTH : natural := 512;
|
||||
HAS_LITEETH : boolean := false;
|
||||
UART0_IS_16550 : boolean := true;
|
||||
HAS_UART1 : boolean := false;
|
||||
ICACHE_NUM_LINES : natural := 64;
|
||||
ICACHE_NUM_WAYS : natural := 2;
|
||||
@@ -244,6 +243,8 @@ architecture behaviour of soc is
|
||||
SLAVE_IO_NONE);
|
||||
signal slave_io_dbg : slave_io_type;
|
||||
|
||||
signal uart0_irq_l : std_ulogic;
|
||||
|
||||
function wishbone_widen_data(wb : wb_io_master_out) return wishbone_master_out is
|
||||
variable wwb : wishbone_master_out;
|
||||
begin
|
||||
@@ -737,7 +738,6 @@ begin
|
||||
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
|
||||
HAS_LITEETH => HAS_LITEETH,
|
||||
HAS_SD_CARD => HAS_SD_CARD,
|
||||
UART0_IS_16550 => UART0_IS_16550,
|
||||
HAS_UART1 => HAS_UART1
|
||||
)
|
||||
port map(
|
||||
@@ -750,74 +750,41 @@ begin
|
||||
soc_reset => open -- XXX TODO
|
||||
);
|
||||
|
||||
--
|
||||
-- UART0
|
||||
--
|
||||
-- Either potato (legacy) or 16550
|
||||
--
|
||||
uart0_pp: if not UART0_IS_16550 generate
|
||||
uart0: entity work.pp_soc_uart
|
||||
generic map(
|
||||
FIFO_DEPTH => 32
|
||||
)
|
||||
port map(
|
||||
clk => system_clk,
|
||||
reset => rst_uart,
|
||||
txd => uart0_txd,
|
||||
rxd => uart0_rxd,
|
||||
irq => uart0_irq,
|
||||
wb_adr_in => wb_uart0_in.adr(11 downto 0),
|
||||
wb_dat_in => wb_uart0_in.dat(7 downto 0),
|
||||
wb_dat_out => uart0_dat8,
|
||||
wb_cyc_in => wb_uart0_in.cyc,
|
||||
wb_stb_in => wb_uart0_in.stb,
|
||||
wb_we_in => wb_uart0_in.we,
|
||||
wb_ack_out => wb_uart0_out.ack
|
||||
);
|
||||
end generate;
|
||||
uart0: uart_top
|
||||
port map (
|
||||
wb_clk_i => system_clk,
|
||||
wb_rst_i => rst_uart,
|
||||
wb_adr_i => wb_uart0_in.adr(4 downto 2),
|
||||
wb_dat_i => wb_uart0_in.dat(7 downto 0),
|
||||
wb_dat_o => uart0_dat8,
|
||||
wb_we_i => wb_uart0_in.we,
|
||||
wb_stb_i => wb_uart0_in.stb,
|
||||
wb_cyc_i => wb_uart0_in.cyc,
|
||||
wb_ack_o => wb_uart0_out.ack,
|
||||
int_o => uart0_irq_l,
|
||||
stx_pad_o => uart0_txd,
|
||||
srx_pad_i => uart0_rxd,
|
||||
rts_pad_o => open,
|
||||
cts_pad_i => '1',
|
||||
dtr_pad_o => open,
|
||||
dsr_pad_i => '1',
|
||||
ri_pad_i => '0',
|
||||
dcd_pad_i => '1'
|
||||
);
|
||||
|
||||
uart0_16550 : if UART0_IS_16550 generate
|
||||
signal irq_l : std_ulogic;
|
||||
-- Add a register on the irq out, helps timing
|
||||
uart0_irq_latch: process(system_clk)
|
||||
begin
|
||||
uart0: uart_top
|
||||
port map (
|
||||
wb_clk_i => system_clk,
|
||||
wb_rst_i => rst_uart,
|
||||
wb_adr_i => wb_uart0_in.adr(4 downto 2),
|
||||
wb_dat_i => wb_uart0_in.dat(7 downto 0),
|
||||
wb_dat_o => uart0_dat8,
|
||||
wb_we_i => wb_uart0_in.we,
|
||||
wb_stb_i => wb_uart0_in.stb,
|
||||
wb_cyc_i => wb_uart0_in.cyc,
|
||||
wb_ack_o => wb_uart0_out.ack,
|
||||
int_o => irq_l,
|
||||
stx_pad_o => uart0_txd,
|
||||
srx_pad_i => uart0_rxd,
|
||||
rts_pad_o => open,
|
||||
cts_pad_i => '1',
|
||||
dtr_pad_o => open,
|
||||
dsr_pad_i => '1',
|
||||
ri_pad_i => '0',
|
||||
dcd_pad_i => '1'
|
||||
);
|
||||
|
||||
-- Add a register on the irq out, helps timing
|
||||
uart0_irq_latch: process(system_clk)
|
||||
begin
|
||||
if rising_edge(system_clk) then
|
||||
uart0_irq <= irq_l;
|
||||
end if;
|
||||
end process;
|
||||
end generate;
|
||||
if rising_edge(system_clk) then
|
||||
uart0_irq <= uart0_irq_l;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
wb_uart0_out.dat <= x"000000" & uart0_dat8;
|
||||
wb_uart0_out.stall <= not wb_uart0_out.ack;
|
||||
|
||||
--
|
||||
-- UART1
|
||||
--
|
||||
-- Always 16550 if it exists
|
||||
--
|
||||
uart1: if HAS_UART1 generate
|
||||
signal irq_l : std_ulogic;
|
||||
begin
|
||||
|
||||
@@ -19,7 +19,6 @@ entity syscon is
|
||||
SPI_FLASH_OFFSET : integer;
|
||||
HAS_LITEETH : boolean;
|
||||
HAS_SD_CARD : boolean;
|
||||
UART0_IS_16550 : boolean;
|
||||
HAS_UART1 : boolean
|
||||
);
|
||||
port (
|
||||
@@ -88,7 +87,7 @@ architecture behaviour of syscon is
|
||||
-- UART0/1 info registers bits
|
||||
--
|
||||
-- 0 ..31 : UART clock freq (in HZ)
|
||||
-- 32 : UART is 16550 (otherwise pp)
|
||||
-- 32 : UART is 16550
|
||||
--
|
||||
|
||||
-- Ctrl register
|
||||
@@ -160,7 +159,7 @@ begin
|
||||
SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);
|
||||
|
||||
-- UART info registers read composition
|
||||
uinfo_16550 <= '1' when UART0_IS_16550 else '0';
|
||||
uinfo_16550 <= '1';
|
||||
uinfo_freq <= std_ulogic_vector(to_unsigned(CLK_FREQ, 32));
|
||||
reg_uart0info <= (32 => uinfo_16550,
|
||||
31 downto 0 => uinfo_freq,
|
||||
|
||||
Reference in New Issue
Block a user