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

Subversion Repositories marca

[/] [marca/] [tags/] [INITIAL/] [vhdl/] [sc_uart.vhd] - Diff between revs 3 and 8

Only display areas with differences | Details | Blame | View Log

Rev 3 Rev 8
--
--
--      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;
 
 
use work.marca_pkg.all;
use work.marca_pkg.all;
use work.sc_pkg.all;
use work.sc_pkg.all;
 
 
entity sc_uart is
entity sc_uart is
 
 
  generic (clock_freq : integer;
  generic (clock_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 (clock         : in  std_logic;
  port (clock         : in  std_logic;
        reset         : in  std_logic;
        reset         : in  std_logic;
 
 
-- SimpCon interface
-- SimpCon interface
        input         : in  SC_IN;
        input         : in  SC_IN;
        output        : out SC_OUT;
        output        : out SC_OUT;
 
 
        intr          : out std_logic;
        intr          : out std_logic;
 
 
        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;
    generic (width : integer;
             depth : integer;
             depth : integer;
             thres : integer);
             thres : integer);
 
 
    port (clk           : in  std_logic;
    port (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;
 
 
  signal rdrf_iena      : std_logic;
  signal rdrf_iena      : std_logic;
  signal tdre_iena      : std_logic;
  signal tdre_iena      : std_logic;
 
 
  constant clk16_cnt    : integer := (clock_freq/baud_rate+8)/16-1;
  constant clk16_cnt    : integer := (clock_freq/baud_rate+8)/16-1;
 
 
begin
begin
 
 
  output.rdy_cnt <= "00";       -- no wait states
  output.rdy_cnt <= "00";       -- no wait states
  output.rd_data(SC_REG_WIDTH-1 downto 8) <= std_logic_vector(to_unsigned(0, SC_REG_WIDTH-8));
  output.rd_data(SC_REG_WIDTH-1 downto 8) <= std_logic_vector(to_unsigned(0, SC_REG_WIDTH-8));
 
 
--
--
--      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(clock, reset)
  process(clock, reset)
  begin
  begin
 
 
    if reset = RESET_ACTIVE then
    if reset = RESET_ACTIVE then
      output.rd_data(7 downto 0) <= (others => '0');
      output.rd_data(7 downto 0) <= (others => '0');
    elsif rising_edge(clock) then
    elsif rising_edge(clock) then
 
 
      ua_rd <= '0';
      ua_rd <= '0';
      if input.rd='1' then
      if input.rd='1' then
        -- that's our very simple address decoder
        -- that's our very simple address decoder
        if input.address(0)='0' then
        if input.address(0)='0' then
          output.rd_data(7 downto 0) <= "0000" & rdrf_iena & tdre_iena & rdrf & tdre;
          output.rd_data(7 downto 0) <= "0000" & rdrf_iena & tdre_iena & rdrf & tdre;
        else
        else
          output.rd_data(7 downto 0) <= ua_dout;
          output.rd_data(7 downto 0) <= ua_dout;
          ua_rd <= input.rd;
          ua_rd <= input.rd;
        end if;
        end if;
      end if;
      end if;
 
 
      if input.wr='1' then
      if input.wr='1' then
        if input.address(0)='0' then
        if input.address(0)='0' then
          rdrf_iena <= input.wr_data(3);
          rdrf_iena <= input.wr_data(3);
          tdre_iena <= input.wr_data(2);
          tdre_iena <= input.wr_data(2);
        end if;
        end if;
      end if;
      end if;
 
 
    end if;
    end if;
 
 
  end process;
  end process;
 
 
  ua_wr <= input.wr and input.address(0);
  ua_wr <= input.wr and input.address(0);
 
 
  intr <= (rdrf and rdrf_iena) or (tdre and tdre_iena);
  intr <= (rdrf and rdrf_iena) or (tdre and tdre_iena);
 
 
--
--
--      serial clock
--      serial clock
--
--
  process(clock, reset)
  process(clock, 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 = RESET_ACTIVE then
    if reset = RESET_ACTIVE 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(clock) then
    elsif rising_edge(clock) 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 (clock, reset, input.wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half);
    port map (clock, reset, input.wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half);
 
 
  txd <= tsr(0);
  txd <= tsr(0);
  tdre <= not tf_full;
  tdre <= not tf_full;
 
 
--
--
--      state machine for actual shift out
--      state machine for actual shift out
--
--
  process(clock, reset)
  process(clock, reset)
 
 
    variable i : integer range 0 to 11;
    variable i : integer range 0 to 11;
 
 
  begin
  begin
 
 
    if reset = RESET_ACTIVE then
    if reset = RESET_ACTIVE 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(clock) then
    elsif rising_edge(clock) 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;
 
 
--
--
--      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 (clock, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half);
    port map (clock, 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(clock, reset)
  process(clock, reset)
 
 
    variable i : integer range 0 to 10;
    variable i : integer range 0 to 10;
 
 
  begin
  begin
 
 
    if reset = RESET_ACTIVE then
    if reset = RESET_ACTIVE 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(clock) then
    elsif rising_edge(clock) 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.