设计背景:
串口是串行接口的简称,也可称为串行通信接口。通信协议是指通信双方的一种约定。约定包括对数据格式、同步方式、传送速度、传送步骤、检纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守。串口通信的两种最基本的方式为:同步串行通信方式和异步串行通信方式。
同步串行通信是指SPI(Serial Peripheral interface)的缩写,顾名思义就是串行外围设备接口。SPI是一种高速的全双工通信总线。封装芯片上总共有四根线,PCB布局布线也简单,所以现在很多芯片集成了这个协议。主要用于CPU和各种外围器件进行通信,TRM450是SPI接口。
异步串行通信是指UART(Universal Asynchronous Receiver/Transmitter),通用异步接收/发送。UART是一个并行输入成为串行输出的芯片,通常集成在主板上。UART包含TTL电平的串口和RS232电平的串口。RS232也称标准串口,也是最常用的一种串行通讯接口。RS-232-C 标准对两个方面作了规定,即信号电平标准和控制信号线的定义。RS-232-C 采用负逻辑规定逻辑电平,信号电平与通常的TTL电平也不兼容,RS-232-C 将-5V~-15V 规定为“1”,+5V~+15V 规定为“0”。
设计原理:
uart的示意图如下:
其端口对应的功能表如下:
在设计过程中只需要关心RS232_TXD和RS232_RXD两个信号,RS232_TXD是数据发送端口,RS232_RXD是数据接收端口。
本设计将通过串口建立起计算机和实验板(ZX_1)之间的通信和控制关系,也就是通常所说的上下位机通信。要实现这样的通信,首先需要用到一个外部的电平转换芯片MAX232,其具体配置电路原理图如下:
注解:
MAX232芯片是美信(MAXIM)公司专为RS-232标准串口设计的单电源电平转换芯片,使用+5v单电源供电。
主要特点:
1、符合所有的RS-232C技术标准;
2、只需要单一+5V电源供电;
3、片载电荷泵具有升压、电压极性反转能力,能够产生+10V和-10V电压V+、V-;
4、功耗低,典型供电电流5mA;
5、内部集成2个RS-232C驱动器;
6、高集成度,片外最低只需4个电容即可工作。
本设计还需要分析在通信过程中,UART所对应的数据格式,
起始位:线路空闲时为高电平,当截获第一个低电平比特时,则为起始位;
信息位:在起始位之后,按照低位首发原则,顺序发送信息位的最低位到最高位,信息位的宽度可以是4、5、6、7、8中的一个;
奇偶校验位:信息位之后则是一个可选的奇偶校验位,它可以是无校验(NONE)、奇校验(ODD)、偶校验(EVEN)中的任意一个,无校验时,信息位之后就是停止位。奇偶校验是,使得信息位和校验位的所有1的个数保持奇数或者偶数位;
停止位:停止位的长度可以是1、1.5或2中的任意一个,它为高电平;
空闲位:持续的高电平;
波特率:每秒传输的数据位(bit)数为波特率。RS-232-C的波特率可以是50、75、100、150、300、600、1200、2400、4800、9600、19200波特。
通过分析上述的数据格式,在本设计中,将波特率设置为9600,起始位设置为1比特,信息位设置为8比特,奇偶校验位设置为0比特,停止位设置为2比特,空闲位设置为1比特
因为在设计中只需要关注RS232_TXD和RS232_RXD这两个信号,,既然只有两条线,所以只需要关注其数据收发时序即可,时序图如下:
设计架构图:
设计架构图如下:
uart_pll模块是一个锁相环,通过50M的外部时钟(ref_clk),倍频得到100M的上游接口的100M系统时钟(sys_clk);divider模块为UART的分频模块,通过用100M的sys_clk作为输入,分频得到波特率为9600的uart_clk时钟。
transmitter模块为串口发送模块,并配合与其对应的trans_fifo发送数据缓存FIFO进行使用,将储存在FIFO中的数据通过RS232-C协议发送出去;
receiver模块为串口接收模块,并配合与其对应的rec_fifo接收数据缓存FIFO进行使用,将储存在FIFO中的数据通过RS232-C协议接收进来;
UART发送器(transmitter)设计
UART发送器的时序如下图:
根据对UART发送器时序的分析可以得到如下的状态转移表(SMF):
UART接收器(receiver)设计
根据对UART时序的分析可以得到如下的状态转移表(SMF):
设计代码:
根据上述的两个状态转移表则可得到如下的代码,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//*代表异步 //10倍uart_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;//100倍uart_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)//10倍uart_clk周期
15`defineTUART_CLK100 (100.0*`TUART_CLK)//100倍uart_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(//锁相环产生系统时钟,作用于fifo、divider
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
仿真图:
分别为发送和接收做仿真测试,发送的仿真波形如下:
接收的仿真波形如下:
根据以上两个仿真波形,可以发现设计是正确的,之后则可利用串口猎人的上位机软件,实现自发自收。
-
FPGA
+关注
关注
1626文章
21679浏览量
602144
发布评论请先 登录
相关推荐
评论