OpenCores
URL https://opencores.org/ocsvn/rise/rise/trunk

Subversion Repositories rise

[/] [rise/] [trunk/] [vhdl/] [sc_uart.vhd] - Diff between revs 127 and 148

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 127 Rev 148
--
--
--      sc_uart.vhd
--      sc_uart.vhd
--
--
--      8-N-1 serial interface
--      8-N-1 serial interface
--      
--      
--      wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later
--      wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later
--
--
--      Author: Martin Schoeberl        martin@jopdesign.com
--      Author: Martin Schoeberl        martin@jopdesign.com
--
--
--
--
--      resources on ACEX1K30-3
--      resources on ACEX1K30-3
--
--
--              100 LCs, max 90 MHz
--              100 LCs, max 90 MHz
--
--
--      resetting rts with fifo_full-1 works with C program on pc
--      resetting rts with fifo_full-1 works with C program on pc
--      but not with javax.comm: sends some more bytes after deassert
--      but not with javax.comm: sends some more bytes after deassert
--      of rts (16 byte blocks regardless of rts).
--      of rts (16 byte blocks regardless of rts).
--      Try to stop with half full fifo.
--      Try to stop with half full fifo.
--
--
--      todo:
--      todo:
--
--
--
--
--      2000-12-02      first working version
--      2000-12-02      first working version
--      2002-01-06      changed tdr and rdr to fifos.
--      2002-01-06      changed tdr and rdr to fifos.
--      2002-05-15      changed clkdiv calculation
--      2002-05-15      changed clkdiv calculation
--      2002-11-01      don't wait if read fifo is full, just drop the byte
--      2002-11-01      don't wait if read fifo is full, just drop the byte
--      2002-11-03      use threshold in fifo to reset rts 
--      2002-11-03      use threshold in fifo to reset rts 
--                              don't send if cts is '0'
--                              don't send if cts is '0'
--      2002-11-08      rx fifo to 20 characters and stop after 4
--      2002-11-08      rx fifo to 20 characters and stop after 4
--      2003-07-05      new IO standard, change cts/rts to neg logic
--      2003-07-05      new IO standard, change cts/rts to neg logic
--      2003-09-19      sync ncts in!
--      2003-09-19      sync ncts in!
--      2004-03-23      two stop bits
--      2004-03-23      two stop bits
--      2005-11-30      change interface to SimpCon
--      2005-11-30      change interface to SimpCon
--      2006-08-07      rxd input register with clk to avoid Quartus tsu violation
--      2006-08-07      rxd input register with clk to avoid Quartus tsu violation
--      2006-08-13      use 3 FFs for the rxd input at clk
--      2006-08-13      use 3 FFs for the rxd input at clk
--
--
 
 
 
 
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std.all;
 
 
entity sc_uart is
entity sc_uart is
 
 
generic (addr_bits : integer;
generic (addr_bits : integer;
        clk_freq : integer;
        clk_freq : integer;
        baud_rate : integer;
        baud_rate : integer;
        txf_depth : integer; txf_thres : integer;
        txf_depth : integer; txf_thres : integer;
        rxf_depth : integer; rxf_thres : integer);
        rxf_depth : integer; rxf_thres : integer);
