完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
//;=================================================================*
//; 模块功能说明: UART Transmit and Receiver * //; 文件版本: v1.00 * //; 开发人员: * //; 创建时间: 2014-06-13 * //;=================================================================* //; 程序修改记录(最新的放在最前面): //; <修改日期>, <修改人员>: <修改功能概述> //;读者需要了解串口的通信协议方便理解程序。 //;原理根据定时器来完成定时的接收和定时的发送。重点是波特率的概念。 //;根据接收字节数,利用状态机完成分段处理。 /////////////////////////////////////////////////////////////////////////////////// module uart( input clk100m,//系统时钟 input reset_n, //复位 input rx_en,//接收使能 input tx_en,//发送使能 input [7:0] tx_data,//待发送数据 output [7:0] rx_data,//已接收数据 output uart_tx_out,//串行发送 input uart_rx_in, //串行接收 output rx_Busy,//当正在接收时拉高Busy。 output rx_Finish,//接收到正确帧拉高一个脉宽。 output tx_Busy,//当正在发送时拉高Busy。 output tx_Finish//当发送到完一帧拉高一个脉宽。 ); //宏定义/////////////////////////////////////////////////////////////////////////// parameter baud_rate = 10414;//接收波特率计算:N=(1/9600)*(1/f) parameter baud_rate_half = 5207;//中间采样时钟 //UART接收部分///////////////////////////////////////////////////////////////////// //一帧起始检测///////////////////////////////////////////////////////////////////// reg rx_in1; reg rx_in2; reg rx_in3; reg rx_in4; wire rx_fall_flag; assign rx_fall_flag = rx_in4 && rx_in3 && (!rx_in2) && (!rx_in1);//下降沿输出高脉冲 always @ (posedge clk100m or negedge reset_n) begin if(~reset_n)begin rx_in1 <= 1'b1; rx_in2 <= 1'b1; rx_in3 <= 1'b1; rx_in4 <= 1'b1; end else begin//连续4次采样进行滤波去抖 rx_in1 <= uart_rx_in; rx_in2 <= rx_in1; rx_in3 <= rx_in2; rx_in4 <= rx_in3; end end //接收波特率生成///////////////////////////////////////////////////////////////////// reg [13:0] rxcnt_bps; reg rxcnt_en; wire rxbps_clk; assign rxbps_clk = (rxcnt_bps == baud_rate_half)? 1'b1 : 1'b0;//产生中间采样时钟 always @ (posedge clk100m or negedge reset_n) begin if(~reset_n)begin rxcnt_bps <= 0; end else if(rxcnt_bps == baud_rate)begin rxcnt_bps <= 14'b0; end else if(rxcnt_en)begin rxcnt_bps <= rxcnt_bps + 1; end else begin rxcnt_bps <= 0; end end //接收控制///////////////////////////////////////////////////////////////////// reg [7:0] rxdata; reg rxBusy; reg rxFinish; reg [3:0] rxstate;//状态机 assign rx_data = rxdata; assign rx_Busy = rxBusy; assign rx_Finish = rxFinish; always @ (posedge clk100m or negedge reset_n)//原理定时中间采样 begin if(~reset_n)begin rxdata <= 8'b0; rxBusy <= 1'b0; rxFinish <= 1'b0; rxstate <= 4'b0; rxcnt_en <= 1'b0; end else if(rx_en)begin case(rxstate) 4'd0 : if(rx_fall_flag)begin//检测到由高到低,起始位 rxstate <= rxstate+1;//进入下一个状态 rxcnt_en <= 1'b1;//使能波特率采样时钟模块 rxFinish <= 1'b1;//置忙信号 rxBusy <= 1'b1; end 4'd1 : if(rxbps_clk)begin//起始位 rxstate <= rxstate+1;//进入下一个状态 end 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, 4'd9 : if(rxbps_clk)begin//接收数据 rxstate <= rxstate+1;//进入下一个状态 rxdata[rxstate - 2] <= uart_rx_in;//接收存储数据,先发地位 end 4'd10 : if(rxbps_clk)begin//校验位 rxstate <= rxstate+1;//进入下一个状态 end 4'd11 : if(rxbps_clk)begin//停止位 rxstate <= rxstate+1;//进入下一个状态 end 4'd12 : begin rxstate <= rxstate+1;//进入下一个状态 rxFinish <= 1'b1;//产生接收完成高脉冲 rxcnt_en <= 1'b0;//停止波特率采样模块 end 4'd13 : begin rxstate <= 4'b0;//返回初始状态 rxBusy <= 1'b0;//不忙,接收完成 rxFinish <= 1'b0;//产生接收完成高脉冲 end endcase end end //UART发送部分///////////////////////////////////////////////////////////////////// //发送波特率生成///////////////////////////////////////////////////////////////////// reg [13:0] txcnt_bps; wire txbps_clk; assign txbps_clk = (txcnt_bps == baud_rate_half)? 1'b1 : 1'b0;//产生中间采样时钟 always @ (posedge clk100m or negedge reset_n) begin if(~reset_n)begin txcnt_bps <= 0; end else if(txcnt_bps == baud_rate)begin txcnt_bps <= 14'b0; end else if(tx_en)begin txcnt_bps <= txcnt_bps + 1; end else begin txcnt_bps <= 0; end end //接收控制///////////////////////////////////////////////////////////////////// reg txBusy; reg txFinish; reg [3:0] txstate;//状态机 reg r_uart_tx_out; assign tx_Busy = txBusy; assign tx_Finish = txFinish; assign uart_tx_out = r_uart_tx_out; always @ (posedge clk100m or negedge reset_n)//原理定时发送 begin if(~reset_n)begin r_uart_tx_out <= 8'b0; txBusy <= 1'b0; txFinish <= 1'b0; txstate <= 4'b0; end else if(tx_en)begin//使能发送 case(txstate) 4'd0: if(txbps_clk)begin txstate <= txstate + 1;//进入下一状态 r_uart_tx_out <= 1'b0;//发送起始位 txBusy <= 1'b1;//拉高忙指示信号 end 4'd1, 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, : //发送数据位 if(txbps_clk)begin txstate <= txstate + 1; r_uart_tx_out <= tx_data[txstate - 1]; end 4'd9: //发送校验位 if(txbps_clk)begin txstate <= txstate + 1; r_uart_tx_out <= 1'b1; end 4'd10: //发送停止位 if(txbps_clk)begin txstate <= txstate + 1; r_uart_tx_out <= 1'b1; end 4'd11: //输出状态信号 if(txbps_clk)begin txstate <= txstate + 1; txFinish <= 1'b1;//输出完成指示脉冲 txBusy <= 1'b0;//拉低忙指示信号 end 4'd12: begin txstate <= 4'b0;//回到初始状态 txFinish <= 1'b0;//输出完成指示脉冲 end endcase end end endmodule |
|
相关推荐
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
610 浏览 0 评论
415 浏览 0 评论
求FPGA 驱动控制ltc2271 或者 ltc2180 或者 ltc2190或者 ltc2202 的代码
1778 浏览 0 评论
480 浏览 0 评论
求助:遇见诡异问题,FPGA模块A输出端口连接模块B输入后,模块A不能正常工作的
1894 浏览 1 评论
4641 浏览 104 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-31 09:30 , Processed in 0.493528 second(s), Total 68, Slave 51 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191