⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart_simple_broken.vhd

📁 适用异步收发器设计的vhdl语言,是学习UART知识的好例程
💻 VHD
字号:
--
--	uart_simple.vhd
--
--	8-N-1 serial interface
--	
--	wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later
--
--	Author: Martin Schoeberl	martin@good-ear.com
--
--
--	resources on ACEX1K30-3
--
--		100 LCs, max 90 MHz
--
--	A VERY simple uart without handshaking and fifos.
--	BUT THIS VERSION DOES NOT WORK!
--
--	2005-01-14	adapted from uart.vhd
--


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity uart is

generic (io_addr : integer; clk_freq : integer;
	baud_rate : integer;
	txf_depth : integer; txf_thres : integer;
	rxf_depth : integer; rxf_thres : integer);
port (
	clk		: in std_logic;
	reset	: in std_logic;
	addr	: in std_logic_vector(3 downto 0);
	din		: in std_logic_vector(31 downto 0);
	wr		: in std_logic;
	dout	: out std_logic_vector(31 downto 0);
	rd		: in std_logic;

	txd		: out std_logic;
	rxd		: in std_logic;
	ncts	: in std_logic;
	nrts	: out std_logic
);
end uart ;

architecture rtl of uart is

--
--	signals for uart connection
--
	signal ua_dout			: std_logic_vector(7 downto 0);
	signal ua_wr, tdre		: std_logic;
	signal ua_rd, rdrf		: std_logic;

	type uart_tx_state_type		is (s0, s1);
	signal uart_tx_state 		: uart_tx_state_type;

	type uart_tdr_state_type	is (s0, s1);
	signal uart_tdr_state 		: uart_tdr_state_type;

	signal tdr			: std_logic_vector(7 downto 0); -- tx buffer
	signal tdrf			: std_logic;					-- tdr has valid data
	signal tdr_rd		: std_logic;					-- tdr was read

	signal tsr			: std_logic_vector(9 downto 0); -- tx shift register

	signal tx_clk		: std_logic;


	type uart_rx_state_type		is (s0, s1, s2);
	signal uart_rx_state 		: uart_rx_state_type;

	type uart_rdr_state_type	is (s0, s1);
	signal uart_rdr_state 		: uart_rdr_state_type;

	signal rdr			: std_logic_vector(7 downto 0); -- rx buffer
	signal rdre			: std_logic;					-- rdr is empty
	signal rdr_wr		: std_logic;					-- rdr was written

	signal rx_buf		: std_logic_vector(2 downto 0);	-- sync in, filter
	signal rx_d			: std_logic;					-- rx serial data
	
	signal rsr			: std_logic_vector(9 downto 0); -- rx shift register

	signal rx_clk		: std_logic;
	signal rx_clk_ena	: std_logic;

	constant clk16_cnt	: integer := (clk_freq/baud_rate+8)/16-1;


begin

--
--	io handling
--
process(addr, rd, ua_dout, rdrf, tdre)

begin
	ua_rd <= '0';
	if addr=std_logic_vector(to_unsigned(io_addr, 4)) then
		dout <= std_logic_vector(to_unsigned(0, 30)) & rdrf & tdre;
	elsif addr=std_logic_vector(to_unsigned(io_addr+1, 4)) then
		dout <= std_logic_vector(to_unsigned(0, 24)) & ua_dout;
		ua_rd <= rd;
	else
		dout <= (others => 'Z');
	end if;

end process;

process(wr, addr)

begin
	ua_wr <= '0';
	if addr=std_logic_vector(to_unsigned(io_addr+1, 4))
		and wr='1' then
		ua_wr <= '1';
	end if;
end process;

--
--	serial clock
--
process(clk, reset)

	variable clk16		: integer range 0 to clk16_cnt;
	variable clktx		: unsigned(3 downto 0);
	variable clkrx		: unsigned(3 downto 0);

begin
	if (reset='1') then
		clk16 := 0;
		clktx := "0000";
		clkrx := "0000";
		tx_clk <= '0';
		rx_clk <= '0';
		rx_buf <= "111";

	elsif rising_edge(clk) then

		if (clk16=clk16_cnt) then		-- 16 x serial clock
			clk16 := 0;
