基于VHDL的串口通信程序

来源:本站
导读:目前正在解读《基于VHDL的串口通信程序》的相关信息,《基于VHDL的串口通信程序》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《基于VHDL的串口通信程序》的详细说明。
简介:本模块的功能是验证实现和PC机进行基本的串口通信的功能。需要在PC机上安装一个串口调试工具来验证程序的功能。 程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控制器,10个bit是1位起始位,8个数据位,1个结束位。

串口的波特律由程序中定义的p_par参数决定,更改该参数可以实现相应的波特率。程序当前设定的p_par 的值是0x104,对应的波特率是9600。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间,划分为8个时隙以使通信同步.

程序的工作过程是:串口处于全双工工作状态,按动key2,CPLD向PC发送皐elcome"字符串(串口调试工具设成按ASCII码接受方式);PC可随时向CPLD发送0-F的十六进制数据,CPLD接受后显示在7段数码管上。

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY UART IS

PORT (

clk : IN std_logic;

rst : IN std_logic;

rxd : IN std_logic; --串行数据接收端

txd : OUT std_logic; --串行数据发送端

en : OUT std_logic_vector(7 downto 0); -- 数码管使能

seg_data : OUT std_logic_vector(7 DOWNTO 0); --数码管数据

key_input : IN std_logic --按键输入

);

END UART;

ARCHITECTURE arch OF UART IS

--//////////////////inner reg////////////////////

SIGNAL p_reg : std_logic_vector(15 DOWNTO 0);--分频计数器,分频值由波特率决定。分频后得到频率8倍波特率的时钟

SIGNAL p8_tras_reg : std_logic_vector(2 DOWNTO 0);--该寄存器的计数值对应发送时当前位于的时隙数

SIGNAL p8_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 : std_logic; --以8倍波特率为频率的时钟,它的作用是将发送或接受一个bit的时钟周期分为8个时隙

SIGNAL recstart : std_logic; -- 开始发送标志

SIGNAL recstart_tmp : std_logic; --开始接受标志

SIGNAL trasstart : std_logic;

SIGNAL rxd_reg1 : std_logic; --接收寄存器1

SIGNAL rxd_reg2 : std_logic; --接收寄存器2,因为接收数据为异步信号,故用两级缓存

SIGNAL txd_reg : std_logic; --发送寄存器

SIGNAL rxd_buf : std_logic_vector(7 DOWNTO 0);--接受数据缓存

SIGNAL txd_buf : std_logic_vector(7 DOWNTO 0);--发送数据缓存

SIGNAL send_state : std_logic_vector(2 DOWNTO 0);--每次按键给PC发送"Welcome"字符串,这是发送状态寄存器

SIGNAL cnt_delay : std_logic_vector(19 DOWNTO 0);--延时去抖计数器

SIGNAL start_delaycnt : std_logic; --开始延时计数标志

SIGNAL key_entry1 : std_logic; --确定有键按下曛?

SIGNAL key_entry2 : std_logic; --确定有键按下标志

--//////////////////////////////////////////////

CONSTANT p_par : std_logic_vector(15 DOWNTO 0) := "0000000100000100";

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

SIGNAL txd_xhdl3 : std_logic;

BEGIN

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

txd <= txd_xhdl3;

txd_xhdl3 <= txd_reg ;

PROCESS(clk,rst)

BEGIN

IF (NOT rst = '1') THEN

cnt_delay <= "00000000000000000000";

start_delaycnt <= '0';

