基于vhdl的fpga串口通信.docx
《基于vhdl的fpga串口通信.docx》由会员分享,可在线阅读,更多相关《基于vhdl的fpga串口通信.docx(13页珍藏版)》请在冰豆网上搜索。
基于vhdl的fpga串口通信
基于vhdl的fpga串口通信
--本模块的功能是验证实现和PC机进行差不多的串口通信的功能。
需要在
--PC机上安装一个串口调试工具来验证程序的功能。
--程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控
--制器,10个bit是1位起始位,8个数据位,1个终止
--位。
串口的波特律由程序中定义的div_par参数决定,更换该参数能够实
--现相应的波特率。
程序当前设定的div_par的值是0x104,对应的波特率是
--9600。
用一个8倍波特率的时钟将发送或同意每一位bit的周期时刻
--划分为8个时隙以使通信同步.
--程序的工作过程是:
串口处于全双工工作状态,按动key2,CPLD向PC发送皐elcome"
--字符串(串口调试工具设成按ASCII码同意方式);PC可随时向CPLD发送0-F的十六进制
--数据,CPLD同意后显示在7段数码管上。
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYUARTIS
PORT(
clk:
INstd_logic;
rst:
INstd_logic;
rxd:
INstd_logic;--串行数据接收端
txd:
OUTstd_logic;--串行数据发送端
en:
OUTstd_logic_vector(7downto0);--数码管使能
seg_data:
OUTstd_logic_vector(7DOWNTO0);--数码管数据
key_input:
INstd_logic--按键输入
);
ENDUART;
ARCHITECTUREarchOFUARTIS
--//////////////////innerreg////////////////////
SIGNALdiv_reg:
std_logic_vector(15DOWNTO0);--分频计数器,分频值由波特率决定。
分频后得到频率8倍波特率的时钟
SIGNALdiv8_tras_reg:
std_logic_vector(2DOWNTO0);--该寄存器的计数值对应发送时当前位于的时隙数
SIGNALdiv8_rec_reg:
std_logic_vector(2DOWNTO0);--寄存器的计数值对应接收时当前位于的时隙数
SIGNALstate_tras:
std_logic_vector(3DOWNTO0);--发送状态寄存器
SIGNALstate_rec:
std_logic_vector(3DOWNTO0);--同意状态寄存器
SIGNALclkbaud_tras:
std_logic;--以波特率为频率的发送使能信号
SIGNALclkbaud_rec:
std_logic;--以波特率为频率的同意使能信号
SIGNALclkbaud8x:
std_logic;--以8倍波特率为频率的时钟,它的作用是将发送或同意一个bit的时钟周期分为8个时隙
SIGNALrecstart:
std_logic;--开始发送标志
SIGNALrecstart_tmp:
std_logic;--开始同意标志
SIGNALtrasstart:
std_logic;
SIGNALrxd_reg1:
std_logic;--接收寄存器1
SIGNALrxd_reg2:
std_logic;--接收寄存器2,因为接收数据为异步信号,故用两级缓存
SIGNALtxd_reg:
std_logic;--发送寄存器
SIGNALrxd_buf:
std_logic_vector(7DOWNTO0);--同意数据缓存
SIGNALtxd_buf:
std_logic_vector(7DOWNTO0);--发送数据缓存
SIGNALsend_state:
std_logic_vector(2DOWNTO0);--每次按键给PC发送"Welcome"字符串,这是发送状态寄存器
SIGNALcnt_delay:
std_logic_vector(19DOWNTO0);--延时去抖计数器
SIGNALstart_delaycnt:
std_logic;--开始延时计数标志
SIGNALkey_entry1:
std_logic;--确定有键按下曛?
SIGNALkey_entry2:
std_logic;--确定有键按下标志
--//////////////////////////////////////////////
CONSTANTdiv_par:
std_logic_vector(15DOWNTO0):
="0000000100000100";
--分频参数,其值由对应的波特率运算而得,按此参数分频的时钟频率是波倍特率的8倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8
SIGNALtxd_xhdl3:
std_logic;
BEGIN
en<="01010101";--7段数码管使能信号赋值
txd<=txd_xhdl3;
txd_xhdl3<=txd_reg;
PROCESS(clk,rst)
BEGIN
IF(NOTrst='1')THEN
cnt_delay<="00000000000000000000";
start_delaycnt<='0';
ELSIF(clk'EVENTANDclk='1')THEN
IF(start_delaycnt='1')THEN
IF(cnt_delay/="11000011010100000000")THEN
cnt_delay<=cnt_delay+"00000000000000000001";
ELSE
cnt_delay<="00000000000000000000";
start_delaycnt<='0';
ENDIF;
ELSE
IF((NOTkey_input='1')AND(cnt_delay="00000000000000000000"))THEN
start_delaycnt<='1';
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clk,rst)
BEGIN
IF(NOTrst='1')THEN
key_entry1<='0';
ELSIF(clk'EVENTANDclk='1')THEN
IF(key_entry2='1')THEN
key_entry1<='0';
ELSE
IF(cnt_delay="11000011010100000000")THEN
IF(NOTkey_input='1')THEN
key_entry1<='1';
ENDIF;
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clk,rst)
BEGIN
IF(NOTrst='1')THEN
div_reg<="0000000000000000";
ELSIF(clk'EVENTANDclk='1')THEN
IF(div_reg=div_par-"0000000000000001")THEN
div_reg<="0000000000000000";
ELSE
div_reg<=div_reg+"0000000000000001";
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clk,rst)--分频得到8倍波特率的时钟
BEGIN
IF(NOTrst='1')THEN
clkbaud8x<='0';
ELSIF(clk'EVENTANDclk='1')THEN
IF(div_reg=div_par-"0000000000000001")THEN
clkbaud8x<=NOTclkbaud8x;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clkbaud8x,rst)
BEGIN
IF(NOTrst='1')THEN
div8_rec_reg<="000";
ELSEIF(clkbaud8x'EVENTANDclkbaud8x='1')THEN
IF(recstart='1')THEN--接收开始标志
div8_rec_reg<=div8_rec_reg+"001";--接收开始后,时隙数在8倍波特率的时钟下加1循环
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clkbaud8x,rst)
BEGIN
IF(NOTrst='1')THEN
div8_tras_reg<="000";
ELSEIF(clkbaud8x'EVENTANDclkbaud8x='1')THEN
IF(trasstart='1')THEN
div8_tras_reg<=div8_tras_reg+"001";--发送开始后,时隙数在8倍波特率的时钟下加1循环
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(div8_rec_reg)
BEGIN
IF(div8_rec_reg="111")THEN
clkbaud_rec<='1';---在第7个时隙,接收鼓苄藕庞行В荽蛉?
ELSE
clkbaud_rec<='0';
ENDIF;
ENDPROCESS;
PROCESS(div8_tras_reg)
BEGIN
IF(div8_tras_reg="111")THEN
clkbaud_tras<='1';--在第7个时隙,发送使能信号有效,将数据发出
ELSE
clkbaud_tras<='0';
ENDIF;
ENDPROCESS;
PROCESS(clkbaud8x,rst)
BEGIN
IF(NOTrst='1')THEN
txd_reg<='1';
trasstart<='0';
txd_buf<="00000000";
state_tras<="0000";
send_state<="000";
key_entry2<='0';
ELSEIF(clkbaud8x'EVENTANDclkbaud8x='1')THEN
IF(NOTkey_entry2='1')THEN
IF(key_entry1='1')THEN
key_entry2<='1';
txd_buf<="01110111";--"w"
ENDIF;
ELSE
CASEstate_trasIS
WHEN"0000"=>--发送起始位
IF((NOTtrasstart='1')AND(send_state<"111"))THEN
trasstart<='1';
ELSE
IF(send_state<"111")THEN
IF(clkbaud_tras='1')THEN
txd_reg<='0';
state_tras<=state_tras+"0001";
ENDIF;
ELSE
key_entry2<='0';
state_tras<="0000";
ENDIF;
ENDIF;
WHEN"0001"=>--发送第1位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"0010"=>--发送第2位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"0011"=>--发送第3位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"0100"=>--发送第4位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"0101"=>--发送第5位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"0110"=>--发送第6位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"0111"=>--发送第7位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"1000"=>--发送第8位
IF(clkbaud_tras='1')THEN
txd_reg<=txd_buf(0);
txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);
state_tras<=state_tras+"0001";
ENDIF;
WHEN"1001"=>--发送停止位
IF(clkbaud_tras='1')THEN
txd_reg<='1';
txd_buf<="01010101";
state_tras<=state_tras+"0001";
ENDIF;
WHEN"1111"=>
IF(clkbaud_tras='1')THEN
state_tras<=state_tras+"0001";
send_state<=send_state+"001";
trasstart<='0';
CASEsend_stateIS
WHEN"000"=>
txd_buf<="01100101";--"e"
WHEN"001"=>
txd_buf<="01101100";--"l"
WHEN"010"=>
txd_buf<="01100011";--"c"
WHEN"011"=>
txd_buf<="01101111";--"o"
WHEN"100"=>
txd_buf<="01101101";--"m"
WHEN"101"=>
txd_buf<="01100101";--"e"
WHENOTHERS=>
txd_buf<="00000000";
ENDCASE;
ENDIF;
WHENOTHERS=>
IF(clkbaud_tras='1')THEN
state_tras<=state_tras+"0001";
trasstart<='1';
ENDIF;
ENDCASE;
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clkbaud8x,rst)--同意PC机的数据
BEGIN
IF(NOTrst='1')THEN
rxd_reg1<='0';
rxd_reg2<='0';
rxd_buf<="00000000";
state_rec<="0000";
recstart<='0';
recstart_tmp<='0';
ELSEIF(clkbaud8x'EVENTANDclkbaud8x='1')THEN
rxd_reg1<=rxd;
rxd_reg2<=rxd_reg1;
IF(state_rec="0000")THEN
IF(recstart_tmp='1')THEN
recstart<='1';
recstart_tmp<='0';
state_rec<=state_rec+"0001";
ELSE
IF((NOTrxd_reg1ANDrxd_reg2)='1')THEN--检测到起始位的下降沿,进入同意状态
recstart_tmp<='1';
ENDIF;
ENDIF;
ELSE
IF(state_rec>="0001"ANDstate_rec<="1000")THEN
IF(clkbaud_rec='1')THEN
rxd_buf(7)<=rxd_reg2;
rxd_buf(6DOWNTO0)<=rxd_buf(7DOWNTO1);
state_rec<=state_rec+"0001";
ENDIF;
ELSE
IF(state_rec="1001")THEN
IF(clkbaud_rec='1')THEN
state_rec<="0000";
recstart<='0';
ENDIF;
ENDIF;
ENDIF;
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(rxd_buf)--将同意的数据用数码管显示出来
BEGIN
CASErxd_bufIS
WHEN"00110000"=>
seg_data<="00000011";--0
WHEN"00110001"=>
seg_data<="10011111";--1
WHEN"00110010"=>
seg_data<="00100101";--2
WHEN"00110011"=>
seg_data<="00001101";--3
WHEN"00110100"=>
seg_data<="10011001";--4
WHEN"00110101"=>
seg_data<="01001001";--5
WHEN"00110110"=>
seg_data<="01000001";--6
WHEN"00110111"=>
seg_data<="00011111";--7
WHEN"00111000"=>
seg_data<="00000001";--8
WHEN"00111001"=>
seg_data<="00001001";--9
WHEN"01000001"=>
seg_data<="00010001";--A
WHEN"01000010"=>
seg_data<="11000001";--B
WHEN"01000011"=>
seg_data<="01100011";--C
WHEN"01000100"=>
seg_data<="10000101";--D
WHEN"01000101"=>
seg_data<="01100001";--E
WHEN"01000110"=>
seg_data<="01110001";--F
WHENOTHERS=>
seg_data<="11111111";
ENDCASE;
ENDPROCESS;
ENDarch;