port (
port (
        clk             : in std_logic;
        clk             : in std_logic;
        reset   : in std_logic;
        reset   : in std_logic;
 
 
-- SimpCon interface
-- SimpCon interface
 
 
        address         : in std_logic_vector(addr_bits-1 downto 0);
        address         : in std_logic_vector(addr_bits-1 downto 0);
        wr_data         : in std_logic_vector(15 downto 0);
        wr_data         : in std_logic_vector(15 downto 0);
        rd, wr          : in std_logic;
        rd, wr          : in std_logic;
        rd_data         : out std_logic_vector(15 downto 0);
        rd_data         : out std_logic_vector(15 downto 0);
        rdy_cnt         : out unsigned(1 downto 0);
        rdy_cnt         : out unsigned(1 downto 0);
 
 
        txd             : out std_logic;
        txd             : out std_logic;
        rxd             : in std_logic;
        rxd             : in std_logic;
        ncts    : in std_logic;
        ncts    : in std_logic;
        nrts    : out std_logic
        nrts    : out std_logic
);
);
end sc_uart;
end sc_uart;
 
 
architecture rtl of sc_uart is
architecture rtl of sc_uart is
 
 
component fifo is
component fifo is
 
 
generic (width : integer; depth : integer; thres : integer);
generic (width : integer; depth : integer; thres : integer);
port (
port (
        clk             : in std_logic;
        clk             : in std_logic;
        reset   : in std_logic;
        reset   : in std_logic;
 
 
        din             : in std_logic_vector(width-1 downto 0);
        din             : in std_logic_vector(width-1 downto 0);
        dout    : out std_logic_vector(width-1 downto 0);
        dout    : out std_logic_vector(width-1 downto 0);
 
 
        rd              : in std_logic;
        rd              : in std_logic;
        wr              : in std_logic;
        wr              : in std_logic;
 
 
        empty   : out std_logic;
        empty   : out std_logic;
        full    : out std_logic;
        full    : out std_logic;
        half    : out std_logic
        half    : out std_logic
);
);
end component;
end component;
 
 
--
--
--      signals for uart connection
--      signals for uart connection
--
--
        signal ua_dout                  : std_logic_vector(7 downto 0);
        signal ua_dout                  : std_logic_vector(7 downto 0);
        signal ua_wr, tdre              : std_logic;
        signal ua_wr, tdre              : std_logic;
        signal ua_rd, rdrf              : std_logic;
        signal ua_rd, rdrf              : std_logic;
 
 
        type uart_tx_state_type         is (s0, s1);
        type uart_tx_state_type         is (s0, s1);
        signal uart_tx_state            : uart_tx_state_type;
        signal uart_tx_state            : uart_tx_state_type;
 
 
        signal tf_dout          : std_logic_vector(7 downto 0); -- fifo out
        signal tf_dout          : std_logic_vector(7 downto 0); -- fifo out
        signal tf_rd            : std_logic;
        signal tf_rd            : std_logic;
        signal tf_empty         : std_logic;
        signal tf_empty         : std_logic;
        signal tf_full          : std_logic;
        signal tf_full          : std_logic;
        signal tf_half          : std_logic;
        signal tf_half          : std_logic;
 
 
        signal ncts_buf         : std_logic_vector(2 downto 0);  -- sync in
        signal ncts_buf         : std_logic_vector(2 downto 0);  -- sync in
 
 
        signal tsr                      : std_logic_vector(9 downto 0); -- tx shift register
        signal tsr                      : std_logic_vector(9 downto 0); -- tx shift register
 
 
        signal tx_clk           : std_logic;
        signal tx_clk           : std_logic;
 
 
 
 
        type uart_rx_state_type         is (s0, s1, s2);
        type uart_rx_state_type         is (s0, s1, s2);
        signal uart_rx_state            : uart_rx_state_type;
        signal uart_rx_state            : uart_rx_state_type;
 
 
        signal rf_wr            : std_logic;
        signal rf_wr            : std_logic;
        signal rf_empty         : std_logic;
        signal rf_empty         : std_logic;
        signal rf_full          : std_logic;
        signal rf_full          : std_logic;
        signal rf_half          : std_logic;
        signal rf_half          : std_logic;
 
 
        signal rxd_reg          : std_logic_vector(2 downto 0);
        signal rxd_reg          : std_logic_vector(2 downto 0);
        signal rx_buf           : std_logic_vector(2 downto 0);  -- sync in, filter
        signal rx_buf           : std_logic_vector(2 downto 0);  -- sync in, filter
        signal rx_d                     : std_logic;                                    -- rx serial data
        signal rx_d                     : std_logic;                                    -- rx serial data
 
 
        signal rsr                      : std_logic_vector(9 downto 0); -- rx shift register
        signal rsr                      : std_logic_vector(9 downto 0); -- rx shift register
 
 
        signal rx_clk           : std_logic;
        signal rx_clk           : std_logic;
        signal rx_clk_ena       : std_logic;
        signal rx_clk_ena       : std_logic;
 
 
        constant clk16_cnt      : integer := (clk_freq/baud_rate+8)/16-1;
        constant clk16_cnt      : integer := (clk_freq/baud_rate+8)/16-1;
 
 
 
 
