时钟频率=波特率*16倍*分频系数
对于传输速度而言,时钟速度越大,传输速率越快。
其中,波特率与分频系数关系如下 :
比特率
频率
分频系数
范围
对比数
9600
153600
325.5208
326
324
19200
307200
162.7604
163
162
38400
614400
81.38021
82
81
56000
896000
55.80357
56
55
57600
921600
54.25347
55
54
115200
1843200
27.12674
28
26
还有波特率与分频系数对应表:
波特率
分频器DLM(H)
分频器DLL(L)
50
09H
00H
75
06H
00H
110
04H
17H
150
03H
00H
300
01H
80H
600
00H
C0H
1200
00H
60H
1800
00H
40H
2400
00H
30H
3600
00H
20H
4800
00H
18H
7200
00H
10H
9600
00H
0CH
11520
00H
0AH
19200
00H
06H
23040
00H
05H
57600
00H
02H
115200
00H
01H
最后是一个参考程序如下:
---------波特率的设置,时钟为8倍的波特率.
---------先检测时钟的上升沿,每第7个时钟的上升沿,进行发送与接收使能,
---------每一位数据在第7个时钟的上升沿发出,每发送完一帧数据,进行数据状态的转换
---------USB转串口器的RX接26,TX接27
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
entity serial is
port(
clk:in std_logic;
txd:out std_logic;
rxd:in std_logic;
key1:in std_logic;
led:out std_logic_vector(7 downto 0)
);
end serial;
architecture behave of serial is
signal clk_div:std_logic;--分频后的时钟
signal div_temp:integer range 0 to 324;--分频计数(采用326)9600
signal txdcounter_reg:std_logic_vector(2 downto 0);--用于计算发送的当前位
signal rxdcounter_reg:std_logic_vector(2 downto 0);--用于计算接收的当前位
signal txd_state:std_logic_vector(3 downto 0);----发送的状态
signal rxd_state:std_logic_vector(3 downto 0);---接收的状态
signal txd_start:std_logic;--开始发送标志
signal rxd_start:std_logic;--开始接收标志
signal rxd_start_temp:std_logic;
signal txd_buffer:std_logic_vector(7 downto 0);--发送缓存器
signal rxd_buffer:std_logic_vector(7 downto 0);--接收缓存器
signal txd_reg:std_logic;--发送寄存器
signal rxd_reg1:std_logic;--接收寄存器1
signal rxd_reg2:std_logic;---接收寄存器2
signal clk_en_txd:std_logic;---用于标志发送时钟处于第7个时钟
signal clk_en_rxd:std_logic;---用于标志接收时钟处于第7个时钟
signal send_over:std_logic;---发送完的标志
signal key_temp:std_logic:='0';--按键标志
signal txd_num:std_logic_vector(2 downto 0);--要传送的数据的个数(这里设置为4个)
signal led_temp:std_logic_vector(7 downto 0):="11111111";--显示寄存器
begin
----------------------波特率的设置-----------------------
process(clk)
begin
if(clk'event and clk='1')then
if(div_temp=26)then --9600=>324
div_temp<=0;
clk_div<=not clk_div;
else
div_temp<=div_temp + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-----------------发送模块--------------------------------------
---------------------------------------------------------------
---------------发送时钟计数-------------------------------------
process(clk_div)
begin
if(clk_div'event and clk_div='1')then
if(txd_start='1')then
txdcounter_reg<=txdcounter_reg+"001";--开始发送后,计算发送时钟的位置
end if;
end if;
end process;
----------------发送使能---------------------------------------
process(txdcounter_reg)
begin
if(txdcounter_reg="111")then
clk_en_txd<='1';--处于第7 个时钟的时隙
else
clk_en_txd<='0';
end if;
end process;
----------------发送模块---------------------------------------
txd<=txd_reg;
process(clk_div)
begin
if(clk_div'event and clk_div='1')then
if(key1='0')then
key_temp<='1';
txd_state<="0000";--状态初始化
end if;
if(key_temp='1')then--每按一次按键发送一次数据
case txd_state is
when "0000"=>--发送起始位
if(not txd_start='1')then--处于发送状态的判断和发送个数的判定
txd_start<='1';
else
if(clk_en_txd='1')then
txd_reg<='0';--起始位
txd_state<=txd_state+"0001";
else
txd_state<="0000";
end if;
end if;
when "0001"=>--第1位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "0010"=>--第2位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "0011"=>--第3位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "0100"=>--第4位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "0101"=>--第5位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "0110"=>--第6位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "0111"=>--第7位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "1000"=>--第8位
if(clk_en_txd='1')then
txd_reg<=txd_buffer(0);
txd_buffer(6 downto 0)<=txd_buffer(7 downto 1);--右移
txd_state<=txd_state+"0001";
end if;
when "1001"=>--停止位
if(clk_en_txd='1')then
txd_reg<='1';
txd_state<=txd_state+"0001";
end if;
when "1111"=>--------发送的字符转换(设置为"1111"是为了跳转到发送起始位的状态中)
if(clk_en_txd='1')then
txd_state<=txd_state+"0001";
txd_start<='0';--关闭发送
case txd_num is
when "000"=>
txd_buffer<="01000110";--F
when "001"=>
txd_buffer<="01010000";--P
when "010"=>
txd_buffer<="01000111";--G
when "011"=>
txd_buffer<="01000001";--A
when "100"=>
txd_buffer<="00001010";--换行
when "101"=>
txd_num<="000";--清零
key_temp<='0';--关闭按键的标志
when others=>
txd_buffer<="00000000";--空
txd_num<="000";
end case;
txd_num<=txd_num+"001";---发送的字符转换
end if;
when others=>
if(clk_en_txd='1')then
txd_start<='1';
txd_state<=txd_state+"0001";
end if;
end case;
end if;
end if;
end process;
--------------------------------------------------
----------------------接收模块-------------------
--------------------------------------------------
----------------发送时钟计数-----------------
process(clk_div)
begin
if(clk_div'event and clk_div='1')then
if(rxd_start='1')then
rxdcounter_reg<=rxdcounter_reg+"001";
end if;
end if;
end process;
---------------接收使能--------------------
process(rxdcounter_reg)
begin
if(rxdcounter_reg="111")then
clk_en_rxd<='1';
else
clk_en_rxd<='0';
end if;
end process;
---------------------------------------------
process(clk_div)
begin
if(clk_div'event and clk_div='1')then
led<=led_temp;--显示
rxd_reg1<=rxd;--rxd_reg1为后一位数据
rxd_reg2<=rxd_reg1;--rxd_reg2为前一位数据
if(rxd_state="0000")then--判断是否接收到起始位
if(rxd_start_temp='1')then--判断是否开始发送
rxd_start<='1';
send_over<='0';--未发送完
rxd_start_temp<='0';
rxd_state<=rxd_state+"0001";--状态转换
else--如果未开始发送,则进行检测
if((not rxd_reg1 and rxd_reg2)='1')then---起始位一般为低电平
rxd_start_temp<='1';
end if;
end if;
else
if(rxd_state>"0000" and rxd_state
if(clk_en_rxd='1')then
rxd_buffer(7)<=rxd_reg2;
rxd_buffer(6 downto 0)<=rxd_buffer(7 downto 1);--从高位向低位移
rxd_state<=rxd_state+"0001";
end if;
else
if(rxd_state="1001")then--停止位
if(clk_en_rxd='1')then
rxd_state<= "0000";
rxd_start<='0';
send_over<='1';
end if;
end if;
end if;
end if;
if(send_over='1')then
led_temp<=rxd_buffer;
send_over<='0';
end if;
end if;
end process;
end behave;