From c4c77be7bd6ef40ea41062706f9f37ec54451f1e Mon Sep 17 00:00:00 2001 From: Alvaro Lopes Date: Tue, 5 May 2009 09:24:25 +0100 Subject: [PATCH] UART rx support --- .../alzpu/v4/designs/benchmark/alzpu_config.vhd | 2 +- .../v4/designs/benchmark/alzpu_config_syn.vhd | 1 - .../alzpu/v4/designs/benchmark/alzpu_system.vhd | 19 ++-- .../alzpu/v4/designs/benchmark/sim/ghdl/Makefile | 4 +- .../v4/designs/benchmark/sim/ghdl/alzpu_config.vhd | 5 +- .../alzpu/v4/designs/benchmark/simulate-ghdl.sh | 2 +- .../v4/designs/benchmark/syn/xst/alzpu_system.prj | 1 + zpu/hdl/alzpu/v4/devices/uart-sim.vhd | 12 ++- zpu/hdl/alzpu/v4/devices/uart.vhd | 97 +++++++++++++---- zpu/hdl/alzpu/v4/devices/uart_rx.vhd | 118 +++++++++++++++++++++ zpu/hdl/alzpu/v4/devices/uart_tx.vhd | 1 + 11 files changed, 223 insertions(+), 39 deletions(-) create mode 100644 zpu/hdl/alzpu/v4/devices/uart_rx.vhd diff --git a/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config.vhd b/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config.vhd index 04ef7b6..c81ffe7 100644 --- a/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config.vhd +++ b/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config.vhd @@ -75,7 +75,7 @@ package alzpu_config is -- UART definitions constant uart_baud_rate: integer := 38600; - constant brgen_count: integer := (ZPU_Frequency * 1e6) / uart_baud_rate; + constant brgen_count: integer := (ZPU_Frequency * 1000000) / uart_baud_rate; -- Use external validator file. Do not enable unless you know what you're doing. constant alzpu_validator_enabled: boolean := false; diff --git a/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config_syn.vhd b/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config_syn.vhd index 8acda4d..cc5393a 100644 --- a/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config_syn.vhd +++ b/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_config_syn.vhd @@ -82,7 +82,6 @@ package alzpu_config is -- UART definitions constant uart_baud_rate: integer := 38600; - constant brgen_count: integer := (ZPU_Frequency * 1e6) / uart_baud_rate; -- Emulated instruction implementation diff --git a/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_system.vhd b/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_system.vhd index 4e393c3..55ee53d 100644 --- a/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_system.vhd +++ b/zpu/hdl/alzpu/v4/designs/benchmark/alzpu_system.vhd @@ -134,12 +134,16 @@ architecture behave of alzpu_system is component uart is generic( - count : integer range 0 to 65535 + clk_mhz: integer := 50; + baud_rate: integer := 38600; + oversample: integer := 16 ); port( - slave_in : in zpu_slave_in_type; - slave_out : out zpu_slave_out_type; - tx_d: out std_logic + slave_in: in zpu_slave_in_type; + slave_out: out zpu_slave_out_type; + tx_d: out std_logic; + rx_d: in std_logic; + intr: out std_logic ); end component; @@ -216,12 +220,15 @@ begin myuart: uart generic map( - count => brgen_count + clk_mhz => ZPU_Frequency, + baud_rate => uart_baud_rate ) port map ( slave_in => uart_si, slave_out => uart_so, - tx_d => txd + tx_d => txd, + rx_d => '1', + intr => open ); core : alzpu diff --git a/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/Makefile b/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/Makefile index c226b82..70e23d2 100644 --- a/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/Makefile +++ b/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/Makefile @@ -13,7 +13,9 @@ SRC= \ ../../../../common/alzpu_slaveselect.vhd \ ../../software/validator.vhd \ ../../software/prom-generic-dp-8-32.vhd \ -../../../../devices/uart-sim.vhd \ +../../../../devices/uart.vhd \ +../../../../devices/uart_tx.vhd \ +../../../../devices/uart_rx.vhd \ ../../../../devices/timer.vhd \ ../../../../devices/brgen.vhd \ ../../alzpu_system.vhd \ diff --git a/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/alzpu_config.vhd b/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/alzpu_config.vhd index 7048170..b0ebeb5 100644 --- a/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/alzpu_config.vhd +++ b/zpu/hdl/alzpu/v4/designs/benchmark/sim/ghdl/alzpu_config.vhd @@ -76,10 +76,11 @@ package alzpu_config is -- UART definitions constant uart_baud_rate: integer := 38600; - constant brgen_count: integer := (ZPU_Frequency * 1e6) / uart_baud_rate; + constant uart_oversampling: integer := 16; + constant brgen_count: integer := (ZPU_Frequency * 1000000) / (uart_baud_rate*uart_oversampling); -- Use external validator file. Do not enable unless you know what you're doing. - constant alzpu_validator_enabled: boolean := true; + constant alzpu_validator_enabled: boolean := false; constant zpu_tech: zpu_tech_type := none; diff --git a/zpu/hdl/alzpu/v4/designs/benchmark/simulate-ghdl.sh b/zpu/hdl/alzpu/v4/designs/benchmark/simulate-ghdl.sh index ed1d2fb..dee0786 100755 --- a/zpu/hdl/alzpu/v4/designs/benchmark/simulate-ghdl.sh +++ b/zpu/hdl/alzpu/v4/designs/benchmark/simulate-ghdl.sh @@ -1,3 +1,3 @@ #!/bin/sh -cd sim/ghdl && make && echo && echo "SIMULATING" && echo && ./benchmark --ieee-asserts=disable +cd sim/ghdl && make && echo && echo "SIMULATING" && echo && ./benchmark --ieee-asserts=disable --vcd=alzpu.vcd diff --git a/zpu/hdl/alzpu/v4/designs/benchmark/syn/xst/alzpu_system.prj b/zpu/hdl/alzpu/v4/designs/benchmark/syn/xst/alzpu_system.prj index f843340..6921a79 100644 --- a/zpu/hdl/alzpu/v4/designs/benchmark/syn/xst/alzpu_system.prj +++ b/zpu/hdl/alzpu/v4/designs/benchmark/syn/xst/alzpu_system.prj @@ -11,6 +11,7 @@ vhdl work "../../../../common/tech_generic.vhd" vhdl work "../../../../common/alzpu_slaveselect.vhd" vhdl work "../../../../devices/uart.vhd" vhdl work "../../../../devices/uart_tx.vhd" +vhdl work "../../../../devices/uart_rx.vhd" vhdl work "../../../../devices/timer.vhd" vhdl work "../../../../devices/brgen.vhd" vhdl work "../../software/prom-virtex-dp-8-32.vhd" diff --git a/zpu/hdl/alzpu/v4/devices/uart-sim.vhd b/zpu/hdl/alzpu/v4/devices/uart-sim.vhd index 62aca1c..408d0ad 100644 --- a/zpu/hdl/alzpu/v4/devices/uart-sim.vhd +++ b/zpu/hdl/alzpu/v4/devices/uart-sim.vhd @@ -10,12 +10,16 @@ use work.txt_util.all; entity uart is generic( - count : integer range 0 to 65535 + clk_mhz: integer := 50; + baud_rate: integer := 38600; + oversample: integer := 16 ); port( - slave_in : in zpu_slave_in_type; - slave_out : out zpu_slave_out_type; - tx_d: out std_logic + slave_in: in zpu_slave_in_type; + slave_out: out zpu_slave_out_type; + tx_d: out std_logic; + rx_d: in std_logic; + intr: out std_logic ); end entity uart; diff --git a/zpu/hdl/alzpu/v4/devices/uart.vhd b/zpu/hdl/alzpu/v4/devices/uart.vhd index b71bae1..fa385d4 100644 --- a/zpu/hdl/alzpu/v4/devices/uart.vhd +++ b/zpu/hdl/alzpu/v4/devices/uart.vhd @@ -5,15 +5,20 @@ use ieee.numeric_std.all; library work; use work.alzpupkg.all; +use work.alzpu_config.all; entity uart is generic( - count : integer range 0 to 65535 + clk_mhz: integer := 50; + baud_rate: integer := 38600; + oversample: integer := 16 ); port( - slave_in : in zpu_slave_in_type; - slave_out : out zpu_slave_out_type; - tx_d: out std_logic + slave_in: in zpu_slave_in_type; + slave_out: out zpu_slave_out_type; + tx_d: out std_logic; + rx_d: in std_logic; + intr: out std_logic ); end entity uart; @@ -31,6 +36,17 @@ component uart_tx is datai_i : in std_logic_vector(7 downto 0)); -- Byte to transmit end component uart_tx; +component uart_rx is + port ( + clk_i: in std_logic; + reset_i: in std_logic; + rx_clken_i: in std_logic; + rxd_i: in std_logic; + clr_ready_i: in std_logic; + data_ready_o:out std_logic; + data_o: out std_logic_vector(7 downto 0) + ); +end component uart_rx; component brgen is generic( @@ -42,53 +58,88 @@ component brgen is o_o : out std_logic); -- output end component brgen; +signal clken: std_logic; signal tx_clken: std_logic; signal tx_data_en: std_logic; signal tx_busy: std_logic; +signal tx_dly_clk: integer range 0 to uart_oversampling-1; + +signal rx_data: std_logic_vector(7 downto 0); +signal rx_data_ready: std_logic; +signal txd_int: std_logic; +signal rxread: std_logic; + +constant brgen_count: integer := (clk_mhz * 1000000) / (baud_rate*oversample); + begin mybrgen: brgen generic map ( - count => count + count => brgen_count ) port map ( clk_i => slave_in.clk, reset_i => slave_in.rst, ce_i => '1', - o_o => tx_clken + o_o => clken ); +ospdiv: if uart_oversampling /= 1 generate + process(slave_in.clk) + begin + if rising_edge(slave_in.clk) then + if slave_in.rst='1' then + tx_clken<='0'; + tx_dly_clk <= oversample - 1; + else + tx_clken<='0'; + if clken='1' then + if tx_dly_clk=0 then + tx_dly_clk <= oversample - 1; + tx_clken <= '1'; + else + tx_dly_clk <= tx_dly_clk - 1; + end if; + end if; + end if; + end if; + end process; +end generate; + +tx_d <= txd_int; + tx: uart_tx port map ( clk_i => slave_in.clk, reset_i => slave_in.rst, enable_i => tx_clken, load_i => tx_data_en, - txd_o => tx_d, + txd_o => txd_int, busy_o => tx_busy, datai_i => slave_in.dati(7 downto 0) ); +rx: uart_rx + port map ( + clk_i => slave_in.clk, + reset_i => slave_in.rst, + rx_clken_i => clken, + rxd_i => txd_int, + clr_ready_i => rxread, + data_ready_o => rx_data_ready, + data_o => rx_data + ); + slave_out.busy <= '0'; tx_data_en <= slave_in.wr_en; -process(slave_in.clk, slave_in.rst) -begin - if rising_edge(slave_in.clk) then - if slave_in.rst='1' then - slave_out.data_valid <= '0'; - else - slave_out.data_valid <= '0'; - if slave_in.rd_en='1' then - slave_out.data_valid <= '1'; - slave_out.dato <= (others=>'0'); - slave_out.dato(8) <= not tx_busy; - end if; - end if; - - end if; -end process; + +slave_out.dato(8) <= not tx_busy; +slave_out.dato(9) <= rx_data_ready; +slave_out.dato(7 downto 0) <= rx_data; + +slave_out.data_valid <= '1'; end behave; diff --git a/zpu/hdl/alzpu/v4/devices/uart_rx.vhd b/zpu/hdl/alzpu/v4/devices/uart_rx.vhd new file mode 100644 index 0000000..3f73e2b --- /dev/null +++ b/zpu/hdl/alzpu/v4/devices/uart_rx.vhd @@ -0,0 +1,118 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.alzpupkg.all; +use work.alzpu_config.all; + +entity uart_rx is + generic ( + oversample: integer := 16 + ); + port ( + clk_i: in std_logic; + reset_i: in std_logic; + rx_clken_i: in std_logic; + rxd_i: in std_logic; + clr_ready_i: in std_logic; + data_ready_o:out std_logic; + data_o: out std_logic_vector(7 downto 0) + ); +end entity uart_rx; + +architecture behave of uart_rx is + +type rxstate_type is ( + idle, + start, + receive, + stop +); + +signal count_in: integer range 0 to oversample + oversample/2; +signal state: rxstate_type; +signal bits: integer range 0 to 8; +signal shiftbits: std_logic_vector(9 downto 0); -- 10 bits. + +signal debug_sample_bit: std_logic; + +begin + +process(clk_i) +begin + if rising_edge(clk_i) then + if reset_i='1' then + state <= idle; + debug_sample_bit <= '0'; + data_ready_o <= '0'; + else + if clr_ready_i='1' then + data_ready_o <= '0'; + end if; + + if rx_clken_i='1' then + + debug_sample_bit <= '0'; + + case state is + when idle => + if rxd_i='0' then + shiftbits<=(others=>'0'); + shiftbits(7) <= '1'; + count_in <= oversample + oversample/2 - 2; + state <= start; + end if; + when start => + -- Do some debouncing/glitch avoidance here + if count_in = 0 then + state <= receive; + shiftbits(7) <= rxd_i; + shiftbits(6 downto 0) <= shiftbits(7 downto 1); + + debug_sample_bit <= '1'; + bits <= 0; + count_in <= oversample - 1; + else + count_in <= count_in - 1; + end if; + when receive => + if count_in = 0 then + debug_sample_bit <= '1'; + shiftbits(7) <= rxd_i; + shiftbits(6 downto 0) <= shiftbits(7 downto 1); + count_in <= oversample - 1; + if shiftbits(0)='1' then + state <= stop; + end if; + else + count_in <= count_in -1; + end if; + + when stop => + if count_in = 0 then + if rxd_i='1' then + data_o <= shiftbits(7 downto 0); + data_ready_o <= '1'; + --count_in <= (oversample/2)-1; + --state <= waitrestart; + state <= idle; + end if; + else + count_in <= count_in - 1; + end if; + --when waitrestart => + -- if count_in = 0 then + -- state<=idle; + -- else + -- count_in <= count_in - 1; + -- end if; + end case; + end if; + end if; + end if; +end process; + + +end behave; + diff --git a/zpu/hdl/alzpu/v4/devices/uart_tx.vhd b/zpu/hdl/alzpu/v4/devices/uart_tx.vhd index a22f361..c03b208 100644 --- a/zpu/hdl/alzpu/v4/devices/uart_tx.vhd +++ b/zpu/hdl/alzpu/v4/devices/uart_tx.vhd @@ -86,6 +86,7 @@ begin when 0 => -- idle or stop bit txd_r <= '1'; if loaded_r='1' then -- start transmit. next is start bit + report "UART transmit"; t_r <= tbuff_r; loaded_r <= '0'; bitpos:=1; -- 2.11.4.GIT