0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FPGA学习系列:28. 串口uart设计

FPGA学习交流 2018-08-14 12:05 次阅读

设计背景:

串口是串行接口的简称,也可称为串行通信接口通信协议是指通信双方的一种约定。约定包括对数据格式、同步方式、传送速度、传送步骤、检纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守。串口通信的两种最基本的方式为:同步串行通信方式和异步串行通信方式。

同步串行通信是指SPISerial Peripheral interface)的缩写,顾名思义就是串行外围设备接口。SPI是一种高速的全双工通信总线。封装芯片上总共有四根线,PCB布局布线也简单,所以现在很多芯片集成了这个协议。主要用于CPU和各种外围器件进行通信TRM450SPI接口。

异步串行通信是指UARTUniversal Asynchronous Receiver/Transmitter),通用异步接收/发送。UART是一个并行输入成为串行输出的芯片,通常集成在主板上。UART包含TTL电平的串口和RS232电平的串口。RS232也称标准串口,也是最常用的一种串行通讯接口。RS-232-C 标准对两个方面作了规定,即信号电平标准和控制信号线的定义。RS-232C 采用负逻辑规定逻辑电平,信号电平与通常的TTL电平也不兼容,RS-232-C -5V-15V 规定为1”,+5V+15V 规定为0”。


设计原理:

uart的示意图如下:


端口对应的功能表如下:


在设计过程中只需要关心RS232_TXD和RS232_RXD两个信号,RS232_TXD是数据发送端口,RS232_RXD是数据接收端口。

本设计将通过串口建立起计算机和实验板(ZX_1)之间的通信和控制关系,也就是通常所说的上下位机通信。要实现这样的通信,首先需要用到一个外部的电平转换芯片MAX232,其具体配置电路原理图如下

image.png


注解:

MAX232芯片是美信(MAXIM)公司专为RS-232标准串口设计的单电源电平转换芯片,使用+5v单电源供电

主要特点:

1、符合所有的RS-232C技术标准

2、只需要单一+5V电源供电

3、片载电荷泵具有升压、电压极性反转能力,能够产生+10V-10V电压V+V-

4、功耗低,典型供电电流5mA

5、内部集成2RS-232C驱动器

6、高集成度,片外最低只需4电容即可工作

本设计还需要分析在通信过程中,UART所对应的数据格式,

起始位:线路空闲时为高电平,当截获第一个低电平比特时,则为起始位;

信息位:在起始位之后,按照低位首发原则,顺序发送信息位的最低位到最高位,信息位的宽度可以是45678中的一个;

奇偶校验位:信息位之后则是一个可选的奇偶校验位,它可以是无校验(NONE)、奇校验(ODD)、偶校验(EVEN)中的任意一个,无校验时,信息位之后就是停止位。奇偶校验是,使得信息位和校验位的所有1的个数保持奇数或者偶数

停止位:停止位的长度可以是11.52中的任意一个,它为高电平;

空闲位:持续的高电平;

波特率:每秒传输的数据位(bit)数为波特率。RS-232-C的波特率可以是5075100150300600120024004800960019200波特。

通过分析上述的数据格式,在本设计中,将波特率设置为9600,起始位设置为1比特,信息位设置为8比特,奇偶校验位设置为0比特,停止位设置为2比特,空闲位设置为1比特

因为在设计中只需要关注RS232_TXDRS232_RXD这两个信号,,既然只有两条线,所以只需要关注其数据收发时序即可,时序图如下:

image.png


设计架构图:

设计架构图如下

image.png


uart_pll模块是一个锁相环,通过50M的外部时钟ref_clk),倍频得到100M的上游接口的100M系统时钟(sys_clk);divider模块为UART的分频模块,通过用100Msys_clk作为输入,分频得到波特率为9600uart_clk时钟。

transmitter模块为串口发送模块,并配合与其对应的trans_fifo发送数据缓存FIFO进行使用,将储存在FIFO中的数据通过RS232-C协议发送出去;

receiver模块为串口接收模块,并配合与其对应的rec_fifo接收数据缓存FIFO进行使用,将储存在FIFO中的数据通过RS232-C协议接收进来;