ELSIF(clk'EVENT AND clk='1')THEN

IF (start_delaycnt = '1') THEN

IF (cnt_delay /= "11000011010100000000") THEN

cnt_delay <= cnt_delay + "00000000000000000001";

ELSE

cnt_delay <= "00000000000000000000";

start_delaycnt <= '0';

END IF;

ELSE

IF ((NOT key_input='1') AND (cnt_delay = "00000000000000000000")) THEN

start_delaycnt <= '1';

END IF;

END IF;

END IF;

END PROCESS;

PROCESS(clk,rst)

BEGIN

IF (NOT rst = '1') THEN

key_entry1 <= '0';

ELSIF(clk'EVENT AND clk='1')THEN

IF (key_entry2 = '1') THEN

key_entry1 <= '0';

ELSE

IF (cnt_delay = "11000011010100000000") THEN

IF (NOT key_input = '1') THEN

key_entry1 <= '1';

END IF;

END IF;

END IF;

END IF;

END PROCESS;

PROCESS(clk,rst)

BEGIN

IF (NOT rst = '1') THEN

p_reg <= "0000000000000000";

ELSIF(clk'EVENT AND clk='1')THEN

IF (p_reg = p_par - "0000000000000001") THEN

p_reg <= "0000000000000000";

ELSE

p_reg <= p_reg + "0000000000000001";

END IF;

END IF;

END PROCESS;

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

BEGIN

IF (NOT rst = '1') THEN

clkbaud8x <= '0';

ELSIF(clk'EVENT AND clk='1')THEN

IF (p_reg = p_par - "0000000000000001") THEN

clkbaud8x <= NOT clkbaud8x;

END IF;

END IF;

END PROCESS;

PROCESS(clkbaud8x,rst)

BEGIN

IF (NOT rst = '1') THEN

p8_rec_reg <= "000";

ELSE IF(clkbaud8x'EVENT AND clkbaud8x = '1') THEN

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

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

END IF;

END IF;

END IF;

END PROCESS;

PROCESS(clkbaud8x,rst)

BEGIN

IF (NOT rst = '1') THEN

p8_tras_reg <= "000";

ELSE IF(clkbaud8x'EVENT AND clkbaud8x = '1') THEN

IF (trasstart = '1') THEN

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

END IF;

END IF;

END IF;

END PROCESS;

PROCESS(p8_rec_reg)

BEGIN

IF (p8_rec_reg = "111") THEN

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

ELSE

clkbaud_rec <= '0';

END IF;

END PROCESS;

PROCESS(p8_tras_reg)

BEGIN

IF (p8_tras_reg = "111") THEN

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

ELSE

clkbaud_tras <= '0';

END IF;

END PROCESS;

PROCESS(clkbaud8x,rst)

BEGIN

IF (NOT rst = '1') THEN

txd_reg <= '1';

trasstart <= '0';

txd_buf <= "00000000";

state_tras <= "0000";

send_state <= "000";

key_entry2 <= '0';

ELSE IF(clkbaud8x'EVENT AND clkbaud8x = '1') THEN

IF (NOT key_entry2 = '1') THEN

IF (key_entry1 = '1') THEN

key_entry2 <= '1';

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

END IF;

ELSE

CASE state_tras IS

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

IF ((NOT trasstart='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";

END IF;

ELSE

key_entry2 <= '0';

state_tras <= "0000";

END IF;

END IF;

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

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "0010" => --发送第2位

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "0011" => --发送第3位

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "0100" => --发送第4位

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "0101" => --发送第5位

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "0110" => --发送第6位

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "0111" => --发送第7位

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "1000" => --发送第8位

IF (clkbaud_tras = '1') THEN

txd_reg <= txd_buf(0);

txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);

state_tras <= state_tras + "0001";

END IF;

WHEN "1001" => --发送停止位

IF (clkbaud_tras = '1') THEN

txd_reg <= '1';

txd_buf <= "01010101";

state_tras <= state_tras + "0001";

END IF;

WHEN "1111" =>

IF (clkbaud_tras = '1') THEN

state_tras <= state_tras + "0001";

send_state <= send_state + "001";

trasstart <= '0';

CASE send_state IS

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"

WHEN OTHERS =>

txd_buf <= "00000000";

END CASE;

END IF;

WHEN OTHERS =>

IF (clkbaud_tras = '1') THEN

state_tras <= state_tras + "0001";

trasstart <= '1';

END IF;

END CASE;

END IF;

END IF;

END IF;

END PROCESS;

PROCESS(clkbaud8x,rst) --接受PC机的数据

BEGIN

IF (NOT rst = '1') THEN

rxd_reg1 <= '0';

rxd_reg2 <= '0';

rxd_buf <= "00000000";

state_rec <= "0000";

recstart <= '0';

recstart_tmp <= '0';

ELSE IF(clkbaud8x'EVENT AND clkbaud8x = '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 ((NOT rxd_reg1 AND rxd_reg2) = '1') THEN --检测到起始位的下降沿,进入接受状态

recstart_tmp <= '1';

END IF;

END IF;

ELSE

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

IF (clkbaud_rec = '1') THEN

rxd_buf(7) <= rxd_reg2;

rxd_buf(6 DOWNTO 0) <= rxd_buf(7 DOWNTO 1);

state_rec <= state_rec + "0001";

END IF;

ELSE

IF (state_rec = "1001") THEN

IF (clkbaud_rec = '1') THEN

state_rec <= "0000";

recstart <= '0';

END IF;

END IF;

END IF;

END IF;

END IF;

END IF;

END PROCESS;

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

BEGIN

CASE rxd_buf IS

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

&nbs p; 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

WHEN OTHERS =>

seg_data <= "11111111";

END CASE;

END PROCESS;

END arch;

提醒:《基于VHDL的串口通信程序》最后刷新时间 2024-03-14 01:15:48,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《基于VHDL的串口通信程序》该内容的真实性请自行鉴别。