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