UART发送器(transmitter)设计

UART发送器的时序如下图:

image.png


根据对UART发送器时序的分析可以得到如下的状态转移表(SMF:

image.png


UART接收器receiver)设计

根据对UART时序的分析可以得到如下的状态转移表(SMF):

image.png


设计代码:

根据上述的两个状态转移表则可得到如下的代码,transmitter模块代码:

0//uart发送模块LSM(线性序列机)

1moduletransmitter(clk,rst_n,empty,data,rdreq,txd);

2

3inputclk,rst_n;//输入时钟复位

4inputempty;//来自fifo的输入空标志信号

5input[7:0]data;//来自fifo的输入数据

6outputregrdreq;//输出到fifo的读请求

7outputregtxd;//输出发送线信号

8

9reg[7:0]temp;//中间寄存器

10reg[7:0]count;//8位计数

11

12`defineEP 192//终止符

13

14always@(posedgeclk ornegedgerst_n)

15begin:lsm_2s1 //线性序列机一段闭节点

16if(!rst_n)//复位

17count <=`EP;

18elseif((count >=`EP)&&!empty)//计数大于终止符和非空(empty=0

19count <=0;

20elseif(count <`EP)//计数小于终止符

21count <=count +1;

22end

23

24always@(posedgeclk ornegedgerst_n)

25begin:lsm_2s2 //线性序列机一段闭节点

26if(!rst_n)//复位

27begin

28txd <=1;//发送线为高

29rdreq <=0;//读请求为0

30temp <=0;//中间寄存器为0

31end

32elseif((count >=`EP)&&!empty)//计数大于终止符fifo为非空,读请求拉高

33rdreq <=1;

34else

35case(count)

360:begin

37rdreq <=0;//读请求拉低

38txd <=0;

39end

401:temp[7:0]<=data[7:0];//输入数据给中间寄存器

411*16:txd <=temp[0];//中间寄存器按位给发送线发送

422*16:txd <=temp[1];

433*16:txd <=temp[2];

444*16:txd <=temp[3];

455*16:txd <=temp[4];

466*16:txd <=temp[5];

477*16:txd <=temp[6];

488*16:txd <=temp[7];

499*16:txd <=1;//拉高

50endcase

51end

52

53endmodule


transmitter(发送)模块的测试代码:

0`include"uart_lsm_head.v"

1

2moduletransmitter_tb;

3

4regclk,rst_n;

5regempty;

6reg[7:0]data;

7wirerdreq;

8wiretxd;

9

10reg[7:0]temp;

11

12transmitter transmitter_dut(

13.clk(clk),

14.rst_n(rst_n),

15.empty(empty),

16.data(data),

17.rdreq(rdreq),

18.txd(txd)

19);

20

21initialbegin

22clk =1;

23rst_n =0;

24data =0;

25empty =1;

26temp =0;

27#200.1rst_n =1;

28

29#200.1empty=1;temp=8'h55;

30#`TBAUD_RATE

31data[0]=temp[0];//发送第一个信息位(LSB

32#`TBAUD_RATE

33data[1]=temp[1];

34#`TBAUD_RATE

35data[2]=temp[2];

36#`TBAUD_RATE

37data[3]=temp[3];

38#`TBAUD_RATE

39data[4]=temp[4];

40#`TBAUD_RATE

41data[5]=temp[5];

42#`TBAUD_RATE

43data[6]=temp[6];

44#`TBAUD_RATE

45data[7]=temp[7];

46#`TBAUD_RATE

47empty =0;

48#2000$stop;

49end

50

51always#`TUART_CLK_HALFclk =~clk;

52

53endmodule


receiver模块代码:

0`include"uart_lsm_head.v"

1

2modulereceiver(clk,rst_n,data,wrreq,rxd);//uart接收模块LSM(线性序列机)

3

4inputclk,rst_n;//输入时钟复位

5outputreg[7:0]data;//输出数据

6outputregwrreq;//输出写请求

7inputrxd;//输入接收线信号

8

9reg[7:0]count;

10//宏定义

11`defineEP 184//终止符

12`defineGET0 24

13`defineGET1 `GET0+16

14`defineGET2 `GET1+16

15`defineGET3 `GET2+16

16`defineGET4 `GET3+16

17`defineGET5 `GET4+16

18`defineGET6 `GET5+16

19`defineGET7 `GET6+16

20`defineGETW `GET7+16//wrreq=1

21`defineGLRW `GETW+1//wrreq=0

22

23always@(posedgeclk ornegedgerst_n)

24begin:lsm_2s1 //线性序列机一段闭节点

25if(!rst_n)

26count <=`EP;

27elseif((count >=`EP)&&!rxd)//rxd=0

28count <=0;

29elseif(count <`EP)

30count <=count +1;

31end

32

33always@(posedgeclk ornegedgerst_n)

34begin:lsm_2s2 //线性序列机二段闭节点

35if(!rst_n)

36begin

37data <=0;

38wrreq <=0;//写请求为0

39end

40else

41case(count)

42`GET0:data[0]<=rxd;//将接收的数据通过data输出

43`GET1:data[1]<=rxd;

44`GET2:data[2]<=rxd;

45`GET3:data[3]<=rxd;

46`GET4:data[4]<=rxd;

47`GET5:data[5]<=rxd;

48`GET6:data[6]<=rxd;

49`GET7:data[7]<=rxd;

50`GETW:wrreq <=1;//写请求拉高一拍,写进fifo

51`GLRW:wrreq <=0;//一拍后写请求为0

52endcase

53end

54

55endmodule


receiver(接收)模块的测试代码:

0`include"uart_lsm_head.v"

1

2modulereceiver_tb;

3

4regclk,rst_n;

5regrxd;

6wire[7:0]data;

7wirewrreq;

8

9reg[7:0]temp;//8位的中间寄存器,产生激励

10

11receiver receiver_dut(

12.clk(clk),

13.rst_n(rst_n),

14.data(data),

15.wrreq(wrreq),

16.rxd(rxd)

17);

18

19initialbegin

20clk =1;

21rst_n =0;

22temp =0;

23rxd =1;

24#`TEN_TUART_CLK//*代表异步 //10uart_clk周期

25rst_n =1;

26

27#`TEN_TUART_CLK//启动一个停止位

28rxd =0;

29temp =8'h55;

30#`TBAUD_RATE//数据使用波特率的周期

31rxd =temp[0];//发送一个信息位(LSB

32#`TBAUD_RATE

33rxd =temp[1];

34#`TBAUD_RATE

35rxd =temp[2];

36#`TBAUD_RATE

37rxd =temp[3];

38#`TBAUD_RATE

39rxd =temp[4];

40#`TBAUD_RATE

41rxd =temp[5];

42#`TBAUD_RATE

43rxd =temp[6];

44#`TBAUD_RATE

45rxd =temp[7];//发送最后一个信息位(HSB

46#`TBAUD_RATE

47rxd =1;

48

49#`TUART_CLK100$stop;//100uart_clk周期

50end

51

52always#`TUART_CLK_HALFclk =~clk;// uart_clk 的时钟,使用uart_clk的半周期

53

54endmodule


参数宏的头文件代码:

0/////uart_lsm_head.v

1

2//////////定义时标////////////

3`timescale1us/1ns

4

5/////////定义设计参数/////////

6`defineBAUD_RATE 9600//波特率=9600

7`defineSYS_CLK 100000000//系统时钟sys_clk 频率=100M

8`defineREF_CLK 50000000//系统时钟ref_clk频率=50M

9

10//////////使用宏自动计算的诸参数////////////

11`defineTBAUD_RATE (1000000.0/`BAUD_RATE)//波特率周期

12`defineUART_CLK (16*`BAUD_RATE)//uart_clk 等于16倍波特率

13`defineTUART_CLK (1000000.0/`UART_CLK)//uart_clk周期

14`defineTEN_TUART_CLK (10.0*`TUART_CLK)//10uart_clk周期

