基于VHDL的串口程序.docx

上传人:b****3 文档编号:4855294 上传时间:2022-12-10 格式:DOCX 页数:22 大小:21.90KB
下载 相关 举报
基于VHDL的串口程序.docx_第1页
第1页 / 共22页
基于VHDL的串口程序.docx_第2页
第2页 / 共22页
基于VHDL的串口程序.docx_第3页
第3页 / 共22页
基于VHDL的串口程序.docx_第4页
第4页 / 共22页
基于VHDL的串口程序.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

基于VHDL的串口程序.docx

《基于VHDL的串口程序.docx》由会员分享,可在线阅读,更多相关《基于VHDL的串口程序.docx(22页珍藏版)》请在冰豆网上搜索。

基于VHDL的串口程序.docx

基于VHDL的串口程序

在quartus里面没找到SCI的LPM部件,又不想自己从头编写,在网上找到了一个verilog的程序,也找到了和这个实现方法相同的VHDL程序。

都是接收到按键按下时候,启动串口发送,发送welcom但是都是发现一个,并延时重新读取按键,然后再重新启动发送。

数据格式是9600boudrate、8数据位、1启动位、1停止位,每16个bit周期发送一个byte,接收程序,没有中间多位判断部分,考虑接收的有效性和可靠性,对程序进行了修改,改为每11个bit周期发送一个byte,这样也可以兼容接收2个停止位的接收程序,在接收程序中进行了多相判断。

程序和截图如下:

--本模块的功能是验证实现和PC机进行基本的串口通信的功能。

需要在PC机上安装一个串口调试工具来验证程序的功能。

--程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控制器,10个bit是1位起始位,8个数据位,1个结束位。

--串口的波特律由程序中定义的div_par参数决定,更改该参数可以实现相应的波特率。

程序当前设定的div_par的值

--是0x145,对应的波特率是9600。

用一个8倍波特率的时钟将发送或接受每一位bit的周期时间划分为8个时隙以使通

--信同步.

--程序的基本工作过程是,按动一个按键key1控制器向PC的串口发送“welcome",

--PC机接收后显示验证数据是否正确(串口调试工具设成按ASCII码接受方式).

--PC可随时向FPGA发送0-F的十六进制数据,FPGA接受后显示在7段数码管上.

libraryieee;--designbyjiaolonglan

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

useieee.std_logic_arith.all;

entitymyserialis

generic(boud_rate:

integer:

=9600;

clk_rate:

integer:

=50_000_000);

port(clk:

instd_logic;

rstn:

instd_logic;

rxd:

instd_logic;--receivebit

txd:

outstd_logic;--sendbit

--txd_buff:

instd_logic_vector(7downto0);--bufferwritein

--write_data:

instd_logic;--writedata

en:

outstd_logic_vector(7downto0);

seg_data:

outstd_logic_vector(7downto0);

--rxd_buff:

outstd_logic_vector(7downto0);

key_input:

instd_logic

--testout:

outstd_logic

--read_data:

instd_logic

);

endentitymyserial;

architecturebhvofmyserialis

SIGNALdiv_reg:

integerrange0to2**16-1;--分频计数器,分频值由波特率决定。

分频后得到频率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_reg:

std_logic_vector(7downto0);--接收寄存器1

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:

integerrange0to2**20-1;--std_logic_vector(19DOWNTO0);--延时去抖计数器

SIGNALstart_delaycnt:

std_logic;--开始延时计数标志

SIGNALkey_entry1:

std_logic;--确定有键按下曛?

SIGNALkey_entry2:

std_logic;--确定有键按下标志

CONSTANTdiv_par:

integer:

=8;--fortest:

=clk_rate/(8*boud_rate);

--分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8

begin

en<="01010101";--7段数码管使能信号赋值

txd<=txd_reg;

PROCESS(clk,rstn)--delaycounter

BEGIN

IF(rstn='0')THEN

cnt_delay<=0;

start_delaycnt<='0';--

key_entry1<='0';