begin
begin
 
 
        rdy_cnt <= "00";        -- no wait states
        rdy_cnt <= "00";        -- no wait states
        rd_data(15 downto 8) <= ( others => '0' );
        rd_data(15 downto 8) <= ( others => '0' );
--
--
--      The registered MUX is all we need for a SimpCon read.
--      The registered MUX is all we need for a SimpCon read.
--      The read data is stored in registered rd_data.
--      The read data is stored in registered rd_data.
--
--
process(clk, reset)
process(clk, reset)
begin
begin
 
 
        if (reset='0') then
        if (reset='0') then
                rd_data(7 downto 0) <= (others => '0');
                rd_data(7 downto 0) <= (others => '0');
        elsif rising_edge(clk) then
        elsif rising_edge(clk) then
 
 
                ua_rd <= '0';
                ua_rd <= '0';
                if rd='1' then
                if rd='1' then
                        -- that's our very simple address decoder
                        -- that's our very simple address decoder
                        if address(0)='0' then
                        if address(0)='0' then
                                rd_data(7 downto 0) <= "000000" & rdrf & tdre;
                                rd_data(7 downto 0) <= "000000" & rdrf & tdre;
                        else
                        else
                                rd_data(7 downto 0) <= ua_dout;
                                rd_data(7 downto 0) <= ua_dout;
                                ua_rd <= rd;
                                ua_rd <= rd;
                        end if;
                        end if;
                end if;
                end if;
        end if;
        end if;
 
 
end process;
end process;
 
 
        -- write is on address offest 1
        -- write is on address offest 1
        ua_wr <= wr and address(0);
        ua_wr <= wr and address(0);
 
 
--
--
--      serial clock
--      serial clock
--
--
process(clk, reset)
process(clk, reset)
 
 
        variable clk16          : integer range 0 to clk16_cnt;
        variable clk16          : integer range 0 to clk16_cnt;
        variable clktx          : unsigned(3 downto 0);
        variable clktx          : unsigned(3 downto 0);
        variable clkrx          : unsigned(3 downto 0);
        variable clkrx          : unsigned(3 downto 0);
 
 
begin
begin
        if (reset='0') then
        if (reset='0') then
                clk16 := 0;
                clk16 := 0;
                clktx := "0000";
                clktx := "0000";
                clkrx := "0000";
                clkrx := "0000";
                tx_clk <= '0';
                tx_clk <= '0';
                rx_clk <= '0';
                rx_clk <= '0';
                rx_buf <= "111";
                rx_buf <= "111";
 
 
        elsif rising_edge(clk) then
        elsif rising_edge(clk) then
 
 
                rxd_reg(0) <= rxd;                       -- to avoid setup timing error in Quartus
                rxd_reg(0) <= rxd;                       -- to avoid setup timing error in Quartus
                rxd_reg(1) <= rxd_reg(0);
                rxd_reg(1) <= rxd_reg(0);
                rxd_reg(2) <= rxd_reg(1);
                rxd_reg(2) <= rxd_reg(1);
 
 
                if (clk16=clk16_cnt) then               -- 16 x serial clock
                if (clk16=clk16_cnt) then               -- 16 x serial clock
                        clk16 := 0;
                        clk16 := 0;