15`defineTUART_CLK100 (100.0*`TUART_CLK)//100uart_clk周期

16

17`defineTUART_CLK_HALF (`TUART_CLK/2.0)//uart_clk半周期

18`defineTREF_CLK (1000000.0/`REF_CLK)//参考时钟周期

19`defineTREF_CLK_HALF (`TREF_CLK/2.0)//参考时钟半周期

20

21//////////使用宏自动计算的分频数(占空比50%////////////

22`defineDW (`SYS_CLK/(2*`UART_CLK))


顶层文件代码:

0`include"uart_lsm_head.v"

1

2moduleuart_lsm(ref_clk,global_reset,tdata,twrreq,

3tfull,rdata,rrdreq,rempty,uart_txd,uart_rxd);

4

5inputref_clk,global_reset;//全局时钟复位

6input[7:0]tdata;//发送fifo输入数据

7inputtwrreq;//发送fifo写请求

8outputtfull;//发送fifo输出写满

9output[7:0]rdata;//接收fifo输出数据

10inputrrdreq;//接收fifo的输入读请求

11outputrempty;//接收fifo的输出入空

12outputuart_txd;//输出发送线信号

13inputuart_rxd;//输入接收线信号

14

15wiretrxd;

16

17wire[7:0]tf_data,rf_data;

18wiretf_rdreq,tf_empty,rf_wrreq;

19wiresys_clk,uart_clk,rst_n;

20

21

22assignrst_n =~global_reset;

23

24trans_fifo t_fifo(//发送fifo

25.data(tdata),

26.rdclk(uart_clk),

27.rdreq(tf_rdreq),

28.wrclk(sys_clk),

29.wrreq(twrreq),

30.q(tf_data),

31.rdempty(tf_empty),

32.wrfull(tfull)

33);

34

35transmitter trans(//发送模块

36.clk(uart_clk),

37.rst_n(rst_n),

38.empty(tf_empty),

39.data(tf_data),

40.rdreq(tf_rdreq),

41.txd(trxd)

42);

43

44rec_fifo r_fifo(//接收fifo

45.data(rf_data),

46.rdclk(sys_clk),

47.rdreq(rrdreq),

48.wrclk(uart_clk),

49.wrreq(rf_wrreq),

50.q(rdata),

51.rdempty(rempty)

52);

53

54receiver rece(//接收模块

55.clk(uart_clk),

56.rst_n(rst_n),

57.data(rf_data),

58.wrreq(rfwrreq),

59.rxd(trxd)

60);

61

62uart_pll u_pll(//锁相环产生系统时钟,作用于fifodivider

63.areset(global_reset),

64.inclk0(ref_clk),

65.c0(sys_clk)

66);

67

68divider_ebd_1s_mealy //分频模块分频uart_clk,作用于receiver transmitter

69#(.HW(`DW),.LW(`DW))

70div(

71.clk_in(sys_clk),

72.rst_n(rst_n),

73.clk_out(uart_clk)

74);

75

76endmodule

仿真:

分别为发送和接收做仿真测试,发送的仿真波形如下:

image.png


接收的仿真波形如下:

image.png


根据以上两个仿真波形,可以发现设计是正确的,之后则可利用串口猎人的上位机软件,实现自发自收。




声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1626

    文章

    21679

    浏览量

    602144
收藏 人收藏

    评论

    相关推荐

    通信技术:UART串口通信开源代码实操!

    今天我们分享的是关于UART串口通信示例,欢迎大家探讨
    的头像 发表于 11-05 11:56 2832次阅读
    通信技术:<b class='flag-5'>UART</b><b class='flag-5'>串口</b>通信开源代码实操!

    UART串口通信示例:开启通信宝藏之门的定位模组LuatOS入门

    今天我们要讲解的是UART串口通信示例,关于Air201资产定位模组LuatOS入门,我会从搭建环境、代码烧录、示例效果等来细说:
    的头像 发表于 11-03 19:55 803次阅读
    <b class='flag-5'>UART</b><b class='flag-5'>串口</b>通信示例:开启通信宝藏之门的定位模组LuatOS入门

    FPGA加速深度学习模型的案例

    FPGA(现场可编程门阵列)加速深度学习模型是当前硬件加速领域的一个热门研究方向。以下是一些FPGA加速深度学习模型的案例: 一、基于FPGA
    的头像 发表于 10-25 09:22 158次阅读

    uart波特率和传输频率的关系 UART串口的常用波特率为多少

    频率是两个关键参数,它们之间存在一定的关系,并且UART串口有一系列常用的波特率。以下是对这两个概念的介绍。 一、UART波特率和传输频率的关系 1. 定义与区别 波特率(Baud R
    的头像 发表于 10-06 16:12 1909次阅读
    <b class='flag-5'>uart</b>波特率和传输频率的关系 <b class='flag-5'>UART</b><b class='flag-5'>串口</b>的常用波特率为多少

    F28M35x串口在线升级设计

    电子发烧友网站提供《F28M35x串口在线升级设计.pdf》资料免费下载
    发表于 09-02 10:58 0次下载
    F<b class='flag-5'>28</b>M35x<b class='flag-5'>串口</b>在线升级设计

    迪文串口屏基础GUI开发流程

    一前言手头有一款闲置串口屏,其型号为,是一款7寸800*480分辨率的电容触摸屏。这款屏幕是支持6~36V供电的,自带3个串口输出,分别是UART2,UART4,
    的头像 发表于 07-05 08:21 634次阅读
    迪文<b class='flag-5'>串口</b>屏基础GUI开发流程

    珠海錾芯实现28纳米FPGA流片

    近日,珠海錾芯半导体有限公司在其官方微博上宣布,已成功实现28纳米流片。此次流片成功的CERES-1 FPGA芯片,不仅对标国际主流28纳米FPGA架构,还实现了管脚和比特流的完全兼容
    的头像 发表于 06-03 11:11 775次阅读

    串口屏可以做什么简单的作品

    学习串口屏(通常指的是通过串行接口(如UART、SPI等)与微控制器通信的显示屏)后,你可以制作多种简单的作品。
    的头像 发表于 05-09 10:13 411次阅读
    学<b class='flag-5'>串口</b>屏可以做什么简单的作品

    UART串口通信协议是什么?

    UART (Universal Asynchronous Receiver/Transmitter) 是一种通信接口协议,用于实现串口通信。它是一种简单的、可靠的、广泛应用的串口通信协议。它是由美国
    的头像 发表于 03-19 17:26 1279次阅读

    fpga芯片系列介绍

    FPGA芯片系列众多,不同厂商会推出各具特色的产品系列以满足不同的应用需求。以下是一些主要的FPGA芯片系列
    的头像 发表于 03-14 16:15 1215次阅读

    fpga学习需要具备哪些课程

    FPGA(Field Programmable Gate Array)学习需要具备一系列的课程知识和实践技能
    的头像 发表于 03-14 15:51 1145次阅读

    蓝牙串口通讯总线——I2C/SPI/UART

    嵌入式工程师在做串口通信调试工作的时候,会经常用到I2C、SPI、UART这3条总线,I2C、SPI、UART这三种通信总线在嵌入式领域很常见,目前主流的SOC芯片都内置了这三种总线的控制器,各种
    的头像 发表于 01-22 09:41 1506次阅读
    蓝牙<b class='flag-5'>串口</b>通讯总线——I2C/SPI/<b class='flag-5'>UART</b>

    常见通信的底层数据传输原理(UART、SPI、I2C)

    UART:Universal Asynchronous Receiver/Transmitter,通用异步收发传输器。 UART串口是最常见的一种串口通信,下面是
    发表于 01-15 10:41 834次阅读
    常见通信的底层数据传输原理(<b class='flag-5'>UART</b>、SPI、I2C)

    学习FPGA必须知道的社区

    学习FPGA必须知道的社区
    的头像 发表于 01-03 17:51 361次阅读
    <b class='flag-5'>学习</b><b class='flag-5'>FPGA</b>必须知道的社区

    什么是串口(UART)?串口的组成和FPGA实现

    串口作为常用的三大低速总线(UART、SPI、IIC)之一,在设计众多通信接口和调试时占有重要地位。
    的头像 发表于 01-03 11:43 1.4w次阅读
    什么是<b class='flag-5'>串口</b>(<b class='flag-5'>UART</b>)?<b class='flag-5'>串口</b>的组成和<b class='flag-5'>FPGA</b>实现