ELSIF(clk'EVENTANDclk='1')THEN

IF(key_entry2='1')THEN--starttransmitandclearkey_entry1

key_entry1<='0';--

ELSE

IF(cnt_delay=98)THEN

IF(key_input='1')THEN

key_entry1<='1';

ENDIF;

ENDIF;

ENDIF;

IF(start_delaycnt='1')THEN--keypress

IF(cnt_delay<99)THEN--20D800000

cnt_delay<=cnt_delay+1;

ELSE--rejudgekey

cnt_delay<=0;

start_delaycnt<='0';

ENDIF;

ELSE

IF((key_input='1')AND(cnt_delay=0))THEN--judgekeypressstart

start_delaycnt<='1';

ENDIF;

ENDIF;

ENDIF;

ENDPROCESS;

PROCESS(clk,rstn)--recyclecounter分频得到8倍波特率的时钟div_par

BEGIN

IF(rstn='0')THEN

div_reg<=0;

clkbaud8x<='0';

ELSIF(clk'EVENTANDclk='1')THEN

IF(div_reg=div_par-1)THEN

div_reg<=0;

clkbaud8x<=NOTclkbaud8x;

ELSE

div_reg<=div_reg+1;

ENDIF;

ENDIF;

ENDPROCESS;

PROCESS(clkbaud8x,clkbaud8x,rstn)

BEGIN

IF(rstn='0')THEN

div8_rec_reg<="000";

div8_tras_reg<="000";

ELSEIF(clkbaud8x'EVENTANDclkbaud8x='1')THEN

IF(recstart='1')THEN--接收开始标志

div8_rec_reg<=div8_rec_reg+"001";--接收开始后,时隙数在8倍波特率的时钟下加1循环

ENDIF;

IF(trasstart='1')THEN

div8_tras_reg<=div8_tras_reg+"001";--发送开始后,时隙数在8倍波特率的时钟下加1循环

ENDIF;

ENDIF;

ENDIF;

ENDPROCESS;

PROCESS(div8_rec_reg,div8_tras_reg)--creatreceiveandtransmitdataclk

BEGIN

IF(div8_rec_reg="111")THEN

clkbaud_rec<='1';--在第7个时隙,接收

ELSE

clkbaud_rec<='0';

ENDIF;

IF(div8_tras_reg="111")THEN

clkbaud_tras<='1';--在第7个时隙,发送使能信号有效,将数据发出

ELSE

clkbaud_tras<='0';

ENDIF;

ENDPROCESS;

PROCESS(clkbaud8x,rstn)--trsnsmitdata

BEGIN

IF(rstn='0')THEN

txd_reg<='1';

trasstart<='0';

txd_buf<="00000000";

state_tras<="0000";

send_state<="000";

key_entry2<='0';

ELSEIF(clkbaud8x'EVENTANDclkbaud8x='1')THEN

IF(key_entry2='0')THEN

IF(key_entry1='1')THEN

key_entry2<='1';

txd_buf<="01110111";--"w"

ENDIF;

ELSE--key_entry2='1';havekeypressstarttransmit

CASEstate_trasIS

WHEN"0000"=>--发送起始位

IF((trasstart='0')AND(send_state<"111"))THEN--haven'tsendalldatathencontinuetransmit

trasstart<='1';

ELSE

IF(send_state<"111")THEN--send_stateischarcounter

IF(clkbaud_tras='1')THEN--enabletransmiteverydatabitflag

txd_reg<='0';--startbit

state_tras<=state_tras+"0001";--state_trasisbitcounter

ENDIF;

ELSE--=7

key_entry2<='0';

state_tras<="0000";

ENDIF;

ENDIF;

WHEN"0001"=>--发送第1位

IF(clkbaud_tras='1')THEN

txd_reg<=txd_buf(0);--undersendregis

txd_buf(6DOWNTO0)<=txd_buf(7DOWNTO1);

state_tras<=state_tras+"0001";--bitaddone

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"1010"=>--1111runto15

IF(clkbaud_tras='1')THEN

state_tras<="0000";--state_tras+"0001";--nextis0000

send_state<=send_state+"001";--judgesendbyte

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=>--runto10and14

IF(clkbaud_tras='1')THEN

--state_tras<=state_tras+"0001";//old

state_tras<="0000";

trasstart<='1';

ENDIF;

ENDCASE;

ENDIF;

ENDIF;

ENDIF;

ENDPROCESS;

PROCESS(clkbaud8x,rstn)--receivePC机的数据

variabletemp:

integerrange0to8;

variablercv_data:

std_logic;

BEGIN

IF(rstn='0')THEN

rxd_reg<=(others=>'0');

rxd_buf<="00000000";--everyphase

state_rec<="0000";

recstart<='0';

recstart_tmp<='0';

ELSEIF(clkbaud8x'EVENTANDclkbaud8x='1')THEN

rxd_reg<=rxd_reg(6downto0)&rxd;

IF(state_rec="0000")THEN

IF(recstart_tmp='1')THEN--havecapturestartbit

recstart<='1';

recstart_tmp<='0';

state_rec<=state_rec+"0001";

ELSE

IF(rxd_reg(7downto4)="1100")THEN--检测到起始位的下降沿,进入接受状态

recstart_tmp<='1';--setcapturestartbitflag

ENDIF;

ENDIF;

ELSE--detectotherbit

IF(state_rec>="0001"ANDstate_rec<="1000")THEN

IF(clkbaud_rec='1')THEN

temp:

=0;

foriin1to3loop--data6,7012345

temp:

=temp+conv_integer(rxd_reg(i));

iftemp>=2then

rcv_data:

='1';

else

rcv_data:

='0';

endif;

endloop;

rxd_buf(7)<=rcv_data;

rxd_buf(6DOWNTO0)<=rxd_buf(7DOWNTO1);

state_rec<=state_rec+"0001";

ENDIF;

ELSE--stopbit

IF(state_rec="1001")THEN

IF(clkbaud_rec='1')THEN

IFrxd_reg

(2)='0'THEN--stopbiterror

rxd_buf<=(others=>'0');

ENDIF;

state_rec<="0000";

recstart<='0';

ENDIF;

ENDIF;

ENDIF;

ENDIF;

ENDIF;

ENDIF;

ENDPROCESS;

PROCESS(rxd_buf,clk)--将接受的数据用数码管显示出来

BEGIN

ifclk'eventandclk='1'then

CASErxd_bufIS

WHEN"00110000"=>

seg_data<="00000011";--00x30

WHEN"00110001"=>

WHEN"00110010"=>

seg_data<="00100101";--2

WHEN"00110011"=>

seg_data<="00001101";--3

WHEN"00110100"=>

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 其它模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1