--
--
--      tx clock
--      tx clock
--
--
                        clktx := clktx + 1;
                        clktx := clktx + 1;
                        if (clktx="0000") then
                        if (clktx="0000") then
                                tx_clk <= '1';
                                tx_clk <= '1';
                        else
                        else
                                tx_clk <= '0';
                                tx_clk <= '0';
                        end if;
                        end if;
--
--
--      rx clock
--      rx clock
--
--
                        if (rx_clk_ena='1') then
                        if (rx_clk_ena='1') then
                                clkrx := clkrx + 1;
                                clkrx := clkrx + 1;
                                if (clkrx="1000") then
                                if (clkrx="1000") then
                                        rx_clk <= '1';
                                        rx_clk <= '1';
                                else
                                else
                                        rx_clk <= '0';
                                        rx_clk <= '0';
                                end if;
                                end if;
                        else
                        else
                                clkrx := "0000";
                                clkrx := "0000";
                        end if;
                        end if;
--
--
--      sync in filter buffer
--      sync in filter buffer
--
--
                        rx_buf(0) <= rxd_reg(2);
                        rx_buf(0) <= rxd_reg(2);
                        rx_buf(2 downto 1) <= rx_buf(1 downto 0);
                        rx_buf(2 downto 1) <= rx_buf(1 downto 0);
                else
                else
                        clk16 := clk16 + 1;
                        clk16 := clk16 + 1;
                        tx_clk <= '0';
                        tx_clk <= '0';
                        rx_clk <= '0';
                        rx_clk <= '0';
                end if;
                end if;
 
 
 
 
        end if;
        end if;
 
 
end process;
end process;
 
 
--
--
--      transmit fifo
--      transmit fifo
--
--
        cmp_tf: fifo generic map (8, txf_depth, txf_thres)
        cmp_tf: fifo generic map (8, txf_depth, txf_thres)
                        port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half);
                        port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half);
 
 
--
--
--      state machine for actual shift out
--      state machine for actual shift out
--
--
process(clk, reset)
process(clk, reset)
 
 
        variable i : integer range 0 to 11;
        variable i : integer range 0 to 11;
 
 
begin
begin
 
 
        if (reset='0') then
        if (reset='0') then
                uart_tx_state <= s0;
                uart_tx_state <= s0;
                tsr <= "1111111111";
                tsr <= "1111111111";
                tf_rd <= '0';
                tf_rd <= '0';
                ncts_buf <= "111";
                ncts_buf <= "111";
 
 
        elsif rising_edge(clk) then
        elsif rising_edge(clk) then
 
 
                ncts_buf(0) <= ncts;
                ncts_buf(0) <= ncts;
                ncts_buf(2 downto 1) <= ncts_buf(1 downto 0);
                ncts_buf(2 downto 1) <= ncts_buf(1 downto 0);
 
 
                case uart_tx_state is
                case uart_tx_state is
 
 
                        when s0 =>
                        when s0 =>
                                i := 0;
                                i := 0;
                                if (tf_empty='0' and ncts_buf(2)='0') then
                                if (tf_empty='0' and ncts_buf(2)='0') then
                                        uart_tx_state <= s1;
                                        uart_tx_state <= s1;
                                        tsr <= tf_dout & '0' & '1';
                                        tsr <= tf_dout & '0' & '1';
                                        tf_rd <= '1';
                                        tf_rd <= '1';
                                end if;
                                end if;
 
 
                        when s1 =>
                        when s1 =>
                                tf_rd <= '0';
                                tf_rd <= '0';
                                if (tx_clk='1') then
                                if (tx_clk='1') then
                                        tsr(9) <= '1';
                                        tsr(9) <= '1';
                                        tsr(8 downto 0) <= tsr(9 downto 1);
                                        tsr(8 downto 0) <= tsr(9 downto 1);
                                        i := i+1;
                                        i := i+1;
                                        if (i=11) then                          -- two stop bits
                                        if (i=11) then                          -- two stop bits
                                                uart_tx_state <= s0;
                                                uart_tx_state <= s0;
                                        end if;
                                        end if;
                                end if;
                                end if;
 
 
                end case;
                end case;
        end if;
        end if;
 
 
end process;
end process;
 
 
        txd <= tsr(0);
        txd <= tsr(0);
        tdre <= not tf_full;
        tdre <= not tf_full;
 
 
 
 
--
--
--      receive fifo
--      receive fifo
--
--
        cmp_rf: fifo generic map (8, rxf_depth, rxf_thres)
        cmp_rf: fifo generic map (8, rxf_depth, rxf_thres)
                        port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half);
                        port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half);
 
 
        rdrf <= not rf_empty;
        rdrf <= not rf_empty;
        nrts <= rf_half;                        -- glitches even on empty fifo!
        nrts <= rf_half;                        -- glitches even on empty fifo!
 
 
--
--
--      filter rxd
--      filter rxd
--
--
        with rx_buf select
        with rx_buf select
                rx_d <= '0' when "000",
                rx_d <= '0' when "000",
                                '0' when "001",
                                '0' when "001",
                                '0' when "010",
                                '0' when "010",
                                '1' when "011",
                                '1' when "011",
                                '0' when "100",
                                '0' when "100",
                                '1' when "101",
                                '1' when "101",
                                '1' when "110",
                                '1' when "110",
                                '1' when "111",
                                '1' when "111",
                                'X' when others;
                                'X' when others;
 
 
--
--
--      state machine for actual shift in
--      state machine for actual shift in
--
--
process(clk, reset)
process(clk, reset)
 
 
        variable i : integer range 0 to 10;
        variable i : integer range 0 to 10;
 
 
begin
begin
 
 
        if (reset='0') then
        if (reset='0') then
                uart_rx_state <= s0;
                uart_rx_state <= s0;
                rsr <= "0000000000";
                rsr <= "0000000000";
                rf_wr <= '0';
                rf_wr <= '0';
                rx_clk_ena <= '0';
                rx_clk_ena <= '0';
 
 
        elsif rising_edge(clk) then
        elsif rising_edge(clk) then
 
 
                case uart_rx_state is
                case uart_rx_state is
 
 
 
 
                        when s0 =>
                        when s0 =>
                                i := 0;
                                i := 0;
                                rf_wr <= '0';
                                rf_wr <= '0';
                                if (rx_d='0') then
                                if (rx_d='0') then
                                        rx_clk_ena <= '1';
                                        rx_clk_ena <= '1';
                                        uart_rx_state <= s1;
                                        uart_rx_state <= s1;
                                else
                                else
                                        rx_clk_ena <= '0';
                                        rx_clk_ena <= '0';
                                end if;
                                end if;
 
 
                        when s1 =>
                        when s1 =>
                                if (rx_clk='1') then
                                if (rx_clk='1') then
                                        rsr(9) <= rx_d;
                                        rsr(9) <= rx_d;
                                        rsr(8 downto 0) <= rsr(9 downto 1);
                                        rsr(8 downto 0) <= rsr(9 downto 1);
                                        i := i+1;
                                        i := i+1;
                                        if (i=10) then
                                        if (i=10) then
                                                uart_rx_state <= s2;
                                                uart_rx_state <= s2;
                                        end if;
                                        end if;
                                end if;
                                end if;
 
 
                        when s2 =>
                        when s2 =>
                                rx_clk_ena <= '0';
                                rx_clk_ena <= '0';
                                if rsr(0)='0' and rsr(9)='1' then
                                if rsr(0)='0' and rsr(9)='1' then
                                        if rf_full='0' then                              -- if full just drop it
                                        if rf_full='0' then                              -- if full just drop it
                                                rf_wr <= '1';
                                                rf_wr <= '1';
                                        end if;
                                        end if;
                                end if;
                                end if;
                                uart_rx_state <= s0;
                                uart_rx_state <= s0;
 
 
                end case;
                end case;
        end if;
        end if;
 
 
end process;
end process;
 
 
end rtl;
end rtl;
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.