一、VHDL实现UART协议代码

1.uart_tx.vhd

--串口发送模块编写
--数据帧格式1位起始位+8位数据位+1位停止位
--低位先行LSB
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
------------------------------------------------------------------------------
entity uart_tx is
	generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic_vector(WIDTH_L-1 downto 0);
		din_vld: in std_logic;
		dout: out std_logic;
		rdy: out std_logic 								--表示可以接收数据
	);
end uart_tx;
---------------------------------------------------------------------------------
architecture uart_tx of uart_tx is 
	signal cnt_baud: integer range 0 to BAUD_MAX-1;
	signal add_cnt_baud,end_cnt_baud: std_logic;
	signal cnt_bit: integer range 0 to 9;
	signal add_cnt_bit,end_cnt_bit: std_logic;
	signal din_vld_flag: std_logic; 							--输入数据有效标志信号
	signal data: std_logic_vector(WIDTH_L+1 downto 0);			--寄存要发送的一帧数据
	
	constant BIT_MAX: INTEGER := 10;

begin	 
	--------------------------baud_cnt------------------------------------------------
	process(rst_n,clk)
	begin 
		if(rst_n = '0') then
			cnt_baud <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_baud = '1') then
				if(end_cnt_baud = '1') then 
					cnt_baud <= 0;
				else 
					cnt_baud <= cnt_baud + 1;
				end if;
			else 
				cnt_baud <= cnt_baud;
			end if;
		end if;
	end process;
	add_cnt_baud <= din_vld_flag;
	end_cnt_baud <= '1' when ((add_cnt_baud = '1') AND (cnt_baud = (BAUD_MAX-1))) else '0';
	----------------------------bit_cnt--------------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			cnt_bit <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_bit = '1') then 
				if(end_cnt_bit = '1') then 
					cnt_bit <= 0;
				else 
					cnt_bit <= cnt_bit + 1;
				end if;
			else 
				cnt_bit <= cnt_bit;
			end if;
		end if;
	end process;
	add_cnt_bit <= end_cnt_baud;
	end_cnt_bit <= '1' when ((add_cnt_bit = '1') AND (cnt_bit = BIT_MAX-1)) else '0';
	--------------------------din_vld_flag-rdy-----------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			din_vld_flag <= '0';
		elsif(clk'event and clk = '1') then
			if(din_vld = '1') then 
				din_vld_flag <= '1';
			elsif(end_cnt_bit = '1') then 
				din_vld_flag <= '0';
			end if;
		end if;
	end process;
	-------------------------------------data------------------------------------------------
	process(clk,rst_n)
	begin
		if(rst_n = '0') then 
			data <= (others => '0');
		elsif(clk'event and clk = '1') then
			if(din_vld = '1') then 
				data <= '1' & din & '0';--数据拼成一帧 LSB stop+data[7:0]+start WIDTH_L+1 发送时倒着发就行
			end if;
		end if;
	end process;
	------------------------------------dout----------------------------------------------------
	process(clk,rst_n)
	begin
		if(rst_n = '0') then 
			dout <= '1';--空闲时高电平
		elsif(clk'event and clk = '1') then
			if(din_vld_flag = '1') then 
				dout <= data(cnt_bit);
			else 
				dout <= '1';
			end if;
		end if;
	end process;
	rdy <= NOT din_vld_flag;
	
end uart_tx;
----------------------------------package uart_tx--------------------------------------------------
-- library ieee;
-- use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.std_logic_arith.all;

-- package uart_tx_package is 
	-- component uart_tx is
		-- generic(WIDTH_L: integer;						--数据位宽
				-- BAUD_MAX: integer  						--波特率115200,计数最大值50_000_000/115200
			-- );
		-- port(
			-- clk: in std_logic;							--50MHZ
			-- rst_n: in std_logic;
			-- din: in std_logic_vector(WIDTH_L-1 downto 0);
			-- din_vld: in std_logic;
			-- dout: out std_logic;
			-- rdy: out std_logic 							--表示可以接收数据
			-- );
	-- end component;
-- end uart_tx_package;

2.uart_tx_tb.v

`timescale 1ns/1ps
module uart_tx_tb();
/* uart_tx is
	generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic_vector(WIDTH_L-1 downto 0);
		din_vld: in std_logic;
		dout: out std_logic;
		rdy: out std_logic 								--表示可以接收数据
	);	 */
	reg				clk;
	reg     		rst_n;
	reg  [7:0]   	din;
	reg				din_vld;
	wire            dout;
	wire     		rdy;
	
	parameter CYCLE = 20;
	
	initial begin
		clk <= 1'b1;
		rst_n <= 1'b0;
		#15
		rst_n <= 1'b1;
	end 
	
	always #(CYCLE/2) clk <= !clk;
	
	initial begin
		din <= 8'd0;
		din_vld <= 1'b0;
		#(20*CYCLE)
		//发送5a
		din <= 8'h5a;
		din_vld <= 1'b1;
		#CYCLE
		din_vld <= 1'b0;
		#(CYCLE*434*12)
		//发送6b
		din <= 8'h6b;
		din_vld <= 1'b1;
		#CYCLE
		din_vld <= 1'b0;
		#(CYCLE*434*15)
		$stop;
	end 
	
	//例化发送模块
	uart_tx u_uart_tx(
		.clk		(clk		),
		.rst_n		(rst_n		),
		.din		(din		),
		.din_vld	(din_vld	),
		.dout		(dout		),
		.rdy		(rdy		)
	);
		
	
endmodule

3.uart_rx.vhd

--串口接收模块编写
--数据帧格式1位起始位+8位数据位+1位停止位
--低位先行LSB
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
------------------------------------------------------------------------------
entity uart_rx is
	generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic;								--接收引脚
		dout: out std_logic_vector(WIDTH_L-1 downto 0);							--接收到的数据
		dout_vld: out std_logic 	        			--接收数据完成							
	);
end uart_rx;
---------------------------------------------------------------------------------
architecture uart_rx of uart_rx is 
	signal cnt_baud: integer range 0 to BAUD_MAX-1;
	signal add_cnt_baud,end_cnt_baud: std_logic;
	signal cnt_bit: integer range 0 to 9;
	signal add_cnt_bit,end_cnt_bit: std_logic;
	signal din_vld_flag: std_logic; 					--输入数据有效标志信号
	signal data: std_logic_vector(WIDTH_L+1 downto 0);	--寄存要接收的一帧数据
	signal nedge: std_logic;							--检测下降沿
	
	constant BIT_MAX: INTEGER := 10;
begin	 
	--------------------------baud_cnt------------------------------------------------
	process(rst_n,clk)
	begin 
		if(rst_n = '0') then
			cnt_baud <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_baud = '1') then
				if(end_cnt_baud = '1') then 
					cnt_baud <= 0;
				else 
					cnt_baud <= cnt_baud + 1;
				end if;
			else 
				cnt_baud <= cnt_baud;
			end if;
		end if;
	end process;
	add_cnt_baud <= din_vld_flag;
	end_cnt_baud <= '1' when ((add_cnt_baud = '1') AND (cnt_baud = (BAUD_MAX-1))) else '0';
	----------------------------bit_cnt--------------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			cnt_bit <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_bit = '1') then 
				if(end_cnt_bit = '1') then 
					cnt_bit <= 0;
				else 
					cnt_bit <= cnt_bit + 1;
				end if;
			else 
				cnt_bit <= cnt_bit;
			end if;
		end if;
	end process;
	add_cnt_bit <= end_cnt_baud;
	end_cnt_bit <= '1' when ((add_cnt_bit = '1') AND (cnt_bit = BIT_MAX-1)) else '0';
	---------------------------nedge 和din_vld_flag--------------------------------------------
	process(clk,rst_n)
		variable temp0: std_logic_vector(1 downto 0);--temp1,
	begin 
		if(rst_n = '0') then 
			temp0 := "00";
			--temp1 := '0';
			nedge <= '0';
		elsif(clk'event and clk = '1') then 
			--(temp1) & (temp0) := (temp0) & (din);
			temp0 := temp0(0) & din;
			--temp1 := temp0;
		end if;
		nedge <= temp0(1) AND (NOT temp0(0));
	end process;
	
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			din_vld_flag <= '0';
		elsif(clk'event and clk = '1') then 
			if(nedge = '1') then 
				din_vld_flag <= '1';
			elsif(end_cnt_bit = '1') then 
				din_vld_flag <= '0';
			end if;
		end if;
	end process;
	--------------------------------------------data-------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			data <= (others => '0');
		elsif(clk'event and clk = '1') then 
			if(cnt_baud = (BAUD_MAX/2-1)) then         --中间时刻采样数据
				data <= din & data(data'left downto 1);--此时数据高位在前
			end if;
		end if;
	end process;
	------------------------------------------dout-----------------------------------------------------
	dout <= data(data'left-1 downto 1);
	dout_vld <= '1' when (end_cnt_bit = '1' AND end_cnt_baud = '1') else '0';
	
end uart_rx;	
-------------------------------------------------------------------------------------------------------
-- library ieee;
-- use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.std_logic_arith.all;
-- package uart_rx_package is
	-- component uart_rx is
		-- generic(WIDTH_L: integer;						    --数据位宽
				-- BAUD_MAX: integer   					    --波特率115200,计数最大值50_000_000/115200
		-- );
		-- port(
			-- clk: in std_logic;								--50MHZ
			-- rst_n: in std_logic;
			-- din: in std_logic;								--接收引脚
			-- dout: out std_logic_vector(WIDTH_L-1 downto 0);	--接收到的数据
			-- dout_vld: out std_logic 	        			--接收数据完成							
		-- );
	-- end component;
-- end uart_rx_package;

	

4.uart_rx_tb.v

`timescale 1ns/1ps
module uart_rx_tb();
	/* generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic;								--接收引脚
		dout: out std_logic_vector(WIDTH_L-1 downto 0);							--接收到的数据
		dout_vld: out std_logic 	        			--接收数据完成							
	); */
	reg				clk;
	reg     		rst_n;
	reg  		   	din;
	wire  [7:0]     dout;
	wire     		dout_vld;
	
	parameter CYCLE = 20;
	
	initial begin
		clk <= 1'b1;
		rst_n <= 1'b0;
		din <= 1'b1;
		#15
		rst_n <= 1'b1;
	end 
	
	always #(CYCLE/2) clk <= !clk;
	
	//将1个8bit的数据按数据帧的格式发送
	task uart_tx_bit(
		input [7:0]	data
	);
	integer i;
	for(i=0;i<10;i=i+1)begin
		case(i)
			0: din <= 1'b0;		//起始位
			1: din <= data[0];
			2: din <= data[1];
			3: din <= data[2];
			4: din <= data[3];
			5: din <= data[4];
			6: din <= data[5];
			7: din <= data[6];
			8: din <= data[7];
			9: din <= 1'b1;		//停止位
			default: din <= 1'b1;//空闲高电平
		endcase
		#(CYCLE*434);
	end 
	endtask
	
	initial begin
		#(200*CYCLE)
		//发送5a
		uart_tx_bit(8'h55);
		din <= 1'b1;//空闲
		#(CYCLE*10)
		uart_tx_bit(8'h72);
		din <= 1'b1;
		#(CYCLE*434*15)
		$stop;
	end 
	
	//例化发送模块
	uart_rx u_uart_rx(
		.clk		(clk		),
		.rst_n		(rst_n		),
		.din		(din		),
		.dout		(dout		),
		.dout_vld   (dout_vld   )
	);
			
endmodule                                                

5.uart_rx_package.vhd

--串口接收模块编写
--数据帧格式1位起始位+8位数据位+1位停止位
--低位先行LSB
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
------------------------------------------------------------------------------
entity uart_rx is
	generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic;								--接收引脚
		dout: out std_logic_vector(WIDTH_L-1 downto 0);							--接收到的数据
		dout_vld: out std_logic 	        			--接收数据完成							
	);
end uart_rx;
---------------------------------------------------------------------------------
architecture uart_rx of uart_rx is 
	signal cnt_baud: integer range 0 to BAUD_MAX-1;
	signal add_cnt_baud,end_cnt_baud: std_logic;
	signal cnt_bit: integer range 0 to 9;
	signal add_cnt_bit,end_cnt_bit: std_logic;
	signal din_vld_flag: std_logic; 					--输入数据有效标志信号
	signal data: std_logic_vector(WIDTH_L+1 downto 0);	--寄存要接收的一帧数据
	signal nedge: std_logic;							--检测下降沿
	
	constant BIT_MAX: INTEGER := 10;
begin	 
	--------------------------baud_cnt------------------------------------------------
	process(rst_n,clk)
	begin 
		if(rst_n = '0') then
			cnt_baud <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_baud = '1') then
				if(end_cnt_baud = '1') then 
					cnt_baud <= 0;
				else 
					cnt_baud <= cnt_baud + 1;
				end if;
			else 
				cnt_baud <= cnt_baud;
			end if;
		end if;
	end process;
	add_cnt_baud <= din_vld_flag;
	end_cnt_baud <= '1' when ((add_cnt_baud = '1') AND (cnt_baud = (BAUD_MAX-1))) else '0';
	----------------------------bit_cnt--------------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			cnt_bit <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_bit = '1') then 
				if(end_cnt_bit = '1') then 
					cnt_bit <= 0;
				else 
					cnt_bit <= cnt_bit + 1;
				end if;
			else 
				cnt_bit <= cnt_bit;
			end if;
		end if;
	end process;
	add_cnt_bit <= end_cnt_baud;
	end_cnt_bit <= '1' when ((add_cnt_bit = '1') AND (cnt_bit = BIT_MAX-1)) else '0';
	---------------------------nedge 和din_vld_flag--------------------------------------------
	process(clk,rst_n)
		variable temp0: std_logic_vector(1 downto 0);--temp1,
	begin 
		if(rst_n = '0') then 
			temp0 := "00";
			--temp1 := '0';
			nedge <= '0';
		elsif(clk'event and clk = '1') then 
			--(temp1) & (temp0) := (temp0) & (din);
			temp0 := temp0(0) & din;
			--temp1 := temp0;
		end if;
		nedge <= temp0(1) AND (NOT temp0(0));
	end process;
	
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			din_vld_flag <= '0';
		elsif(clk'event and clk = '1') then 
			if(nedge = '1') then 
				din_vld_flag <= '1';
			elsif(end_cnt_bit = '1') then 
				din_vld_flag <= '0';
			end if;
		end if;
	end process;
	--------------------------------------------data-------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			data <= (others => '0');
		elsif(clk'event and clk = '1') then 
			if(cnt_baud = (BAUD_MAX/2-1)) then         --中间时刻采样数据
				data <= din & data(data'left downto 1);--此时数据高位在前
			end if;
		end if;
	end process;
	------------------------------------------dout-----------------------------------------------------
	dout <= data(data'left-1 downto 1);
	dout_vld <= '1' when (end_cnt_bit = '1' AND end_cnt_baud = '1') else '0';
	
end uart_rx;	
-------------------------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
package uart_rx_package is
	component uart_rx is
		generic(WIDTH_L: integer;						    --数据位宽
				BAUD_MAX: integer   					    --波特率115200,计数最大值50_000_000/115200
		);
		port(
			clk: in std_logic;								--50MHZ
			rst_n: in std_logic;
			din: in std_logic;								--接收引脚
			dout: out std_logic_vector(WIDTH_L-1 downto 0);	--接收到的数据
			dout_vld: out std_logic 	        			--接收数据完成							
		);
	end component;
end uart_rx_package;

	

6.uart_tx_package.vhd

--串口发送模块编写
--数据帧格式1位起始位+8位数据位+1位停止位
--低位先行LSB
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
------------------------------------------------------------------------------
entity uart_tx is
	generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic_vector(WIDTH_L-1 downto 0);
		din_vld: in std_logic;
		dout: out std_logic;
		rdy: out std_logic 								--表示可以接收数据
	);
end uart_tx;
---------------------------------------------------------------------------------
architecture uart_tx of uart_tx is 
	signal cnt_baud: integer range 0 to BAUD_MAX-1;
	signal add_cnt_baud,end_cnt_baud: std_logic;
	signal cnt_bit: integer range 0 to 9;
	signal add_cnt_bit,end_cnt_bit: std_logic;
	signal din_vld_flag: std_logic; 							--输入数据有效标志信号
	signal data: std_logic_vector(WIDTH_L+1 downto 0);			--寄存要发送的一帧数据
	
	constant BIT_MAX: INTEGER := 10;

begin	 
	--------------------------baud_cnt------------------------------------------------
	process(rst_n,clk)
	begin 
		if(rst_n = '0') then
			cnt_baud <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_baud = '1') then
				if(end_cnt_baud = '1') then 
					cnt_baud <= 0;
				else 
					cnt_baud <= cnt_baud + 1;
				end if;
			else 
				cnt_baud <= cnt_baud;
			end if;
		end if;
	end process;
	add_cnt_baud <= din_vld_flag;
	end_cnt_baud <= '1' when ((add_cnt_baud = '1') AND (cnt_baud = (BAUD_MAX-1))) else '0';
	----------------------------bit_cnt--------------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			cnt_bit <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_bit = '1') then 
				if(end_cnt_bit = '1') then 
					cnt_bit <= 0;
				else 
					cnt_bit <= cnt_bit + 1;
				end if;
			else 
				cnt_bit <= cnt_bit;
			end if;
		end if;
	end process;
	add_cnt_bit <= end_cnt_baud;
	end_cnt_bit <= '1' when ((add_cnt_bit = '1') AND (cnt_bit = BIT_MAX-1)) else '0';
	--------------------------din_vld_flag-rdy-----------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			din_vld_flag <= '0';
		elsif(clk'event and clk = '1') then
			if(din_vld = '1') then 
				din_vld_flag <= '1';
			elsif(end_cnt_bit = '1') then 
				din_vld_flag <= '0';
			end if;
		end if;
	end process;
	-------------------------------------data------------------------------------------------
	process(clk,rst_n)
	begin
		if(rst_n = '0') then 
			data <= (others => '0');
		elsif(clk'event and clk = '1') then
			if(din_vld = '1') then 
				data <= '1' & din & '0';--数据拼成一帧 LSB stop+data[7:0]+start WIDTH_L+1 发送时倒着发就行
			end if;
		end if;
	end process;
	------------------------------------dout----------------------------------------------------
	process(clk,rst_n)
	begin
		if(rst_n = '0') then 
			dout <= '1';--空闲时高电平
		elsif(clk'event and clk = '1') then
			if(din_vld_flag = '1') then 
				dout <= data(cnt_bit);
			else 
				dout <= '1';
			end if;
		end if;
	end process;
	rdy <= NOT din_vld_flag;
	
end uart_tx;
----------------------------------package uart_tx--------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

package uart_tx_package is 
	component uart_tx is
		generic(WIDTH_L: integer;						--数据位宽
				BAUD_MAX: integer  						--波特率115200,计数最大值50_000_000/115200
			);
		port(
			clk: in std_logic;							--50MHZ
			rst_n: in std_logic;
			din: in std_logic_vector(WIDTH_L-1 downto 0);
			din_vld: in std_logic;
			dout: out std_logic;
			rdy: out std_logic 							--表示可以接收数据
			);
	end component;
end uart_tx_package;

7.uart_package.vhd

--tx
----------------------------------------------------------------------------------------------------------------------
--串口发送模块编写
--数据帧格式1位起始位+8位数据位+1位停止位
--低位先行LSB
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
------------------------------------------------------------------------------
entity uart_tx is
	generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic_vector(WIDTH_L-1 downto 0);
		din_vld: in std_logic;
		dout: out std_logic;
		rdy: out std_logic 								--表示可以接收数据
	);
end uart_tx;
---------------------------------------------------------------------------------
architecture uart_tx of uart_tx is 
	signal cnt_baud: integer range 0 to BAUD_MAX-1;
	signal add_cnt_baud,end_cnt_baud: std_logic;
	signal cnt_bit: integer range 0 to 9;
	signal add_cnt_bit,end_cnt_bit: std_logic;
	signal din_vld_flag: std_logic; 							--输入数据有效标志信号
	signal data: std_logic_vector(WIDTH_L+1 downto 0);			--寄存要发送的一帧数据
	
	constant BIT_MAX: INTEGER := 10;

begin	 
	--------------------------baud_cnt------------------------------------------------
	process(rst_n,clk)
	begin 
		if(rst_n = '0') then
			cnt_baud <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_baud = '1') then
				if(end_cnt_baud = '1') then 
					cnt_baud <= 0;
				else 
					cnt_baud <= cnt_baud + 1;
				end if;
			else 
				cnt_baud <= cnt_baud;
			end if;
		end if;
	end process;
	add_cnt_baud <= din_vld_flag;
	end_cnt_baud <= '1' when ((add_cnt_baud = '1') AND (cnt_baud = (BAUD_MAX-1))) else '0';
	----------------------------bit_cnt--------------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			cnt_bit <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_bit = '1') then 
				if(end_cnt_bit = '1') then 
					cnt_bit <= 0;
				else 
					cnt_bit <= cnt_bit + 1;
				end if;
			else 
				cnt_bit <= cnt_bit;
			end if;
		end if;
	end process;
	add_cnt_bit <= end_cnt_baud;
	end_cnt_bit <= '1' when ((add_cnt_bit = '1') AND (cnt_bit = BIT_MAX-1)) else '0';
	--------------------------din_vld_flag-rdy-----------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			din_vld_flag <= '0';
		elsif(clk'event and clk = '1') then
			if(din_vld = '1') then 
				din_vld_flag <= '1';
			elsif(end_cnt_bit = '1') then 
				din_vld_flag <= '0';
			end if;
		end if;
	end process;
	-------------------------------------data------------------------------------------------
	process(clk,rst_n)
	begin
		if(rst_n = '0') then 
			data <= (others => '0');
		elsif(clk'event and clk = '1') then
			if(din_vld = '1') then 
				data <= '1' & din & '0';--数据拼成一帧 LSB stop+data[7:0]+start WIDTH_L+1 发送时倒着发就行
			end if;
		end if;
	end process;
	------------------------------------dout----------------------------------------------------
	process(clk,rst_n)
	begin
		if(rst_n = '0') then 
			dout <= '1';--空闲时高电平
		elsif(clk'event and clk = '1') then
			if(din_vld_flag = '1') then 
				dout <= data(cnt_bit);
			else 
				dout <= '1';
			end if;
		end if;
	end process;
	rdy <= NOT din_vld_flag;
	
end uart_tx;

-------------------------------------------------------------------rx-------------------------------------------
--串口接收模块编写
--数据帧格式1位起始位+8位数据位+1位停止位
--低位先行LSB
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
------------------------------------------------------------------------------
entity uart_rx is
	generic(WIDTH_L: integer := 8;						--数据位宽
			BAUD_MAX: integer := 434 					--波特率115200,计数最大值50_000_000/115200
			);
	port(
		clk: in std_logic;								--50MHZ
		rst_n: in std_logic;
		din: in std_logic;								--接收引脚
		dout: out std_logic_vector(WIDTH_L-1 downto 0);							--接收到的数据
		dout_vld: out std_logic 	        			--接收数据完成							
	);
end uart_rx;
---------------------------------------------------------------------------------
architecture uart_rx of uart_rx is 
	signal cnt_baud: integer range 0 to BAUD_MAX-1;
	signal add_cnt_baud,end_cnt_baud: std_logic;
	signal cnt_bit: integer range 0 to 9;
	signal add_cnt_bit,end_cnt_bit: std_logic;
	signal din_vld_flag: std_logic; 					--输入数据有效标志信号
	signal data: std_logic_vector(WIDTH_L+1 downto 0);	--寄存要接收的一帧数据
	signal nedge: std_logic;							--检测下降沿
	
	constant BIT_MAX: INTEGER := 10;
begin	 
	--------------------------baud_cnt------------------------------------------------
	process(rst_n,clk)
	begin 
		if(rst_n = '0') then
			cnt_baud <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_baud = '1') then
				if(end_cnt_baud = '1') then 
					cnt_baud <= 0;
				else 
					cnt_baud <= cnt_baud + 1;
				end if;
			else 
				cnt_baud <= cnt_baud;
			end if;
		end if;
	end process;
	add_cnt_baud <= din_vld_flag;
	end_cnt_baud <= '1' when ((add_cnt_baud = '1') AND (cnt_baud = (BAUD_MAX-1))) else '0';
	----------------------------bit_cnt--------------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			cnt_bit <= 0;
		elsif(clk'event and clk = '1') then 
			if(add_cnt_bit = '1') then 
				if(end_cnt_bit = '1') then 
					cnt_bit <= 0;
				else 
					cnt_bit <= cnt_bit + 1;
				end if;
			else 
				cnt_bit <= cnt_bit;
			end if;
		end if;
	end process;
	add_cnt_bit <= end_cnt_baud;
	end_cnt_bit <= '1' when ((add_cnt_bit = '1') AND (cnt_bit = BIT_MAX-1)) else '0';
	---------------------------nedge 和din_vld_flag--------------------------------------------
	process(clk,rst_n)
		variable temp0: std_logic_vector(1 downto 0);--temp1,
	begin 
		if(rst_n = '0') then 
			temp0 := "00";
			--temp1 := '0';
			nedge <= '0';
		elsif(clk'event and clk = '1') then 
			--(temp1) & (temp0) := (temp0) & (din);
			temp0 := temp0(0) & din;
			--temp1 := temp0;
		end if;
		nedge <= temp0(1) AND (NOT temp0(0));
	end process;
	
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			din_vld_flag <= '0';
		elsif(clk'event and clk = '1') then 
			if(nedge = '1') then 
				din_vld_flag <= '1';
			elsif(end_cnt_bit = '1') then 
				din_vld_flag <= '0';
			end if;
		end if;
	end process;
	--------------------------------------------data-------------------------------------------------
	process(clk,rst_n)
	begin 
		if(rst_n = '0') then 
			data <= (others => '0');
		elsif(clk'event and clk = '1') then 
			if(cnt_baud = (BAUD_MAX/2-1)) then         --中间时刻采样数据
				data <= din & data(data'left downto 1);--此时数据高位在前
			end if;
		end if;
	end process;
	------------------------------------------dout-----------------------------------------------------
	dout <= data(data'left-1 downto 1);
	dout_vld <= '1' when (end_cnt_bit = '1' AND end_cnt_baud = '1') else '0';
	
end uart_rx;	
-------------------------------------------------package------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
package uart_package is
	component uart_rx is
		generic(WIDTH_L: integer;						    --数据位宽
				BAUD_MAX: integer   					    --波特率115200,计数最大值50_000_000/115200
		);
		port(
			clk: in std_logic;								--50MHZ
			rst_n: in std_logic;
			din: in std_logic;								--接收引脚
			dout: out std_logic_vector(WIDTH_L-1 downto 0);	--接收到的数据
			dout_vld: out std_logic 	        			--接收数据完成							
		);
	end component;
	
	component uart_tx is
		generic(WIDTH_L: integer;						--数据位宽
				BAUD_MAX: integer  						--波特率115200,计数最大值50_000_000/115200
			);
		port(
			clk: in std_logic;							--50MHZ
			rst_n: in std_logic;
			din: in std_logic_vector(WIDTH_L-1 downto 0);
			din_vld: in std_logic;
			dout: out std_logic;
			rdy: out std_logic 							--表示可以接收数据
			);
	end component;
	
end uart_package;

	

8.uart_top.vhd

--uart 顶层模块
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.uart_tx_package.all;
use work.uart_rx_package.all;

---------------------------------------------------------------------------------------------
entity uart_top is 
	generic(WIDTH_L: integer := 8;
			BAUD_MAX: integer := 434);
	port(
		clk: in std_logic;
		rst_n: in std_logic;
		rx: in std_logic;			--接收引脚
		tx: out std_logic
	);
end uart_top;
-------------------------------------------------------------------------------------------------
architecture uart_top of uart_top is
	signal din_r: std_logic;
	signal dout_r: std_logic_vector(WIDTH_L-1 downto 0);
	signal dout_vld_r: std_logic;
	signal rdy_r: std_logic;	
begin
	U1: uart_rx generic map(WIDTH_L,BAUD_MAX) port map(clk,rst_n,rx,dout_r,dout_vld_r);
	U2: uart_tx generic map(WIDTH_L,BAUD_MAX) port map(clk,rst_n,dout_r,dout_vld_r,tx,rdy_r);
end uart_top;

9.uart_top_tb.v

`timescale 1ns/1ps
module uart_top_tb();

	reg				clk;
	reg     		rst_n;
	wire     	    rx;
	wire     		tx;
	
	reg [7:0] 		din;
	reg             din_vld;
	wire            rdy;
	
	parameter CYCLE = 20;
	
	initial begin
		clk <= 1'b1;
		rst_n <= 1'b0;
		#15
		rst_n <= 1'b1;
	end 
	
	always #(CYCLE/2) clk <= !clk;
	
	initial begin
		din <= 8'd0;
		din_vld <= 1'b0;
		#(20*CYCLE)
		//发送5a
		din <= 8'h5a;
		din_vld <= 1'b1;
		#CYCLE
		din_vld <= 1'b0;
		#(CYCLE*434*12)
		//发送6b
		din <= 8'h6b;
		din_vld <= 1'b1;
		#CYCLE
		din_vld <= 1'b0;
		#(CYCLE*434*15)
		$stop;
	end 
	
	//例化发送模块
	uart_tx u_uart_tx(
		.clk		(clk		),
		.rst_n		(rst_n		),
		.din		(din		),
		.din_vld	(din_vld	),
		.dout		(rx  		),
		.rdy		(rdy		)
	);
	
	//例化顶层
	uart_top u_uart_top(
		.clk	(clk	),
		.rst_n	(rst_n	),
		.tx		(tx		),
		.rx		(rx		)
	);
		
	
endmodule

  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vivado 是一种集成设计环境,用于进行FPGA和SoC的设计和开发。在 Vivado 中实现 UART 串口通信需要进行以下几个步骤: 1. 创建工程:在 Vivado 中创建一个工程,并选择目标设备。 2. 添加模块:创建一个新的 Verilog 或 VHDL 模块来实现 UART 通信功能。这个模块将负责处理 UART 协议,并与其他模块进行数据交换。 3. IP 核配置:在 Vivado 中添加一个 IP 核,来实现 UART 控制器。可以选择现有的 UART IP 核,或者根据需要自定义一个。 4. 连接模块和 IP 核:使用 Vivado 的连接编辑器将自定义模块和 UART IP 核进行连接,以便数据传输和控制。 5. 约束文件设置:创建一个约束文件,对 I/O 端口进行约束和引脚映射。 6. 综合和实现:运行综合和实现过程,将设计映射到目标设备上。 7. 配置串口参数:在 SDK(Software Development Kit)中配置串口通信的参数,如波特率、数据位数、校验位等。 8. 软件开发:使用 C 或 C++ 编程语言编写软件来实现 UART 通信的逻辑。可以使用 SDK 提供的串口库函数来进行数据的发送和接收操作。 9. 编译和生成可执行文件:在 SDK 中编译软件代码,并生成可烧录到目标设备上的可执行文件。 10. 下载和调试:通过 JTAG 或者其他下载方式将可执行文件下载到目标设备上,并进行调试和验证。 通过以上步骤,就可以在 Vivado 中实现 UART 串口通信功能。使用自定义的模块和 UART IP 核,可以灵活地实现各种不同需求的串口通信功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值