FPGA模拟串口自收发-Verilog
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实现功能,FPGA 里实现从PC 串口接收数据,接着把接收到的数据发回去。波特率可选 9600bps,可调1bit 起始位,8bit 数据,1bit 停止位,无校验位。
参考《VHDL 硬件描述语言与和数字逻辑电路设计》
模块介绍如下
一、串口数据接收模块: 特别注意一个数据位占 4个clk_bps_4时钟周期。
串口数据接收控制
当数据接收端rxd 出现起始位低电平,启动接收控制计数器rx_cnt,置位为 8' b0111_00(28),
即 rx_cnt[5:2]
== 4 ' b0111(7),rx_cnt[1:0]
== 2'b00(0); —个计数周期开始,伴随
clk_bps_4, rx_cnt 加1 (每一个数据位加 4) 串口接收数据移位控制(关键采样点的选取)
每当rx_cnt[1:0] == 2'b01, 为了保证在 rxd 一位数据靠近中间位置采样;每 4个 clk_bps_4, rx_cnt[5:2] 力口 1 当 rx_cnt[5:2] == 8,9,10
….15,完成 8 位的数据采样,
串并变换
置位标志位rxdF 数据接收标志
rxd 出现起始位低电平,rxdF 置1 ,表示数据接收开始;当rx_cnt 计数到
rxd
flk reser
r do hich F 1 fr 冲 '豔 K / tt / L J 弃 L -- X rdbLLL CLK RESET I r rpset | EMPTY 8'b1111_11( 63), 数据接收完成,rxdF 置0 置位标志位rdFULL; 5,完成一位起始位,8 位的数据位发送,随后txd 置1(停止位),完成并串转换 置位标志位txdF ,tdEMPTY st_n(rst_n), .clk_bps_4(clk_bps_4), .wr(wr), .tdEMPTY(tdEMPTY), .DATA(DATA), .txd(txd) );st_n(rst_n), .clk_bps_4(clk_bps_4), .rd(rd), .rdFULL(rdFULL), .do_latch(do_latch), .rxd(rxd) ); /* 针对9600bps ,生成的时钟信号,用于接收数据采样与数据发送*/ Baudrate baud(.clk(clk), .rst_n(rst_n), .clk_bps_4(clk_bps_4)); Endmodule 串口数据接收模块: module Uart_RX(rst_n, clk_bps_4, rd, rdFULL, do_latch, rxd); input rst_n; // 低电平复位 input clk_bps_4; //4 倍于波特率时钟信号即一个数据位占4 个时钟周期 input rd;// 接收使能, 低电平有效 output reg[7:0] do_latch;// 接收数据锁存 output reg rdFULL;// 接收锁存器满标志 input rxd;// 串口引脚输入 reg[7:0] data_r = 8'bx; // 接收数据寄存器 reg[5:0] rx_cnt; reg rxdF;// 数据接收标志,RX模块内部信号 /* 当数据接收端rxd 出现起始位低电平,启动接收控制计数器rx_cnt, 置位为b0111_00(28), 8'即rx_cnt[5:2]== 4 'b0111(7),rx_cnt[1:0] == 2'b00(0); 一个计数周期开始,伴随clk_bps_4, rx_cnt 加1(每一个数据位加4) */ always@(posedge clk_bps_4 or negedge rst_n) begin if(!rst_n) begin rx_cnt <= 0; end else if(rx_cnt <= 27 && rxd == 0) begin rx_cnt <= 28; end else if(rx_cnt <= 27 && rxd == 1)// 串口无数据时,rx_cnt 保持0 begin rx_cnt <= 0; end else begin rx_cnt <= rx_cnt + 1;end end /* 空闲时rdFULL 置0,当数据接收完成,数据锁存到do_latch, 同时rdFULL置1,向上层模块表示数据以准备0K可以来读取; rd 置0, 表示上层模块开始读取数据,rdFULL 置0,表示数据已读走*/ always@(posedge clk_bps_4 or negedge rst_n)// 置位标志位rdFULL begin if(!rst_n) begin rdFULL <= 0; end else if(rd == 0) begin rdFULL <= 0; end else if(rxdF == 1 && rx_cnt == 63) begin do_latch <= data_r;// 数据锁存 rdFULL <= 1;// 锁存器数据准备0K end end /*rxd 出现起始位低电平, rxdF 置1 ,表示数据接收开始; 当rx_cnt计数到8' b1111_11(63),数据接收完成,rxdF置0* always@(posedge clk_bps_4 or negedge rst_n)// 置位标志位rxdF