《基于vhdl 的串口程序》由会员分享,可在线阅读,更多相关《基于vhdl 的串口程序(18页珍藏版)》请在金锄头文库上搜索。
1、基于VHDL的串口收发设计20161227在quartus里面没找到SCI的LPM部件,又不想自己从头编写,在网上找到了一个verilog的程序,也找到了和这个实现方法相同的VHDL程序。都是接收到按键按下时候,启动串口发送,发送welcom但是都是发现一个,并延时重新读取按键,然后再重新启动发送。数据格式是9600 boud rate、 8数据位、 1启动位、 1停止位,每16个bit周期发送一个byte,接收程序,没有中间多位判断部分,考虑接收的有效性和可靠性,对程序进行了修改,改为每11个bit周期发送一个byte,这样也可以兼容接收2个停止位的接收程序,在接收程序中进行了多相判断。程序
2、和截图如下:-本模块的功能是验证实现和PC机进行基本的串口通信的功能。需要在PC机上安装一个串口调试工具来验证程序的功能。-程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控制器,10个bit是1位起始位,8个数据位,1个结束位。-串口的波特律由程序中定义的div_par参数决定,更改该参数可以实现相应的波特率。程序当前设定的div_par 的值-是0x145,对应的波特率是9600。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间划分为8个时隙以使通-信同步.-程序的基本工作过程是,按动一个按键key1 控制器向PC的串口发送“welcome,-PC机接收后显示验证数据是否
3、正确(串口调试工具设成按ASCII码接受方式).-PC可随时向FPGA发送0-F的十六进制数据,FPGA接受后显示在7段数码管上.library ieee;- design by jiaolonglan20161227use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use ieee.std_logic_arith.all;entity myserial isgeneric ( boud_rate:integer := 9600;clk_rate :integer := 50_000_000);port( clk : in
4、std_logic;rstn : in std_logic;rxd : in std_logic; -receive bittxd : out std_logic; -send bit -txd_buff :in std_logic_vector(7 downto 0); - buffer write in-write_data: in std_logic; - write data en :out std_logic_vector(7 downto 0); seg_data:out std_logic_vector(7 downto 0);-rxd_buff :out std_logic_v
5、ector(7 downto 0);key_input:in std_logic-testout: out std_logic-read_data: in std_logic);end entity myserial; architecture bhv of myserial is SIGNAL div_reg : integer range 0 to 2*16-1;-分频计数器,分频值由波特率决定。分频后得到频率8倍波特率的时钟 SIGNAL div8_tras_reg : std_logic_vector(2 DOWNTO 0);-该寄存器的计数值对应发送时当前位于的时隙数 SIGNAL
6、div8_rec_reg : std_logic_vector(2 DOWNTO 0);- 寄存器的计数值对应接收时当前位于的时隙数 SIGNAL state_tras : std_logic_vector(3 DOWNTO 0);- 发送状态寄存器 SIGNAL state_rec : std_logic_vector(3 DOWNTO 0);- 接受状态寄存器 SIGNAL clkbaud_tras : std_logic; -以波特率为频率的发送使能信号 SIGNAL clkbaud_rec : std_logic;- 以波特率为频率的接受使能信号 SIGNAL clkbaud8x :
7、std_logic; -以8倍波特率为频率的时钟,它的作用是将发送或接受一个bit的时钟周期分为8个时隙 SIGNAL recstart : std_logic; -开始发送标志 SIGNAL recstart_tmp : std_logic; -开始接受标志 SIGNAL trasstart : std_logic; - SIGNAL rxd_reg : std_logic_vector(7 downto 0); -接收寄存器1 SIGNAL txd_reg : std_logic; -发送寄存器 SIGNAL rxd_buf : std_logic_vector(7 DOWNTO 0);-
8、接受数据缓存 SIGNAL txd_buf : std_logic_vector(7 DOWNTO 0);-发送数据缓存 SIGNAL send_state : std_logic_vector(2 DOWNTO 0);-每次按键给PC发送Welcome字符串,这是发送状态寄存器 SIGNAL cnt_delay : integer range 0 to 2*20-1;- std_logic_vector(19 DOWNTO 0);-延时去抖计数器 SIGNAL start_delaycnt : std_logic; - 开始延时计数标志 SIGNAL key_entry1 : std_log
9、ic; - 确定有键按下曛? SIGNAL key_entry2 : std_logic; - 确定有键按下标志 CONSTANT div_par : integer :=8; -for test :=clk_rate/(8*boud_rate); - 分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8 beginen =01010101 ;-7段数码管使能信号赋值txd = txd_reg ;PROCESS(clk,rstn)- delay counter BEGIN IF( rstn =0) THEN
10、cnt_delay = 0; start_delaycnt=0; - key_entry1 =0; ELSIF(clkEVENT AND clk = 1)THEN IF (key_entry2 =1) THEN - start transmit and clear key_entry1 key_entry1 =0; - ELSEIF (cnt_delay = 98) THEN IF ( key_input = 1) THEN key_entry1 = 1; END IF; END IF; END IF; IF (start_delaycnt = 1) THEN - key press IF (
11、cnt_delay 99 ) THEN -20D800000 cnt_delay = cnt_delay + 1; ELSE -rejudge key cnt_delay = 0; start_delaycnt =0; END IF; ELSE IF (key_input=1) AND (cnt_delay = 0) THEN-judge key press start start_delaycnt =1; END IF; END IF; END IF; END PROCESS; PROCESS(clk,rstn) -recycle counter分频得到8倍波特率的时钟 div_par BE
12、GIN IF (rstn =0) THEN div_reg = 0; clkbaud8x =0; ELSIF(clkEVENT AND clk=1)THEN IF (div_reg = div_par - 1) THEN div_reg = 0; clkbaud8x = NOT clkbaud8x; ELSE div_reg = div_reg + 1; END IF; END IF; END PROCESS; PROCESS(clkbaud8x,clkbaud8x,rstn) BEGIN IF (rstn =0) THEN div8_rec_reg = 000; div8_tras_reg = 000; ELSE IF(clkbaud8xEVENT AND clkbaud8x =1) THEN IF (recstart =1) THEN - 接收开始标志 div8_rec_reg = div8_rec_reg + 001;-接收开始后,时隙数在8倍波特率的时钟下加1循环 END IF; IF (trasstart =1) THEN