Remove Potato UART

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
remove-potato-uart
Anton Blanchard 3 years ago committed by Anton Blanchard
parent 1896e5f803
commit 1d29cdcfb4

@ -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
*/

@ -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)

@ -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;

@ -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,

Loading…
Cancel
Save