--
--	tx clock
--
			clktx := clktx + 1;
			if (clktx="0000") then
				tx_clk <= '1';
			else
				tx_clk <= '0';
			end if;
--
--	rx clock
--
			if (rx_clk_ena='1') then
				clkrx := clkrx + 1;
				if (clkrx="1000") then
					rx_clk <= '1';
				else
					rx_clk <= '0';
				end if;
			else
				clkrx := "0000";
			end if;
--
--	sync in filter buffer
--
			rx_buf(0) <= rxd;
			rx_buf(2 downto 1) <= rx_buf(1 downto 0);
		else
			clk16 := clk16 + 1;
			tx_clk <= '0';
			rx_clk <= '0';
		end if;


	end if;

end process;

--
--	state machine for tdr
--
process(clk, reset)

begin

	if (reset='1') then
		uart_tdr_state <= s0;
		tdrf <= '0';
		tdr <= "00000000";
	elsif rising_edge(clk) then

		case uart_tdr_state is

			when s0 =>
				if (ua_wr='1') then
					tdr <= din(7 downto 0);
					tdrf <= '1';
					uart_tdr_state <= s1;
				end if;

			when s1 =>
				if (tdr_rd='1') then
					tdrf <= '0';
					uart_tdr_state <= s0;
				end if;

		end case;
	end if;

end process;

	tdre <= not tdrf;

--
--	state machine for actual shift out
--
process(clk, reset)

	variable i : integer range 0 to 11;

begin

	if (reset='1') then
		uart_tx_state <= s0;
		tsr <= "1111111111";
		tdr_rd <= '0';

	elsif rising_edge(clk) then

		case uart_tx_state is

			when s0 =>
				i := 0;
				if tdrf='1' then
					uart_tx_state <= s1;
					tsr <= tdr & '0' & '1';
					tdr_rd <= '1';
				end if;

			when s1 =>
				tdr_rd <= '0';
				if (tx_clk='1') then
					tsr(9) <= '1';
					tsr(8 downto 0) <= tsr(9 downto 1);
					i := i+1;
					if (i=11) then				-- two stop bits
						uart_tx_state <= s0;
					end if;
				end if;
				
		end case;
	end if;

end process;

	txd <= tsr(0);

	nrts <= ncts;	-- no handshake

--
--	state machine for rdr
--
process(clk, reset)

begin

	if (reset='1') then
		uart_rdr_state <= s0;
		rdre <= '1';
	elsif rising_edge(clk) then

		case uart_rdr_state is

			when s0 =>
				if (rdr_wr='1') then
					rdre <= '0';
					uart_rdr_state <= s1;
				end if;

			when s1 =>
				if (ua_rd='1') then
					rdre <= '1';
					uart_rdr_state <= s0;
				end if;

		end case;
	end if;

end process;

	ua_dout <= rdr;
	rdrf <= not rdre;

--
--	filter rxd
--
	with rx_buf select
		rx_d <=	'0' when "000",
				'0' when "001",
				'0' when "010",
				'1' when "011",
				'0' when "100",
				'1' when "101",
				'1' when "110",
				'1' when "111",
				'X' when others;

--
--	state machine for actual shift in
--
process(clk, reset)

	variable i : integer range 0 to 10;

begin

	if (reset='1') then
		uart_rx_state <= s0;
		rsr <= "0000000000";
		rdr_wr <= '0';
		rx_clk_ena <= '0';

	elsif rising_edge(clk) then

		case uart_rx_state is


			when s0 =>
				i := 0;
				rdr_wr <= '0';
				if (rx_d='0') then
					rx_clk_ena <= '1';
					uart_rx_state <= s1;
				else
					rx_clk_ena <= '0';
				end if;

			when s1 =>
				if (rx_clk='1') then
					rsr(9) <= rx_d;
					rsr(8 downto 0) <= rsr(9 downto 1);
					i := i+1;
					if (i=10) then
						uart_rx_state <= s2;
					end if;
				end if;
					
			when s2 =>
				rx_clk_ena <= '0';
				if rsr(0)='0' and rsr(9)='1' then
					rdr <= rsr(8 downto 1);
					rdr_wr <= '1';
				end if;
				uart_rx_state <= s0;

		end case;
	end if;

end process;


end rtl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -