基于FPGA的串口实验(共13页)_第1页
基于FPGA的串口实验(共13页)_第2页
基于FPGA的串口实验(共13页)_第3页
基于FPGA的串口实验(共13页)_第4页
基于FPGA的串口实验(共13页)_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精选优质文档-倾情为你奉上 基于Verilog的串口实验报告 一、 前言 随着计系统和网络的快速发展,通信 发挥的作用越来越重要。在电路设计和制 作上越来越多的采用数字化指令 , 在一 个系统内对外和内部通信越来越多。串行 通信作为一种主要的通信方式 , 由于所用 的传输线少 , 因此特别适合于远距离传 送 , 应用非常广泛。FPGA(现场可编程门 阵列)在数字电路的设计中已经被广泛使 用。这种设计方式可以增强系统的可靠性 和设计的灵活性。二、 实验内容本实验使用Verilog编写rs232串口通信程序,利用波形仿真工具进行前仿真,下载到开发板,利用串口调试助手进行验证。本串口实现的功能是可以

2、设置八种波特率,实现多字节的收发。实验芯片选择xilinx的spartan6系列,编译软件使用xilinx专用的ise14.1,仿真工具使用ise自带工具isim。三、 实验过程 (1)、分模块编写代码,本次设计共有四个模块,分别是串口接收波特率产生模块,串口接收模块,串口发送波特率产生模块,串口发送模块。以下是各模块之间的联系图:由图所示,顶层各端口功能如下Key_in按键选择波特率端口Clk时钟输入端口Rst_n复位端口Rs232_rx数据接收端口Rs232_tx数据发出端口顶层文件主要用于连接以下各个模块接收数据波特率产生模块端口功能如下Key_in按键选择波特率端口Bps_start启

3、动波特率发生模块Clk时钟端口Rst_n复位端口Sample_clk波特率时钟输出端口 本模块的作用主要用于产生所需的波特率,共有八种选择,本模块的内部又有以下几个部分:1、波特率选择部分:这一部分主要通过按键输入控制波特率,由case语句完成2、波特率时钟计数部分:这一部分主要是通过计数器对输入时钟进行分频来达到所需的波特率。3、波特率时钟产生部分:这一部分用来产生连接下一模块的波特率时钟。串口接收模块Clk时钟端口Rst_n复位端口Rs232_rx数据输入端口Sample_clk波特率时钟输入端口Rx_data数据存储寄存器Bps_start启动波特率发生模块端口Rx_int发送模块使能端

4、口本模块的作用主要是根据波特率时钟产生模块所产生的波特率,进行数据的接收,包含如下几个部分1、检测数据开始位:这一部分主要依据数据帧的起始位为0这一设置,通过检测下降沿来检测数据的开始位,当检测到下降沿后,发出一系列开始接收数据的信号。2、数据接收部分:这一部分主要通过波特率来采样数据,每一个数据采样九次,选取其中的三次经过加和来判断本位是0还是1。3、数据存储部分:这一部分主要把接收到的数据存储到设定的寄存器中,以便发送。串口发送波特率产生模块Key_in按键选择波特率端口Bps_start启动波特率发生模块(由串口发送模块产生)Clk时钟端口Rst_n复位端口Sample_clk波特率时钟

5、输出端口本模块的作用主要用于产生所需的波特率,共有八种选择,本模块的内部又有以下几个部分:1、波特率选择部分:这一部分主要通过按键输入控制波特率,由case语句完成2、波特率时钟计数部分:这一部分主要是通过计数器对输入时钟进行分频来达到所需的波特率。3、波特率时钟产生部分:这一部分用来产生连接下一模块的波特率时钟。串口发送模块Clk时钟端口Rst_n复位端口Rs232_tx数据输出端口Clk_bps波特率时钟输入端口Rx_data数据存储寄存器Bps_start启动波特率发生模块端口Rx_int发送模块使能端口(由串口接收模块产生)这一模块分为以下几个部分:1,、检测发送使能信号部分:这一部分

6、通过检测下降沿来识别发送使能信号,并产生一系列的发送开始信号。2、发送帧部分:这一部分主要将之前存储在寄存器中的数据逐位发送出去,并加入开始位0,与结束位1,构成一帧十位数据。通过对各个模块的了解,分别编写各个模块的代码(2)、修改程序,编写仿真程序。由于本次实验代码量较小,仿真时采用ise自带的波形仿真工具即可完成仿真,仿真图如下波形为任意两帧数据的接收与发送,可以看出连续两帧数据接收与发送并没有发生错误。(3)、将程序下载到芯片,结合串口助手进行验证。四、实验代码顶层代码:module uart_top(clk,rst_n,rs232_rx,rs232_tx,key_in); input

7、clk; /时钟信号50M input rst_n; /复位信号,低有效 input rs232_rx; /数据输入信号 input 2:0key_in; output rs232_tx; /数据输出信号/ wire 2:0key_in; wire sample_clk1; wire bps_start1,bps_start2;/ wire clk_bps1,clk_bps2; wire 7:0rx_data;/接收数据存储器,用来存储接收到的数据,直到下一个数据接收 wire rx_int; /接收数据中断信号,接收过程中一直为高, /子模块端口申明/speed_select_rx spee

8、d_rx( /数据接收波特率选择模块 .clk(clk), .rst_n(rst_n), .bps_start(bps_start1), .sample_clk(sample_clk1),/这一个时钟是九分之一波特率时钟.key_in(key_in)/用来选择波特率 ); uart_rx uart_rx( /数据接收模块 .clk(clk), .rst_n(rst_n), .bps_start(bps_start1),/这一个信号用来控制波特率发生器的开启,当检测到输入数据中的下降沿后,开始波特率计数 .sample_clk(sample_clk1), .rs232_rx(rs232_rx),

9、/数据输入端口 .rx_data(rx_data),/数据输入后存储寄存器 .rx_int(rx_int)/这一信号用来表示数据接收完成,接受过程是高,接收完成后变为低,发送模块用此信号来判断是否可以发送 );speed_select_tx speed_tx( /数据发送波特率控制模块 .clk(clk), .rst_n(rst_n), .bps_start(bps_start2),/ .clk_bps(clk_bps2),/发送数据波特率生成端口.key_in(key_in) ); uart_tx uart_tx( .clk(clk), .rst_n(rst_n), .bps_start(b

10、ps_start2),/当检测到int下降沿以后开始启动 .clk_bps(clk_bps2), .rs232_tx(rs232_tx),/接收数据存储寄存器 .rx_data(rx_data), .rx_int(rx_int)/这个是波特率开始发送的标志,由串口接收模块产生 );endmodule接收模块波特率发生器:module speed_select_rx(clk,rst_n,bps_start,key_in,sample_clk);/波特率设定 input clk; /50M时钟 input rst_n; /复位信号 input bps_start; input 2:0key_in;

11、 /接收到信号以后,波特率时钟信号置位,当接收到uart_rx传来的信号以后,模块开始运行/ output clk_bps; /接收数据中间采样点, output sample_clk;/ define BPS_PARA 5207;/9600波特率分频计数值/ define BPS_PARA_2 2603;/计数一半时采样 reg sample_clk; reg13:0 cnt;/分频计数器 reg clk_bps_r;/波特率时钟寄存器 reg13:0cntt; parameter system_clk = 50_000_000; /*输入时钟频率设定,默认50M*/localparam b

12、ps9600 = system_clk/9600/9 - 1;localparam bps19200 = system_clk/19200/9 - 1;localparam bps38400 = system_clk/38400/9 - 1;localparam bps57600 = system_clk/57600/9 - 1;localparam bps = system_clk/9 - 1;localparam bps = system_clk/9 - 1;localparam bps = system_clk/9 - 1;localparam bps = system_clk/9 -

13、1;/*选择波特率部分程序*/always(posedge clk or negedge rst_n)if(!rst_n)begincntt <= bps9600;/*复位时波特率默认为9600bps*/endelse begincase(key_in)/*根据波特率控制信号选择不同的波特率计数器计数最大值*/3'd0: cntt <= bps9600;3'd1: cntt <= bps19200;3'd2: cntt <= bps38400;3'd3: cntt <= bps57600;3'd4: cntt <= b

14、ps;3'd5: cntt <= bps;3'd6: cntt <= bps;3'd7: cntt <= bps;default: cntt<= bps9600;endcaseend /*波特率时钟计数器工作*/ always (posedge clk or negedge rst_n) begin if(!rst_n) cnt<=13'd0; else if(cnt=cntt)| !bps_start)/判断计数是否达到1个脉宽 cnt<=13'd0; else cnt<=cnt+1'b1;/波特率时钟

15、启动end /*产生波特率时钟*/ always(posedge clk or negedge rst_n)beginif(!rst_n)sample_clk<=0;else if(cnt=1)sample_clk<=1;elsesample_clk<=0;endendmodule接收模块:module uart_rx( clk, rst_n, bps_start, sample_clk, rs232_rx, rx_data, rx_int ); input clk; /时钟 input rst_n; /复位 input rs232_rx; /接收数据信号 input sam

16、ple_clk; /九倍波特率采样点 output bps_start; /接收信号时,波特率时钟信号置位 output 7:0 rx_data;/接收数据寄存器 output rx_int; /接收数据中断信号,接收过程中为高 reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3;/接收数据寄存器 reg 7:0rx_data; reg 1:0 Data_Tmp7:0; reg rx_int; wire neg_rs232_rx;/表示数据线接收到下沿 /*检测下降沿*/ always (posedge clk or negedge rst_n) begin

17、 if(!rst_n) begin rs232_rx0 <= 1'b0; rs232_rx1 <= 1'b0; rs232_rx2 <= 1'b0; rs232_rx3 <= 1'b0; end else begin rs232_rx0 <= rs232_rx; rs232_rx1 <= rs232_rx0; rs232_rx2 <= rs232_rx1; rs232_rx3 <= rs232_rx2; endendassign neg_rs232_rx = rs232_rx3 & rs232_rx2 &a

18、mp; rs232_rx1 & rs232_rx0;/串口传输线的下沿标志reg bps_start;/波特率发生器的使能信号reg clk_en; /*产生一些控制信号*/reg6:0sample_clk_cnt;always (posedge clk or negedge rst_n)if(!rst_n) beginbps_start <=1'b0;rx_int <= 1'b0;clk_en<=0;endelse if(neg_rs232_rx) begin/bps_start <= 1'b1; /启动串口,准备接收数据rx_int

19、<= 1'b1; /接收数据中断使能 clk_en<=1;endelse if(sample_clk_cnt = 7'd89)beginrx_int<=1'b0;bps_start<=1'b0;end /*这一部分是*/integer i;always (posedge clk or negedge rst_n)if(!rst_n)beginsample_clk_cnt <= 7'd0;end/*这里在一帧十位数据发送完以后不能使接收终端使能置零,是个问题,但是每次数据发送都是要检测下降沿的,可能并不影响数据正常发送*/el

20、se if(clk_en)beginfor(i=0;i<=7;i=i+1)if(Data_Tmpi>1)rx_datai<=1;elserx_datai<=0;if(sample_clk_cnt = 7'd89)sample_clk_cnt <= 7'd0;else if(sample_clk)sample_clk_cnt <= sample_clk_cnt + 1'b1;endreg 1:0Start_Bit; /*起始位,这里虽然定义,但并未使用该位来判断接收数据的正确性,即默认接收都是成功的*/reg 1:0Stop_Bit;

21、/*停止位,这里虽然定义,但并未使用该位来判断接收数据的正确性,即默认接收都是成功的*/always (posedge clk or negedge rst_n)/beginif(!rst_n)beginData_Tmp0 <= 2'd0;Data_Tmp1 <= 2'd0;Data_Tmp2 <= 2'd0;Data_Tmp3 <= 2'd0;Data_Tmp4 <= 2'd0;Data_Tmp5 <= 2'd0;Data_Tmp6 <= 2'd0;Data_Tmp7 <= 2'd

22、0;Start_Bit <= 2'd0;Stop_Bit <= 2'd0;endelse if(sample_clk)begincase(sample_clk_cnt)7'd0:beginData_Tmp0 <= 2'd0;Data_Tmp1 <= 2'd0;Data_Tmp2 <= 2'd0;Data_Tmp3 <= 2'd0;Data_Tmp4 <= 2'd0;Data_Tmp5 <= 2'd0;Data_Tmp6 <= 2'd0;Data_Tmp7 <

23、;= 2'd0;Start_Bit <= 2'd0;Stop_Bit <= 2'd0;end7'd3,7'd4,7'd5: Start_Bit <= Start_Bit + rs232_rx;7'd12,7'd13,7'd14:Data_Tmp0 <= Data_Tmp0 + rs232_rx;7'd21,7'd22,7'd23:Data_Tmp1 <= Data_Tmp1 + rs232_rx;7'd30,7'd31,7'd32:Data_Tm

24、p2 <= Data_Tmp2 + rs232_rx;7'd39,7'd40,7'd41:Data_Tmp3 <= Data_Tmp3 + rs232_rx;7'd48,7'd49,7'd50:Data_Tmp4 <= Data_Tmp4 + rs232_rx;7'd57,7'd58,7'd59:Data_Tmp5 <= Data_Tmp5 + rs232_rx;7'd66,7'd67,7'd68:Data_Tmp6 <= Data_Tmp6 + rs232_rx;7&

25、#39;d75,7'd76,7'd77:Data_Tmp7 <= Data_Tmp7 + rs232_rx;7'd84,7'd85,7'd86:Stop_Bit <= Stop_Bit + rs232_rx;default:;endcaseendelse;/endendmodule发送模块波特率产生器:module speed_select_tx(clk,rst_n,bps_start,clk_bps,key_in);/波特率设定 input clk; /50M时钟 input rst_n; /复位信号 input bps_start; /接

26、收到信号以后,波特率时钟信号置位,当接收到uart_rx传来的信号以后,模块开始运行 input 2:0key_in; output clk_bps; /接收数据中间采样点, reg13:0cntt; reg13:0 cnt;/分频计数器 reg clk_bps_r;/波特率时钟寄存器 reg clk_out; parameter system_clk = 50_000_000; /*输入时钟频率设定,默认50M*/localparam bps9600 = system_clk/9600 - 1;/*频率除以频率,可以得出每接受一个数据需要多少个时钟周期*/localparam bps1920

27、0 = system_clk/19200 - 1;localparam bps38400 = system_clk/38400 - 1;localparam bps57600 = system_clk/57600 - 1;localparam bps = system_clk/ - 1;localparam bps = system_clk/ - 1;localparam bps = system_clk/ - 1;localparam bps = system_clk/ - 1;always(posedge clk or negedge rst_n)if(!rst_n)begincntt &

28、lt;= bps9600;/*复位时波特率默认为9600bps*/endelse begincase(key_in)/*根据波特率控制信号选择不同的波特率计数器计数最大值*/3'd0: cntt <= bps9600;3'd1: cntt <= bps19200;3'd2: cntt <= bps38400;3'd3: cntt <= bps57600;3'd4: cntt <= bps;3'd5: cntt <= bps;3'd6: cntt <= bps;3'd7: cntt <

29、= bps;default: cntt<= bps9600;endcaseend always (posedge clk or negedge rst_n) if(!rst_n)cnt<=13'd0; else if(cnt=cntt)| !bps_start)/判断计数是否达到1个脉宽 cnt<=13'd0; else cnt<=cnt+1'b1;/波特率时钟启动/这里有问题 always (posedge clk or negedge rst_n) begin if(!rst_n) clk_bps_r<=1'b0; else i

30、f(cnt= cntt/2)/当波特率计数到一半时,进行采样存储clk_bps_r<=1'b1; else begin clk_bps_r<=1'b0;end end assign clk_bps = clk_bps_r;/将采样数据输出给uart_rx模块endmodule发送模块:module uart_tx( clk, rst_n, bps_start, clk_bps, rs232_tx, rx_data, rx_int ); input clk; input rst_n; input clk_bps;/中间采样点 input 7:0 rx_data;/接收

31、数据寄存器 input rx_int;/数据接收中断信号 output rs232_tx;/发送数据信号 output bps_start;/发送信号置位 reg rx_int0,rx_int1,rx_int2;/信号寄存器,捕捉下降沿 wire neg_rx_int; /下降沿标志 always (posedge clk or negedge rst_n) begin if(!rst_n) begin rx_int0 <= 1'b0; rx_int1 <= 1'b0; rx_int2 <= 1'b0; end else begin rx_int0 <= rx_int; rx_int1 <= rx_int0; rx_int2 <= rx_int1; end end assign neg_rx_int = rx_int1 & rx_int2;/捕捉下沿 reg 7:0 tx_data;/待发送数据 reg bps_start_r; reg tx_en;/发送信号使能,高有效 reg 3:0 num; always (posedge clk o

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论